zlog日志库(笔记) —— 介绍

zlog是什么?

zlog是一个高可靠、高性能、线程安全、灵活、概念清晰的纯C编写的开源日志库。

项目主页:http://hardysimpson.github.io/zlog/
github源码地址:https://github.com/HardySimpson/zlog
参考文档地址:http://hardysimpson.github.io/zlog/UsersGuide-CN.html

printf优点:使用简单、灵活。
printf缺点:同步输出,无法通过配置改变日志格式或输出文件。

syslog:系统日志或系统记录,速度慢,功能单调,而且系统所有进程都能往内部添加日志。

log4c也是一个纯C日志库,目前已停止更新。zlog在效率、功能、安全性上超过log4c(作者自称,未验证)。

zlog特点:

  • syslog分类模型,比log4j模型更直接
  • 日志格式定制,类似于log4j的pattern layout
  • 多种输出,包括动态文件、静态文件、stdout、stderr、syslog、用户自定义输出函数
  • 运行时手动、自动刷新配置文件(同时保证安全性)
  • 高性能,在作者笔记本上可达25万条日志每秒,大约是syslog(3)配合rsyslogd的1000倍速度
  • 用户自定义等级
  • 多线程和多进程环境下保证安全转档
  • 精确到微秒
  • 简单调用包装dzlog(一个程序默认只用一个分类)
  • MDC,线程键-值对的表,可以扩展用户自定义的字段
  • 自诊断,可运行时输出zlog自己的日志和配置状态
  • 不依赖其他库,不过系统需要支持POSIX + C99兼容的vsnprintf

zlog不做什么

zlog目标是成为一个精简的日志函数库,不支持网络输出或写入数据库,不支持日志内容的过滤和解析。

因为日志库是被APP调用,所以日志库运行时间是APP运行时间点一部分。而上述操作很费时,会拖慢APP。这些事情,应该在别的进程或机器上做。

如果想要这些特性(网络、数据库、日志归档),建议用rsyslog、zLogFabric、Logstash,这些日志搜集、过滤、存储软件。而这些也都是单独的进程,不是APP一部分。


zlog模型

分类、规则、格式

zlog 3个重要概念:分类(Category)、规则(Rule)、格式(Format)。

分类:用于区分不同的输入。分类变量的名字是一个字符串,APP可以通过不同的分类名称获取category,以输出不同分类的日志,用于不同目的。

格式:用于描述日志的格式,如是否带时间戳,是否包含文件位置信息等。

规则:把分类、级别、输出文件、格式组合起来,决定一条代码中的日志是否输出,输出到哪(文件/终端),以什么格式输出。

例如,当程序执行下面语句时,

zlog_category_t *c;
c = zlog_category("my_cat");
zlog_info(c, "hello, zlog");

zlog会找到分类c对象的名字是"my_cat",对应配置文件(.conf)中规则:

[rules]
my_cat.DEBUG    >stdout; simple

当输出一条日志时,库会检查该日志级别是否符合规则中的级别要求:当前级别 >= DEBUG。如果满足,该条日志就输出。根据规则,日志会被输出到stdout(标准输出)。

输出格式simple,是什么样的呢?在配置文件中定义:

[formats]
simple = "%m%n"

最后,在屏幕(stdout)上打印:

hello, zlog

整个过程中,库用户需要做的就是写自己的信息。日志往哪输出,以什么格式输出,都是由库和配置文件来完成。

syslog模型 vs log4j模型

到目前为止,zlog采用的模型(category、rules、formats)还比较像log4j。log4j模型里有logger, appender, layout。区别在于:log4j里面,代码中的logger和配置中的logger是一一对应的,并且一个logger有唯一的级别。log4j, log4cxx, log4cpp, log4cplus, log4net都是一对一关系。

log4j模型缺点是不灵活。因此,发明了过滤器(filters)来弥补,但同时让模型更复杂、难以理解。

继前面例子,如果zlog配置文件(.conf)有这两条规则:

[rules]
my_cat.DEBUG     >stdout; simple
my_cat.INFO      >stdout;

一行输出日志的代码,会产生两行输出:

hello, zlog
2022-09-11 08:42:40 INFO [736:test_hello.c:30] hello, zlog

现在,代码中的同一个分类“my_cat"对应配置文件中两条规则。而在log4j中,需要放两个appender。

继续下面的例子。
配置文件:

[rules]
my_cat.INFO     "/var/log/aa.log"
my_cat.DEBUG    "/var/log/bb.log"

APP输出日志代码:

zlog_category_t *c;
c = zlog_category("my_cat");
...
zlog_info(c, "info, zlog");
zlog_debug(c, "debug, zlog");

最后,在aa.log中只有1条日志

$ sudo cat aa.log
2022-09-11 09:21:26 INFO [1410:test_hello.c:33] info, zlog

而在bb.log中有2条日志

$ sudo cat bb.log
2022-09-11 09:21:26 INFO [1410:test_hello.c:33] info, zlog
2022-09-11 09:21:26 DEBUG [1410:test_hello.c:34] debug, zlog

扩展syslog模型

现在,zlog模型似乎更像syslog模型。不过,syslog里的设施(facility)是int型,而且必须从系统定义的那几种选择(关于syslog,可参见这篇文章Unix/Linux syslogd守护进程 & 日志记录syslog )。zlog在此基础上,做了改善:可以用一个字符串来标识分类。

匹配设施
syslog有个通配符"",匹配所有的设施。zlog也采用了这种做法,""匹配所有分类。例如,只需要用一个很简单的办法,就能重定向系统种各个组件的错误:

[rules]
*.error    "/var/log/error.log"

这样,
1)"*"会匹配所有分类(category);
2)只有级别高于error的日志消息,才会被输出到error.log文件中。

匹配级别
zlog一个强大特性是独有的上下级分类匹配。如果你的分类是这样:

zlog_category_t *c;
c = zlog_category("my_cat");

对应配置文件是这样:

[rules]
my_cat.*      "/var/log/my_cat.log"
my_.NOTICE "/var/log/my.log"

这两条规则都会匹配c分类"my_cat"。配置文件中,通配符"-"标识上级分类,也就是说,"my_"是"my_cat"和"my_dog"的上级分类。

另一个通配符"!",见【分类匹配】部分。

posted @ 2022-09-10 23:55  明明1109  阅读(1519)  评论(0编辑  收藏  举报