Qslog开源库使用

news2024/12/28 23:39:57

Qslog源码下载地址:https://github.com/victronenergy/QsLog

1.QSLOG使用方式

(1)源码集成

在你的工程中,直接包含QsLog.pri文件,进行源码集成。当然你也可以包含QsLog.pri后,编译为xx.dll,在应用工程中去调用xx.dll。

(2)动态库集成

编译QsLogSharedLibrary.pro,生成动态链接库QsLog2.dll,在你的工程中进行调用。

2.日志级别

支持六个日志级别,优先级从低到高依次为:Trace、Debug、Info、Warn、Error、Fatal、Off。如下:

enum Level
{
    TraceLevel = 0,
    DebugLevel,
    InfoLevel,
    WarnLevel,
    ErrorLevel,
    FatalLevel,
    OffLevel
};
  • Trace:跟踪,最低等级的,用于打开所有日志记录。
  • Debug:调试,打印一些细粒度调试运行信息。
  • Info:信息,打印粗粒度信息,突出强调程序的运行过程。打印一些感兴趣或者重要的信息,可用于环境中输出程序运行的一些重要信息,但不能滥用,避免打印过多日志。
  • Warn:警告,表明会出现潜在错误的情形,有些信息不是错误信息,但是也要给程序员的一些提示。
  • Error:错误,指出虽然发生错误,但仍然不影响系统的继续运行。打印错误和异常信息。
  • Fatal:致命的,发生严重错误,将导致应用程序的退出。这个级别比较高,程序直接停止运行了。
  • Off:最高等级的,用于关闭所有日志记录。

可以通过setLoggingLevel()设置记录日志的级别。

void setLoggingLevel(Level newLevel)

注意:

一般我们可以将日志级别保存到配置文件,以便程序发布后,可通过修改配置来改变记录日志级别。

3.日志输出目的地

QsLog的使用很简单,在我们自己的工程中直接include它的QsLog.pri文件,然后源文件中包含QsLog.h就可以使用了。

(1)输出到文件(支持文件分割)

// 测试文件为目的地
void test_output_file()
{
    // 初始化日志机制
    Logger& logger = Logger::instance();
    logger.setLoggingLevel(QsLogging::TraceLevel);

    // 添加文件为目的地
    const QString sLogPath(QDir(QApplication::applicationDirPath()).filePath("log.txt"));
    DestinationPtr fileDestination(DestinationFactory::MakeFileDestination(
      sLogPath, EnableLogRotation, MaxSizeBytes(512*1024), MaxOldLogCount(5)));
    logger.addDestination(fileDestination);

    // 打印日志
    QLOG_TRACE() << "1-trace msg";
    QLOG_DEBUG() << "2-debug msg";
    QLOG_INFO() << "3-info msg";
    QLOG_WARN() << "4-warn msg";
    QLOG_ERROR() << "5-error msg";
    QLOG_FATAL()  << "6-fatal msg";

    QsLogging::Logger::destroyInstance();
}
  • 代码很简单,setLoggingLevel()设置记录的日志级别;

目前为TraceLevel,则日志级别比TraceLevel高的都会输出到文件;

若为ErrorLevel,则只有"5-error msg"和"6-fatal msg"这2条会输出。

  • 然后设置文件名和输出目的地。其中目的地是由DestinationFactory::MakeFileDestination()函数进行构造的,其原型为:
static DestinationPtr MakeFileDestination(
    const QString& filePath,
    LogRotationOption rotation = DisableLogRotation,
    const MaxSizeBytes &sizeInBytesToRotateAfter = MaxSizeBytes(),
    const MaxOldLogCount &oldLogsToKeep = MaxOldLogCount()
);

函数参数含义:

  • filePath: 日志文件名
  • rotation: 取值DisableLogRotation和EnableLogRotation,

前者表示禁止日志文件分割,即日志始终往一个文件中写入。

后者表示启用日志文件分割,此时sizeInBytesToRotateAfter和oldLogsToKeep参数才有意义。

  • sizeInBytesToRotateAfter: 每个日志文件的字节数大小限制,即到达此大小后,自动新建文件,在新文件中进行写入。
  • oldLogsToKeep: 旧日志文件保留(备份)个数,超过此数量,自动删除最久远文件,备份文件最多支持10个。
  • 若为2,则如下三个文件中内容,按照时间先后顺序排列为:log.txt.2->log.txt.1->log.txt,在log.txt中为最新日志,log.txt.1为次新,log.txt.2为最久远日志。
  • 若此时log.txt超过sizeInBytesToRotateAfter限制,则会发生log.txt.2被删除,log.txt.1被改名log.txt.2,log.txt被改名log.txt.1,新建log.txt。

