6、Qt使用Log4Qt日志

news2025/1/11 17:10:12

一、知识点

1、Log4Qt有三部分
  • logger:负责捕获日志信息
  • layout:负责使用不同的样式输出日志
  • appender:负责输出信息到不同的目的地,比如数据库、文件、控制台等等
2、 日志级别如下,从上往下依次递增
  • ALL:所有日志的级别都包括
  • TRACE:指定比DEBUG更粗粒度的调试日志
  • DEBUG:指定的信息事件的粒度是DEBUG,在调试应用的时候会有帮助
  • INFO::指定信息消息,强调应用粗粒度的运行情况
  • WARN:输出具有潜在风险的
  • ERROR:指定错误事件,并且这些事件还会保证应用继续运行
  • FATAL:指定严重的错误事件,该事件导致应用暂停
  • OFF:最高级别,相当于关闭日志
3、 日志消息格式
通过转换说明符来表示,以百分号(%)开始,后跟转换字符。
如下实例:
layout->setConversionPattern("%d{yyyy-MM-dd hh:mm:ss} %p %c %m %r %t %F %M %L %l %n");
  • %d: 输出日志时间点的日期或时间,比如:%d{yyyy-MM-dd hh:mm:ss},输出:2023-10-26 13:37:29
  • %p: 输出日志级别,即DEBUG,INFO,WARN,ERROR,FATAL,
  • %c:输出Logger 名称
  • %m: 输出代码中指定的消息
  • %r: 输出自应用启动到输出该日志信息耗费的毫秒数
  • %t: 输出线程信息,当用QThread::currentThread()->setObjectName("XXX");设置线程名之后,输出的时线程名:“XXX”(QThread::currentThread()->objectName());没设置线程名,输出的是线程地址:0x000000000xxxxxxxxxx(QThread::currentThread())
  • %F: 输出日志消息产生时所在的文件名称
  • %M:输出日志消息产生时所在的函数名称
  • %L: 输出日志消息产生时所在代码中的行号
  • %l: 输出日志消息产生时所在位置,相当于%F:%L-%M的组合
  • %n: 输出一个回车换行符,Windows平台为"\r\n",Unix平台为"\n"

二、下载

访问下面的网址,下载Log4Qt源码压缩包
https://github.com/MEONMedical/Log4Qt

三、链接库方式使用

下载的压缩包,解压之后,如下图所示,用Qt打开log4qt.pro

选择编译器

右击项目名,进行重新构建

在构建目录中生成log4qt.dll

新建一个Qt项目

在新建的项目中新建一个“bin”文件夹,把刚才生成的log4qt.dll拷贝进去

在新建的项目中新建一个“include/log4qt”文件夹,把下载文件夹中的Log4Qt-master\src\log4qt中的三个文件夹和.h文件拷贝过去

在Log4QtDll.pro文件中增加如下代码:
DESTDIR = $$PWD/bin
INCLUDEPATH += $$PWD/include
LIBS += -L$$PWD/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文件夹下生成日志文件

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:..\Log4QtDll\mainwindow.cpp 
  • %M:MainWindow::MainWindow(QWidget*) 
  • %L:11 
  • %l:..\Log4QtDll\mainwindow.cpp:11 - MainWindow::MainWindow(QWidget*)
  • %n:换行

四、源码方式使用

新建一个Qt项目

把下载解压的文件夹中的如下文件夹拷贝到新建项目中

再把如下两个文件拷贝到新建项目的log4qt文件夹中

在Log4QtSrc.pro文件中添加如下代码
INCLUDEPATH += $$PWD/log4qt
include($$PWD/log4qt/log4qt.pri)

重新构建

项目结构中出现如下内容,报错先不用管

在log4qt.pri文件中添加如下代码
QT += xml network concurrent sql

DEFINES +=LOG4QT_STATIC
include($$PWD/build.pri)
include($$PWD/g++.pri)

再重新构建

