> 文章列表 > (Qt) 重定向内置日志

(Qt) 重定向内置日志

(Qt) 重定向内置日志

文章目录

  • 前言
  • 代码
    • .pri 独立的包
      • log.pri
      • LOG_Config.hpp
      • LOG.h
      • LOG.cpp
    • example
      • log_test.pro
      • main.cpp
  • 使用效果
  • 分析
    • Qt内部结构
    • 核心函数
    • 核心配置
  • END

前言

在软件开发过程中,避免不了日志的使用。

在Qt中,我们平常用的#include <QDebug>就是Qt自带的日志的一部分,平常我们最常用的就是在控制台进行输出。

而本文通过自定义重定向qInstallMessageHandler(),来将信息打到日志文件中。

代码

E:\\Qt\\demo\\saved\\LOG>tree /f
卷 新加卷 的文件夹 PATH 列表
卷序列号为 BAEE-AEDC
E:.
│  log_test.pro
│  main.cpp
│
└─logLOG.cppLOG.hlog.priLOG_Config.hpp

.pri 独立的包

log.pri

QT += widgetsINCLUDEPATH += $$PWDCONFIG(release, debug|release) {# 取消release优化# 取消优化这些信息:文件名、函数名、行数DEFINES += QT_MESSAGELOGCONTEXT# 消除debug输出DEFINES += QT_NO_DEBUG_OUTPUT
}HEADERS += \\$$PWD/LOG.h \\$$PWD/LOG_Config.hppSOURCES += \\$$PWD/LOG.cpp

LOG_Config.hpp

#ifndef __LOG__CONFIG__HPP__BY__CuberLotus__
#define __LOG__CONFIG__HPP__BY__CuberLotus__namespace LOG {/// 保存路径
const char * const _SAVE_PATH_ = "./myFiles/log";
/// 文件后缀名
const char * const _FILE_SUFFIX_NAME_ = ".log";/// 根据日期分文件夹
/// 这里是具体日志的内容
const char * const _DATA_FIRMAT_ = "yyyy年MM月dd日";
const char * const _TIME_FORMAT_ = "hh:mm:ss";} // namespace LOG#endif // __LOG__CONFIG__HPP__BY__CuberLotus__

LOG.h

#ifndef __LOG__H__BY__CuberLotus__
#define __LOG__H__BY__CuberLotus__
#include <QDebug>namespace LOG {
/// 给外部调用设置的唯一接口
void QLog_Init();
}#endif  // __LOG__HPP__BY__CuberLotus__

LOG.cpp

#include <QApplication>
#include <QDateTime>
#include <QDebug>
#include <QDir>#include "LOG.h"
#include "LOG_Config.hpp"namespace LOG {
/// data
/// 软件版本
static QString appVersion;
/// 日志存储路径
static QString logPath;
/// 日志文件后缀名
static QString suffixName;
/// 日期时间格式
static QString timeFormat;
/// 日志类型的字符串
static QVector<QString> typeStrList;/* @brief init_Config* 初始化配置* enum QtMsgType {*  QtDebugMsg,*  QtWarningMsg,*  QtCriticalMsg,*  QtFatalMsg,*  QtInfoMsg,*  QtSystemMsg = QtCriticalMsg* };*/
static void init_config() {/// V1.2.3.4appVersion = QCoreApplication::applicationVersion();if (appVersion.isEmpty()) {appVersion = "No Version";} else {appVersion = "V" + appVersion;}/// .logsuffixName = QString(_FILE_SUFFIX_NAME_);/// hh:mm:sstimeFormat = QString(_TIME_FORMAT_);/// ./SMTPCR/log/yyyy年MM月dd日logPath = QDir(_SAVE_PATH_).absoluteFilePath(QDateTime::currentDateTime().toString(_DATA_FIRMAT_));/// 生成pathQDir().mkpath(logPath);typeStrList << QString("Debug") << QString("Warning") << QString("Critical")<< QString("Fatal") << QString("Info") << QString("System");
}/* @brief QtMessageHandler* @param type* @param context* @param msg* 重定向的回调函数* 样例:[V0.1.2.0] [18:08:52] [@File:..\\LOG\\main.cpp @Func:int qMain(int,* char) @Line:16]*/
static void QtMessageHandler(QtMsgType type, const QMessageLogContext& context,const QString& msg) {QString filePath = QDir(logPath).absoluteFilePath(typeStrList[type] + suffixName);QString&& time = QDateTime::currentDateTime().toString(timeFormat);QString&& locate = QString("@File:%1 @Func:%2 @Line:%3").arg(context.file).arg(context.function).arg(context.line);/// 注意这里使用 \\r\\nQString&& str = QString("[%1] [%2] [%3]\\r\\n%4\\r\\n").arg(appVersion).arg(time).arg(locate).arg(msg);QFile file(filePath);file.open(QIODevice::WriteOnly | QIODevice::Append);QTextStream(&file) << str;file.close();
}/// 给外部调用设置的唯一接口
void QLog_Init() {init_config();
#ifdef QT_NO_DEBUGqInstallMessageHandler(QtMessageHandler);
#endif
}}  // namespace LOG

