【嵌入式学习-Zlog】Zlog日志框架学习

Zlog日志框架

Zlog介绍

Zlog是一个高可靠性、高性能、线程安全、灵活、概念清晰的纯C日志函数库。它支持日志分级、切片、自定义格式等操作。

以下是对Zlog的简单介绍:

  • Zlog是一个高可靠性、高性能(笔记本上达到25万条日志每秒)、线程安全、灵活、概念清晰的纯C日志函数库。
  • 它支持日志分级、切片、自定义格式等操作。
  • Zlog具有三个重要的概念:分类(Category)、规则(Rule)和格式(Format)。
    • 分类(Category)用于区分不同的输入,可以根据需要获取不同分类名的category来输出不同分类的日志,用于不同的目的。
    • 格式(Format)用来描述输出日志的格式,比如是否带有时间戳,是否包含文件位置信息等。
    • 规则(Rule)则是把分类、级别、输出文件和格式组合起来,决定一条代码中的日志是否输出,输出到哪里,以什么格式输出。
  • Zlog的行为大部分取决于配置文件,比如把日志打到哪里去,用什么格式,怎么转档,都由配置文件来决定。

Zlog使用方法

以下是使用Zlog框架的步骤:

  1. 安装Zlog库:使用git获取Zlog库,然后进行编译和安装。
  2. 引入头文件:在代码开头增加#include "zlog.h"
  3. 初始化Zlog:使用zlog_init函数从配置文件中读取配置信息到内存。
  4. 获取分类:使用zlog_get_category函数从全局分类表中找到分类,用于以后输出日志。
  5. 记录日志:使用zlog函数增加一条新日志。

下面是一个简单的示例代码:

#include <stdio.h>
#include <stdlib.h>
#include "zlog.h"

zlog_category_t *g_zc;

int main() {
    int rc;
    rc = zlog_init("log.ini");
    if (rc) {
        printf("初始化失败\n");
        exit(-1);
    }
    g_zc = zlog_get_category("zlogdemo");
    if (!g_zc) {
        printf("获取分类失败\n");
        zlog_fini();
        exit(-2);
    }
    zlog_info(g_zc, "Zlog info message!");
    zlog_warn(g_zc, "Zlog warn message!");
    zlog_error(g_zc, "Zlog error message!");
    zlog_fini();
}

zlogdemo是一个分类名称,用于标识日志的输出. 在示例代码中,通过调用zlog_get_category函数,我们从全局分类表中获取了名为zlogdemo的分类. 这个分类用于以后输出日志.

至于具体内容,示例代码中的内容是一个简单的C语言程序,使用了Zlog框架记录了三条日志信息:info、warn和error. 这些日志信息将被写入到配置文件中指定的日志文件中. 示例代码中的配置文件log.ini定义了日志的格式和输出方式.

以下是示例代码中的log.ini文件的具体内容:

#DEBUG = 20, LOG_DEBUG
#INFO = 40, LOG_INFO
#NOTICE = 60, LOG_NOTICE
#WARN = 80, LOG_WARNING
#ERROR = 100, LOG_ERR
#FATAL = 120, LOG_ALERT
#UNKNOWN = 254, LOG_ERR

[global]
default format = "%d.%us %-6V (%F:%L) - %m%n"

[rules]
zlogdemo.info "../log/zlogdemo.log", 1 MB ~ "../log/zlogdemo-%d (%Y%m%d).#2s.log"
zlogdemo.info >stdout;

基本原理

直接上代码

#include <stdio.h>
#include <stdarg.h>

#define OPEN_LOG 1  // 定义日志是否开始
#define LOG_LEVEL LOG_INFO  //定义日志开启的等级


// 定义一个log等级的枚举类型
typedef enum{
    LOG_DEBUG =0,
    LOG_INFO,
    LOG_WARN,
    LOG_ERROR,
}E_LOGLEVEL;

