编译安装
github clone下载:github.com/HardySimpson/zlog.git
cd zlog
make
sudo make install
默认安装路径是:/usr/local
自定义安装路径:src/makefile 中的PREFIX= /usr/local 改为自定义目录即可
若系统ld的目录中没有自定义的目录,添加方法:
vim /etc/ld.so.conf
#(根据实际安装目录灵活替换)
/usr/local/lib
sudo ldconfig
要使用zlog库 只需要在代码开头添加
#include "zlog.h"
编译链接
cc -c -o test_hello.o test_hello.c -I/usr/local/include
cc -o test_hello test_hello.o -L/usr/local/lib -lzlog
API介绍
API | 说明 |
int zlog_init(const char *confpath); | 从配置文件confpath中读取配置信息到内存 |
zlog_category_t *zlog_get_category(const char *cname) | 从zlog的全局分类表里面找到分类,用于以后输出日志。 |
void zlog_fini(void) | 清理所有zlog API申请的内存,关闭它们打开的文件。 |
void zlog_profile(void) | 调用 `zlog_profile()` 函数会输出一个包含zlog库各个模块的统计信息的表格到标准输出(控制台) |
void zlog(zlog_category_t * category, const char *file, size_t filelen, const char *func, size_t funclen, long line, int level, const char *format, ...); |
增加一条新日志。 zlog_category_t * category:分类标识 |
zlog_fatal(cat, format, …) | 打印fata级别的消息 |
zlog_error(cat, format, …) | 打印error级别的消息 |
zlog_warn(cat, format, …) | 打印warn级别的消息 |
zlog_notice(cat, format, …) | 打印notice级别的消息 |
zlog_info(cat, format, …) | 打印info级别的消息 |
zlog_debug(cat, format, …) | 打印debug级别的消息 |
zlog(cat, __FILE__, sizeof(__FILE__)-1,__func__, sizeof(__func__)-1, __LINE__,ZLOG_LEVEL_FATAL, format, args...)
typedef enum {
ZLOG_LEVEL_DEBUG = 20,
ZLOG_LEVEL_INFO = 40,
ZLOG_LEVEL_NOTICE = 60,
ZLOG_LEVEL_WARN = 80,
ZLOG_LEVEL_ERROR = 100,
ZLOG_LEVEL_FATAL = 120
} zlog_level;
zlog_fatal
zlog_error
zlog_warn
zlog_notice
zlog_info
zlog_debug
这些函数不返回. 如果有错误发生, 详细错误会被写在由环境变量ZLOG_PROFILE_ERROR指定的错误日志里面.
配置文件
完整的配置文件*.conf 配置文件具体内容如下:
[global]
strict init = true
reload conf period = 60
buffer min = 1024
buffer max = 2MB # 0表示不设最大值
rotate lock file = /tmp/zlog.lock
default format = "%d.%us %-6V (%c:%F:%L) - %m%n"
file perms = 600
[levels]
TRACE = 30, LOG_DEBUG
[formats]
simple = "%m%n"
normal = "%d %m%n"
[rules]
default.* >stdout; simple
*.* "%12.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;
配置文件参数 | 说明 |
strict init |
true:zlog_init()将严格检查所有的格式和规则,任何错误都会导致zlog_init()失败并返回-1; false:zlog_init()将忽略错误的格式和规则。 |
reload conf period |
zlog能在一段时间后,自动重载配置文件。重载的间隔以每进程写日志的次数来定义。当写日志次数到了一定值后,内会将会调用zlog_reload()进行重载。每次zlog_reload()或zlog_init()后重新计数累加。因为zlog_reload()是原子的,重载失败继续用当前的配置信息,所以自动重载是(线程)安全的。 默认值0,标识自动重载关闭。 |
buffer |
zlog在堆上为每个线程申请缓存,"buffer min"是单个缓存最小值,zlog_init()申请这个长度的内存。如果单条日志长度 > 缓存大小,缓存会自动扩充,直到"buffer max"。单条日志长度 > "buffer max"时,该日志就会被截断。 如果"buffer max"值为0,表示不限制缓存,每次扩充为原来2倍,直到进程用完所有内存。 |
rotate lock file | 指定一个锁文件,用来保证多进程情况下日志安全转档。zlog会在zlog_init()时,以读写权限打开该文件 |
file perms | 指定了创建日志文件的缺省访问权限,表示只允许当前用户读写 |
[levels] |
可选。除了支持系统默认的几个日志等级:DEBUG,INFO,NOTICE,WARN,ERROR,FATAL。zlog还支持用户自定义日志等级。 语法: 自定义的等级数,必须在[1, 253]之间 |
[formats] |
"%d(%m-%d %T) %-8V [%p:%F:%L] %m%n"
|
[rules] |
aa.debug 代码内等级 >= debug |
|
|
|
rules的规则:
- 标准输出 >stdout
- 标准错误输出 >stderr
- 管道输出
*.* | /usr/bin/cronolog /www/logs/example_%Y%m%d.log ; normal
- 文件
*.* "%T.log" 每个线程一个日志,在程序运行的目录下
*.* "%E(HOME)/log/aa.%p.%d(%F).log",1GB * 5 输出到有进程号区分的日志,每天,在$HOME/log目录,每1GB转档一次,保持5个日志文件。
aa_.* "/var/log/%c.log" aa_及下级分类,每个分类一个日志
- 文件转档
因为日志文件过大,可能导致系统硬盘被撑爆;或者,单个日志文件过大,导致grep需要花费很多时间来查找需要匹配的日志、
按固定时间切分日志
*.* "aa.%d(%F).log"
按日志大小切分
*.* "aa.log", 10MB * 7
该配置是Rolling的情况,每次aa.log超过10MB的时候,会这样做重命名:
aa.log.2 -> aa.log.3
aa.log.1 -> aa.log.2
aa.log.0 -> aa.log.1
aa.log -> aa.log.0
*.* "aa.log", 10MB * 0 ~ "aa.log.#r"
逗号后,第一个参数表示文件达到多大后,开始进行转档;
第二个参数表示保留多少个存档文件(0表示不删除任何存档文件);
第三个参数表示转档的文件名,其中#r表示存档文件的序号,r是rolling的缩写。还可以放#s,s是sequence缩写。转档文件名必须包含#r或#s。
按日志大小切分,但同时加上时间标签
*.* "aa.log", 100MB ~ "aa-%d(%Y%m%d).#2s.log"
自定义等级
修改配置文件
[levels]
TRACE = 30, LOG_DEBUG
创建一个.h文件
test_level.h
#ifndef __test_level_h
#define __test_level_h
#include "zlog.h"
enum {
ZLOG_LEVEL_TRACE = 30,
/* must equals conf file setting */
};
#define zlog_trace(cat, format, ...) \
zlog(cat, __FILE__, sizeof(__FILE__)-1, \
__func__, sizeof(__func__)-1, __LINE__, \
ZLOG_LEVEL_TRACE, format, ## __VA_ARGS__)
#endif
这样zlog_trace就能在.c文件里面调用了
example
test_hello.c
/*
* This file is part of the zlog Library.
*
* Copyright (C) 2011 by Hardy Simpson <HardySimpson1984@gmail.com>
*
* Licensed under the LGPL v2.1, see the file COPYING in base directory.
*/
#include <stdio.h>
#include "zlog.h"
int main(int argc, char** argv)
{
int rc;
zlog_category_t *zc;
rc = zlog_init("3test_hello.conf");
if (rc) {
printf("init failed\n");
return -1;
}
zc = zlog_get_category("my_cat");
#调用`zlog_get_category`函数获取名为“my_cat”的分类对象,并将其存储在变量zc中。如果该分类对象尚未创建,则将自动创建一个名为“mycat”的默认分类对象
if (!zc) {
printf("get cat fail\n");
zlog_fini();
return -2;
}
zlog_debug(zc, "zlog_debug");
zlog_info(zc, "zlog_info");
zlog_notice(zc, "zlog_notice");
zlog_warn(zc, "zlog_warn");
zlog_error(zc, "zlog_error");
zlog_fatal(zc, "zlog_fatal");
zlog_fini();
return 0;
}
test_hello.conf
[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 = "%d.%ms %m%n"
simple2 = "%d(%F) %m%n"
simple3 = "%d(%m-%d) %T %m%n"
simple4 = "%d %m%n"
simple5 = "%d [%V] [%p-%F-%L] %m%n "
[rules]
my_cat.FATAL >stderr;
my_cat.FATAL >stderr;simple
my_cat.FATAL >stderr;simple2
my_cat.FATAL >stderr;simple3
my_cat.FATAL >stderr;simple4
my_cat.FATAL >stderr;simple5
my_cat.DEBUG "%T.log";
my_cat.FATAL "/var/log/test.%p.%d(%F).log",10MB * 5
输出:
# ./test_hello
2023-06-16 15:02:57.950838 FATAL (my_cat:test_hello.c:35) - zlog_fatal
2023-06-16 15:02:57.950 zlog_fatal
2023-06-16 zlog_fatal
06-16 139885687220032 zlog_fatal
2023-06-16 15:02:57 zlog_fatal
2023-06-16 15:02:57 [FATAL] [67085-test_hello.c-35] zlog_fatal
# cat 139885687220032.log
2023-06-16 15:02:57.950794 DEBUG (my_cat:test_hello.c:30) - zlog_debug
2023-06-16 15:02:57.950828 INFO (my_cat:test_hello.c:31) - zlog_info
2023-06-16 15:02:57.950832 NOTICE (my_cat:test_hello.c:32) - zlog_notice
2023-06-16 15:02:57.950834 WARN (my_cat:test_hello.c:33) - zlog_warn
2023-06-16 15:02:57.950836 ERROR (my_cat:test_hello.c:34) - zlog_error
2023-06-16 15:02:57.950838 FATAL (my_cat:test_hello.c:35) - zlog_fatal
# cat //log/test.67085.2023-06-16.log
2023-06-16 15:02:57.950838 FATAL (my_cat:test_hello.c:35) - zlog_fatal
日志格式化字符
转换字符 | 效果 | 实例 |
%c | 分类名 | aa_bb |
%d() |
打印日志的时间。后面要跟一对小括号(),内含说明具体的日期格式。 就像%d(%F)或%d(%m-%d %T)。 |
%d(%F) 2022-12-01 %d(%m-%d %T) 12-01 17:17:42 %d(%T) 17:17:42.035 %d 2022-02-14 17:03:12 |
%E() | 获取环境变量的值 | %E(USER) martin |
%ms |
毫秒,3位数字字符串 取自gettimeofday(2) |
13 |
%us |
微秒,6位数字字符串 取自gettimeofday(2) |
2323 |
%F |
源代码文件名,来源于__FILE__宏。某些编译器,__FILE__是绝对路径, 可用%f去掉目录只保留文件名,或编译器有选项可用调节 |
test_hello.c 或某些编译器下,/home/zlog/src/test/test_hello.c |
%f | 源代码文件名,输出%F最后一个'/'后面的部分。会有一定性能损失。 | test_hello.c |
%H | 主机名,来源于gethostname(2) | zlog-dev |
%L | 源代码行号,来源于__LINE__宏 | 125 |
%m | 用户日志,用户从zlog接口输入的日志(内容) | hello, zlog |
%M | MDC(mapped diagnostic context),每个线程一张键值对表,输出键相对应的值。后面必需跟一对小括号()内含键。例如,%M(clientNumber),clientNumber。可参见【MDC】 | %M(clientNumber) 123456 |
%n | 换行符,目前还不支持Windows换行符 | \n |
%p | 进程ID,来源于个getpid() | |
%U | 调用函数名,源于__func__(C99)或__FUNCTION__(gcc) | main |
%V | 日志级别,大写 | INFO |
%v | 日志级别,小写 | info |
%t |
16进制表示线程ID,来源于phtread_self() "0x%x", (unsigned int) pthread_t |
0xba01e70 |
%T |
相当于%t,不过以长整型表示 "%lu", (unsinged long)pthread_t |
1.40633E+14 |
%% | 一个百分号` | % |
%[其他字符] | 解析为错误,zlog_init()将会失败 | |
宽度修饰符 | 左对齐 | 最小字段宽度 | 最大字段宽度 | 附注 |
---|---|---|---|---|
%20c | 否 | 20 | 无 | 左补空格,如果分类名 < 20个字符 |
%-20c | 是 | 20 | 无 | 右补空格,如果分类名 < 20个字符 |
%.30c | 无 | 无 | 30 | 如果分类名 > 30个字符,取前30个字符,去掉后面的 |
%20.30c | 否 | 20 | 30 | 如果分类名 < 20个字符,左补齐空格。如果在20~30之间,按原样输出。如果 > 30个字符,取前30个,去掉后面的 |
%-20.30c | 是 | 20 | 30 | 如果分类名 < 20个字符,右补齐空格。如果在20~30之间,按原样输出。如果 > 30个字符,取前30个,去掉后面的 |