C加加下的日志库有很多,如log4cpp、Easylogging++等,Qt下也有log4qt。

不过我们今天要说的是QsLog,它是一个基于Qt的轻量级开源日志库。

git地址:https://github.com/victronenergy/QsLog

轻到什么程度,请看如下:

代码文件就是这么点。花点时间阅读一下,秒改造成你自己的私有轮子。

虽然轻量级,但是对于基本的日志功能需求还是够用的。

特征

  • 六个日志级别(从跟踪到致命)
  • 运行时可配置的日志级别阈值。
  • 关闭日志记录时的最小开销。
  • 支持多个目标,附带文件和调试目标。
  • 线程安全
  • 支持现成的常见Qt类型的日志记录。
  • 小依赖:直接把它放到你的项目中。

接下来,我们研究下它都有哪些功能。

一、QsLog使用方式

1. 源码集成

在你的工程中,直接包含QsLog.pri文件,进行源码集成。

当然你也可以包含QsLog.pri后,编译为xx.dll,在应用工程中去调用xx.dll。

2. 动态库集成

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

二、日志级别

支持六个日志级别,优先级从低到高依次为: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)

注意:

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

三、日志输出目的地

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));
}

修改后的QsLog库,下载链接:

https://download.csdn.net/download/u011832525/12520461

运行效果:

小结:

总结下,日志打印输出目的地可以有4种,分别是:

  • 输出到文件;
  • 输出到控制台stdout;
  • 输出到函数;
  • 输出到QObject。

并且可以添加任意多个目的地址,比如输出到文件的同时,还要输出到控制台进行显示,以方便查看调试打印信息。

四、打印源文件名称和行号

在QsLog.pri文件中

DEFINES += QS_LOG_LINE_NUMBERS

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

运行效果:

五、禁止日志记录

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

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

六、线程安全

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

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()函数不是线程安全的。

七、日志的异步打印

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

在QsLog.pri文件中

DEFINES += QS_LOG_SEPARATE_THREAD

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

八、总结

以下内容来自QsLog的git仓库介绍:

QsLog is an easy to use logger that is based on Qt’s QDebug class. QsLog is released as open source, under the MIT license.

###Contribution policy### Bug fixes are welcome, larger changes however are not encouraged at this point due to the lack of time on my side for reviewing and integrating them. Your best bet in this case would be to open a ticket for your change or forking the project and implementing your change there, with the possibility of having it integrated in the future. All contributions will be credited, license of the contributions should be MIT.

意思就是有问题,欢迎提bug,不过我没啥时间,修不修复就看我的心情了。如果你想玩,最好自己fork仓库,以后,万一未来哪天心情好了,想继续迭代版本,你敲的代码还是有可能merge进来的,到时候给你颁朵小红花,不过要遵守老麻的许可噢!

看完本文后,有需要的客官大老爷,请自行斟酌。


若对你有帮助,欢迎点赞、收藏、评论,你的支持就是我的最大动力!!!

同时,阿超为大家准备了丰富的学习资料,欢迎关注公众号“超哥学编程”,即可领取。

本文涉及工程代码,公众号回复:47QsLog,即可下载。

