####简介 MESA_handle_logger_new是基于开源C++日志库[easylogging++](https://github.com/muflihun/easyloggingpp)封装的新的日志库。具有以下特性: * 线程安全 * 强大的配置功能 * 保留旧接口不变,完全兼容旧程序 #### 安装方法 ``` git clone https://git.mesalab.cn/leo/MESA_handle_logger_new cd MESA_handle_logger_new //install到MESA_handle_logger_new/lib/下 make && make install //指定运行时链接的日志库为新的.so的目录 export LD_LIBRARY_PATH="xxxx" ``` #### 对外接口 * 获取日志句柄 * 为了兼容旧程序,我们保留了旧的接口,同时提供了一个新的方法用来获取句柄 * MESA_create_runtime_log_handle( )和MESA_create_runtime_log_handle_new( )中会使用一份默认的日志配置。具体内容见src/MESA_handle_logger.c中的set_default_conf( )函数 ``` /* functionality: 旧接口,用来获取日志句柄 params: file_path: 日志文件保存路径, 长度不能超过256 level: 日志文件级别,>=该级别的日志才会输出,level = {RLOG_LV_DEBUG, RLOG_LV_INFO, RLOG_LV_FATAL } returns: void*: 返回一个日志句柄 */ void *MESA_create_runtime_log_handle(const char *file_path, int level); /* functionality: 新接口,用来获取日志句柄 desc: 新接口不用显示指定日志文件路径和日志级别,可以在配置文件配置或者通过MESA_set_runtime_log_handle_opt指定 对于新程序,我们推荐使用这种方法 params: logger_id: 一个logger_id唯一标识一个日志句柄 returns: void*: 返回一个日志句柄 */ void* MESA_create_runtime_log_handle_new(const char* logger_id); ``` * 配置日志属性 * 我们提供了两种方法用来配置日志属性 * 读取配置文件 * 在代码中显式配置某个属性 ``` /* functionality: 读取日志配置文件,我们推荐使用这种方法 params: handle: 日志句柄 conf_file_path: 配置文件路径 returns: 0: 成功 -1: 失败 */ int MESA_read_runtime_log_handle_conf(void* handle, const char* conf_file_path); /* functionality: 设置某个日志属性 desc: 可配置的属性值见"可配置日志属性" params: handle: 日志句柄 level: 设置的日志级别,level = {RLOG_LV_DEBUG, RLOG_LV_INFO, RLOG_LV_FATAL } key: 配置的属性 value: 配置的属性值 returns: 0: 成功 -1: 失败 */ int MESA_set_runtime_log_handle_opt(void* handle, int level, const char* key, const char* value); ``` * 写日志 * 写日志接口保持和原来一致 ``` /* functionality: 写日志 params: handle: 日志句柄 level: 设置的日志级别,level = {RLOG_LV_DEBUG, RLOG_LV_INFO, RLOG_LV_FATAL } module: 日志所属模块 fmt: 格式化字符串,单条日志长度不能超过4096 returns: none */ void MESA_handle_runtime_log(void *handle, int level, const char *module, const char *fmt, ...); ``` * 释放句柄 * 释放句柄保持和原来一致 ``` /* functionality: 释放日志句柄 params: handle: 日志句柄 returns: none */ void MESA_destroy_runtime_log_handle(void *handle); ``` #### 可配置日志属性 | Configuration Name | Description | Value | | --- | --- | --- | | enabled | Determines whether or not corresponding level for logger is enabled | {“true”, “false”} | | to_file | Whether or not to write corresponding log to log file | {“true”, “false”} | | to_standard_output | Whether or not to write logs to standard output e.g, terminal or command prompt | {“true”, “false”} | | format | Determines format/pattern of logging for corresponding level and logger. | 如: ”[%level%datetime{%Y-%M-%d %H:%m:%s}]: %msg“ | | file_name | Determines log file (full path) to write logs to for corresponding level and logger | 如: “./log2/debug_log_%datetime{%Y-%M-%d}“ | | max_log_file_size | If log file size of corresponding level is >= specified size, log file will be truncated. | 如: “2097152” | | sub_second_precision | Specifies subsecond precision (previously called 'milliseconds width')|{“1”, “2”, “3”, “4”, “5”, “6”,}| |performance_tracking |determines whether or not performance tracking is enabled|{“true”, “false”}| | log_flush_threshold | Specifies number of log entries to hold until we flush pending log data|如: “100” | ####日志配置文件格式 * 这里仅仅以FATAL级别的配置为例,完整配置参考sample/new/sample.conf * %level, %datetime是格式化变量,运行时会变成对应的值 * GLOBAL是全局配置,作用于所有Level。其相当于一个开关。 * 若GLOBAL中配置了属性A: * Level(DEBUG,INFO,FATAL)中配置了属性A:Level使用自己配置的属性A * Level(DEBUG,INFO,FATAL)中没有配置属性A:Level使用GLOBAL中配置的属性A * 若GLOBAL中没有配置属性A: * 无论Level(DEBUG,INFO,FATAL)中是否配置属性A,属性A均不生效 ``` * GLOBAL: FORMAT = "[%level|%datetime{%Y-%M-%d %H:%M:%s}]: %msg" FILENAME = "myeasylog.log" ENABLED = true TO_FILE = true TO_STANDARD_OUTPUT = true ## SUBSECOND_PRECISION = 6 ## PERFORMANCE_TRACKING = true ## MAX_LOG_FILE_SIZE = 2097152 ## LOG_FLUSH_THRESHOLD = 100 * FATAL: FORMAT = "[%level|%datetime{%Y-%M-%d %H:%m:%s}]: %msg" ##日志内容格式 FILENAME = "./log1/fatal_log_%datetime{%Y-%M-%d}" ##日志保存路径 ENABLED = true TO_FILE = true TO_STANDARD_OUTPUT = true ##SUBSECOND_PRECISION = 6 ## 暂时用不到 ##PERFORMANCE_TRACKING = true ## 暂时用不到 ##MAX_LOG_FILE_SIZE = 2097152 ## 文件最大值,超过该值后日志文件会truncated,这里是2MB ##LOG_FLUSH_THRESHOLD = 100 ## Flush after every 100 logs, 暂时用不到 ``` ####示例程序 * 旧程序 ``` void* handle = MESA_create_runtime_log_handle("./log/sample_log", RLOG_LV_DEBUG); MESA_handle_runtime_log(handle, RLOG_LV_DEBUG, "module", "test debug log:%s", "xxxxx"); MESA_destroy_runtime_log_handle(handle); ``` * 新程序 ``` ##通过读取配置文件设置日志属性 void* handle1 = MESA_create_runtime_log_handle_new("logger_id1"); int rtn = MESA_read_runtime_log_handle_conf(handle, "./sample.conf"); MESA_handle_runtime_log(handle, RLOG_LV_DEBUG, "module_test_read_conf", "test debug log:%s", "xxxxx"); MESA_destroy_runtime_log_handle(handle1); ##通过代码中显式设置某个日志属性 void* handle2 = MESA_create_runtime_log_handle("logger_id2"); MESA_set_runtime_log_handle_opt(handle, RLOG_LV_DEBUG, "Enabled", "true"); MESA_set_runtime_log_handle_opt(handle, RLOG_LV_DEBUG, "ToFile", "true"); MESA_set_runtime_log_handle_opt(handle, RLOG_LV_DEBUG, "ToStandardOutput", "true"); MESA_set_runtime_log_handle_opt(handle, RLOG_LV_DEBUG, "Format", "[%level|%datetime{%Y-%M-%d %H:%m:%s}]: %msg"); MESA_set_runtime_log_handle_opt(handle, RLOG_LV_DEBUG, "Filename", "./log2/debug_log_%datetime{%Y-%M-%d}"); MESA_handle_runtime_log(handle, RLOG_LV_DEBUG, "module_test_set_opt", "test debug log:%s", "xxxxx"); MESA_destroy_runtime_log_handle(handle2); ``` #### F.A.Q * 对于旧的程序,如果想在不修改代码的情况下也想使用配置文件进行日志配置,可不可以呢? * 可以,在旧接口MESA_create_runtime_log_handle( )中,我们会读取 **MESA_HANDLE_LOGGER_CONF_PATH**这个环境变量。然后根据环境变量中的路径读取配置文件进行配置。 * 所以你只需要编写配置文件,然后export MESA_HANDLE_LOGGER_CONF_PATH="xxxxx"就可以使用配置文件进行配置了。 * 其中xxxx为你的配置文件所在的路径