log4qt库的使用

news2024/9/28 13:28:56

log4qt库的使用

  • 一,什么是log4qt?
  • 二,log4qt的下载
  • 三,如何集成log4qt?
    • 1.在vs2022中集成log4qt的方法:
    • 模块一:配置log4qt的步骤
      • 步骤一,将下好的log4qt库进行解压,然后再库文件中,新建build和Log4Qt文件夹
      • 步骤二,打开cmake,有两个填写路径的位置.
      • 步骤三,点击cmake的configure按钮,按照下图进行选择,然后点击finish
      • 步骤四,Configuring done之后,点击Generate
      • 步骤五,修改cmake的CMAKE_INSTALL_PREFIX路径为`步骤一中,我们创建好的Log4Qt文件夹的绝对路径`(剧透一下,这个目录,将产生log4qt的动态库,静态库以及库的头文件)
      • 步骤六,点击cmake的Open Project
      • 步骤七,将编译模式改为Release,然后右击生成ALL_BUILD和INSTALL
      • 步骤八,打开集成在vs2022的任意一个qt项目
    • 模块二:当我们集成好log4qt之后,有两种可以使用日志的方式:
        • 方式一,直接使用conf文件,在项目中进行加载conf文件,加载好之后,所有的qDebug,qInfo(),qWaring()代码,都会以日志的形式在控制台打印出来,并保存到文本文档中(当然,conf里面的配置文件可以随便改)
        • 方式二,不使用conf文件,直接在项目中调用log4qt库中的代码
    • 2.在QtCreator中集成log4qt的方法:
      • 步骤一,新建一个qt项目,比如:MyLog4qtProject
      • 步骤二,将log4qt库的源码复制,放在MyLog4qtProject\目录下
      • 步骤三,配置MyLog4qtProject.pro文件
      • 步骤四,配置log4qt.pri
      • 步骤五,编辑main.cpp
      • 最后一个步骤,编辑log4qt.conf(名字只要以.conf结尾,与main.cpp中初始化的conf文件名一致即可)
      • 实现效果
  • 四,关于log4qt.conf理解

一,什么是log4qt?

Log4Qt是一个用于Qt应用程序的开源日志记录库。它是基于Apache Log4j的C++实现,并提供了一种灵活和可配置的方式来记录应用程序的日志信息。

Log4Qt允许你在应用程序中定义日志记录器、日志级别和日志输出目标,并根据需要进行动态配置。它支持多个日志记录器以及不同的日志级别,使你能够根据应用程序的需要进行细粒度的日志控制。

使用Log4Qt,你可以将日志信息输出到不同的目标,例如控制台、文件、网络套接字等。它还支持日志消息的格式化,包括日期、时间、日志级别、线程信息等。

Log4Qt 是Log4cpp 的Qt移植版,所以看Log4cpp的资料应该是最直接有效的(因为 Log4Qt的直接资料太少了)。

Log4Qt主要是用来记录日志(有助于程序调试)。有3个主要的组件:

1. Logger
提供日志记录服务,可以有多个Logger存在,每个有它们自己的名字。Logger间存在隶属关系,有一个Logger称为根Logger。
  2. Appender
用来指明将日志记录到什么地方:比如,控制台、文件、数据库,等等
  3. Layout
控制日志的输出格式,可以类比一下C中的printf。

二,log4qt的下载

log4qt下载地址:

https://github.com/MEONMedical/Log4Qt

三,如何集成log4qt?

1.在vs2022中集成log4qt的方法:

模块一:配置log4qt的步骤

步骤一,将下好的log4qt库进行解压,然后再库文件中,新建build和Log4Qt文件夹

在这里插入图片描述

步骤二,打开cmake,有两个填写路径的位置.

一个填log4qt库所在的路径,另一个填build的绝对路径,如下图:

在这里插入图片描述

步骤三,点击cmake的configure按钮,按照下图进行选择,然后点击finish

在这里插入图片描述

步骤四,Configuring done之后,点击Generate

在这里插入图片描述

步骤五,修改cmake的CMAKE_INSTALL_PREFIX路径为步骤一中,我们创建好的Log4Qt文件夹的绝对路径(剧透一下,这个目录,将产生log4qt的动态库,静态库以及库的头文件)

在这里插入图片描述

然后再次点击Configuring done,然后点击Generate

步骤六,点击cmake的Open Project

在这里插入图片描述

然后,系统将自动打开vs2022,如下图:

在这里插入图片描述

步骤七,将编译模式改为Release,然后右击生成ALL_BUILD和INSTALL

在这里插入图片描述

当生成完成之后,打开Log4Qt(就是步骤一创建的那个文件夹),就会有如下效果:

在这里插入图片描述

步骤八,打开集成在vs2022的任意一个qt项目

1)打开项目属性页

在这里插入图片描述

2)在c/c++常规中,在附加包含目录下添加生成库的头文件的路径,也就是步骤七生成的include文件夹的绝对路径

在这里插入图片描述

