Jak przekierować wyjście qDebug, qWarning, qCritical itp.?
Używam wielu qDebug() <<
poleceń do debugowania. Czy jest jakiś wieloplatformowy sposób na przekierowanie wyjścia debugowania do pliku, bez uciekania się do skryptów powłoki? Domyślam się, że open () i dup2 () sprawdzą się w Linuksie, ale czy będą działać skompilowane z MinGW w Windowsie?
A może jest na to jakiś sposób Qt?
6 answers
Musisz zainstalować program obsługi wiadomości za pomocą funkcji qInstallMsgHandler
, a następnie możesz użyć QTextStream
, aby zapisać wiadomość debug do pliku. Oto przykładowy przykład:
#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();
}
Wzięte z doc z qInstallMsgHandler
(dodałem tylko komentarze):
W powyższym przykładzie funkcja myMessageOutput
używa stderr
, którą możesz zastąpić innym strumieniem plików lub całkowicie ponownie zapisać funkcja!
Po napisaniu i zainstalowaniu tej funkcji, wszystkie twoje qDebug
(jak również qWarning
, qCritical
itd) wiadomości będą przekierowywane do pliku, do którego piszesz w programie obsługi.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-21 09:35:44
Z Tutaj wszystkie zasługi należą do 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();
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-23 04:21:46
Oto działający przykład podłączenia domyślnego programu obsługi wiadomości.
Thank you @ 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-27 08:28:26
Oto wieloplatformowe rozwiązanie do logowania do konsoli, jeśli aplikacja została uruchomiona z Qt Creator, oraz do pliku debug.log
, gdy jest kompilowana i uruchamiana jako samodzielna aplikacja.
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
Formatowanie logów jest obsługiwane przez QString("%1 %2: %3 (%4)").arg...
(dla pliku) i fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...
(dla konsoli).
Inspiracja: https://gist.github.com/polovik/10714049 .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-22 08:16:21
Cóż, powiedziałbym, że moment, w którym musisz przekierować wyjście debugowania na coś innego niż stderr, jest momentem, w którym możesz pomyśleć o jakimś narzędziu do logowania. Jeśli uważasz, że potrzebujesz, polecam użycie QxtLogger
("Klasa QxtLogger jest łatwym w użyciu, łatwym do rozszerzenia narzędziem rejestrującym.") z Qxt
biblioteki.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-16 20:31:27
Oto prosty, bezpieczny dla wątku idiomatyczny przykład Qt do logowania zarówno do stderr
, jak i do pliku:
void messageHandler(QtMsgType type, const QMessageLogContext& context, const QString& message) { static QMutex mutex; QMutexLocker lock(&mutex); static QFile logFile(LOGFILE_LOCATION); static bool logFileIsOpen = logFile.open(QIODevice::Append | QIODevice::Text); std::cerr << qPrintable(qFormatLogMessage(type, context, message)) << std::endl; if (logFileIsOpen) { logFile.write(qFormatLogMessage(type, context, message).toUtf8() + '\n'); logFile.flush(); } }
Zainstaluj go za pomocą qInstallMessageHandler(messageHandler)
, jak opisano w innych odpowiedziach.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-26 12:22:30