logo MSJO.kr

Logging with Qt/C++

2020-04-23
MsJ
 

QT/C++ 개발환경에서 디버그 메시지(로깅)를 파일로 저장해보는 예제이다. qDebug(), qInfo(), qWarning(), qCritical(), qFatal() 매크로를 사용하고 윈도우 환경에서 OutputDebugString 모니터링을 위해 사용한 툴은 여기에서 다운로드한다.

LogWriter.h
// logwriter.h
#ifndef LOGWRITER_H
#define LOGWRITER_H

#include <QCoreApplication>
#include <QDateTime>
#include <QDir>
#include <QFile>
#include <QLoggingCategory>
#include <QScopedPointer>
#include <QTextStream>

class LogWriter {
  public:
    LogWriter();
    ~LogWriter();
    static QScopedPointer<QFile> m_logFile;
    static void WriteLog();
    static void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg);
};
#endif // LOGWRITER_H
LogWriter.cpp
#include "logwriter.h"

QScopedPointer<QFile> LogWriter::m_logFile(nullptr);

LogWriter::LogWriter()
{
    // https://evileg.com/en/post/154/ 추가
    // qSetMessagePattern("%{time yyyy-MM-dd hh:mm:ss} %{category} %{file}(%{line}): %{message}");
}

void LogWriter::WriteLog()
{
    QString path(QCoreApplication::applicationDirPath() + "/Log/" + QDateTime::currentDateTime().toString("yyyy-MM"));
    QDir dir;
    if (!dir.exists(path))
        dir.mkpath(path);

    m_logFile.reset(new QFile(path + "/log_" + QDateTime::currentDateTime().toString("yyyy-MM-dd") + ".txt"));
    m_logFile.data()->open(QFile::Append | QFile::Text);

    qInstallMessageHandler(MessageHandler);
}

void LogWriter::MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QTextStream out(m_logFile.data());
    out << QDateTime::currentDateTime().toString("hh:mm:ss ");

    switch (type) {
    case QtInfoMsg:
        out << "[ INFO]";
        break;
    case QtDebugMsg:
        out << "[DEBUG]";
        break;
    case QtWarningMsg:
        out << "[ WARN]";
        break;
    case QtCriticalMsg:
        out << "[ERROR]";
        break;
    case QtFatalMsg:
        out << "[FATAL]";
        break;
    }

    out << " : " << msg << " <SRC" << context.file << "(" << context.line << ")>" << endl;
    out.flush();
}

LogWriter::~LogWriter() = default;
main.cpp
#include "logwriter.h"
#include <QCoreApplication>
#include <iostream>

#ifdef WIN32
#include <windows.h>
#endif

using namespace std;

float Divison(int i, int j)
{
    if (j == 0)
        throw runtime_error("Attempted to divide by Zero");
    return (i / j);
}

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    LogWriter::WriteLog();
#ifdef QT_DEBUG
    qInfo() << "Info Log 메시지 입니다.";
    qDebug() << "Debug Log 메시지 입니다.";
    qWarning() << "Warning Log 메시지 입니다.";
    qCritical() << "Error Log 메시지 입니다."; //[ERROR]
    // windows dbgview.exe
#ifdef WIN32
    // wchar_t buff[100], tmp[] = L"헬로우월드-Dbgview.exe에서 모니터링";
    // swprintf(buff, sizeof(buff), tmp);
    QString s = "헬로우월드-Dbgview.exe에서 모니터링";
    const wchar_t *buff = reinterpret_cast<LPCWSTR>(s.utf16());
    OutputDebugStringW(buff);
#endif
    return 0;
#else
    qInfo("*****START*********");
    try {
        int i = 1, j = 0;
        cout << Divison(i, j) << endl;
    }
    catch (exception &ex) { // runtime_error
        cout << ex.what();
        qCritical() << ex.what();
    }
    // a.exec();
    // return 0;
    qFatal("*****QUIT**********");
#endif
}
log_yyyy-MM-dd.txt
// {AppPath}/Log/2020-04/log_2020-04-23.txt
/* Release Mode
12:19:14 [ INFO] : *****START********* <SRC(0)>
12:19:14 [ERROR] : Attempted to divide by Zero <SRC(0)>
12:19:14 [FATAL] : *****QUIT********** <SRC(0)>
*/

/* Debug Mode
12:55:42 [ INFO] : Info Log 메시지 입니다. <SRC..\LogTest\main.cpp(23)>
12:55:42 [DEBUG] : Debug Log 메시지 입니다. <SRC..\LogTest\main.cpp(24)>
12:55:42 [ WARN] : Warning Log 메시지 입니다. <SRC..\LogTest\main.cpp(25)>
12:55:42 [ERROR] : Error Log 메시지 입니다. <SRC..\LogTest\main.cpp(26)>
*/
Reference

Prεv   Nεxt
Content
Search     RSS Feed     BY-NC-ND