更改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;
}
重新构建,并运行,输出如下:
同时在项目构建目录下生成日志文件

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

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

相关文章

echarts实际开发中遇到的问题

当tooltip内容过高时&#xff0c;增加滚动条 enterable:true, extraCssText: height:500px;overflow-y:auto;

Linux虚拟化的模式

三种虚拟化方式&#xff1a;完全虚拟化&#xff08;Full virtualization&#xff09;、硬件辅助虚拟化&#xff08;Hardware-Assisted Virtualization&#xff09;、半虚拟化&#xff08;Paravirtualization&#xff09;。 服务器上的虚拟化软件&#xff0c;多使用 qemu&#…

School training competition ( Second )

A. Medium Number 链接 : Problem - 1760A - Codeforces 就是求三个数的中位数 : #include<bits/stdc.h> #define IOS ios::sync_with_stdio(0);cin.tie(0);cout.tie(0); #define endl \nusing namespace std; typedef long long LL; const int N 2e510;inline void …

【无头双向链表和链表练习题2】

文章目录 以给定值x为基准将链表分割成两部分&#xff0c;所有小于x的结点排在大于或等于x的结点之前输入两个链表&#xff0c;找出它们的第一个公共结点。给定一个链表&#xff0c;判断链表中是否有环无头双向链表的模拟实现ArrayList&#xff08;顺序表&#xff09;和LinkedL…

Netty I/O模型和线程模型

目录 1.概述 1.1 为什么使用Netty 1.2 Netty的优势 1.3 Netty的常见使用场景 2.Netty高性能的原因 2.1 I/O模型 2.1.1 阻塞IO 2.1.2 IO复用模型 2.2 线程模型 2.2.1 线程模型1&#xff1a;传统阻塞 I/O 服务模型 2.2.2 线程模型2&#xff1a;Reactor 模式 2.2.2.1 …

rdf-file:API

一&#xff1a;组件架构 intefaces模块&#xff1a;主要包含用户使用接口APItools模块&#xff1a;包含组件内核实现的文件操作工具codec模块&#xff1a;对文件结构&#xff0c;行数据&#xff0c;字段数据进行编码解码meta模块&#xff1a; 元数据配置以及加载loader/extensi…

中低压MOSFET 2N7002KW 60V 300mA 双N通道 SOT-323封装

2N7002KW小电流双N通道MOSFET&#xff0c;电压60V电流300mA&#xff0c;采用SOT-323封装形式。超高密度电池设计&#xff0c;适用于极低的ros (on)&#xff0c;具有导通电阻和最大直流电流能力&#xff0c;ESD保护。可应用于笔记本中的电源管理&#xff0c;电池供电系统等产品应…

CANdelaStudio 使用教程6 编辑DTC

文章目录 DTC的导入导出定义 19 服务的DTC编辑快照数据 DTC的导入导出 DTC导出的文件是 Excel 文件&#xff0c;可以先将这个池子的DTC导出去修改&#xff0c;再导入进来&#xff0c;完成DTC的修改 定义 19 服务的DTC 编辑快照数据

Java Thread 介绍

线程是操作系统调度的最小单元, 也叫轻量级进程。它被包含在进程之中, 是进程中的实际运作单位。 同一进程可以创建多个线程, 每个线程都有自己独立的一块内存空间, 并且能够访问共享的内存变量。 1 线程的分类 在 Java 中, 线程可以分为 2 种 守护线程: 守护线程是为用户线程…

使用Terraform创建Docker镜像和容器

为了实现自动化操作&#xff0c;Terraform需要明确指定所使用的提供者。因此&#xff0c;在主要的main.tf文件中&#xff0c;需要提供提供者的名称、源和版本信息。对于Docker&#xff0c;可以在main.tf中使用以下代码块。 1 Terraform配置模块 使用块和资源创建Terraform脚本…

nodejs+vue+elementui+express青少年编程课程在线考试系统