然后确定->应用->确定

3)链接器->常规->附加库目录->添加步骤七生成的lib文件夹的绝对路径

在这里插入图片描述

4)链接器->输入->附加依赖项->添加log4qt.lib

在这里插入图片描述

5)将log4qt.dll放在项目的可执行目录(即存放exe文件的地方)

在这里插入图片描述

6)验证一下:

在任意一个cpp文件中添加如下头文件:
#include<log4qt/log4qt.h>
#include<log4qt/logger.h>
#include<log4qt/layout.h>
#include<log4qt/patternlayout.h>
#include <log4qt/consoleappender.h>
#include<log4qt/logmanager.h>
#include<log4qt/propertyconfigurator.h>



然后再cpp文件中加入如下代码进行验证:
Log4Qt::Logger* logger = Log4Qt::Logger::logger("MyLogger");
logger->setLevel(Log4Qt::Level::DEBUG_INT); // 设置日志级别为DEBUG


// 配置ConsoleAppender 日志输出到控制台
Log4Qt::ConsoleAppender* consoleAppender = new Log4Qt::ConsoleAppender();


Log4Qt::PatternLayout* layout = new Log4Qt::PatternLayout();
layout->setConversionPattern("%d [%t] %-5p %c - %m%n"); // 设置日志消息的格式
consoleAppender->setLayout(layout); // 设置布局
consoleAppender->activateOptions(); // 激活Appender配置选项

consoleAppender->setThreshold(Log4Qt::Level::DEBUG_INT); // 设置Appender的阈值级别
consoleAppender->activateOptions(); // 激活Appender配置选项

// 添加Appender到Logger
logger->addAppender(consoleAppender);

// 使用Logger对象记录日志消息
logger->debug("This is a debug message");
logger->info("This is an info message");
logger->warn("This is a warning message");
logger->error("This is an error message");

在这里插入图片描述


模块二:当我们集成好log4qt之后,有两种可以使用日志的方式:

方式一,直接使用conf文件,在项目中进行加载conf文件,加载好之后,所有的qDebug,qInfo(),qWaring()代码,都会以日志的形式在控制台打印出来,并保存到文本文档中(当然,conf里面的配置文件可以随便改)

目前我改好的conf文件有如下效果:

-将qDebug,qInfo(),qWaring()替换为%d{yyyy,MM,dd HH:mm:ss} [%t] {%l} %-5p %c - %m%n的格式(具体想要以什么格式将信息打印出来,还可以在conf文件中自定义修改)

-在控制台打印信息的同时,还可以将日志信息保存在本地(目前我编辑的这个log4qt.conf文件的效果是:在同级目录下,自动创建一个logs的文件夹,日志文件都会保存在这里面)

-日志文件的名字为当前年月日.log为名字,每天的日志文件都会保存在当天的这个log文件中

在这里插入图片描述


方式一的具体操作方法如下:

1)将log4qt.conf放在可执行目录下

如果你是在Release模式下运行,就把log4qt.conf放在Release目录下;
如果你是在Debug模式下运行,就把log4qt.conf放在Debug目录下;

我是在Release模式下运行,所以我放在Release目录下,如下图:

在这里插入图片描述

2)在项目中加载log4qt.conf.

先说一下我的项目结构:

目前我的源文件及头文件只有MainWindow.h,MainWindow.cpp,main.cpp三个文件(当然,qt的ui文件就不说了),我在MainWindow的构造函数中加载(或者说初始化)log4qt.conf之后, 当在mian.cpp中创建完MainWindow 对象之后,项目的其他所有地方的日志系统都会生效.

在这里插入图片描述

1)在MainWindow.cpp中加上如下头文件:

#include<log4qt/log4qt.h>
#include<log4qt/logger.h>
#include<log4qt/layout.h>
#include<log4qt/patternlayout.h>
#include <log4qt/consoleappender.h>
#include<log4qt/logmanager.h>
#include<log4qt/propertyconfigurator.h>

在这里插入图片描述

2)在MainWindow的构造函数中加入下面两行代码:

Log4Qt::PropertyConfigurator::configure("D:/vs2022/code/QtVTKProject2/build/Release/log4qt.conf");//从log4qt.conf的绝对路径中去加载这个项目(或者改成相对路径也可)
Log4Qt::LogManager::setHandleQtMessages(true);//启用 Log4Qt 库处理 Qt 框架的消息。(即使你已经加载了log4qt.conf文件,但是默认情况下它不会处理 Qt 框架生成的日志消息,所以我们需要进行启动。)

在这里插入图片描述

3)测试

qDebug() << "Log4Qt test begin";
qDebug() << QString::fromLocal8Bit("我是启用log4qt后的qDebug");
qInfo() << QString::fromLocal8Bit("我是启用log4qt后的qInfo");
qWarning() << QString::fromLocal8Bit("我是启用log4qt后的qWarning");
//qFatal注释掉了,是因为qFatal一旦调用,系统就会短暂停留两秒,然后立刻终止程序!!!
//qFatal()<< QString::fromLocal8Bit("我是启用log4qt后的qFatal");
qDebug() << "Log4Qt test end";

