#ifndef LOG4_H #define LOG4_H #if defined(__cplusplus) && __cplusplus >= 201103L #define LOG_TLS_SPEC thread_local #else /* C 或旧编译器,走 GCC 扩展 */ #define LOG_TLS_SPEC __thread #endif /* ★统一的对外声明(别在其他头/源里再声明不同版本!) */ extern LOG_TLS_SPEC int g_log_code_tls; #ifdef __cplusplus #include #include //防止#include 里的冲突 #ifdef min #undef min #endif #ifdef max #undef max #endif //防止#include 里的冲突 #include "logger.h" #include #include "loggingmacros.h" #include "appender.h" #define LOGTYPE_COM 1 #define LOGTYPE_DATA 2 struct TypedLogger { log4cplus::Logger logger; int logtype; TypedLogger(); TypedLogger(const log4cplus::Logger& l, int t); }; struct DebugSwitch { bool debug_open; std::set targets; int min_level; std::map type_enable; DebugSwitch(); void open(); void close(); void set_target(const std::string& name); void set_level(int level); void enable_type(int type); void disable_type(int type); bool match(const std::string& logger_name, int level, int logtype); }; extern std::map logger_map; extern DebugSwitch g_debug_switch; extern void send_reply_to_queue(const std::string& guid, const std::string& step, const std::string& result); //std::string get_front_type_from_subdir(); // 不带 Appender 的版本 log4cplus::Logger init_logger(const std::string& full_name, const std::string& file_dir, const std::string& base_file); // 带 Appender 的版本 log4cplus::Logger init_logger(const std::string& full_name, const std::string& file_dir, const std::string& base_file, log4cplus::SharedAppenderPtr fileAppender); void process_log_command(const std::string& id, const std::string& level, const std::string& grade, const std::string& logtype_str); void update_log_entries_countdown(); extern "C" { #endif void remove_loggers_by_terminal_id(const std::string& terminal_id_cstr); void init_logger_process(); void init_loggers(); void init_loggers_bydevid(const std::string& dev_id); void log_debug(const char* key, const char* msg); void log_info(const char* key, const char* msg); void log_warn(const char* key, const char* msg); void log_error(const char* key, const char* msg); void send_reply_to_queue_c(const char* guid, const char* step, const char* result); void format_log_msg(char* buf, size_t buf_size, const char* fmt, ...); // ====================== ★新增:线程局部变量透传 code ====================== // 说明:使用编译器的 TLS(__thread)保存当前日志的 code 值。 // 在每次打日志前写入,打完后恢复,Appender 读取该值写入 JSON。 // ====================== ★新增结束 ====================== typedef enum LogCode { LOG_CODE_OTHER = 99, /* 其他类型 */ LOG_CODE_LEDGER = 100, /* 台账类型 */ LOG_CODE_RPTINIT = 101, /* 报告初始化 */ LOG_CODE_ICD_AND_DOWNLOAD = 200, /* ICD 和文件下载类型 */ LOG_CODE_TRANSIENT = 300, /* 暂态发生 */ LOG_CODE_TRANSIENT_COMM = 301, /* 暂态接口 */ LOG_CODE_COMTRADE_FILE = 302, /* 录波文件(Comtrade) */ LOG_CODE_MQ = 400, /* MQ发送 */ LOG_CODE_RT_DATA = 401, /* 实时数据 */ LOG_CODE_LEDGER_UPDATE = 402, /* 台账更新 */ LOG_CODE_PROCESS_CONTROL = 403, /* 进程控制 */ LOG_CODE_RECALL = 404, /* 补招相关 */ LOG_CODE_LOG_REQUEST = 405, /* 日志请求 */ LOG_CODE_REPORT = 500, /* 报告处理 */ LOG_CODE_COMM = 600, /* 通讯状态 */ LOG_CODE_SPACE_ALARM = 700, /* 空间告警 */ LOG_CODE_DEV_ALARM = 800 /* 装置告警 */ } LogCode; // ====================== 日志宏区域 ====================== // 原始不带 code 的实现(兼容/复用) #define DIY_LOG(LEVEL_FUNC, KEY, ...) \ do { \ char buf[256]; \ format_log_msg(buf, sizeof(buf), __VA_ARGS__); \ LEVEL_FUNC(KEY, buf); \ } while (0) // ★新增:带 code 的实现(C/C++ 通用,使用 TLS 保存/恢复) #define DIY_LOG_CODE(LEVEL_FUNC, KEY, LEVEL_INT, CODE_INT, ...) \ do { \ /* 备份并设置本次日志 code */ \ int __old_code__ = g_log_code_tls; \ g_log_code_tls = static_cast(CODE_INT); \ \ /* 组装消息 */ \ char __msg_buf__[256]; \ format_log_msg(__msg_buf__, sizeof(__msg_buf__), __VA_ARGS__); \ \ /* 将 KEY 规范化为字符串(兼容 const char* / std::string 等) */ \ std::ostringstream __oss_key__; \ __oss_key__ << (KEY); \ std::string __key_raw__ = __oss_key__.str(); \ \ /* 根据 LEVEL_INT 构造最终 key */ \ char __key_buf__[256]; \ switch (static_cast(LEVEL_INT)) { \ case 0: \ std::snprintf(__key_buf__, sizeof(__key_buf__), "process"); \ break; \ case 1: \ std::snprintf(__key_buf__, sizeof(__key_buf__), \ "terminal.%s", __key_raw__.c_str()); \ break; \ case 2: \ std::snprintf(__key_buf__, sizeof(__key_buf__), \ "monitor.%s", __key_raw__.c_str()); \ break; \ default: \ std::snprintf(__key_buf__, sizeof(__key_buf__), "%s", \ __key_raw__.c_str()); \ break; \ } \ \ /* 输出日志 */ \ LEVEL_FUNC(__key_buf__, __msg_buf__); \ \ /* 恢复旧值 */ \ g_log_code_tls = __old_code__; \ } while (0) // ★修改:默认宏改为 code=0(兼容原有用法) #define DIY_ERRORLOG(KEY, ...) DIY_LOG_CODE(log_error, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0 #define DIY_WARNLOG(KEY, ...) DIY_LOG_CODE(log_warn, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0 #define DIY_INFOLOG(KEY, ...) DIY_LOG_CODE(log_info, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0 #define DIY_DEBUGLOG(KEY, ...) DIY_LOG_CODE(log_debug, KEY, 0, LOG_CODE_OTHER,__VA_ARGS__) // ★修改:默认 code=0 // ★新增:显式传入 code 的便捷宏 // 用法示例:DIY_WARNLOG_CODE(full_key_m_c, warn_recallstart, "【WARN】监测点:%s ...", ...); #define DIY_ERRORLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_error, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增 #define DIY_WARNLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_warn, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增 #define DIY_INFOLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_info, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增 #define DIY_DEBUGLOG_CODE(KEY, LEVEL_INT,CODE_INT, ...) DIY_LOG_CODE(log_debug, KEY, LEVEL_INT, CODE_INT, __VA_ARGS__) // ★新增 // ====================== 日志宏区域 ====================== #ifdef __cplusplus } #endif #endif // LOG4_H