Qt轻量级日志库QsLog的使用相关推荐

  1. Google 出的C++轻量级日志库_GLog_了解_使用

    文章目录 1.Google Logging(glog)是一个C++轻量级.稳定.开源的日志系统日志库,是一个实现应用程序级日志记录的C++98库,支持以下功能: 2.GLog日志级别: 3.GLog分 ...

  2. 号称C/C++高性能日志库

    ** 以下都是号称高性能日志库 ** 腾讯 C++日志库:Mars XLOG https://github.com/Tencent/mars 美团 C/C++日志库 https://github.co ...

  3. linux c c 常用的日志库,mslog: 一款超轻量级的C日志库,无需依赖额外的库,测试或移植过的系统有Linux(ubuntu,centos),Windows以及部分嵌入式设备;...

    mslog 1.综述 ​ 一款超轻量级的C日志库,无需依赖额外的库,库的设计目标为"简洁,可移植性强".测试或移植过的系统有Linux(ubuntu,centos),Windows ...

  4. QT使用log4cpp日志库

    文章目录 QT使用log4cpp日志库 1. 从官网下载log4cpp源码 2. 编译项目 3. 在QT中使用log4cpp 4. log4cpp 4.1. Category 4.2. Appende ...

  5. C++plog库,轻量级日志框架(日志库)

    文章目录 为何建议程序员在项目中使用第三方日志库 第三方日志库plog的优势 plog主要头文件及使用方法解释 plog/Log.h plog/Appenders/ColorConsoleAppend ...

  6. 日志库EasyLogging++学习系列(1)—— 简要介绍

    对于有开发经验的程序员来说,记录程序执行日志是一件必不可少的事情.通过查看和分析日志信息,不仅可以有效地帮助我们调试程序,而且当程序正式发布运行之后,更是可以帮助我们快速.准确地定位问题.在现在这个开 ...

  7. 轻量级日志采集系统Loki+grafana搭建

    轻量级日志采集系统Loki+grafana搭建 一.Loki介绍 整体架构 Loki的架构非常简单,使用了和prometheus一样的标签来作为索引,也就是说,你通过这些标签既可以查询日志的内容也可以 ...

  8. Logan:美团点评的开源移动端基础日志库

    前言 Logan是美团点评集团移动端基础日志组件,这个名称是Log和An的组合,代表个体日志服务.同时Logan也是"金刚狼"大叔的名号,当然我们更希望这个产品能像金刚狼大叔一样犀 ...

  9. c++日志库实战——spdlog,是不是感觉log4cxx有点笨重,不妨试一试spdlog

    c++日志库实战--spdlog,是不是感觉log4cxx有点笨重,不妨试一试spdlog 背景 更新记录 spdlog是什么 spdlog快速入门 编译 CMake手动方式 Vcpkg全自动方式(推 ...

最新文章

  1. python是一种编译的编程语言_Python这种编程语言
  2. [CF407B] Long Path
  3. 【学亮IT手记】AngularJS增删改查服务请求+代码剥离封装抽取示例
  4. spring boot web项目_SpringBoot2.x入门到项目实战课程系列(第四章)
  5. 11. 盛最多水的容器 golang
  6. ruby 集合 分组_在Ruby中找到两个集合之间的区别
  7. 企业要做有价值的私域流量三大关键
  8. 《众妙之门——移动交互体验设计》—— 1.2 物物互联
  9. Linux驱动的ioctl函数简要说明
  10. 3月7日学习内容整理:restframework的解析器组件
  11. C++ OpenCV 学习笔记【1】-安装环境搭建+基础文件资源链接
  12. Introduction to Computer Networking学习笔记(四):路由转发表及转发规则
  13. 硬件电路设计之按键消抖(利用瞬态抑制二极管TVS加低通滤波器)
  14. c语言定时器1khz占空比,555定时器产生方波原理(四款555定时器产生方波的电路详解)...
  15. Win10 AMD610显卡驱动安装出现错误206安装失败
  16. 关于校园招聘 - 秋招和春招
  17. 图解Activity启动流程
  18. 智比奈特万兆光口网卡 ZB-10G-1F 驱动安装和带宽测试
  19. 基于嵌入式设备的 单目标跟踪算法
  20. 一个好的学习算法的网站

热门文章

  1. 单细胞基因个性化作图之气泡图
  2. 查看android数据库sqlite3中的表及数据、手机上直接编辑数据库
  3. linux shell中 '' ``的区别
  4. 祝酒歌--蒙语发音对照
  5. 在国内怎么玩LOL韩服呢?
  6. 如何打开信息服务器,internet信息服务怎么打开?一招轻松打开internet信息服务的方法...
  7. 我搭建了一个网站,请问怎么给网站备案?网站备案的流程怎么操作?
  8. Mac版微信突然显示音频设备启动失败
  9. 贪吃蛇游戏项目(Java版含源代码)
  10. 通过客户端编程的方式调用webservice