在这里插入图片描述

运行效果:

在这里插入图片描述

方式二,不使用conf文件,直接在项目中调用log4qt库中的代码

方式二的具体操作方法如下:

在项目中,添加如下两个文件:Logger.h与Logger.cpp,然后以在MainWindow.cpp演示为例:

//Logger.h
#pragma once

#include <log4qt/log4qt.h>
#include <log4qt/logger.h>
#include <log4qt/layout.h>
#include <log4qt/patternlayout.h>
#include <log4qt/consoleappender.h>//输出到控制台
#include <log4qt/fileappender.h>//重定向到文本文件中
#include <log4qt/logmanager.h>
#include <log4qt/propertyconfigurator.h>

#include <QDate>//获取时间
//#include <QTextCodec>//设置文本编码,但是不能用,因为已经被Qt5.15.2弃用了

namespace wxn {
	class Logger
	{
	private:
		Log4Qt::Logger* logger_;//日志记录器类
		Log4Qt::ConsoleAppender* consoleAppender_;
		QDate currentData_;


		Log4Qt::FileAppender* fileAppender_;
		QString filename_;
		Log4Qt::PatternLayout* layout_;
	public:

		Logger(QString LogName);
		~Logger();
		QString getTime();
		void init();

		void Debug(const char* message);
		void Info(const char* message);
		void Warn(const char* message);
		void Error(const char* message);
	};
}
//Logger.cpp
#include "Logger.h"


wxn::Logger::Logger(QString LogName) {
	logger_ = Log4Qt::Logger::logger(LogName);//传入的是日志记录器类的名字
	consoleAppender_ = new Log4Qt::ConsoleAppender();// 配置ConsoleAppender 日志输出到控制台
	currentData_ = QDate::currentDate();
	fileAppender_ = new Log4Qt::FileAppender();

	layout_ = new Log4Qt::PatternLayout();//设置日志格式,布局//

}
wxn::Logger::~Logger()
{
	//if(logger_) delete logger_;//Log4Qt::Logger这个类的析构函数时私有的,不可访问
	if (consoleAppender_)delete consoleAppender_;
	//if (currentData_)delete currentData_; //QDate对象会在其作用域结束时自动销毁,不需要手动释放。
	if (fileAppender_)delete fileAppender_;

	if (layout_)delete layout_;
}


QString wxn::Logger::getTime() {
	int year = currentData_.year();
	int month = currentData_.month();
	int day = currentData_.day();
	return QString::number(year) + "_"
		+ QString::number(month).rightJustified(2, '0')
		+ "_" + QString::number(day).rightJustified(2, '0');//将月份和日期转换为2位数的字符串
}
void wxn::Logger::init()
{
	logger_->setLevel(Log4Qt::Level::DEBUG_INT); // 设置日志级别为DEBUG
	logger_->addAppender(consoleAppender_);// 添加Appender到Logger

	QString filename;
	filename += "./logs/";
	filename += getTime();
	filename += ".log";
	fileAppender_->setFile(filename);//设置log文本的位置
	fileAppender_->setAppendFile(true);//让log内容在文本中追加,而不是每次都重新写入

	logger_->addAppender(fileAppender_);// 添加Appender到Logger

	layout_->setConversionPattern("%d{yyyy-MM-dd hh:mm::ss} [%t] [%L] %-5p %c - %m%n"); // 设置日志消息的格式
	consoleAppender_->setLayout(layout_);//给控制台设置布局
	fileAppender_->setLayout(layout_); // 给文本设置布局


	//对于控制台:
	consoleAppender_->activateOptions(); // 激活Appender配置选项
	consoleAppender_->setThreshold(Log4Qt::Level::DEBUG_INT); // 设置Appender的阈值级别


	//对于输出到文本中:
	fileAppender_->activateOptions(); // 激活Appender配置选项
	fileAppender_->setThreshold(Log4Qt::Level::DEBUG_INT); // 设置Appender的阈值级别

}

void wxn::Logger::Debug(const char* message)
{
	QString qstr = QString::fromUtf8(message); // 将const char*转换为QString

	// 将消息转换为指定编码
	QByteArray asciiData = qstr.toLatin1(); // 将QString转换为ASCII编码的QByteArray

	logger_->debug(asciiData.constData());// asciiData.constData():获取ASCII编码的C风格字符串
}