// 根据level等级返回对应的日志等级名
char * EM_LOGLevelGet(const int level){
    if(level == LOG_DEBUG){
        return "DEBUG";
    }else if(level == LOG_INFO){
        return "INFO";
    }else if(level == LOG_WARN){
        return "WARN";
    }else if(level == LOG_ERROR){
        return "ERROR";
    }
    return "UNKNOW";
}


void EM_LOG(const level, const char *fun, const int line, const char *fmt, ...){
    #if OPEN_LOG  // 根据OPEN_LOG是否开始来开始LOG模式
    va_list arg; 
    va_start(arg, fmt);
    char buf[1+vsnprintf(NULL,0,fmt,arg)];//获取整体的字符串所需要占的大小,并申请一个同等大小的buf缓存,加一是为了存结束符。
    vsnprintf(buf,sizeof(buf), fmt, arg); // 将内容存储到buf中
    va_end(arg);
    if(level >= LOG_LEVEL) printf("[%s] [%s %d] %s\n",EM_LOGLevelGet(level),fun,line,buf); // 等级大于LOG_LEVEL,打印日志等级、执行所处函数、所在行号、以及buf内容。
    #endif
}


#define EMlog(level, fmt...) EM_LOG(level, __FUNCTION__, __LINE__, fmt);
void main(){
    int a = 10, b = 20;
    // EM_LOG(LOG_WARN, __FUNCTION__, __LINE__, "A = %d", a);
    // EMlog(LOG_DEBUG,"App start");
    EMlog(LOG_WARN,"A = %d", a);
}

当然我们也可以把这把EMLog封装成一个方法,只需要引入log.h头文件,即可使用。代码如下

log.h

#include <stdio.h>
#include <stdarg.h>

#define OPEN_LOG 1  // 定义日志是否开始
#define LOG_LEVEL LOG_DEBUG  //定义日志开启的等级


// 定义一个log等级的枚举类型
typedef enum{
    LOG_DEBUG =0,
    LOG_INFO,
    LOG_WARN,
    LOG_ERROR,
}E_LOGLEVEL;


void EM_LOG(const int level, const char *fun, const int line, const char *fmt, ...);
#define EMlog(level, fmt...) EM_LOG(level, __FUNCTION__, __LINE__, fmt);

log.c

#include <stdio.h>
#include <stdarg.h>
#include "log.h"



// 根据level等级返回对应的日志等级名
char * EM_LOGLevelGet(const int level){
    if(level == LOG_DEBUG){
        return "DEBUG";
    }else if(level == LOG_INFO){
        return "INFO";
    }else if(level == LOG_WARN){
        return "WARN";
    }else if(level == LOG_ERROR){
        return "ERROR";
    }
    return "UNKNOW";
}


void EM_LOG(const int level, const char *fun, const int line, const char *fmt, ...){
    #if OPEN_LOG  // 根据OPEN_LOG是否开始来开始LOG模式
    va_list arg; 
    va_start(arg, fmt);
    char buf[1+vsnprintf(NULL,0,fmt,arg)];//获取整体的字符串所需要占的大小,并申请一个同等大小的buf缓存,加一是为了存结束符。
    vsnprintf(buf,sizeof(buf), fmt, arg); // 将内容存储到buf中
    va_end(arg);
    if(level >= LOG_LEVEL) printf("[%s] [%s %d] %s\n",EM_LOGLevelGet(level),fun,line,buf); // 等级大于LOG_LEVEL,打印日志等级、执行所处函数、所在行号、以及buf内容。
    #endif
}

app.c

#include <stdio.h>
#include "log.h"



void main(){
    int a = 10, b = 20;
    // EM_LOG(LOG_WARN, __FUNCTION__, __LINE__, "A = %d", a);
    EMlog(LOG_DEBUG,"App start");
    EMlog(LOG_WARN,"A = %d", a);
}

我们只需要在所处文件的位置打开命令行,执行

gcc app.c log.c -o app

生成 app.exe,之后直接执行即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值