开发平台:Win10 64位
开发环境:Qt Creator 13.0.0
构建环境:Qt 5.15.2 +MSVC2019 64位
一、Log4Qt简介
Log4Qt是使用Trolltech Qt Framework的Apache Software Foundation Log4j包的C ++端口。它旨在供开源和商业Qt项目使用。所以 Log4Qt 是Apache Log4J 的Qt移植版,Log4Qt主要是用来记录日志(有助于程序调试)。henxin:
Logger | 提供日志记录服务,可以有多个Logger存在,每个有它们自己的名字。Logger间存在隶属关系,有一个Logger称为根Logger。 |
Appender | 用来指明将日志记录到什么地方:比如,控制台、文件、数据库,等等 |
Layout | 控制日志的输出格式,可以类比一下C中的printf。 |
Filter | 在日志消息被追加器处理之前进行筛选。 可以有多个筛选条件。 |
Level | 代表日志级别(如 TRACE< DEBUG< INFO< WARN< ERROR< FATAL)。 决定哪些日志消息应该被记录。 所以,如果你设置了 INFO 级别,那么 TRACE 和 DEBUG 消息将被忽略,而 INFO, WARN, ERROR, 和 FATAL 消息会被处理。同样地,如果设置为 ERROR 级别,那么只有 ERROR 和 FATAL 消息会被处理。 |
LoggingEvent | 代表一个日志事件,包含日志消息、时间戳、日志级别等信息。 |
LoggerRepository | 用于管理和检索日志器的容器。 默认实现是 LoggerRepository,但可以有其他实现。 |
LogManager | 提供静态方法管理日志器和配置。 |
Configuration 类 | 这些类和方法允许从外部配置文件(如 XML 或 properties 文件)配置 Log4Qt。这样,开发者可以不修改代码即可更改日志配置。 PropertyConfigurator 和 XmlConfigurator 是两个主要的配置器类。 |
二、下载使用
2.1 下载说明
Qt4版本的log4qt当前最新版本为log4qt-0.3.zIP,这源码包最后修改日期为2009年。
Sourceforge下载地址:Log4Qt - Logging for C++/Qt download | SourceForge.net
Github:devbean/log4qt: Logger for Qt. (github.com)
Gitee: Gitee 极速下载/log4qt
笔者使用的QT版本是5.15.2,从github上面下载的log4qt源码,Releases · MEONMedical/Log4Qt (github.com),支持的QT版本为>5.12。
2.2 编译链接库
将下载的Log4Qt解压,双击log4qt.pro,生成项目,然后右键选择重新构建项目。
在/build/Desktop_Qt_5_15_2_MSVC2019_64bit-Release/bin文件夹下就会生成log4qt.dll等文件。(具体路径根据自己选择的构建环境)。
现在我们需要的链接库就有了。
2.3 准备文件
新建一个文件夹,在新建的文件夹下面在新建两个文件夹,一个是bin,一个是include,在include文件夹下面再新建一个log4qt文件夹。下面开始将源码中的文件依次倒入我们新建的这个文件夹中。首先将刚刚生成的链接库复制到bin文件夹中,然后将Log4Qt-master\src\log4qt路径下的三个文件夹和.h文件拷贝进include文件夹下面的log4gt文件夹中。
2.4 程序实现
上一步我们已经将log4qt的链接库、头文件等准备好了,现在开始通过代码的方式实现日志的配置和生成,下一小节通过配置文件来实现日志内容的配置和日志生成。新建工程,然后将新建的文件夹(log4qtlibs) 复制到工程目录下。
在untitled02.pro文件中增加如下代码:
DESTDIR = $$PWD/log4qtlibs/bin//这个要注意,exe及日志文件都会在这个目录下生成
INCLUDEPATH += $$PWD/log4qtlibs/include
LIBS += -L$$PWD/log4qtlibs/bin -llog4qt
更改main.cpp中的代码
#include "mainwindow.h"
#include <QApplication>
#include "log4qt/logger.h"
#include "log4qt/logmanager.h"
#include "log4qt/patternlayout.h"
#include "log4qt/consoleappender.h"
#include "log4qt/dailyfileappender.h"
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
//Logger:记录器,有一个根Logger,可以有多个其他Logger
Log4Qt::Logger *logger = Log4Qt::Logger::rootLogger(); //根Logger,name为root
//Log4Qt::Logger *mylog1 = Log4Qt::Logger::logger("Mylog1"); //其他Logger,name为Mylog1的
logger->setLevel(Log4Qt::Level::DEBUG_INT); //设置日志输出级别
Log4Qt::LogManager::setHandleQtMessages(true); //处理qt调试输出信息,将qDebug之类的信息重定向,不开启这个qDebug()、qWri
/****************PatternLayout配置日志的输出格式****************************/
Log4Qt::PatternLayout *layout = new Log4Qt::PatternLayout();
layout->setConversionPattern("%d{yyyy-MM-dd hh:mm:ss} %p %c %m %r %t %F %M %L %l %n");
layout->activateOptions(); // 激活Layout
/***************************配置日志的输出位置***********/
//ConsoleAppender:输出到控制台
Log4Qt::ConsoleAppender *appender = new Log4Qt::ConsoleAppender(layout, Log4Qt::ConsoleAppender::STDOUT_TARGET);
appender->activateOptions();
logger->addAppender(appender);
//DailyFileAppender:每天新建一个文件,保存当天的日志,超过指定的天数,删除最开始的日志
Log4Qt::DailyFileAppender *dailiAppender = new Log4Qt::DailyFileAppender;
dailiAppender->setLayout(layout); //设置输出格式
dailiAppender->setFile("logFile.log"); //日志文件名:固定前缀
dailiAppender->setDatePattern("_yyyy_MM_dd"); //日志文件名:根据每天日志变化的后缀
dailiAppender->setAppendFile(true); //true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是false
dailiAppender->setKeepDays(30); //设置保留天数
dailiAppender->activateOptions();
logger->addAppender(dailiAppender);
// 关闭 logger
// logger->removeAllAppenders();
// logger->loggerRepository()->shutdown();
MainWindow w;
w.show();
return a.exec();
}
更改mainwindow.cpp中的代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
qDebug() << "mainwindow debug";
qCritical() << "mainwindow critical";
}
MainWindow::~MainWindow()
{
delete ui;
}
重新构建,并运行,在项目目录的bin文件夹下生成日志文件
注意:如果是Debug模式下,可能MainWinwos中的这两句不能输出到日志文件中,需要改成release模式。
qDebug() << "mainwindow debug";
qCritical() << "mainwindow critical";
2.5 配置文件使用
使用配置文件首先得获取配置文件,log4qt提供了获取配置文件的函数
Log4Qt::PropertyConfigurator::configure(const QString &configFilename);
参数就是配置文件名,但是,直接填写参数名会报错,系统找不到。所以,对于配置文件,我们首先要明确配置文件放在哪?然后明确这个参数应该怎么写。
首先配置文件的位置可以放在任意可以访问的位置。然后这个参数就是配置文件的全路径。
Log4Qt::PropertyConfigurator::configure(a.applicationDirPath() + "/log4qt.ini");
笔者将这个 log4qt.ini放在了exe文件夹下,通过applicationDirPath函数,获取到exe的文件路径,然后拼接上文件名,就可以给configure函数配置文件的全路径了。
其实在参考文献3.5中有这么一种方式默认方案,但是不适合生产环境,毕竟我们使用配置文件的需求就是灵活性嘛,这种默认的需要文件名和地址都得符合log4qt的要求,不然log4qt找不到配置文件。
2.6 配置文件
#设置储存log文件的根目录
logpath=.
log4j.reset=true
log4j.Debug=WARN
log4j.threshold=NULL
#设置是否监听QDebug输出的字符串
log4j.handleQtMessages=true
#在运行中,是否监视此文件配置的变化
log4j.watchThisFile=false
#设置根Logger的输出log等级为All
log4j.rootLogger=ALL, console, daily
#设置Log输出的几种输出源(appender.console、appender.daily、appender.rolling):
#console:设置终端打印记录器
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=STDOUT_TARGET
log4j.appender.console.layout=org.apache.log4j.TTCCLayout
log4j.appender.console.layout.dateFormat=dd.MM.yyyy hh:mm:ss.zzz
log4j.appender.console.layout.contextPrinting=true
log4j.appender.console.threshold=ALL
#daily:设置一个每日储存一个log文件的记录器
log4j.appender.daily=org.apache.log4j.DailyFileAppender
log4j.appender.daily.file=${logpath}/propertyconfigurator.log
log4j.appender.daily.appendFile=true
log4j.appender.daily.datePattern=_yyyy_MM_dd
log4j.appender.daily.keepDays=90
log4j.appender.daily.layout=${log4j.appender.console.layout}
log4j.appender.daily.layout.dateFormat=${log4j.appender.console.layout.dateFormat}
log4j.appender.daily.layout.contextPrinting=${log4j.appender.console.layout.contextPrinting}
#rolling:配置一个滚动文件记录器
log4j.appender.rolling=org.apache.log4j.RollingFileAppender
log4j.appender.rolling.file= ${logpath}/propertyconfigurator_rolling.log
log4j.appender.rolling.appendFile=true
log4j.appender.rolling.maxFileSize= 20MB
log4j.appender.rolling.maxBackupIndex= 10
log4j.appender.rolling.layout=${log4j.appender.console.layout}
log4j.appender.rolling.layout.dateFormat=${log4j.appender.console.layout.dateFormat}
log4j.appender.rolling.layout.contextPrinting=${log4j.appender.console.layout.contextPrinting}
# 给“LoggerObjectPrio”这个类的Logger定义log输出等级为Error,
# 给“LoggerObjectPrio”这个类的Logger定义log输出源:daily, console
log4j.logger.LoggerObjectPrio=ERROR, rolling
#设置为false,表示“LoggerObjectPrio”这个类的logger不继承的rootLogger输出源(appender)
log4j.additivity.LoggerObjectPrio=false
log4j.rootLogger=debug,File
log4j.appender.File=org.apache.log4j.FileAppender
log4j.appender.File=org.apache.log4j.RollingFileAppender
log4j.appender.File.File=Log.log
log4j.appender.File.MaxFileSize=3072KB
log4j.appender.File.AppendFile=true
log4j.appender.File.layout=org.apache.log4j.PatternLayout
log4j.appender.File.layout.ConversionPattern=%-d{yyyy-MM-dd HH:mm:ss} [%p] %m%n
(1)org.apache.log4j.ConsoleAppender(控制台)
(2)org.apache.log4j.FileAppender(文件)
(3)org.apache.log4j.DailyRollingFileAppender(每天产生一个日志文件)
(4)org.apache.log4j.RollingFileAppender(文件大小到达指定尺寸的时候产生一个新的文件)
(5)org.apache.log4j.WriterAppender(将日志信息以流格式发送到任意指定的地方)
(1)ConsoleAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Target=System.err:默认值是System.out。
(2)FileAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
(3)DailyRollingFileAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定当前消息输出到logging.log4j文件中。
DatePattern=’.‘yyyy-MM:每月滚动一次日志文件,即每月产生一个新的日志文件。当前月的日志文件名为logging.log4j,前一个月的日志文件名为logging.log4j.yyyy-MM。
另外,也可以指定按周、天、时、分等来滚动日志文件,对应的格式如下:
1)’.‘yyyy-MM:每月
2)’.‘yyyy-ww:每周
3)’.‘yyyy-MM-dd:每天
4)’.‘yyyy-MM-dd-a:每天两次
5)’.‘yyyy-MM-dd-HH:每小时
6)’.'yyyy-MM-dd-HH-mm:每分钟
(4)RollingFileAppender选项:
Threshold=WARN:指定日志信息的最低输出级别,默认为DEBUG。
ImmediateFlush=true:表示所有消息都会被立即输出,设为false则不输出,默认值是true。
Append=false:true表示消息增加到指定文件中,false则将消息覆盖指定的文件内容,默认值是true。
File=D:/logs/logging.log4j:指定消息输出到logging.log4j文件中。
MaxFileSize=100KB:后缀可以是KB, MB 或者GB。在日志文件到达该大小时,将会自动滚动,即将原来的内容移到logging.log4j.1文件中。
MaxBackupIndex=2:指定可以产生的滚动文件的最大数,例如,设为2则可以产生logging.log4j.1,logging.log4j.2两个滚动文件和一个logging.log4j文件。
配置日志信息的输出格式(Layout):
log4j.appender.appenderName.layout=className
className:可设值如下:
(1)org.apache.log4j.HTMLLayout(以HTML表格形式布局)
(2)org.apache.log4j.PatternLayout(可以灵活地指定布局模式)
(3)org.apache.log4j.SimpleLayout(包含日志信息的级别和信息字符串)
(4)org.apache.log4j.TTCCLayout(包含日志产生的时间、线程、类别等等信息)
(1)HTMLLayout选项:
LocationInfo=true:输出java文件名称和行号,默认值是false。
Title=My Logging: 默认值是Log4J Log Messages。
(2)PatternLayout选项:
ConversionPattern=%m%n:设定以怎样的格式显示消息。
格式化符号说明:
%p:输出日志信息的优先级,即DEBUG,INFO,WARN,ERROR,FATAL。
%d:输出日志时间点的日期或时间,默认格式为ISO8601,也可以在其后指定格式,如:%d{yyyy/MM/dd HH:mm:ss,SSS}。
%r:输出自应用程序启动到输出该log信息耗费的毫秒数。
%t:输出产生该日志事件的线程名。
%l:输出日志事件的发生位置,相当于%c.%M(%F:%L)的组合,包括类全名、方法、文件名以及在代码中的行数。例如:test.TestLog4j.main(TestLog4j.java:10)。
%c:输出日志信息所属的类目,通常就是所在类的全名。
%M:输出产生日志信息的方法名。
%F:输出日志消息产生时所在的文件名称。
%L::输出代码中的行号。
%m::输出代码中指定的具体日志信息。
%n:输出一个回车换行符,Windows平台为"/r/n",Unix平台为"/n"。
%x:输出和当前线程相关联的NDC(嵌套诊断环境),尤其用到像java servlets这样的多客户多线程的应用中。
%%:输出一个"%“字符。
另外,还可以在%与格式字符之间加上修饰符来控制其最小长度、最大长度、和文本的对齐方式。如:
1)%20c:指定输出category的名称,最小的长度是20,如果category的名称长度小于20的话,默认的情况下右对齐。
2)%-20c:”-"号表示左对齐。
3)%.30c:指定输出category的名称,最大的长度是30,如果category的名称长度大于30的话,就会将左边多出的字符截掉,但小于30的话也不会补空格。
log4j.logger.debug=CONSOLE,debug
log4j.appender.debug=org.apache.log4j.RollingFileAppender
log4j.appender.debug.Threshold=DEBUG
log4j.appender.debug.appendFile=true
log4j.appender.debug.Encoding=UTF-8
log4j.appender.debug.File=log/debug.txt
log4j.appender.debug.MaxFileSize=4096KB
log4j.appender.debug.MaxBackupIndex=7
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.zzz}[%t][%p] %m%n
log4j.logger.info=CONSOLE,info,debug
log4j.appender.info=org.apache.log4j.RollingFileAppender
log4j.appender.info.Threshold=DEBUG
log4j.appender.info.appendFile=true
log4j.appender.info.Encoding=UTF-8
log4j.appender.info.File=log/info.txt
log4j.appender.info.MaxFileSize=4096KB
log4j.appender.info.MaxBackupIndex=7
log4j.appender.info.layout=org.apache.log4j.PatternLayout
log4j.appender.info.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.zzz}[%t][%p] %m%n
log4j.logger.warn=CONSOLE,info,debug,warn
log4j.appender.warn=org.apache.log4j.RollingFileAppender
log4j.appender.warn.Threshold=DEBUG
log4j.appender.warn.appendFile=true
log4j.appender.warn.Encoding=GBK
log4j.appender.warn.File=log/warn.txt
log4j.appender.warn.MaxFileSize=4096KB
log4j.appender.warn.MaxBackupIndex=2
log4j.appender.warn.layout=org.apache.log4j.PatternLayout
log4j.appender.warn.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss.zzz}[%t][%p] %m%n
log4j.logger.error=CONSOLE,info,debug,warn,error
log4j.appender.error=org.apache.log4j.RollingFileAppender
log4j.appender.error.Threshold=DEBUG
log4j.appender.error.appendFile=true
log4j.appender.error.Encoding=UTF-8
log4j.appender.error.File=log/error.txt
还是要重点说明下,生产环境下一般这个配置文件储存在软件可执行文件所在的目录。log文件储存的位置由配置文件配置。
mian.cpp中的代码是设置日志输出格式:
layout->setConversionPattern("%d{yyyy-MM-dd hh:mm:ss} %p %c %m %r %t %F %M %L %l %n");
输出的对应内容如下:
%d{yyyy-MM-dd hh:mm:ss}:2023-10-27 10:31:19
%p:DEBUG
%c:Qt default
%m:mainwindow debug
%r:1454
%t:0x000000000d816d00
%F:..\log4qtlibs\mainwindow.cpp
%M:MainWindow::MainWindow(QWidget*)
%L:11
%l:..\log4qtlibs\mainwindow.cpp:11 - MainWindow::MainWindow(QWidget*)
%n:换行
三、参考文献
3.1 Qt使用Log4Qt日志-CSDN博客
3.2 log4Qt史上最详细介绍、编译和使用-CSDN博客
3.3 使用 log4qt.properties 配置 Log4Qt-轻识 (qinglite.cn)
3.4 Qt扩展-Log4Qt 简介及配置_qt log4qt-CSDN博客
3.5 使用 log4qt.properties 配置 Log4Qt-轻识 (qinglite.cn)
3.6 12.4-在Qt中使用Log4Qt输出Log文件,看这一篇就足够了_qt log4qt-CSDN博客