qDebug, qWarning, qCritical 등 출력을 리디렉션하는 방법은 무엇입니까? 사용하고 있습니다 . 셸

qDebug() <<디버그 출력을 위해 많은 문을 사용하고 있습니다 . 셸 스크립트에 의존하지 않고 디버그 출력을 파일로 리디렉션 할 수있는 크로스 플랫폼 방법이 있습니까? 나는 open ()dup2 () 가 Linux에서 작업을 수행하지만 Windows에서 MinGW로 컴파일하여 작동합니까?

그리고 그것을 수행하는 Qt 방법이 있습니까?



답변

qInstallMsgHandler함수를 사용하여 메시지 처리기를 설치 한 다음을 사용 QTextStream하여 디버그 메시지를 파일 에 쓸 수 있습니다 . 다음은 샘플 예입니다.

#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();
}

의 문서에서 가져온 것입니다 qInstallMsgHandler(댓글 만 추가했습니다).

위의 예에서 함수 myMessageOutputstderr다른 파일 스트림으로 바꾸거나 함수를 완전히 다시 작성하려는 것을 사용합니다!

당신이 작성하고이 기능을 설치하면 모든 qDebug(물론 qWarning, qCritical등) 메시지는 핸들러에 파일 당신이있는 거 쓰기로 리디렉션 될 것이다.


답변

에서 여기에 모든 신용에 간다 정신 .

#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();
}


답변

다음은 기본 메시지 처리기를 연결하는 작업 예제입니다.

@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;
}


답변

다음은 앱이 Qt Creator에서 실행 된 경우 콘솔에 로그하고 debug.log파일이 컴파일되고 독립 실행 형 앱으로 실행될 때 파일 에 로깅하는 크로스 플랫폼 솔루션 입니다.

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

로그 형식화는 QString("%1 %2: %3 (%4)").arg...(파일 용) 및 fprintf(stderr, "%s %s: %s (%s:%u, %s)\n"...(콘솔 용)에서 처리합니다.

영감 : https://gist.github.com/polovik/10714049 .


답변

음, 디버그 출력을 stderr와 다른 것으로 리디렉션해야하는 순간은 로깅 도구에 대해 생각할 수있는 순간이라고 말하고 싶습니다. 필요한 경우 라이브러리 에서 사용하는 것이 좋습니다 QxtLogger( “QxtLogger 클래스는 사용하기 쉽고 확장하기 쉬운 로깅 도구입니다.” ) Qxt.


답변

다음은 stderr및 파일에 모두 로깅하는 간단한 스레드 안전 관용적 Qt 예제입니다 .

void messageHandler (QtMsgType 유형, const QMessageLogContext & 컨텍스트, const QString & 메시지)
{
    정적 QMutex 뮤텍스;
    QMutexLocker 잠금 (& mutex);

    정적 QFile logFile (LOGFILE_LOCATION);
    static bool logFileIsOpen = logFile.open (QIODevice :: Append | QIODevice :: Text);

    std :: cerr << qPrintable (qFormatLogMessage (유형, 컨텍스트, 메시지)) << std :: endl;

    if (logFileIsOpen) {
        logFile.write (qFormatLogMessage (유형, 컨텍스트, 메시지) .toUtf8 () + '\ n');
        logFile.flush ();
    }
}

qInstallMessageHandler(messageHandler)다른 답변에 설명 된대로 설치하십시오 .


답변