void wxn::Logger::Info(const char* message)
{
	QString qstr = QString::fromUtf8(message); // 将const char*转换为QString

	// 将消息转换为指定编码
	QByteArray asciiData = qstr.toLatin1(); // 将QString转换为ASCII编码的QByteArray

	logger_->info(asciiData.constData());// asciiData.constData():获取ASCII编码的C风格字符串
}
void wxn::Logger::Warn(const char* message)
{
	QString qstr = QString::fromUtf8(message); // 将const char*转换为QString

	// 将消息转换为指定编码
	QByteArray asciiData = qstr.toLatin1(); // 将QString转换为ASCII编码的QByteArray

	logger_->warn(asciiData.constData());// asciiData.constData():获取ASCII编码的C风格字符串
}
void wxn::Logger::Error(const char* message)
{
	QString qstr = QString::fromUtf8(message); // 将const char*转换为QString

	// 将消息转换为指定编码
	QByteArray asciiData = qstr.toLatin1(); // 将QString转换为ASCII编码的QByteArray

	logger_->error(asciiData.constData());// asciiData.constData():获取ASCII编码的C风格字符串
}
//MainWindow.cpp
#include <MainWindow.h>
#include "ui_MainWindow.h"

#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkPolyDataMapper.h>
#include <vtkRenderer.h>

#include "Logger.h"

#include <iostream>

class CVector3d {
public:
    float x;
    float y;
    float z;

    const char* getInfo()
    {
        QString information;
        information = "x:" + QString::number(x)+",y:"+QString::number(y)+",z:"+QString::number(z);

        QByteArray byteArray = information.toUtf8(); // 将 QString 转换为 UTF-8 编码的 QByteArray

        return byteArray.constData();
    }
    
};


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow),
    mRenderWindow(vtkSmartPointer<vtkGenericOpenGLRenderWindow>::New()),
    mRenderer(vtkSmartPointer<vtkRenderer> ::New()),
    mInteractor(vtkSmartPointer<QVTKInteractor> ::New()),
    mInteractorStyle(vtkSmartPointer<vtkInteractorStyle> ::New())
{
    ui->setupUi(this);

    /*****log4qt使用示例-begin******/
    wxn::Logger *logger = new  wxn::Logger("MyLogger");
    logger->init();
    // 使用Logger对象记录日志消息
    logger->Debug("=================<This is a new running!>=================");
    logger->Debug("This is a debug message");
    logger->Info("This is an info message");
    logger->Warn("This is a warning message");
    logger->Error("This is an error message");

    CVector3d cv3d({1.236,2.347,4.156});
    logger->Debug(cv3d.getInfo());
	/*****log4qt使用示例-end******/
    

    // Set up the rendering
    mRenderWindow->AddRenderer(mRenderer);
    mRenderWindow->SetInteractor(mInteractor);
    /*
    * 在文件 QVTKOpenGLStereoWidget.cxx 的第 137 行中,
    * 函数 SetRenderWindow 在 VTK 9.0 中已被弃用,并将在将来的版本中被移除。
    * 相反,你应该使用 QVTKOpenGLStereoWidget 类提供的 setRenderWindow 函数。
    */
    ui->openGLWidget->setRenderWindow(mRenderWindow);
    mInteractor->SetInteractorStyle(mInteractorStyle);
    mInteractor->Initialize();

    // Set the background color
    mRenderer->SetBackground(1, 0, 0);

    //Set the UI connections
    QObject::connect(ui->drawSphere_button, &QPushButton::clicked,
        this, &MainWindow::onDrawSphereClick);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::onDrawSphereClick()
{
    // Create sphere
    vtkSmartPointer<vtkSphereSource> sphereSource =
        vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->SetRadius(5);
    sphereSource->Update();

    //Create the actor where the sphere is rendered
    vtkSmartPointer<vtkPolyDataMapper> sphereMapper =
        vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereMapper->SetInputData(sphereSource->GetOutput());

    vtkSmartPointer<vtkActor> sphere = vtkSmartPointer<vtkActor>::New();
    sphere->SetMapper(sphereMapper);

    //Add the sphere actor to the OpenGL
    mRenderer->AddViewProp(sphere);
    mRenderer->ResetCamera();
    mRenderWindow->Render();
}

2.在QtCreator中集成log4qt的方法:

步骤一,新建一个qt项目,比如:MyLog4qtProject

如图一所示:

在这里插入图片描述

步骤二,将log4qt库的源码复制,放在MyLog4qtProject\目录下

1)log4qt库源码的位置

(在你从github上下载的log4qt库的src目录下,有个log4qt文件夹,就是源码)

如图二所示:

在这里插入图片描述

2)将log4qt源码放在MyLog4qtProject\目录下

如图三所示:

在这里插入图片描述

步骤三,配置MyLog4qtProject.pro文件

1)如果你的项目结构和图三一样,那么你可以直接复制下面的已经配置内容:

QT       += core gui network concurrent


DEFINES +=LOG4QT_STATIC

LOG4QTSRCPATH = $$PWD/log4qt

INCLUDEPATH += -L $$LOG4QTSRCPATH \
                $$LOG4QTSRCPATH/helpers \
                 $$LOG4QTSRCPATH/spi \
                 $$LOG4QTSRCPATH/varia

DEPENDPATH  +=  $$LOG4QTSRCPATH \
            $$LOG4QTSRCPATH/helpers \
            $$LOG4QTSRCPATH/spi \
            $$LOG4QTSRCPATH/varia

