Doc: Improve documentation for qInstallMessageHandler()
Mention that QtMessageHandler needs to be reentrant, as well as other caveats. Mention QLoggingCategory, so people do know that they don't have to necessarily implement their own handler to filter messages (and that not all messages reach the handler). Also mention qFormatLogMessage(). Finally, give a more useful example for a custom message handler that logs to a file. Note that the example leaks a file handle at exit, but that is arguably not that bad. Pick-to: 6.5 6.6 Change-Id: I5be44167b266c9bbdbb0e94806bb024c9b352a32 Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
parent
7a87149c25
commit
cb841b449a
@ -210,37 +210,26 @@ const TInputType &myMin(const TInputType &value1, const TInputType &value2)
|
|||||||
|
|
||||||
|
|
||||||
//! [23]
|
//! [23]
|
||||||
#include <qapplication.h>
|
#include <QApplication>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
QtMessageHandler originalHandler = nullptr;
|
||||||
|
|
||||||
|
void logToFile(QtMsgType type, const QMessageLogContext &context, const QString &msg)
|
||||||
{
|
{
|
||||||
QByteArray localMsg = msg.toLocal8Bit();
|
QString message = qFormatLogMessage(type, context, msg);
|
||||||
const char *file = context.file ? context.file : "";
|
static FILE *f = fopen("log.txt", "a");
|
||||||
const char *function = context.function ? context.function : "";
|
fprintf(f, "%s\n", qPrintable(message));
|
||||||
switch (type) {
|
fflush(f);
|
||||||
case QtDebugMsg:
|
|
||||||
fprintf(stderr, "Debug: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
if (originalHandler)
|
||||||
break;
|
*originalHandler(type, context, msg);
|
||||||
case QtInfoMsg:
|
|
||||||
fprintf(stderr, "Info: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
||||||
break;
|
|
||||||
case QtWarningMsg:
|
|
||||||
fprintf(stderr, "Warning: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
||||||
break;
|
|
||||||
case QtCriticalMsg:
|
|
||||||
fprintf(stderr, "Critical: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
||||||
break;
|
|
||||||
case QtFatalMsg:
|
|
||||||
fprintf(stderr, "Fatal: %s (%s:%u, %s)\n", localMsg.constData(), file, context.line, function);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
qInstallMessageHandler(myMessageOutput);
|
originalHandler = qInstallMessageHandler(logToFile);
|
||||||
QApplication app(argc, argv);
|
QApplication app(argc, argv);
|
||||||
...
|
...
|
||||||
return app.exec();
|
return app.exec();
|
||||||
|
@ -2086,34 +2086,61 @@ void qErrnoWarning(int code, const char *msg, ...)
|
|||||||
\relates <QtLogging>
|
\relates <QtLogging>
|
||||||
\since 5.0
|
\since 5.0
|
||||||
|
|
||||||
Installs a Qt message \a handler which has been defined
|
Installs a Qt message \a handler.
|
||||||
previously. Returns a pointer to the previous message handler.
|
Returns a pointer to the previously installed message handler.
|
||||||
|
|
||||||
The message handler is a function that prints out debug messages,
|
A message handler is a function that prints out debug, info,
|
||||||
warnings, critical and fatal error messages. The Qt library (debug
|
warning, critical, and fatal messages from Qt's logging infrastructure.
|
||||||
mode) contains hundreds of warning messages that are printed
|
By default, Qt uses a standard message handler that formats and
|
||||||
when internal errors (usually invalid function arguments)
|
prints messages to different sinks specific to the operating system
|
||||||
occur. Qt built in release mode also contains such warnings unless
|
and Qt configuration. Installing your own message handler allows you
|
||||||
QT_NO_WARNING_OUTPUT and/or QT_NO_DEBUG_OUTPUT have been set during
|
to assume full control, and for instance log messages to the
|
||||||
compilation. If you implement your own message handler, you get total
|
file system.
|
||||||
control of these messages.
|
|
||||||
|
|
||||||
The default message handler prints the message to the standard output
|
Note that Qt supports \l{QLoggingCategory}{logging categories} for
|
||||||
under X11 or to the debugger under Windows. If it is a fatal message, the
|
grouping related messages in semantic categories. You can use these
|
||||||
application aborts immediately after handling that message. Custom
|
to enable or disable logging per category and \l{QtMsgType}{message type}.
|
||||||
message handlers should not attempt to exit an application on their own.
|
As the filtering for logging categories is done even before a message
|
||||||
|
is created, messages for disabled types and categories will not reach
|
||||||
|
the message handler.
|
||||||
|
|
||||||
Only one message handler can be defined, since this is usually
|
A message handler needs to be
|
||||||
done on an application-wide basis to control debug output.
|
\l{Reentrancy and Thread-Safety}{reentrant}. That is, it might be called
|
||||||
|
from different threads, in parallel. Therefore, writes to common sinks
|
||||||
|
(like a database, or a file) often need to be synchronized.
|
||||||
|
|
||||||
To restore the message handler, call \c qInstallMessageHandler(0).
|
Qt allows to enrich logging messages with further meta-information
|
||||||
|
by calling \l qSetMessagePattern(), or setting the \c QT_MESSAGE_PATTERN
|
||||||
|
environment variable. To keep this formatting, a custom message handler
|
||||||
|
can use \l qFormatLogMessage().
|
||||||
|
|
||||||
Example:
|
Try to keep the code in the message handler itself minimal, as expensive
|
||||||
|
operations might block the application. Also, to avoid recursion, any
|
||||||
|
logging messages generated in the message handler itself will be ignored.
|
||||||
|
|
||||||
|
The message handler should always return. For
|
||||||
|
\l{QtFatalMsg}{fatal messages}, the application aborts immediately after
|
||||||
|
handling that message.
|
||||||
|
|
||||||
|
Only one message handler can be installed at a time, for the whole application.
|
||||||
|
If there was a previous custom message handler installed,
|
||||||
|
the function will return a pointer to it. This handler can then
|
||||||
|
be later reinstalled by another call to the method. Also, calling
|
||||||
|
\c qInstallMessageHandler(nullptr) will restore the default
|
||||||
|
message handler.
|
||||||
|
|
||||||
|
Here is an example of a message handler that logs to a local file
|
||||||
|
before calling the default handler:
|
||||||
|
|
||||||
\snippet code/src_corelib_global_qglobal.cpp 23
|
\snippet code/src_corelib_global_qglobal.cpp 23
|
||||||
|
|
||||||
|
Note that the C++ standard guarantees that \c{static FILE *f} is
|
||||||
|
initialized in a thread-safe way. We can also expect \c{fprintf()}
|
||||||
|
and \c{fflush()} to be thread-safe, so no further synchronization
|
||||||
|
is necessary.
|
||||||
|
|
||||||
\sa QtMessageHandler, QtMsgType, qDebug(), qInfo(), qWarning(), qCritical(), qFatal(),
|
\sa QtMessageHandler, QtMsgType, qDebug(), qInfo(), qWarning(), qCritical(), qFatal(),
|
||||||
{Debugging Techniques}
|
{Debugging Techniques}, qFormatLogMessage()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Loading…
Reference in New Issue
Block a user