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)>
*/