嵌入式大杂烩每周日记第7期zlog

大家好,我是乔德先生。

 

嵌入式大杂烩周日记主要是学习和分享一些实践项目,每周一篇文章,每篇文章都有一个主题。

内容主要来自我们之前收集的信息:

本期主角:zlog

zlog是一个纯C日志函数库,具有高可靠性、高性能、线程安全、灵活、概念清晰的特点。

Zlog在效率、功能、安全性方面都大大超过了log4c。 它是用C语言编写的,具有比较好的通用性。

zlog有以下特点:

zlog仓库链接:

zlog用户手册:

许可证:LGPL-2.1。

开源软件协议相关文章:常用的开源协议有哪些?

zlog的使用 1.x86平台的使用

首先是编译安装zlog。

我们可以按照默认路径安装:

git clone git@github.com:HardySimpson/zlog.git
cd zlog 
make 
sudo make install

 

也可以安装到指定路径。 这里我们简单验证一下,所以安装到指定路径了。 安装到指定路径build_x86:

git clone git@github.com:HardySimpson/zlog.git
cd zlog 
mkdir build_x86
make 
sudo make PREFIX=../build_x86 install

 

安装完成,您将得到:

嵌入式应用例子_嵌入式应用案例的分析_嵌入式系统应用实例有哪些/

为了让应用程序在运行时能够找到zlog库,我们可以将libzlog.so的路径添加到系统动态链接库加载器能够找到的目录中,修改/etc/ld.so.conf文件,并在其中添加 libzlog。 so路径,如:

/home/LinuxZn/tmp/zlog/build_x86/lib

 

执行sudo ldconfig命令即可生效。

我们只是暂时使用,您不需要这样添加。 在运行应用程序之前,使用export命令修改LD_LIBRARY_PATH变量,将libzlog.so的路径添加到LD_LIBRARY_PATH变量中并在当前终端生效。

测试如下:

我们创建一个新的 zlog_test 文件夹。 为了方便zlog的使用,我们将上面编译安装的整个build_x86文件夹复制到zlog_test文件夹下; 然后创建一个新的 test.c 和 test.conf 文件:

嵌入式应用案例的分析_嵌入式系统应用实例有哪些_嵌入式应用例子/

测试.c:

#include 
#include "zlog.h"
int main(int argc, char** argv)
{
 int rc;
 zlog_category_t *zc;
 rc = zlog_init("test.conf");
 if (rc) 
 {
 printf("init failed\n");
 return -1;
 }
 zc = zlog_get_category("my_cat");
 if (!zc) 
 {
 printf("get cat fail\n");
 zlog_fini();
 return -2;
 }
 zlog_info(zc, "微信公众号:嵌入式大杂烩");
 zlog_info(zc, "hello, zlog");
 zlog_fini();
 
 return 0;
}

 

测试.conf:

[rules]
my_cat.INFO >stdout

 

编译:

gcc test.c -o test_zlog -I ./build_x86/include -L ./build_x86/lib/ -lzlog -lpthread

 

运行时出现如下错误:

./test_zlog: error while loading shared libraries: libzlog.so.1.2: cannot open shared object file: No such file or directory

 

嵌入式应用案例的分析_嵌入式应用例子_嵌入式系统应用实例有哪些/

那是因为找不到libzlog.so库。 正如我们上面所说,使用导出命令:

export LD_LIBRARY_PATH=./build_x86/lib:$LD_LIBRARY_PATH

 

再次运行:

嵌入式系统应用实例有哪些_嵌入式应用例子_嵌入式应用案例的分析/

至此,我们已经使用了zlog。

zlog 如此强大的部分原因是它可以通过与项目绑定的 .conf 配置文件进行配置。 可以在配置文件中进行日志相关的配置,例如日志格式、日志级别定义等。

zlog配置文件及相关使用方法在zlog用户手册中有详细介绍:

我们先看一下zlog配置文件的一些基本内容。

zlog有3个重要的概念:

在上面的例子中:

zc = zlog_get_category("my_cat");

 

对应conf文件:

[rules]
my_cat.INFO >stdout

 

zlog conf文件有一定的书写格式,例如:

# comments
[global]
strict init = true
buffer min = 1024
buffer max = 2MB
rotate lock file = /tmp/zlog.lock
default format = "%d.%us %-6V (%c:%F:%L) - %m%n"
file perms = 600
[levels]
TRACE = 10
CRIT = 130, LOG_CRIT
[formats]
simple = "%m%n"
normal = "%d %m%n"
 