include($$PWD/log4qt/log4qt.pri)



greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

CONFIG += c++17

# You can make your code fail to compile if it uses deprecated APIs.
# In order to do so, uncomment the following line.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0

SOURCES += \
    main.cpp \
    MainWindow.cpp

HEADERS += \
    MainWindow.h

FORMS += \
    MainWindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target

与原来的MyLog4qtProject.pro文件相比,新MyLog4qtProject.pro文件有以下变化,

如图四所示:

在这里插入图片描述

以下是对新添加的代码的解释:
1.QT       += core gui network concurrent
我们新引入了network和concurrent模块,
network :提供网络功能(因为日志肯定是要获取当前的时间的)
concurrent :提供多线程和并发编程的支持(日志写入文本,肯定就会用到读写锁,来保证日志的线程安全)

2.DEFINES +=LOG4QT_STATIC 
告诉编译器,我们是用静态链接的方法,将Log4Qt 库的代码编译并链接到最终的可执行文件中,而不是作为动态库加载运行.

3.LOG4QTSRCPATH = $$PWD/log4qt
$$PWD 是一个预定义变量,表示当前工程文件的所在路径。
这里将 LOG4QTSRCPATH 设置为当前工程文件所在路径下的 log4qt 目录。

4.INCLUDEPATH += -L $$LOG4QTSRCPATH \
                $$LOG4QTSRCPATH/helpers \
                 $$LOG4QTSRCPATH/spi \
                 $$LOG4QTSRCPATH/varia

5.DEPENDPATH  +=  $$LOG4QTSRCPATH \
            $$LOG4QTSRCPATH/helpers \
            $$LOG4QTSRCPATH/spi \
            $$LOG4QTSRCPATH/varia
INCLUDEPATH 和 DEPENDPATH: 这两个变量用于指定包含和依赖搜索路径。通过将 Log4Qt 的不同子目录添加到这些变量中,确保编译器和构建系统能够找到 Log4Qt 源代码所在的位置。
6.include($$PWD/log4qt/log4qt.pri)
用于引入 log4qt.pri 文件。

步骤四,配置log4qt.pri

如图五所示:

在这里插入图片描述

(注:当我们按照步骤三配置好MyLog4qtProject.pro文件后,进行ctrl+c保存,编译器会自动加载图五中的log4qt模块)

在log4qt.pri文件的末尾添加如下内容:

INCLUDEPATH += -L $$PWD \
                $$PWD/helpers \
                 $$PWD/spi \
                 $$PWD/varia

DEPENDPATH  += $$PWD \
            $$PWD/helpers \
            $$PWD/spi \
            $$PWD/varia

DEFINES +=LOG4QT_STATIC
LOG4QT_VERSION_MAJOR = 1
LOG4QT_VERSION_MINOR = 6
LOG4QT_VERSION_PATCH = 0

DEFINES += LOG4QT_VERSION_MAJOR=$${LOG4QT_VERSION_MAJOR}
DEFINES += LOG4QT_VERSION_MINOR=$${LOG4QT_VERSION_MINOR}
DEFINES += LOG4QT_VERSION_PATCH=$${LOG4QT_VERSION_PATCH}
DEFINES += LOG4QT_VERSION_STR='\\"$${LOG4QT_VERSION_MAJOR}.$${LOG4QT_VERSION_MINOR}.$${LOG4QT_VERSION_PATCH}\\"'

DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
DEFINES += QT_DEPRECATED_WARNINGS

效果如图六所示:

在这里插入图片描述

1.INCLUDEPATH += -L $$PWD
$$PWD/helpers
$$PWD/spi
$$PWD/varia

2.DEPENDPATH += $$PWD
$$PWD/helpers
$$PWD/spi
$$PWD/varia

INCLUDEPATH 和 DEPENDPATH: 这两个变量用于指定包含和依赖搜索路径。
$$PWD 表示当前工程文件的所在路径。

3.DEFINES +=LOG4QT_STATIC
LOG4QT_VERSION_MAJOR = 1
LOG4QT_VERSION_MINOR = 6
LOG4QT_VERSION_PATCH = 0

用于告诉编译器在静态链接方式下使用 Log4Qt 库。

4.DEFINES += LOG4QT_VERSION_MAJOR=$${LOG4QT_VERSION_MAJOR}
DEFINES += LOG4QT_VERSION_MINOR=$${LOG4QT_VERSION_MINOR}
DEFINES += LOG4QT_VERSION_PATCH=$${LOG4QT_VERSION_PATCH}

LOG4QT_VERSION_MAJOR, LOG4QT_VERSION_MINOR, LOG4QT_VERSION_PATCH: 这些变量用于定义 Log4Qt 版本号的主、次、修订版本号。

DEFINES += LOG4QT_VERSION_STR='\"$${LOG4QT_VERSION_MAJOR}.$${LOG4QT_VERSION_MINOR}.$${LOG4QT_VERSION_PATCH}\"'