(2)输出到控制台STDOUT

// 测试stdout为目的地
void test_output_stdout()
{
    // 初始化日志机制
    Logger& logger = Logger::instance();
    logger.setLoggingLevel(QsLogging::TraceLevel);

    // 添加stdout为目的地
    DestinationPtr debugDestination(DestinationFactory::MakeDebugOutputDestination());
    logger.addDestination(debugDestination);

    // 打印日志
    QLOG_TRACE() << "1-trace msg";
    QLOG_DEBUG() << "2-debug msg";
    QLOG_INFO() << "3-info msg";
    QLOG_WARN() << "4-warn msg";
    QLOG_ERROR() << "5-error msg";
    QLOG_FATAL()  << "6-fatal msg";

    QsLogging::Logger::destroyInstance();
}

(3) 输出到处理函数

void logFunction(const QString &message, QsLogging::Level level)
{
    qDebug() << "From log function: " << qPrintable(message) << " " << static_cast<int>(level);
}

// 测试函数为目的地
void test_output_function()
{
    // 初始化日志机制
    Logger& logger = Logger::instance();
    logger.setLoggingLevel(QsLogging::TraceLevel);

    // 添加函数为目的地
    DestinationPtr functorDestination(DestinationFactory::MakeFunctorDestination(&logFunction));
    logger.addDestination(functorDestination);

    // 打印日志
    QLOG_TRACE() << "1-trace msg";
    QLOG_DEBUG() << "2-debug msg";
    QLOG_INFO() << "3-info msg";
    QLOG_WARN() << "4-warn msg";
    QLOG_ERROR() << "5-error msg";
    QLOG_FATAL()  << "6-fatal msg";

    QsLogging::Logger::destroyInstance();
}

输出到函数,该函数需要定义为如下类型:

typedef void (*LogFunction)(const QString &message, Level level);

(4)输出到QTEXTEDIT控件

除了上面的输出方式,还可以输出到一个QObject对象上,主要是通过信号槽机制,将打印日志发送到QObject的槽函数进行处理。

void MainWindow::writeLog(const QString &message, int level)
{
    ui->textEdit->append(message + " " + QString::number(level));
}
// 测试QObject为目的地
void test_output_qobject(MainWindow* window)
{
    // 初始化日志机制
    Logger& logger = Logger::instance();
    logger.setLoggingLevel(QsLogging::TraceLevel);

    // 添加QObject为目的地
    DestinationPtr objectDestination(DestinationFactory::MakeFunctorDestination(window, SLOT(writeLog(QString,int))));
    logger.addDestination(objectDestination);

    // 打印日志
    QLOG_TRACE() << "1-trace msg";
    QLOG_DEBUG() << "2-debug msg";
    QLOG_INFO() << "3-info msg";
    QLOG_WARN() << "4-warn msg";
    QLOG_ERROR() << "5-error msg";
    QLOG_FATAL()  << "6-fatal msg";

    QsLogging::Logger::destroyInstance();
}

输出到QObject时,需要定义其槽函数,为如下类型:

void xxxx(const QString &message, int level)

写本例子时,发现TRACE信息不能输出到QObject,是因为QsLogDestFunctor.cpp文件中,write函数有个bug,如下:

void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level)
{
    if (mLogFunction)
        mLogFunction(message, level);

    if (level > QsLogging::TraceLevel)
        emit logMessageReady(message, static_cast<int>(level));
}

应将>改为>=,修改后即可解决,如下:

void QsLogging::FunctorDestination::write(const QString &message, QsLogging::Level level)
{
    if (mLogFunction)
        mLogFunction(message, level);

    if (level >= QsLogging::TraceLevel)
        emit logMessageReady(message, static_cast<int>(level));
}
4.打印源文件名称和行号

在QsLog.pri文件中

DEFINES += QS_LOG_LINE_NUMBERS

打开此宏定义,重新编译,即可打印带源文件名称和行号的日志。如下:

5.禁止日志记录

禁用日志记录,有时候关闭日志记录是有必要的。可以通过3种方式实现:

  • 全局地,在编译时,通过在QsLog.pri文件,打开DEFINES += QS_LOG_DISABLE宏定义。
  • 全局地,在运行时,通过将日志级别设置为关闭,即setLoggingLevel(QsLogging::OffLevel)。
  • 在编译时,通过在目标文件中包含QsLogDisableForThisFile.h,为每个文件创建一个。