[rules]
default.* >stdout; simple
*.* ".2E(HOME)/log/%c.log", 1MB*12; simple
my_.INFO >stderr;
my_cat.!ERROR "/var/log/aa.log"
my_dog.=DEBUG >syslog, LOG_LOCAL0; simple
my_mice.* $user_define;

 

配置参数是可选的,不需要完整配置。 这里我们重点关注格式和规则。

在上面的示例中,如果没有正确的格式,则输出将采用默认格式。 默认格式为:

"%d %V [%p:%F:%L] %m%n"

 

具体例子包括:

2022-03-19 04:23:43 INFO [86557:test.c:35] 微信公众号:嵌入式大杂烩

 

我们想要自定义输出的格式就是配置formats。 比如上面的demo,我们想要修改日志前面的时间戳对我们来说是准确的,那么配置文件修改为:

[formats]
simple = "%d.%us %m%n"
[rules]
my_cat.INFO >stdout;simple

 

嵌入式系统应用实例有哪些_嵌入式应用案例的分析_嵌入式应用例子/

具体格式转换字符如下(具体请参考用户手册):

嵌入式应用案例的分析_嵌入式系统应用实例有哪些_嵌入式应用例子/

规则是组合类别、级别、输出文件和格式。 例如,上面的规则表示将简单格式日志输出到标准输出。

接下来我们修改日志输出到文件的规则:

[formats]
simple = "%d.%us %m%n"
[rules]
my_cat.INFO "./log/test.log"

 

意思就是将日志输出到当前目录下log文件夹中的test.log中:

嵌入式应用案例的分析_嵌入式应用例子_嵌入式系统应用实例有哪些/

关于规则的输出动作(具体请参考用户手册):

嵌入式应用例子_嵌入式系统应用实例有哪些_嵌入式应用案例的分析/

zlog还支持日志切割功能和日志循环存储,防止日志存储爆硬盘。 我们简单看一下zlog的日志切割和循环存储功能:

[formats]
simple = "%d.%us %m%n"
[rules]
my_cat.INFO "./log/demo.log",1KB*5~"./log/demo.log.#r";simple

 

上面标注了当日志存储超过1KB时,会存储在另一个文件中,并在5个文件之间来回循环。 r表示相反的顺序。 例如,先存储demo.log4,然后存储demo.log3。

将上面的代码修改为:

#include 
#include 
#include "zlog.h"
int main(int argc, char** argv)
{
 int rc;
 zlog_category_t *zc;
 rc = zlog_init("test.conf");
 if (rc) 
 {
 printf("init failed\n");
 return -1;
 }
 zc = zlog_get_category("my_cat");
 if (!zc) 
 {
 printf("get cat fail\n");
 zlog_fini();
 return -2;
 }
 zlog_info(zc, "微信公众号:嵌入式大杂烩");
 int i = 0;
 while (1)
 {
 zlog_info(zc, "hello, zlog, %d", i++);
 usleep(1000);
 }
 zlog_fini();
 
 return 0;
}

 

编译并运行:

嵌入式应用例子_嵌入式系统应用实例有哪些_嵌入式应用案例的分析/

嵌入式系统应用实例有哪些_嵌入式应用例子_嵌入式应用案例的分析/

有时候我们不需要自定义一些复杂的配置,我们也可以遵循默认的配置,这样就可以精简代码。 这时候就需要使用另一组API来初始化和打印:

int dzlog_init(const char *confpath, const char *cname);
dzlog_info(format, ...);

 

dzlog 是一组忽略类别的简单 zlog 接口(zlog_category_t)。 它使用内置的默认分类。

示例包括:

#include 
#include "zlog.h"
int main(int argc, char** argv)
{
 int rc;
 rc = dzlog_init("test.conf", "my_cat");
 if (rc) {
 printf("init failed\n");
 return -1;
 }
 
 dzlog_info("微信公众号:嵌入式大杂烩");
 dzlog_info("hello, zlog");
 zlog_fini();
 
 return 0;
}

 

最简单的配置文件:

[rules]
my_cat.* >stdoutc

 

编译并运行:

嵌入式应用例子_嵌入式系统应用实例有哪些_嵌入式应用案例的分析/