zlog日志库(笔记) —— zlog接口(API)

引入头文件

zlog所有接口都是线程安全的,使用时只需要包含头文件

#include "zlog.h"

初始化和清理

总览

ini zlog_init(const char *confpath);
int zlog_reload(const char *confpath);
void zlog_fini(void);

接口描述

zlog_init: 从配置文件confpath读取配置信息到内存。如果confpath为NULL,会寻找环境变量ZLOG_CONF_PATH的值作为配置文件名;如果环境变量 ZLOG_CONF_PATH为空,所有日志以内置格式写到标准输出(stdout)上。每个进程只有第一次调用zlog_init()有效,后面多余调用都会失败并且不做任何事情。

zlog_reload(): 从confpath重载配置,并根据该配置文件重新计算内部的分类规则匹配、重建每个线程的缓存,并设置原有的用户自定义输出函数。可以做配置文件发生改变后调用该函数。该函数调用次数不限。如果confpath为NULL,会重载上一次zlog_init()或zlog_reload()时使用的配置文件;如果zlog_reload()失败,上一次的配置依然有效。所以zlog_reload()具有原子性。

zlog_fini(): 清理所有zlog API申请的内存,关闭它们打开的文件。使用次数不限。

返回值

如果成功,zlog_init()和zlog_reload()返回0;失败,zlog_init()和zlog_reload()返回-1。详细错误,会被写到由环境变量ZLOG_PROFILE_ERROR指定的错误日志里去。

分类(Category)操作

总览

typedef struct zlog_category_st zlog_category_t;
zlog_category_t *zlog_get_category(const char *name);

接口描述

zlog_get_category() 从zlog的全局分类表里找到分类,用于以后输出日志;如果没有的话,就新建一个。然后,函数会遍历所有的规则,寻找和cname匹配的规则并绑定。

配置文件规则中的分类名匹配cname的规律描述如下:
1)*匹配任意cname;
2)以下划线("")结尾的分类名同时匹配本级分类和下级分类,例如"aa"匹配aa, aa_, aa_bb, aa_bb_cc这几个cname;
3)不以下划线("_")结尾的分类名精确匹配cname,例如"aa_bb"匹配"aa_bb"这个cname;
4)"!"匹配目前还没有规则的cname;

每个zlog_category_t*对应的规则,在zlog_relaod()时会被自动重新计算。不用担心内存释放,zlog_fini()最后会清理一切。

返回值

如果调用成功,返回zlog_category_t的指针;如果失败,返回NULL。详细错误,会被写到由环境变量ZLOG_PROFILE_ERROR指定的错误日志里去。

写日志函数及宏

总览

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_CHECK_PRINTF(8,9);

void vzlog(zlog_category_t * category,
    const char *file, size_t filelen,
    const char *func, size_t funclen,
    long line, int level,
    const char *format, va_list args);

void hzlog(zlog_category_t * category,
    const char *file, size_t filelen,
    const char *func, size_t funclen,
    long line, int level,
    const void *buf, size_t buflen);

接口描述

3个函数是实际写日志的函数,输入的数据对应于配置文件中的%m。category来源于调用zlog_get_category()。
zlog()和vzlog()根据format输出,就像printf(3)和vprintf(3)。vzlog()相当于zlog(),不过它用一个va_list参数args,来表示可变参数列表,而不是"..."。vzlog()内部使用了va_copy宏,args内容在vzlog()后保持不变,可参考stdarg(3)。

hzlog()有些区别,它产生下面这样的输出,长度buf_len的内存buf以16进制的形式表示出来。

hex_buf_len=[5365]  
             0  1  2  3  4  5  6  7  8  9  A  B  C  D  E  F      0123456789ABCDEF
0000000001   23 21 20 2f 62 69 6e 2f 62 61 73 68 0a 0a 23 20   #! /bin/bash..#
0000000002   74 65 73 74 5f 68 65 78 20 2d 20 74 65 6d 70 6f   test_hex - tempo
0000000003   72 61 72 79 20 77 72 61 70 70 65 72 20 73 63 72   rary wrapper scr

参数file和line填写为__FILE__和__LINE__宏,用于标识日志是在哪个文件和哪一行发生的。参数func填写为__func__ (C99)或__FUNCTION__ (GCC),如果编译器不支持的话,就填写为""。

level是一个整数,应该在下面几个里面取值:

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;

每个函数都有便于使用的宏,如:

#define zlog_fatal(cat, ...) \
    zlog(cat, __FILE__, sizeof(__FILE__)-1, __func__, sizeof(__func__)-1, __LINE__, \
    ZLOG_LEVEL_FATAL, __VA_ARGS__)

由于编译器下,可变参数的使用有所区别,因此这里不展示所有编译器下的宏实现。只列出所有宏列表:

/* 便于用户调用的写日志接口(宏函数) */

/* zlog macros */
zlog_fatal(cat, format, ...)
zlog_error(cat, format, ...)
zlog_warn(cat, format, ...)
zlog_notice(cat, format, ...)
zlog_info(cat, format, ...)
zlog_debug(cat, format, ...)

/* vzlog macros */
vzlog_fatal(cat, format, args)
vzlog_error(cat, format, args)
vzlog_warn(cat, format, args)
vzlog_notice(cat, format, args)
vzlog_info(cat, format, args)
vzlog_debug(cat, format, args)