针对传统线下考试存在的老师阅卷工作量较大&#xff0c;统计成绩数据时间长等问题&#xff0c;实现一套高效、灵活、功能强大的管理系统是非常必要的。该系统可以迅速完成随机组卷&#xff0c;及时阅卷、统计考试成绩排名的效果。该考试系统要求&#xff1a;该系统将采用B/S结构…

C++类与对象(6)—初始化列表、explicit关键字、static成员

目录 一、初始化列表 1、定义 2、注意事项 3、尽量使用初始化列表初始化 4、初始化顺序 二、 explicit关键字 1、定义 2、特点 三、static成员 1、定义 2、特性 3、例题 一、初始化列表 下面这段代码可以正常编译&#xff1a; class A { private:int _a1;//成员…

innovus如何在floorplan view显示所有module

我正在「拾陆楼」和朋友们讨论有趣的话题&#xff0c;你⼀起来吧&#xff1f; 拾陆楼知识星球入口 如题&#xff0c;innovus的图形界面在floorplan view下默认只能显示instance数量超过100个的module&#xff0c;如果要显示更小的module&#xff0c;需要在VIEW-Set Perference…

LeetCode Hot100 394.字符串解码

题目&#xff1a; 给定一个经过编码的字符串&#xff0c;返回它解码后的字符串。 编码规则为: k[encoded_string]&#xff0c;表示其中方括号内部的 encoded_string 正好重复 k 次。注意 k 保证为正整数。 你可以认为输入字符串总是有效的&#xff1b;输入字符串中没有额外的…

东胜物流软件 SQL注入漏洞复现

0x01 产品简介 东胜物流软件是一款致力于为客户提供IT支撑的 SOP&#xff0c; 帮助客户大幅提高工作效率&#xff0c;降低各个环节潜在风险的物流软件。 0x02 漏洞概述 东胜物流软件 TCodeVoynoAdapter.aspx、/TruckMng/MsWlDriver/GetDataList、/MvcShipping/MsBaseInfo/Sav…

C语言——I /深入理解指针(二)

一、数组名的理解 int arr[10] {1,2,3,4,5,6,7,8,9,10}; int *p &arr[0];这⾥我们使⽤ &arr[0] 的⽅式拿到了数组第⼀个元素的地址&#xff0c;但是其实数组名本来就是地址&#xff0c;⽽且 是数组⾸元素的地址&#xff0c;我们来做个测试。 #include <stdio.…

C++ :静态成员

静态成员 静态成员就是在成员变量和成员函数前加上关键字 static &#xff0c;称为静态成员 静态成员分为&#xff1a; 静态成员变量 1.所有对象共享同一份数据 2.在编译阶段分配内存 3.类内声明&#xff0c;类外初始化 静态成员函数 1.所有对象共享同一个函数 2.静态成…

计算机毕业设计springboot+vue高校田径运动会报名管理系统61s38

高校田径运动会管理采用java技术&#xff0c;基于springboot框架&#xff0c;mysql数据库进行开发&#xff0c;实现了首页、个人中心、运动员管理、裁判员管理、场地信息管理、项目类型管理、比赛项目管理、比赛报名管理、比赛成绩管理、通知公告管理、留言板管理、交流论坛、系…

1.ORB-SLAM3中如何保存多地图、关键帧、地图点到二进制文件中

1 保存多地图 1.1 为什么保存(视觉)地图 因为我们要去做导航&#xff0c;导航需要先验地图。因此需要保存地图供导航使用&#xff0c;下面来为大家讲解如何保存多地图。 1.2 保存多地图的主函数SaveAtlas /*** brief 保存地图* param type 保存类型*/ void System::SaveAtlas(…

Kubernetes基础入门:Kubernetes的有关概述

Kubernetes基础入门&#xff1a;Kubernetes的有关概述 一、摘要二、为什么需要 Kubernetes&#xff1f;三、Kubernetes 的功能架构 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 一、摘要 随着云计算和容器技术的快速发展&#xff0c;现代…