6.线程安全

使用日志宏进行打印日志是线程安全的,日志宏如下:

QLOG_TRACE() << "1-trace msg";
QLOG_DEBUG() << "2-debug msg";
QLOG_INFO() << "3-info msg";
QLOG_WARN() << "4-warn msg";
QLOG_ERROR() << "5-error msg";
QLOG_FATAL()  << "6-fatal msg";

这在前面我们已经使用过了。

如setLoggingLevel()、addDestination()函数不是线程安全的。

7.日志的异步打印

所谓的异步打印,其实就是单独开一个线程来专门写日志。

在QsLog.pri文件中

DEFINES += QS_LOG_SEPARATE_THREAD

打开此宏定义,重新编译,日志内容就会在单独的线程中排队并写入

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

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

相关文章

数据可视化练习

文章目录 试题示例 试题示例 绘制下图所示的表格 根据下表的数据&#xff0c;将班级名称一列作为x轴的刻度标签&#xff0c;将男生和女生两列的数据作为刻度标签对应的数值&#xff0c;使用bar()函数绘制下图所示的柱形图。 方式一 import numpy as np import matplotlib.p…

CUDA编程- - GPU线程的理解 thread,block,grid - 再次学习

GPU线程的理解 thread,block,grid 一、从 cpu 多线程角度理解 gpu 多线程1、cpu 多线程并行加速2、gpu多线程并行加速2.1、cpu 线程与 gpu 线程的理解&#xff08;核函数&#xff09;2.1.1 、第一步&#xff1a;编写核函数2.1.2、第二步&#xff1a;调用核函数&#xff08;使用…

跟着cherno手搓游戏引擎【12】渲染context和首个三角形

渲染上下文&#xff1a; 目的&#xff1a;修改WindowsWindow的结构&#xff0c;把glad抽离出来 WindowsWindow.h:新建m_Context #pragma once #include "YOTO/Window.h" #include <YOTO/Renderer/GraphicsContext.h> #include<GLFW/glfw3.h> #include…

iperf3网络带宽性能测试工具 局域网网络最大带宽高阶教程

iperf3 是一个 TCP, UDP, 和 SCTP (传输层协议)网络带宽测量工具&#xff0c;iperf 是一个用于主动测量 IP 网络上最大可用带宽的工具. 它支持与时间、协议和缓冲区相关的各种参数的调优. 对于每个测试&#xff0c;它报告测量的吞吐量/比特率(带宽), 丢包率和其他参数&#xff…

MySQL 覆盖索引

目录 一、什么是索引 二、索引的有哪些种类&#xff1f; 三、InnoDB的不同的索引组织结构是怎样的呢&#xff1f; 四、什么是覆盖索引 五、如何使用是覆盖索引&#xff1f; 六、如何确定数据库成功使用了覆盖索引呢 总结&#xff1a; 一、什么是索引 索引&#xff08;在 …

Log4j2-01-log4j2 hello world 入门使用

拓展阅读 Log4j2 系统学习 Logback 系统学习 Slf4j Slf4j-02-slf4j 与 logback 整合 SLF4j MDC-日志添加唯一标识 分布式链路追踪-05-mdc 等信息如何跨线程? Log4j2 与 logback 的实现方式 日志开源组件&#xff08;一&#xff09;java 注解结合 spring aop 实现自动输…

openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板

文章目录 openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板概述笔记工程中需要的openssl的库实现END openssl3.2 - 测试程序的学习 - 准备openssl测试专用工程的模板 概述 openssl3.2 - 测试程序的学习 整了几个test.c, 每开一个新的测试工程, 总要改这改那的. …

【RH850U2A芯片】Reset Vector和Interrupt Vector介绍

目录 前言 正文 1. 什么是Reset Vector 1.1 S32K144芯片的Reset Vector 1.2 RH850芯片的Reset Vector 2. 什么是Interrupt Vector 2.1 S32K144芯片的Interrupt Vector 2.2 RH850芯片的Interrupt Vector 3. Reset Vector等价于Interrupt Vector吗 4. 总结 前言 最近在…

uniapp微信小程序-input默认字的样式

需要的是这样的 问题 正常是在input框上面写样式就行&#xff0c;但是uniapp不起作用 解决 直接在input上写placeholder-style"color就解决了 <input class"findInput" type"text" placeholder"关键词查询"placeholder-style"co…