/* hzlog macros */
hzlog_fatal(cat, buf, buf_len)
hzlog_error(cat, buf, buf_len)
hzlog_warn(cat, buf, buf_len)
hzlog_notice(cat, buf, buf_len)
hzlog_info(cat, buf, buf_len)
hzlog_debug(cat, buf, buf_len)

返回值

无返回值。如果有错误发生,详细错误会被写在由环境变量ZLOG_PROFILE_ERROR指定的错误日志里面。

MDC操作

总览

int zlog_put_mdc(const char *key, const char *value);
char *zlog_get_mdc(const char *key);
void zlog_remove_mdc(const char *key);
void zlog_clean_mdc(void);

接口描述

MDC(Mapped Diagnostic Context) 是一个线程拥有的键-值表,和分类没什么关系。
key-value是字符串,长度不能超过MAXLEN_PATH(1024);如果超过,则会被截断。
记住这个表是和线程绑定到,每个线程都有自己的表,所以在一个线程内的调用不会影响其他线程,也就是说对其操作是线程安全的。

返回值

zlog_put_mdc()成功返回0,失败返回-1。
zlog_get_mdc成功返回value的指针;失败返回没有相应的key,则返回NULL。
如果有错误发生,详细错误会被写在由环境变量ZLOG_PROFILE_ERROR指定的错误日志里面。

dzlog接口

总览

int dzlog_init(const char *confpath, const char *cname);
int dzlog_set_category(const char *cname);
void dzlog(const char *file, size_t filelen,
        const char *func, size_t funclen,
        long line, int level,
        const char *format, ...);
void vdzlog(const char *file, size_t filelen,
        const char *func, size_t funclen,
        long line, int level,
        const char *format, va_list args);
void hdzlog(const char *file, size_t filelen,
        const char *func, size_t funclen,
        long line, int level,
        const void *buf, size_t buflen);

接口描述

dzlog是忽略分类(zlog_category_t)的一组简单zlog接口。它采用内置的一个默认分类,该分类置于锁的保护之下。这些接口也是线程安全的。忽略了分类,意味着用户不需要操心创建、存储、传输zlog_category_t类型的变量。当然,也可以在用dzlog接口的同时,用一般的zlog接口函数。

dzlog_init()和zlog_init()一样做初始化,就是多需要一个默认分类名cname的参数。zlog_reload()、zlog_fini()可以和以前一样使用,用来刷新配置,或者清理。

dzlog_set_category()用来改变默认分类用的。上一个分类会被替换成新的。同样不用担心内存释放问题,zlog_fini()最后会做清理。

dzlog相关便捷宏,也定义中zlog.h里面。

/* 采用内置的默认分类 */

dzlog_fatal(format, ...)
dzlog_error(format, ...)
dzlog_warn(format, ...)
dzlog_notice(format, ...)
dzlog_info(format, ...)
dezlog_debug(format, ...)

vdzlog_fatal(format, args)
vdzlog_error(format, args)
vdzlog_warn(format, args)
vdzlog_notice(format, args)
vdzlog_info(format, args)
vdzlog_debug(format, args)

hdzlog_fatal(buf, buf_len)
hdzlog_error(buf, buf_len)
hdzlog_warn(buf, buf_len)
hdzlog_noticebuf, buf_len)
hdzlog_info(buf, buf_len)
hdzlog_debug(buf, buf_len)

返回值

成功调用,dzlog_init()和dzlog_set_category()返回0;失败时,dzlog_init()和dzlog_set_category()返回-1。详细错误会被写在ZLOG_PROFILE_ERROR指定错误日志里面。

用户自定义输出

总览

typedef struct zlog_msg_s {
    char *buf;
    size_t len;
    char *path;
} zlog_msg_t;
typedef int (*zlog_record_fn)(zlog_msg_t *msg);

int zlog_set_record(const char *name, zlog_record_fn record);

接口描述

zlog允许用户自定义输出函数。输出函数需要绑定到某条特殊规则(rules)上。例:

[rules]
*.*      $name, "record path %c %d"; simple

zlog_set_record()做绑定动作。规则中,输出段有$name,会被用来做用户自定义输出。输出函数record。该函数需要为zlog_record_fn格式。

zlog_msg_t结构的各成员描述如下:

  • path 来自规则的逗号后的字符串,该字符串会被动态解析,输出当前path,就像动态文件路径一样;
  • buf和len是zlog格式化后的日志信息和长度;

所有zlog_set_record()做的绑定,在zlog_reload()使用后继续有效。

返回值

成功调用时,返回0;失败返回-1。详细错误会被写在ZLOG_PROFILE_ERROR指定错误日志里面。

调试和诊断

总览

void zlog_profile(void);

接口描述

环境变量ZLOG_PROFILE_ERROR指定zlog本身的错误日志。
环境变量ZLOG_PROFILE_DEBUG指定zlog本身的调试日志。
zlog_profile()打印所有内存中的配置信息到ZLOG_PROFILE_ERROR。可以把这个和配置文件比较,看看有没有问题。

原文链接: https://www.cnblogs.com/fortunely/p/16686346.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍;

也有高质量的技术群,里面有嵌入式、搜广推等BAT大佬

    zlog日志库(笔记) —— zlog接口(API)

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/402463

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年4月21日 上午11:04
下一篇 2023年4月21日 上午11:04

相关推荐