c++ - qinfo - q_assert qt
¿Cómo redirigir la salida de qDebug, qWarning, qCritical, etc.? (5)
Estoy usando muchas qDebug() <<
para la salida de depuración. ¿Hay alguna forma de plataforma cruzada que pueda redirigir esa salida de depuración a un archivo, sin recurrir a scripts de shell? Supongo que open() y dup2() harán el trabajo en Linux, pero ¿funcionará compilado con MinGW en Windows?
Y tal vez hay una forma Qt para hacerlo?
Aquí hay un ejemplo de trabajo de conectar el controlador de mensajes predeterminado.
¡Gracias @Ross Rogers!
// -- main.cpp
// Get the default Qt message handler.
static const QtMessageHandler QT_DEFAULT_MESSAGE_HANDLER = qInstallMessageHandler(0);
void myCustomMessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
// Handle the messages!
// Call the default handler.
(*QT_DEFAULT_MESSAGE_HANDLER)(type, context, msg);
}
int main(int argc, char *argv[])
{
qInstallMessageHandler(myCustomMessageHandler);
QApplication a(argc, argv);
qDebug() << "Wello Horld!";
return 0;
}
Aquí hay una solución multiplataforma para iniciar sesión en la consola, si la aplicación se ejecutó desde Qt Creator y hasta el archivo debug.log
, cuando se compila y se ejecuta como una aplicación independiente.
main.cpp :
#include <QApplication>
#include <QtGlobal>
#include <QtDebug>
#include <QTextStream>
#include <QTextCodec>
#include <QLocale>
#include <QTime>
#include <QFile>
const QString logFilePath = "debug.log";
bool logToFile = false;
void customMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QHash<QtMsgType, QString> msgLevelHash({{QtDebugMsg, "Debug"}, {QtInfoMsg, "Info"}, {QtWarningMsg, "Warning"}, {QtCriticalMsg, "Critical"}, {QtFatalMsg, "Fatal"}});
QByteArray localMsg = msg.toLocal8Bit();
QTime time = QTime::currentTime();
QString formattedTime = time.toString("hh:mm:ss.zzz");
QByteArray formattedTimeMsg = formattedTime.toLocal8Bit();
QString logLevelName = msgLevelHash[type];
QByteArray logLevelMsg = logLevelName.toLocal8Bit();
if (logToFile) {
QString txt = QString("%1 %2: %3 (%4)").arg(formattedTime, logLevelName, msg, context.file);
QFile outFile(logFilePath);
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
outFile.close();
} else {
fprintf(stderr, "%s %s: %s (%s:%u, %s)/n", formattedTimeMsg.constData(), logLevelMsg.constData(), localMsg.constData(), context.file, context.line, context.function);
fflush(stderr);
}
if (type == QtFatalMsg)
abort();
}
int main(int argc, char *argv[])
{
QByteArray envVar = qgetenv("QTDIR"); // check if the app is ran in Qt Creator
if (envVar.isEmpty())
logToFile = true;
qInstallMessageHandler(customMessageOutput); // custom message handler for debugging
QApplication a(argc, argv);
// ...and the rest of ''main'' follows
El formato del registro lo maneja QString("%1 %2: %3 (%4)").arg...
(para el archivo) y fprintf(stderr, "%s %s: %s (%s:%u, %s)/n"...
(para la consola).
Inspiración: https://gist.github.com/polovik/10714049 .
Bueno, yo diría que el momento en que necesitas redirigir tu resultado de depuración a algo diferente de stderr es cuando puedes pensar en alguna herramienta de registro. Si cree que necesita uno, le recomendaría usar QxtLogger
( "La clase QxtLogger es una herramienta de registro fácil de usar y fácil de ampliar" ) de la biblioteca Qxt
.
De here todo el crédito va al spirit .
#include <QApplication>
#include <QtDebug>
#include <QFile>
#include <QTextStream>
void myMessageHandler(QtMsgType type, const QMessageLogContext &, const QString & msg)
{
QString txt;
switch (type) {
case QtDebugMsg:
txt = QString("Debug: %1").arg(msg);
break;
case QtWarningMsg:
txt = QString("Warning: %1").arg(msg);
break;
case QtCriticalMsg:
txt = QString("Critical: %1").arg(msg);
break;
case QtFatalMsg:
txt = QString("Fatal: %1").arg(msg);
break;
}
QFile outFile("log");
outFile.open(QIODevice::WriteOnly | QIODevice::Append);
QTextStream ts(&outFile);
ts << txt << endl;
}
int main( int argc, char * argv[] )
{
QApplication app( argc, argv );
qInstallMessageHandler(myMessageHandler);
...
return app.exec();
}
QTextStream
instalar un manejador de mensajes usando la función qInstallMsgHandler
y luego, puede usar QTextStream
para escribir el mensaje de depuración en un archivo. Aquí hay un ejemplo de muestra:
#include <QtGlobal>
#include <stdio.h>
#include <stdlib.h>
void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
QByteArray localMsg = msg.toLocal8Bit();
switch (type) {
case QtDebugMsg:
fprintf(stderr, "Debug: %s (%s:%u, %s)/n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtInfoMsg:
fprintf(stderr, "Info: %s (%s:%u, %s)/n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtWarningMsg:
fprintf(stderr, "Warning: %s (%s:%u, %s)/n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtCriticalMsg:
fprintf(stderr, "Critical: %s (%s:%u, %s)/n", localMsg.constData(), context.file, context.line, context.function);
break;
case QtFatalMsg:
fprintf(stderr, "Fatal: %s (%s:%u, %s)/n", localMsg.constData(), context.file, context.line, context.function);
abort();
}
}
int main(int argc, char **argv)
{
qInstallMessageHandler(myMessageOutput); // Install the handler
QApplication app(argc, argv);
...
return app.exec();
}
Tomado del doc de qInstallMsgHandler
(solo agregué los comentarios):
En el ejemplo anterior, la función myMessageOutput
usa stderr
que es posible que desee reemplazar con alguna otra secuencia de archivos, ¡o reescribe completamente la función!
Una vez que escriba e instale esta función, todos sus qDebug
(así como qWarning
, qCritical
, etc.) se redirigirán al archivo en el que está escribiendo en el controlador.