这个宏定义用于将 Log4Qt 的完整版本号作为预处理器定义,并将其包装在双引号内。


5.DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x050F00
(QT_DISABLE_DEPRECATED_BEFORE=0x050F00)意味着在 Qt 版本 5.15.0 之前被弃用的功能的警告将被禁用。

6.DEFINES += QT_DEPRECATED_WARNINGS
QT_DEPRECATED_WARNINGS: 这个宏定义用于启用 Qt 框架中关于已弃用功能的警告信息。(5和6是有语义上是有冲突的,但是一些源代码也是这么写的,实际使用中可任选5或6之一[5和6都写的话,代码也不会中断])

步骤五,编辑main.cpp

增加以下内容:
//main.cpp
#include <QtDebug>
#include "logmanager.h"
#include "propertyconfigurator.h"


    Log4Qt::PropertyConfigurator::configure(a.applicationDirPath() + "/log4qt.conf");
    Log4Qt::LogManager::setHandleQtMessages(true);
    qDebug("start working...");


//main.cpp的完整内容:
#include "MainWindow.h"

#include <QApplication>

#include <QtDebug>
#include "logmanager.h"
#include "propertyconfigurator.h"

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    MainWindow w;

    Log4Qt::PropertyConfigurator::configure(a.applicationDirPath() + "/log4qt.conf");
    Log4Qt::LogManager::setHandleQtMessages(true);
    qDebug("start working...");

    w.show();
    return a.exec();
}

最后一个步骤,编辑log4qt.conf(名字只要以.conf结尾,与main.cpp中初始化的conf文件名一致即可)

  1. log4qt.conf的内容如下:
# 设置储存log文件的根目录
logpath=.

log4j.reset=true
log4j.Debug=WARN
log4j.threshold=NULL
# 设置是否监听QDebug输出的字符串
log4j.handleQtMessages=true
# 在运行中,是否监视此文件配置的变化
log4j.watchThisFile=false

# 设置根Logger的输出log等级为All
# 设置Log输出的几种输出源(appender):console, daily, rolling
log4j.rootLogger=ALL, console, daily

# 设置终端打印记录器
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.target=STDOUT_TARGET
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d{yyyy,MM,dd HH:mm:ss} [%t] {%l} %-5p %c - %m%n
log4j.appender.console.threshold=ALL

# 设置一个每日储存一个log文件的记录器
log4j.appender.daily=org.apache.log4j.DailyFileAppender
log4j.appender.daily.file=${logpath}/logs/.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.ConversionPattern=${log4j.appender.console.layout.ConversionPattern}





# 给“LoggerObjectPrio”这个类的Logger定义log输出等级为Error,
# 给“LoggerObjectPrio”这个类的Logger定义log输出源:daily, console
log4j.logger.LoggerObjectPrio=ERROR
#, rolling

# 设置为false,表示“LoggerObjectPrio”这个类的logger不继承的rootLogger输出源(appender)
log4j.additivity.LoggerObjectPrio=false

2)将log4qt.conf放在你项目的build目录下

(如果你是以Debug模式下编译的话,就将log4qt.conf放在"项目/Debug/debug"文件夹下)

效果如图七所示:

在这里插入图片描述

(如果你是以Release模式下编译的话,就将log4qt.conf放在"项目/Release/release"文件夹下)

实现效果

在这里插入图片描述

四,关于log4qt.conf理解

logpath=.:设置存储日志文件的根目录为当前目录。
log4j.reset=true:重置 Log4j 配置。
log4j.Debug=WARN:设置 Log4j 调试级别为 WARN。
log4j.threshold=NULL:设置 Log4j 阈值级别为 NULL,即不限制任何级别的日志输出。
log4j.handleQtMessages=true:设置是否监听 QtDebug 输出的字符串。
log4j.watchThisFile=false:设置在运行时是否监视此文件配置的变化。
log4j.rootLogger=ALL, console, daily:设置根 Logger 的输出级别为 ALL,并指定了两个输出源:console(终端打印)和 daily(每日文件)。
针对 console 输出源的配置:

log4j.appender.console=org.apache.log4j.ConsoleAppender:指定使用 ConsoleAppender 输出到控制台。
log4j.appender.console.target=STDOUT_TARGET:设置输出目标为标准输出。

#TTCCLayout 布局是 Log4Qt 的默认布局
#log4j.appender.console.layout=org.apache.log4j.TTCCLayout:指定使用 TTCCLayout 布局。
#log4j.appender.console.layout.dateFormat=yyyy.dd.MM hh:mm:ss   :设置日期格式。
#log4j.appender.console.layout.contextPrinting=true:设置是否打印上下文信息。

#PatternLayout` 布局允许您自定义日志输出的格式
log4j.appender.console.layout=org.apache.log4j.PatternLayout:指定使用 PatternLayout 布局。
log4j.appender.console.layout.ConversionPattern=%d{yyyy,MM,dd HH:mm:ss} [%t] {%l} %-5p %c - %m%n
#%d:时间戳。
#%t:线程号。
#%l: 输出日志事件的发生位置,包括类目名、发生的线程,以及在代码中的行数。
#%p:日志级别。
#%c:类别。
#%m:日志消息。
#%n:换行符。

