syslog

syslog#

在改动开源模块时,每个开源项目都有自己的日志系统,我们可能会花很长时间去分析它们的日志系统的流程是怎么样的。但是有一个更加简单地方法,就是我们覆盖掉原来的日志模块,重新定义符合自己习惯的日志系统。等待调试完成后,再把自己定义的日志去掉,恢复开源代码原来的样子。

示例请参考:https://gitee.com/zhyantao/misc/blob/master/leetcode/cpp/include/debug.h

/////////////////////////////////////  ONLY FOR DEBUG USE  /////////////////////////////////////
#ifndef DEBUG_H
#define DEBUG_H

#include <stdio.h>
#include <time.h>
#include <string.h>

// 日志级别
typedef enum {
    LOG_LEVEL_DEBUG = 0,
    LOG_LEVEL_INFO,
    LOG_LEVEL_WARN,
    LOG_LEVEL_ERROR,
    LOG_LEVEL_FATAL
} LogLevel;

// 默认日志级别
#ifndef LOG_LEVEL
#define LOG_LEVEL LOG_LEVEL_DEBUG
#endif

// 将日志级别转为字符串
static inline const char* log_level_to_str(LogLevel level) {
    switch (level) {
    case LOG_LEVEL_DEBUG: return "DEBUG";
    case LOG_LEVEL_INFO: return "INFO ";
    case LOG_LEVEL_WARN: return "WARN ";
    case LOG_LEVEL_ERROR: return "ERROR";
    case LOG_LEVEL_FATAL: return "FATAL";
    default: return "UNKWN";
    }
}

// 获取时间戳
static inline void get_timestamp(char* buffer, size_t size) {
    time_t t = time(NULL);
    struct tm tm;
    localtime_r(&t, &tm); // 线程安全版本
    strftime(buffer, size, "%Y-%m-%d %H:%M:%S", &tm);
}

// 带日志级别的日志宏(使用字符串表示级别)
#define LOG_WITH_LVL(level, fmt, ...)                                                         \
    do {                                                                                      \
        if (level >= LOG_LEVEL) {                                                             \
            char timestamp[64];                                                               \
            get_timestamp(timestamp, sizeof(timestamp));                                      \
            printf("[%s] %-5s %s:%d " fmt "\n", timestamp, log_level_to_str(level), __FILE__, \
                   __LINE__, ##__VA_ARGS__);                                                  \
        }                                                                                     \
    } while (0)

// 默认日志宏
#define LOG(fmt, ...) LOG_WITH_LVL(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__)

// https://gitlab.com/gpsd/gpsd/-/blob/release-3.25/include/gpsd.h?ref_type=tags#L1128
// 重写 GPSD_LOG(lvl, eo, ...), 将日志打印到控制台
#ifdef GPSD_LOG
#undef GPSD_LOG
#define GPSD_LOG(lvl, eo, fmt, ...) LOG_WITH_LVL(lvl, fmt, ##__VA_ARGS__)
#endif

// https://github.com/nwtime/linuxptp/blob/master/print.h#L70
// 重写 pr_debug(x...),将日志打印到控制台
#ifdef pr_debug
#undef pr_debug
// #define pr_debug(x...) LOG_WITH_LVL(LOG_LEVEL_DEBUG, x)                   /* GCC 扩展语法 (非标准) */
// #define pr_debug(...) LOG_WITH_LVL(LOG_LEVEL_DEBUG, __VA_ARGS__)          /* C99 语法 (标准) */
#define pr_debug(fmt, ...) LOG_WITH_LVL(LOG_LEVEL_DEBUG, fmt, ##__VA_ARGS__) /* 比 pr_debug(...) 更安全 */
#endif

#endif // DEBUG_H