微信小程序-04

rpx&#xff08;responsive pixel&#xff09;是微信小程序独有的&#xff0c;用来解决屏适配的尺寸单位。 import 后跟需要导入的外联样式表的相对路径&#xff0c;用 ; 表示语句结束。 定义在 app.wxss 中的样式为全局样式&#xff0c;作用于每一个页面。 在页面的 .wxss 文…

第九篇 华为云Iot SDK的简单应用

第九篇 华为云Iot SDK的简单应用 一、华为云Iot SDK API的简单使用 1.初始化SDK 2.绑定连接配置信息 3.连接服务器 4.上报属性 5.接收命令 二、实现智能家居灯光状态上报 &#x1f516;以下是上报数据到华为云Iot的代码片段&#xff0c;配合串口控制灯光&#xff0c;改变灯…

DolphinDB学习(2):增删改查数据表(分布式表的基本操作)

文章目录 创建数据表1. 创建数据表全流程2. 核心&#xff1a;创建table3. 在已有的数据表中追加新的数据 数据表自身的操作1. 查询有哪些数据表2. 删除某张数据表3. 修改数据表的名称 博客里只介绍最常见的分区表&#xff08;createPartitionedTable&#xff09;的创建方法&…

【机器学习笔记】1 线性回归

回归的概念 二分类问题可以用1和0来表示 线性回归&#xff08;Linear Regression&#xff09;的概念 是一种通过属性的线性组合来进行预测的线性模型&#xff0c;其目的是找到一条直线或者一个平面或者更高维的超平面&#xff0c;使得预测值与真实值之间的误差最小化&#x…

Hive3.1.3基础(续)

参考B站尚硅谷 分区表和分桶表 分区表 Hive中的分区就是把一张大表的数据按照业务需要分散的存储到多个目录&#xff0c;每个目录就称为该表的一个分区。在查询时通过where子句中的表达式选择查询所需要的分区&#xff0c;这样的查询效率会提高很多。 分区表基本语法 分区表…

JVM系列-9.性能调优

&#x1f44f;作者简介&#xff1a;大家好&#xff0c;我是爱吃芝士的土豆倪&#xff0c;24届校招生Java选手&#xff0c;很高兴认识大家&#x1f4d5;系列专栏&#xff1a;Spring原理、JUC原理、Kafka原理、分布式技术原理、数据库技术、JVM原理&#x1f525;如果感觉博主的文…

c++ QT 信号的个人理解 信号就是独立文件调用的一种“协议”

一. 简介 就我个人来理解&#xff0c;信号槽机制与Windows下消息机制类似&#xff0c;消息机制是基于回调函数&#xff0c;Qt中用信号与槽来代替函数指针&#xff0c;使程序更安全简洁。 信号和槽机制是 Qt 的核心机制&#xff0c;可以让编程人员将互不相关的对象绑定在一起&a…

JavaEE-自定义SSM-编写核心- my spring bean工厂(IoC、DI)

3.4 my spring bean工厂&#xff08;IoC、DI&#xff09; 加载类解析类获得类 3.4.0 分析 3.4.1 扫描指定包下的所有类 package com.czxy.bean;import java.io.File; import java.util.ArrayList; import java.util.List; import java.util.Objects;public class MyBeanFac…

面向Java开发者的ChatGPT提示词工程(11)扩写

什么是扩写&#xff1f; 扩写是指将较短的文本交给GPT生成更长的文本。比如&#xff1a;根据一组基本指令&#xff0c;写出一封完整的电子邮件&#xff1b;或者根据一系列主题&#xff0c;创作出一篇包含这些主题的文章。 这样的技术&#xff0c;有着广阔的应用场景&#xff…

【JavaEE】传输层网络协议

传输层网络协议 1. UDP协议 1.1 特点 面向数据报&#xff08;DatagramSocket&#xff09;数据报大小限制为64k全双工不可靠传输有接收缓冲区&#xff0c;无发送缓冲区 UDP的特点&#xff0c;我理解起来就是工人组成的**“人工传送带”**&#xff1a; 面向数据报&#xff08;…

CMake简明教程 笔记

推荐B站视频&#xff1a;1.1 Cmake构建项目的流程_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV1xa4y1R7vT?p1&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 >>目录 1&#xff09;CMake初体验 CMake构建流程Windows下使用CMake构建项目Linux下使用CMake构…