log4j.appender.console.threshold=ALL:设置输出级别为 ALL。
针对 daily 输出源的配置:

log4j.appender.daily=org.apache.log4j.DailyFileAppender:指定使用 DailyFileAppender 每日文件记录器。
log4j.appender.daily.file=${logpath}/logs/.log:设置日志文件的路径和名称。
log4j.appender.daily.appendFile=true:设置是否在日志文件末尾追加内容。
log4j.appender.daily.datePattern=yyyy_MM_dd:设置日期格式模式。
#所以最终log文件的名字是yyyy_MM_dd.log

log4j.appender.daily.keepDays=90:设置保留日志文件的天数。
log4j.appender.daily.layout=${log4j.appender.console.layout}:设置布局与 console 输出源相同。

log4j.appender.daily.layout.dateFormat=${log4j.appender.console.layout.dateFormat}:设置日期格式与 console 输出源相同。
log4j.appender.daily.layout.contextPrinting=${log4j.appender.console.layout.contextPrinting}:设置是否打印上下文信息与 console 输出源相同。
对上面daily 输出源的配置的补充:
#设置日志文件的文件名:
①将日志文件的文件名设置为"年月日.log"
log4j.appender.daily.file=${logpath}/logs/.log
log4j.appender.daily.datePattern=yyyy_MM_dd
②将日志文件的文件名设置为"年月日时分秒.log"(经过测试,不支持这样的写法)
log4j.appender.daily.file=${logpath}/.log
log4j.appender.daily.datePattern=yyyy_MM_dd_hh_mm_ss(error!)
log4j.appender.daily.datePattern=yyyy_MM_dd_HH_mm_ss(error!)
针对 LoggerObjectPrio 类的 Logger 的配置:

log4j.logger.LoggerObjectPrio=ERROR, rolling:设置 LoggerObjectPrio 类的日志输出级别为 ERROR,并指定输出源为 rolling。
log4j.additivity.LoggerObjectPrio=false:设置不继承 rootLogger 的输出源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/984770.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

(2023,Diffusion)稳定扩散模型是不稳定的

Stable Diffusion is Unstable 公众号&#xff1a;EDPJ&#xff08;添加 VX&#xff1a;CV_EDPJ 进交流群获取资料&#xff09; 0. 摘要 最近&#xff0c;文本到图像模型一直蓬勃发展。 尽管它们具有强大的生成能力&#xff0c;但我们的研究发现这一生成过程缺乏稳健性。 具体…

【C++】平衡二叉搜索树的模拟实现

&#x1f307;个人主页&#xff1a;平凡的小苏 &#x1f4da;学习格言&#xff1a;命运给你一个低的起点&#xff0c;是想看你精彩的翻盘&#xff0c;而不是让你自甘堕落&#xff0c;脚下的路虽然难走&#xff0c;但我还能走&#xff0c;比起向阳而生&#xff0c;我更想尝试逆风…

【数据结构】设计环形队列

环形队列是一种线性数据结构&#xff0c;其操作表现基于 FIFO&#xff08;先进先出&#xff09;原则并且队尾被连接在队首之后以形成一个循环。它也被称为“环形缓冲器”。 环形队列的一个好处是我们可以利用这个队列之前用过的空间。在一个普通队列里&#xff0c;一旦一个队列…

使用Caffeine实现帖子的缓存来优化网站的运行速度

导入依赖 <!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine --><dependency><groupId>com.github.ben-manes.caffeine</groupId><artifactId>caffeine</artifactId><version>3.1.7</version>…

【产品应用】一体化伺服电机在全自动咖啡研磨机中的应用

在现代社会中&#xff0c;咖啡已经成为人们生活中不可或缺的一部分。为了满足咖啡爱好者对于口感和品质的追求&#xff0c;全自动咖啡研磨机应运而生。 而其中的一体化伺服电机作为关键组件&#xff0c;发挥着重要的作用。本文将探讨一体化伺服电机在全自动咖啡研磨机中的应用&…

Magisk隐藏外挂解决方案

自2008年1.0测试版发布以来&#xff0c;安卓系统已经发展了近16年&#xff0c;凭借着优秀的开源生态&#xff0c;安卓系统飞速成长&#xff0c;已经成了当下手机系统中的龙头。据研究机构 Canalys 报告称&#xff0c;今年第一季度安卓设备的整体市场份额占比达到 78 %。 开源生…

走进中国水果罐头领军品牌真心罐头—快消食品企业的全链路数字化

近日&#xff0c;【数字中国-高效增长】名城优企游学系列之走进真心罐头活动成功举办&#xff01; 真心罐头食品有限公司&#xff08;以下简称为“真心罐头”&#xff09;初创于1990年&#xff0c;位于素有“北方明珠”、“黄桃之乡”美誉的海滨城市——辽宁省大连市&#xff0…