example

log_test.pro

QT += widgetsDESTDIR = $$PWD/bin/VERSION = 0.1.3
TARGET = log_test_V$$VERSIONCONFIG(debug, debug|release) {CONFIG += console
}INCLUDEPATH += code
include($$PWD/log/log.pri)SOURCES += \\main.cpp

main.cpp

#include <QApplication>
#include <QDebug>
#include "LOG.h"int main(int argc, char *argv[]) {QApplication __app(argc, argv);LOG::QLog_Init();qDebug("This is a debug message");qWarning("This is a warning message");qCritical("This is a critical message");qInfo() << "这是" << "链式操作" << __func__ << __FUNCTION__ << __PRETTY_FUNCTION__;return 0;// return __app.exec();
}

使用效果

debug模式

debug模式,设定为在控制台输出

在这里插入图片描述

release模式

release模式设定为记录到文件中

E:\\Qt\\demo\\saved\\LOG\\bin>tree /f
卷 新加卷 的文件夹 PATH 列表
卷序列号为 BAEE-AEDC
E:.
│  log_test_V0.1.3.exe
│
└─myFiles└─log└─2023年04月18日Critical.logInfo.logWarning.log

在这里插入图片描述

分析

Qt内部结构

/// qlogging.h
enum QtMsgType { QtDebugMsg, QtWarningMsg, QtCriticalMsg, QtFatalMsg, QtInfoMsg, QtSystemMsg = QtCriticalMsg 
};class Q_CORE_EXPORT QMessageLogger {
#ifndef Q_CC_MSVCQ_NORETURN
#endifQ_DECL_COLD_FUNCTION/// 最高危险等级,使用一次程序直接终止void fatal(const char *msg, ...) const noexcept Q_ATTRIBUTE_FORMAT_PRINTF(2, 3);#ifndef QT_NO_DEBUG_STREAMQDebug debug() const;QDebug debug(const QLoggingCategory &cat) const;QDebug debug(CategoryFunction catFunc) const;QDebug info() const;QDebug info(const QLoggingCategory &cat) const;QDebug info(CategoryFunction catFunc) const;QDebug warning() const;QDebug warning(const QLoggingCategory &cat) const;QDebug warning(CategoryFunction catFunc) const;QDebug critical() const;QDebug critical(const QLoggingCategory &cat) const;QDebug critical(CategoryFunction catFunc) const;QNoDebug noDebug() const noexcept;
#endif // QT_NO_DEBUG_STREAM
};#define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug
#define qInfo QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).info
#define qWarning QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).warning
#define qCritical QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).critical
#define qFatal QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).fatal/// 重定向的设定
typedef void (*QtMessageHandler)(QtMsgType, const QMessageLogContext &, const QString &);
Q_CORE_EXPORT QtMessageHandler qInstallMessageHandler(QtMessageHandler);

核心函数

#include <QApplication>/* @brief QtMessageHandler* @param type     日志类型* @param context  日志上下文* @param msg      日志的信息* 重定向的回调函数*/
void QtMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) {
}int main(int argc, char *argv[]) {/// 必须有 QApplication 的实例QApplication a(argc, argv);/// 全局函数qInstallMessageHandler(QtMessageHandler);
}

核心配置

# QApplication 所在的库
QT += widgets# 由于release模式会对程序进行优化
# 通过设定 DEFINES 取消这些优化
# 并取消 debug 信息的输出
CONFIG(release, debug|release) {# 取消release优化# 取消优化这些信息:文件名、函数名、行数DEFINES += QT_MESSAGELOGCONTEXT# 消除debug输出DEFINES += QT_NO_DEBUG_OUTPUT
}



END