Server/马丽萍/code/log/.vscode/c_cpp_properties.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/.vscode/settings.json | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/README.md | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/block_queue.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/locker.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/log.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/log.h | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 | |
Server/马丽萍/code/log/test_log.cpp | ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史 |
Server/ÂíÀöƼ/code/log/.vscode/c_cpp_properties.json
@@ -5,7 +5,7 @@ "includePath": [ "${workspaceFolder}/**" ], "compilerPath": "gcc", "compilerPath": "C:\\Users\\lenovo\\AppData\\Local\\GitHubDesktop\\bin\\g++.exe", "cStandard": "${default}", "cppStandard": "${default}", "intelliSenseMode": "windows-gcc-x64", Server/ÂíÀöƼ/code/log/.vscode/settings.json
@@ -55,5 +55,9 @@ "C_Cpp_Runner.useLeakSanitizer": false, "C_Cpp_Runner.showCompilationTime": false, "C_Cpp_Runner.useLinkTimeOptimization": false, "C_Cpp_Runner.msvcSecureNoWarnings": false "C_Cpp_Runner.msvcSecureNoWarnings": false, "files.associations": { "iosfwd": "cpp", "thread": "cpp" } } Server/ÂíÀöƼ/code/log/README.md
@@ -1,10 +1,12 @@ # 弿¥æ¥å¿ç³»ç» 弿¥æ¥å¿ç³»ç» =============== 弿¥æ¥å¿ç³»ç»ä¸»è¦æ¶åäºä¸¤ä¸ªæ¨¡åï¼ä¸ä¸ªæ¯æ¥å¿æ¨¡åï¼ä¸ä¸ªæ¯é»å¡é忍¡å,å ¶ä¸å å ¥é»å¡é忍¡åä¸»è¦æ¯è§£å³å¼æ¥åå ¥æ¥å¿ååå¤. ## ç®ä» 弿¥æ¥å¿ç³»ç»ä¸»è¦æ¶å两个模åï¼ä¸ä¸ªæ¯æ¥å¿æ¨¡åï¼ä¸ä¸ªæ¯é»å¡é忍¡åï¼å ¶ä¸å å ¥é»å¡é忍¡åä¸»è¦æ¯è§£å³å¼æ¥åå ¥æ¥å¿çåå¤å·¥ä½ã > * èªå®ä¹é»å¡éå > * å便¨¡å¼å建æ¥å¿ > * 忥æ¥å¿ > * 弿¥æ¥å¿ > * å®ç°æå¤©ãè¶ è¡åç±» > * æä»¶éå¶å¤§å° 鲿¢æ¥å¿æä»¶è¿å¤§ > * æä»¶éå¶å¤§å°ï¼é²æ¢æ¥å¿æä»¶è¿å¤§ Server/ÂíÀöƼ/code/log/block_queue.h
@@ -8,9 +8,12 @@ #include <iostream> #include <stdlib.h> #include <pthread.h> #include <sys/time.h> #include "../lock/locker.h" #include <thread> // æ¿æ¢ pthread.h #include <chrono> #include <ctime> #include "locker.h" using namespace std; template <class T> Server/ÂíÀöƼ/code/log/locker.h
New file @@ -0,0 +1,25 @@ #ifndef LOCKER_H #define LOCKER_H #include <mutex> #include <stdexcept> class locker { public: locker() = default; ~locker() = default; void lock() { m_mutex.lock(); } void unlock() { m_mutex.unlock(); } private: std::mutex m_mutex; }; #endif // LOCKER_H Server/ÂíÀöƼ/code/log/log.cpp
@@ -1,166 +1,150 @@ #include <string.h> #include <time.h> #include <sys/time.h> #include <chrono> #include <ctime> #include <stdarg.h> #include "log.h" #include <pthread.h> #include <sstream> #include <fstream> #include <iostream> #include <chrono> using namespace std; Log::Log() { m_count = 0; m_is_async = false; // æé 彿° Log::Log() { m_count = 0; // åå§åæ¥å¿è¡æ° m_is_async = false; // åå§åä¸ºåæ¥ } Log::~Log() { if (m_fp != NULL) { fclose(m_fp); // ææå½æ° Log::~Log() { if (m_fp.is_open()) { m_fp.close(); // å ³éæ¥å¿æä»¶ } } bool Log::init(const char *file_name, int close_log, int log_buf_size, int split_lines, int max_queue_size) { if (max_queue_size >= 1) { m_is_async = true; m_log_queue = new block_queue<string>(max_queue_size); pthread_t tid; pthread_create(&tid, NULL, flush_log_thread, NULL); // æ¥æ¶åå§æ¥å¿å¹¶è§£æ void Log::receiveLog(const std::string &raw_log) { ParsedLog parsed_log = parseLog(raw_log); write_log(levelToInt(parsed_log.level), "%s [%s] %s", parsed_log.timestamp.c_str(), parsed_log.device_id.c_str(), parsed_log.content.c_str()); } // è§£ææ¥å¿å符串 ParsedLog Log::parseLog(const std::string &log) { ParsedLog parsed_log; std::istringstream iss(log); std::string level; // è¯»åæ¶é´æ³ã设å¤ID忥å¿çº§å« iss >> parsed_log.timestamp >> parsed_log.device_id >> level; std::getline(iss, parsed_log.content); parsed_log.level = level; // 设置解æåççº§å« return parsed_log; } // åå§åæ¥å¿ç³»ç» bool Log::init(const std::string &file_name, int close_log, int log_buf_size, int split_lines, int max_queue_size) { if (max_queue_size >= 1) { m_is_async = true; // å¯ç¨å¼æ¥åå ¥ m_log_queue = new block_queue<string>(max_queue_size); // å建é»å¡éå std::thread(&Log::flush_log_thread, this).detach(); // åå»ºå·æ°æ¥å¿çº¿ç¨ } m_close_log = close_log; m_log_buf_size = log_buf_size; m_buf = new char[m_log_buf_size]; memset(m_buf, '\0', m_log_buf_size); m_split_lines = split_lines; m_close_log = close_log; // è®¾ç½®å ³éæ¥å¿æ å¿ m_log_buf_size = log_buf_size; // 设置ç¼å²åºå¤§å° m_buf = new char[m_log_buf_size]; // åé ç¼å²åº memset(m_buf, '\0', m_log_buf_size); // æ¸ ç©ºç¼å²åº m_split_lines = split_lines; // 设置æå¤§è¡æ° time_t t = time(NULL); struct tm *sys_tm = localtime(&t); const char *p = strrchr(file_name, '/'); char log_full_name[256] = {0}; std::string log_full_name; if (p == NULL) { snprintf(log_full_name, 255, "%d_%02d_%02d_%s", sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday, file_name); } else { strcpy(log_name, p + 1); strncpy(dir_name, file_name, p - file_name + 1); snprintf(log_full_name, 255, "%s%d_%02d_%02d_%s", dir_name, sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday, log_name); // æ ¹æ®æä»¶è·¯å¾åå½åæ¥æçæå®æ´æ¥å¿æä»¶å if (file_name.find('/') == std::string::npos) { log_full_name = to_string(sys_tm->tm_year + 1900) + "_" + to_string(sys_tm->tm_mon + 1) + "_" + to_string(sys_tm->tm_mday) + "_" + file_name; } else { std::string log_name = file_name.substr(file_name.find_last_of('/') + 1); std::string dir_name = file_name.substr(0, file_name.find_last_of('/') + 1); log_full_name = dir_name + to_string(sys_tm->tm_year + 1900) + "_" + to_string(sys_tm->tm_mon + 1) + "_" + to_string(sys_tm->tm_mday) + "_" + log_name; } m_today = sys_tm->tm_mday; m_fp = fopen(log_full_name, "a"); if (m_fp == NULL) { return false; m_today = sys_tm->tm_mday; // è®°å½ä»å¤©çæ¥æ m_fp.open(log_full_name, std::ios::out | std::ios::app); // æå¼æ¥å¿æä»¶ if (!m_fp.is_open()) { return false; // æå¼å¤±è´¥ } return true; return true; // åå§åæå } void Log::write_log(int level, const char *format, ...) { struct timeval now; gettimeofday(&now, NULL); time_t t = now.tv_sec; struct tm *sys_tm = localtime(&t); char s[16] = {0}; #include <chrono> switch (level) { case 0: strcpy(s, "[debug]:"); break; case 1: strcpy(s, "[info]:"); break; case 2: strcpy(s, "[warn]:"); break; case 3: strcpy(s, "[erro]:"); break; default: strcpy(s, "[info]:"); break; void Log::write_log(int level, const char *format, ...) { auto now = std::chrono::system_clock::now(); auto now_time_t = std::chrono::system_clock::to_time_t(now); struct tm *sys_tm = localtime(&now_time_t); std::string s; // æ ¹æ®æ¥å¿çº§å«è®¾ç½®åç¼ switch (level) { case DEBUG: s = "[debug]: "; break; case INFO: s = "[info]: "; break; case WARN: s = "[warn]: "; break; case ERROR: s = "[error]: "; break; default: s = "[info]: "; break; } m_mutex.lock(); m_count++; m_mutex.lock(); // éå®äºæ¥ä½ m_count++; // å¢å æ¥å¿è®¡æ° if (m_today != sys_tm->tm_mday || m_count % m_split_lines == 0) { char new_log[256] = {0}; fflush(m_fp); fclose(m_fp); char tail[16] = {0}; snprintf(tail, 16, "%d_%02d_%02d_", sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday); if (m_today != sys_tm->tm_mday) { snprintf(new_log, 255, "%s%s%s", dir_name, tail, log_name); m_today = sys_tm->tm_mday; m_count = 0; // æ£æ¥æ¯å¦éè¦è½®æ¢æ¥å¿ if (m_today != sys_tm->tm_mday || m_count % m_split_lines == 0) { // ... (æ¥å¿è½®æ¢ä»£ç ) } // åå ¥æ¥å¿å 容 va_list valist; va_start(valist, format); vsnprintf(m_buf, m_log_buf_size, format, valist); // åå ¥æ¥å¿å 容 m_fp << s << m_buf << std::endl; // 使ç¨ofstreamåå ¥æä»¶ m_mutex.unlock(); // è§£éäºæ¥ä½ // 弿¥åå ¥æ¥å¿ if (m_is_async && !m_log_queue->full()) { m_log_queue->push(m_buf); // å°æ¥å¿æ¨å ¥éå } } // å·æ°æ¥å¿æä»¶ void Log::flush(void) { m_mutex.lock(); // éå®äºæ¥ä½ m_fp.flush(); // å·æ°æä»¶ m_mutex.unlock(); // è§£éäºæ¥ä½ } // å·æ°æ¥å¿çº¿ç¨ void Log::flush_log_thread() { while (m_is_async) { // ä»éåä¸è·åæ¥å¿å¹¶åå ¥ string log; if (m_log_queue->pop(log)) { write_log(INFO, "%s", log.c_str()); } else { snprintf(new_log, 255, "%s%s%s.%lld", dir_name, tail, log_name, m_count / m_split_lines); } m_fp = fopen(new_log, "a"); } // å¨åå ¥ä¹åæ£æ¥æ¥å¿æä»¶å¤§å° if (check_log_size()) { rotate_logs(); // å¦æè¶ è¿æå¤§æä»¶å¤§å°ï¼è¿è¡æ¥å¿è½®æ¢ } va_list valst; va_start(valst, format); string log_str; int n = snprintf(m_buf, 48, "%d-%02d-%02d %02d:%02d:%02d.%06ld %s ", sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday, sys_tm->tm_hour, sys_tm->tm_min, sys_tm->tm_sec, now.tv_usec, s); int m = vsnprintf(m_buf + n, m_log_buf_size - n - 1, format, valst); m_buf[n + m] = '\n'; m_buf[n + m + 1] = '\0'; log_str = m_buf; m_mutex.unlock(); if (m_is_async && !m_log_queue->full()) { m_log_queue->push(log_str); } else { m_mutex.lock(); fputs(log_str.c_str(), m_fp); m_mutex.unlock(); } va_end(valst); } void Log::flush(void) { m_mutex.lock(); fflush(m_fp); m_mutex.unlock(); } // æ·»å çæä»¶å¤§å°æ£æ¥å½æ° bool Log::check_log_size() { if (m_fp) { fseek(m_fp, 0, SEEK_END); long file_size = ftell(m_fp); return file_size >= max_size; // è¿åæä»¶æ¯å¦è¶ åºéå¶ } return false; } void Log::rotate_logs() { fclose(m_fp); // å ³éå½åæ¥å¿æä»¶ char new_log[256] = {0}; snprintf(new_log, sizeof(new_log), "%s/%s.%lld", dir_name, log_name, m_count / m_split_lines); m_fp = fopen(new_log, "a"); // æå¼æ°çæ¥å¿æä»¶ m_count = 0; // éç½®æ¥å¿è®¡æ° // æ¥å¿çº§å«è½¬æ¢ä¸ºæ´æ° int Log::levelToInt(const std::string &level) { if (level == "[debug]:") return DEBUG; if (level == "[info]:") return INFO; if (level == "[warn]:") return WARN; if (level == "[error]:") return ERROR; return INFO; // é»è®¤è¿åINFO } Server/ÂíÀöƼ/code/log/log.h
@@ -5,93 +5,92 @@ #include <iostream> #include <string> #include <stdarg.h> #include <pthread.h> #include <thread> #include "block_queue.h" #include "locker.h" // ç¡®ä¿ locker.h 被å å« #include <fstream> using namespace std; // æ¥å¿çº§å«æä¸¾ enum LogLevel { DEBUG = 0, INFO, WARN, ERROR }; // åå¨è§£ææ¥å¿æä»¶çç»æä½ struct ParsedLog { std::string timestamp; // æ¶é´æ³ std::string device_id; // 设å¤ID std::string level; // æ¥å¿çº§å« std::string content; // æ¥å¿å 容 }; class Log { public: // C++11以å,使ç¨å±é¨åéææ±ä¸ç¨å é // è·ååä¾å®ä¾ static Log *get_instance() { static Log instance; return &instance; } static void *flush_log_thread(void *args) { Log::get_instance()->async_write_log(); } // å·æ°æ¥å¿çº¿ç¨ void flush_log_thread(); // ä¿®æ¹ä¸ºééææå彿° // å¯éæ©çåæ°ææ¥å¿æä»¶ãæ¥å¿ç¼å²åºå¤§å°ãæå¤§è¡æ°ä»¥åæé¿æ¥å¿æ¡éå bool init(const char *file_name, int close_log, int log_buf_size = 8192, int split_lines = 5000000, int max_queue_size = 0); // åå§åæ¥å¿ç³»ç»ï¼åæ°å æ¬æä»¶åãæ¯å¦å ³éæ¥å¿ãç¼å²åºå¤§å°ãæå¤§è¡æ°åæå¤§éåå¤§å° bool Log::init(const char *file_name, int close_log, int log_buf_size, int split_lines, int max_queue_size); // åå ¥æ¥å¿ void write_log(int level, const char *format, ...); // å·æ°æ¥å¿æä»¶ void flush(void); //æ¥æ¶åå§çè¦å ¬å ±ç±» void receiveLog(const std::string& raw_log); // æ¥æ¶åå§æ¥å¿ private: Log(); virtual ~Log(); Log(); // æé 彿° virtual ~Log(); // ææå½æ° void async_write_log(); // 弿¥åå ¥æ¥å¿ bool check_log_size(); // æ£æ¥æ¥å¿æä»¶å¤§å° void rotate_logs(); // è½®æ¢æ¥å¿æä»¶ void *async_write_log() { string single_log; // ä»é»å¡éåä¸ååºä¸ä¸ªæ¥å¿stringï¼åå ¥æä»¶ while (m_log_queue->pop(single_log)) { m_mutex.lock(); if (check_log_size()) // æ£æ¥æä»¶å¤§å° { rotate_logs(); // è½®æ¢æ¥å¿ } fputs(single_log.c_str(), m_fp); m_mutex.unlock(); } } ParsedLog parseLog(const std::string& log); // è§£ææ¥å¿ bool init(const std::string &file_name, int close_log, int log_buf_size, int split_lines, int max_queue_size); void queryLogs(const std::string &device_id); // æ¥è¯¢æ¥å¿ // æ£æ¥æ¥å¿æä»¶å¤§å° bool check_log_size() { if (m_fp) { fseek(m_fp, 0, SEEK_END); long file_size = ftell(m_fp); return file_size >= max_size; // è¿åæä»¶æ¯å¦è¶ åºéå¶ } return false; } // è½®æ¢æ¥å¿æä»¶ void rotate_logs() { fclose(m_fp); // å ³éå½åæ¥å¿æä»¶ char new_log[256] = {0}; snprintf(new_log, sizeof(new_log), "%s/%s.%lld", dir_name, log_name, m_count / m_split_lines); m_fp = fopen(new_log, "a"); // æå¼æ°çæ¥å¿æä»¶ m_count = 0; // éç½®æ¥å¿è®¡æ° } const char* log_level_to_string(int level); // å°æ¥å¿çº§å«è½¬æ¢ä¸ºå符串 int levelToInt(const std::string &level); private: char dir_name[128]; // è·¯å¾å char log_name[128]; // logæä»¶å char dir_name[128]; // æ¥å¿æä»¶ç®å½ char log_name[128]; // æ¥å¿æä»¶å int m_split_lines; // æ¥å¿æå¤§è¡æ° int m_log_buf_size; // æ¥å¿ç¼å²åºå¤§å° long long m_count; // æ¥å¿è¡æ°è®°å½ int m_today; // å 为æå¤©åç±»,è®°å½å½åæ¶é´æ¯é£ä¸å¤© FILE *m_fp; // æå¼logçæä»¶æé char *m_buf; int m_today; // è®°å½å½åæ¶é´ std::ofstream m_fp; // å° FILE * m_fp æ´æ¹ä¸º std::ofstream m_fp char *m_buf; // æ¥å¿ç¼å²åº block_queue<string> *m_log_queue; // é»å¡éå bool m_is_async; // æ¯å¦åæ¥æ å¿ä½ locker m_mutex; int m_close_log; // å ³éæ¥å¿ bool m_is_async; // æ¯å¦å¼æ¥æ å¿ä½ locker m_mutex; // äºæ¥é int m_close_log; // å ³éæ¥å¿çæ å¿ long max_size = 10 * 1024 * 1024; // 10MB //æµè¯æä»¶éé¢ç int m_close_log; // ç¡®ä¿å¨è¿éå®ä¹ }; #define LOG_DEBUG(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(0, format, ##__VA_ARGS__); Log::get_instance()->flush();} #define LOG_INFO(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(1, format, ##__VA_ARGS__); Log::get_instance()->flush();} #define LOG_WARN(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(2, format, ##__VA_ARGS__); Log::get_instance()->flush();} #define LOG_ERROR(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(3, format, ##__VA_ARGS__); Log::get_instance()->flush();} // å®å®ä¹ç¨äºä¸å级å«çæ¥å¿è®°å½ #define LOG_DEBUG(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(DEBUG, format, ##__VA_ARGS__); Log::get_instance()->flush();} #define LOG_INFO(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(INFO, format, ##__VA_ARGS__); Log::get_instance()->flush();} #define LOG_WARN(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(WARN, format, ##__VA_ARGS__); Log::get_instance()->flush();} #define LOG_ERROR(format, ...) if(0 == m_close_log) {Log::get_instance()->write_log(ERROR, format, ##__VA_ARGS__); Log::get_instance()->flush();} #endif Server/ÂíÀöƼ/code/log/test_log.cpp
New file @@ -0,0 +1,25 @@ #include <iostream> #include "log.h" int main() { // åå§åæ¥å¿ç³»ç» if (!Log::get_instance()->init("test_log.txt", 0, 8192, 5000000, 1000)) { std::cerr << "Failed to initialize log system." << std::endl; return 1; } // æµè¯åå ¥ä¸å级å«çæ¥å¿ Log::get_instance()->write_log(DEBUG, "This is a debug message."); Log::get_instance()->write_log(INFO, "This is an info message."); Log::get_instance()->write_log(WARN, "This is a warning message."); Log::get_instance()->write_log(ERROR, "This is an error message."); // æ¨¡ææ¥æ¶åå§æ¥å¿ Log::get_instance()->receiveLog("[info]: Device123 Operation successful."); // å·æ°æ¥å¿ Log::get_instance()->flush(); std::cout << "Logs written successfully." << std::endl; return 0; }