软件测试面试题(Python全栈自动化测试面试题)

1、你的测试职业发展是什么? 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前3年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自己&#xff0c;不…

Java不定参数使用及一些注意情况

一、背景 在项目中使用到了StringUtils.isAllBlack(String …css)方法。可以很方便地传递不定数量的参数进行空判。 但开发过程中遇到了一些问题&#xff0c;所以特地记录一下。 二、不定参数传参 不定参数的传参本质上是一个泛型的数组。参数数量大于等于两个的时候&#x…

薅羊毛零撸小游戏是这样赚米的!

薅羊毛小游戏作为一种特殊类型的游戏&#xff0c;吸引了一大批用户的关注。本文将探讨薅羊毛小游戏的盈利模式、用户体验以及对游戏产业的影响&#xff0c;旨在为读者提供专业而有深度的思考和启示。 一、薅羊毛小游戏的盈利模式&#xff1a; 1.广告变现&#xff1a;薅羊毛小游…

R-CNN

目标检测、语义分割 由于我们将区域建议与CNN相结合&#xff0c;我们将我们的方法称为R-CNN:带有CNN特征的区域。 目标检测系统由三个模块组成。第一种方法生成分类独立的区域提案。这些提议定义了可供我们的检测器使用的候选检测集合。第二个模块是一个大型卷积神经网络&…

【C++基础】类与对象(中):默认成员函数、构造函数、析构函数、拷贝构造、赋值重载函数……

​&#x1f47b;内容专栏&#xff1a; C/C编程 &#x1f428;本文概括&#xff1a; C基础语法。六大默认构造函数简介、构造函数、析构函数、拷贝构造函数、赋值重载函数、const成员函数、取地址重载等。 &#x1f43c;本文作者&#xff1a; 阿四啊 &#x1f438;发布时间&…

开开心心带你学习MySQL数据库之第六篇上

​ &#x1f4ae; &#x1f4ae;&#x1f4ae; 只要路是对的&#xff0c;就不害怕遥远! &#x1f4ae; &#x1f4ae;&#x1f4ae; &#x1f386;&#x1f386;&#x1f386;窗台是风景&#xff0c;笔下有前途&#xff0c;低头是题海&#xff0c;抬头是未来&#x1f386;&…

扩散模型 DDPM 核心代码梳理

参考内容&#xff1a; 大白话AI | 图像生成模型DDPM | 扩散模型 | 生成模型 | 概率扩散去噪生成模型 AIGC 基础&#xff0c;从VAE到DDPM 原理、代码详解 全网最简单的扩散模型DDPM教程 The Annotated Diffusion Model LaTeX公式编辑器 备注&#xff1a; 具体公式的推导请查看…

BC类电池取代TOPCon?隆基绿能看得很“远”

隆基绿能在业绩会上喊话&#xff0c;BC类电池在未来会逐步取代TOPCON电池&#xff0c;成为晶硅电池的绝对主流&#xff0c;并指出N型TOPCon电池只是短期过渡技术路线。 “All in ”BC类电池的隆基绿能&#xff0c;重新定义技术路线的野望藏不住。 目前来看&#xff0c;相比TO…

数据接口工程对接BI可视化大屏(一)

文章目录 第1章 案例概述1.1 案例目标1.2 BI最终效果1.2.1 PC端显示效果1.2.2 移动端显示效果 后记 第1章 案例概述 1.1 案例目标 此项目以常见的手机零售BI场景为例&#xff0c;介绍如何编写数据接口工程对接BI可视化大屏。 如何从当前常见的主流大数据场景中为后台程序推送…

入行测试一年半的心得体会

成为xx一员测试已经有1年半了&#xff0c;一直没有真正坐下来花些时间将自己的思路理清一下。刚好近期公司落地了OKR&#xff0c;给自己制定了OKR之后思路终于开始清晰起来&#xff0c;朦朦胧胧地开始看清了远方的路&#xff0c;麻着胆子分析一下自己&#xff0c;毕竟摸黑走路的…

2023年9月CSPM-3国标项目管理中级认证报名,找弘博创新

CSPM-3中级项目管理专业人员评价&#xff0c;是中国标准化协会&#xff08;全国项目管理标准化技术委员会秘书处&#xff09;&#xff0c;面向社会开展项目管理专业人员能力的等级证书。旨在构建多层次从业人员培养培训体系&#xff0c;建立健全人才职业能力评价和激励机制的要…

【效率提升】手把手教你如何使用免费的 Amazon Code Whisperer 提升开发效率堪比 GitHub Copilot 平替

说明 GitHub copilot 虽然很强&#xff0c;但是一个月10美金的费用拿来吃个小火锅他不香吗&#xff1f;而身为云计算博主将向你推荐一款可以平替 GitHub copilot 并且免费的支持多种编程语言的 AI 编程助手 Amazon Code Whisperer。 亚马逊云科技开发者社区为开发者们提供全球…