123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- #include "Log4CPP.h"
- #include <sys/stat.h> // 用于目录创建
- #include <cctype> // 用于字符串转换
- #include <algorithm> // 用于字符串转换
- #include <cstdio>
- #include <ctime>
- #include <cstdarg>
- #include <vector>
- #include <sstream>
- #include <iomanip>
- #include <cstring> // 添加strerror支持
- #include <memory>
- #include "ResDataObject.h"
- Log4CPP* Log4CPP::instance = NULL;
- std::string Log4CPP::_screenInfo = "screenInfo";
- std::string Log4CPP::_logName = "log";
- // 初始化配置
- LogConfig Log4CPP::config;
- log4cpp::Category& root = log4cpp::Category::getRoot();
- log4cpp::Category& Log4CPP::logCat = root.getInstance(Log4CPP::_logName);
- log4cpp::Category& Log4CPP::coutCat = root.getInstance(Log4CPP::_screenInfo);
- // 优先级
- log4cpp::Priority::PriorityLevel Log4CPP::coutPri = COUNT_PRITY; // 控制台
- log4cpp::Priority::PriorityLevel Log4CPP::logPri = LOG_PRITY; // 本地文件
- log4cpp::PatternLayout* Log4CPP::logLayout = NULL;
- log4cpp::PatternLayout* Log4CPP::screenLayout = NULL;
- log4cpp::PatternLayout* Log4CPP::logLayout2 = NULL; /* 回卷用这个 */
- log4cpp::FileAppender* Log4CPP::logFile = NULL;//文件日志输入
- log4cpp::OstreamAppender* Log4CPP::logScreen = NULL;//屏幕日志输入
- log4cpp::RollingFileAppender* Log4CPP::rollLogFile; /* 回卷用这个 */
- // 创建目录函数
- bool Log4CPP::createDirectory(const std::string& path) {
- struct stat st;
- if (stat(path.c_str(), &st) == 0) {
- if (S_ISDIR(st.st_mode)) {
- return true; // 目录已存在
- }
- return false; // 存在同名文件
- }
- // 递归创建目录
- size_t pos = 0;
- do {
- pos = path.find_first_of('/', pos + 1);
- std::string subdir = path.substr(0, pos);
- if (mkdir(subdir.c_str(), 0755) != 0) {
- if (errno != EEXIST) {
- std::cerr << "Failed to create directory: " << subdir
- << " Error: " << strerror(errno) << std::endl;
- return false;
- }
- }
- } while (pos != std::string::npos);
- return true;
- }
- // 解析日志级别
- log4cpp::Priority::PriorityLevel Log4CPP::parseLogLevel(const std::string& level) {
- std::string upper;
- std::transform(level.begin(), level.end(), std::back_inserter(upper), ::toupper);
- if (upper == "EMERG") return log4cpp::Priority::EMERG;
- if (upper == "FATAL") return log4cpp::Priority::FATAL;
- if (upper == "ALERT") return log4cpp::Priority::ALERT;
- if (upper == "CRIT") return log4cpp::Priority::CRIT;
- if (upper == "ERROR") return log4cpp::Priority::ERROR;
- if (upper == "WARN") return log4cpp::Priority::WARN;
- if (upper == "NOTICE") return log4cpp::Priority::NOTICE;
- if (upper == "INFO") return log4cpp::Priority::INFO;
- if (upper == "DEBUG") return log4cpp::Priority::DEBUG;
- if (upper == "NOTSET") return log4cpp::Priority::NOTSET;
- std::cerr << "Unknown log level: " << level << ". Using DEBUG as default." << std::endl;
- return log4cpp::Priority::DEBUG;
- }
- // 加载配置文件
- bool Log4CPP::loadConfig(const std::string& configFile) {
- // 读取基本配置
- ResDataObject temp;
- if (!temp.loadFile(configFile.c_str())) {
- std::cerr << "Failed to load log config file: " << configFile
- << ". Using default settings." << std::endl;
- return false;
- }
- // 获取log_config节点
- ResDataObject LogConfig = temp["log_config"];
- // 读取基本配置 - 修复变量名错误
- if (LogConfig.GetKeyCount("root_level")) {
- config.root_level = (std::string)LogConfig["root_level"];
- std::cout << "Log4CPP::loadConfig: config.root_level:" << config.root_level << std::endl;
- }
- if (LogConfig.GetKeyCount("log_dir")) {
- config.log_dir = (std::string)LogConfig["log_dir"];
- std::cout << "Log4CPP::loadConfig: config.log_dir:" << config.log_dir << std::endl;
- }
- if (LogConfig.GetKeyCount("history_dir")) {
- config.history_dir = (std::string)LogConfig["history_dir"];
- std::cout << "Log4CPP::loadConfig: config.history_dir:" << config.history_dir << std::endl;
- }
- if (LogConfig.GetKeyCount("max_file_size")) {
- config.max_file_size = (size_t)(int)LogConfig["max_file_size"];
- std::cout << "Log4CPP::loadConfig: config.max_file_size:" << config.max_file_size << std::endl;
- }
- if (LogConfig.GetKeyCount("max_backups")) {
- config.max_backups = (int)LogConfig["max_backups"];
- std::cout << "Log4CPP::loadConfig: config.max_backups:" << config.max_backups << std::endl;
- }
- if (LogConfig.GetKeyCount("file_pattern")) {
- config.file_pattern = (std::string)LogConfig["file_pattern"];
- std::cout << "Log4CPP::loadConfig: config.file_pattern:" << config.file_pattern << std::endl;
- }
- if (LogConfig.GetKeyCount("console_pattern")) {
- config.console_pattern = (std::string)LogConfig["console_pattern"];
- std::cout << "Log4CPP::loadConfig: config.console_pattern:" << config.console_pattern << std::endl;
- }
- // 创建日志目录
- if (!createDirectory(config.log_dir)) {
- std::cerr << "Failed to create log directory: " << config.log_dir << std::endl;
- }
- if (!createDirectory(config.history_dir)) {
- std::cerr << "Failed to create history directory: " << config.history_dir << std::endl;
- }
- return true;
- }
- bool Log4CPP::init(const std::string& configFile, std::string logName, bool toScreen) {
- // 加载配置文件
- if (!loadConfig(configFile)) {
- std::cerr << "Log4CPP::init: Failed to load config, using defaults" << std::endl;
- }
- std::cout << "Log4CPP::init: Config loaded" << std::endl;
- // 解析日志级别
- Log4CPP::coutPri = parseLogLevel(config.root_level);
- Log4CPP::logPri = parseLogLevel(config.root_level);
- std::cout << "Log4CPP::init: Log levels parsed" << std::endl;
- if (Log4CPP::instance == NULL) {
- Log4CPP::instance = new Log4CPP(toScreen);
- // 使用配置的日志目录
- std::string year, month, day, hour, min, sec;
- getCurrentTime(year, month, day, hour, min, sec);
- std::string logPath = config.log_dir + "/" + logName + "." +
- year + month + day + ".log";
- Log4CPP::_logName = logPath;
- log4cpp::Category& logCat = root.getInstance(Log4CPP::_logName);
- log4cpp::Category& coutCat = root.getInstance(Log4CPP::_screenInfo);
- logScreen = new log4cpp::OstreamAppender("logScreen", &std::cout);
- logFile = new log4cpp::FileAppender("logFile", Log4CPP::_logName); /* 然后注释这个 */
- //rollLogFile = new log4cpp::RollingFileAppender("rollLogFile", Log4CPP::_logName, 1024*1024, 5); /* 回卷用这个 */ // 单个日志文件大小1M,5个回卷
- //设置布局
- Log4CPP::logLayout = new log4cpp::PatternLayout(); /* 然后注释这个 */
- Log4CPP::screenLayout = new log4cpp::PatternLayout();
- Log4CPP::logLayout2 = new log4cpp::PatternLayout(); /* 回卷用这个 */
- // 设置日志格式
- Log4CPP::logLayout->setConversionPattern(config.file_pattern.c_str());
- Log4CPP::screenLayout->setConversionPattern(config.console_pattern.c_str());
- Log4CPP::logLayout2->setConversionPattern(config.file_pattern.c_str());
- Log4CPP::logScreen->setLayout(screenLayout);
- Log4CPP::logFile->setLayout(logLayout); /* 然后注释这个 */
- //Log4CPP::rollLogFile->setLayout(logLayout2); /* 回卷用这个 */
- std::cout << "Log4CPP::init: Setting layouts" << std::endl;
- //追加到目录
- Log4CPP::logCat.addAppender(Log4CPP::logFile); /* 然后注释这个 */
- //Log4CPP::logCat.addAppender(Log4CPP::rollLogFile); /* 回卷用这个 */
- Log4CPP::coutCat.addAppender(Log4CPP::logScreen);
- //设置优先级
- Log4CPP::logCat.setPriority(Log4CPP::logPri);
- Log4CPP::coutCat.setPriority(Log4CPP::coutPri);
- }
- Log4CPP::instance->outToScreen = toScreen;
- return true;
- }
- //获取日志函数,默认参数选择是否输出到屏幕
- Log4CPP* Log4CPP::getLog(bool toScreen) {
- Log4CPP::instance->outToScreen = toScreen;
- if (NULL == Log4CPP::instance) {
- printf("Log4CPP::log is NULL, please use Log4CPP::init!\n");
- return NULL;
- }
- return Log4CPP::instance;
- }
- //销毁日志对象
- void Log4CPP::destoryLog() {
- log4cpp::Category::shutdown();
- delete Log4CPP::instance;
- }
- //设置日志记录优先级
- void Log4CPP::setPri(log4cpp::Priority::PriorityLevel coutLevel, log4cpp::Priority::PriorityLevel logLevel) {
- Log4CPP::logPri = logLevel;
- Log4CPP::coutPri = coutLevel;
- Log4CPP::logCat.setPriority(Log4CPP::logPri);
- Log4CPP::coutCat.setPriority(Log4CPP::coutPri);
- }
- // 辅助函数:格式化消息
- std::string Log4CPP::formatMessage(const char* format, va_list args) {
- char buffer[4096];
- vsnprintf(buffer, sizeof(buffer), format, args);
- return std::string(buffer);
- }
- // 类型转换函数
- template <typename T>
- std::string Log4CPP::toString(const T& value) {
- std::ostringstream oss;
- oss << value;
- return oss.str();
- }
- // 指针特化
- std::string Log4CPP::toString(const void* value) {
- std::ostringstream oss;
- oss << "0x" << std::hex << reinterpret_cast<uintptr_t>(value);
- return oss.str();
- }
- // 布尔值特化
- std::string Log4CPP::toString(bool value) {
- return value ? "true" : "false";
- }
- // 修改后的日志函数
- void Log4CPP::warn(int line, const char* function, const char* format, ...) {
- char info[4096] = { 0 };
- snprintf(info, sizeof(info), "[%s][%d]: ", function, line);
- va_list args;
- va_start(args, format);
- std::string formatted = formatMessage(format, args);
- va_end(args);
- std::string message = info + formatted;
- if (outToScreen) {
- logCat.warn(message);
- coutCat.warn(message);
- }
- else {
- logCat.warn(message);
- }
- }
- // 其他日志函数实现类似
- void Log4CPP::error(int line, const char* function, const char* format, ...) {
- char info[4096] = { 0 };
- snprintf(info, sizeof(info), "[%s][%d]: ", function, line);
- va_list args;
- va_start(args, format);
- std::string formatted = formatMessage(format, args);
- va_end(args);
- std::string message = info + formatted;
- if (outToScreen) {
- logCat.error(message);
- coutCat.error(message);
- }
- else {
- logCat.error(message);
- }
- }
- void Log4CPP::debug(int line, const char* function, const char* format, ...) {
- char info[4096] = { 0 };
- snprintf(info, sizeof(info), "[%s][%d]: ", function, line);
- va_list args;
- va_start(args, format);
- std::string formatted = formatMessage(format, args);
- va_end(args);
- std::string message = info + formatted;
- if (outToScreen) {
- logCat.debug(message);
- coutCat.debug(message);
- }
- else {
- logCat.debug(message);
- }
- }
- void Log4CPP::info(int line, const char* function, const char* format, ...) {
- char info[4096] = { 0 };
- snprintf(info, sizeof(info), "[%s][%d]: ", function, line);
- va_list args;
- va_start(args, format);
- std::string formatted = formatMessage(format, args);
- va_end(args);
- std::string message = info + formatted;
- if (outToScreen) {
- logCat.info(message);
- coutCat.info(message);
- }
- else {
- logCat.info(message);
- }
- }
- std::string Log4CPP::getCurrentTime(std::string& year, std::string& month, std::string& day, std::string& hour, std::string& min, std::string& sec) {
- // 获取系统时间 - 年月日时分秒
- time_t _time;
- struct tm* target_time;
- time(&_time);
- target_time = localtime(&_time);
- year = std::to_string(target_time->tm_year + 1900);
- month = target_time->tm_mon + 1 > 9 ? std::to_string(target_time->tm_mon + 1) : "0" + std::to_string(target_time->tm_mon + 1);
- day = target_time->tm_mday > 9 ? std::to_string(target_time->tm_mday) : "0" + std::to_string(target_time->tm_mday);
- hour = target_time->tm_hour > 9 ? std::to_string(target_time->tm_hour) : "0" + std::to_string(target_time->tm_hour);
- min = target_time->tm_min > 9 ? std::to_string(target_time->tm_min) : "0" + std::to_string(target_time->tm_min);
- sec = target_time->tm_sec > 9 ? std::to_string(target_time->tm_sec) : "0" + std::to_string(target_time->tm_sec);
- return year + month + day + hour + min + sec;
- }
|