| | |
| | | |
| | | #include <stdio.h> |
| | | #include <iostream> |
| | | #include <string> |
| | | #include <stdarg.h> |
| | | #include <pthread.h> |
| | | #include <thread> |
| | | #include "block_queue.h" |
| | | #include "locker.h" |
| | | #include <fstream> |
| | | #include <sqlite3.h> // æ·»å SQLite æ°æ®åºç头æä»¶ |
| | | |
| | | using namespace std; |
| | | |
| | | // æ¥å¿çº§å«æä¸¾ |
| | | enum LogLevel { |
| | | DEBUG = 0, |
| | | INFO, |
| | | WARN, |
| | | ERROR |
| | | }; |
| | | |
| | | // åå¨è§£ææ¥å¿æä»¶çç»æä½ |
| | | struct ParsedLog { |
| | | char timestamp[64]; // æ¶é´æ³ |
| | | char device_id[64]; // 设å¤ID |
| | | char level[16]; // æ¥å¿çº§å« |
| | | char content[256]; // æ¥å¿å
容 |
| | | char source[64]; // æ¥æºæ¨¡å |
| | | char user_id[64]; // ç¨æ·ID |
| | | }; |
| | | |
| | | 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 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 char* raw_log); |
| | | |
| | | // å°æ¥å¿åå
¥æ°æ®åº |
| | | void writeLogToDatabase(const ParsedLog& 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 char* log); // è§£ææ¥å¿ |
| | | bool init(const char *file_name, int close_log, int log_buf_size, int split_lines, int max_queue_size); |
| | | void queryLogs(const char *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 char *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; |
| | | block_queue<string> *m_log_queue; // é»å¡éå |
| | | bool m_is_async; // æ¯å¦åæ¥æ å¿ä½ |
| | | locker m_mutex; |
| | | int m_close_log; // å
³éæ¥å¿ |
| | | long max_size = 10 * 1024 * 1024; // 10MB |
| | | int m_today; // è®°å½å½åæ¶é´ |
| | | std::ofstream m_fp; // å° FILE * m_fp æ´æ¹ä¸º std::ofstream m_fp |
| | | char *m_buf; // æ¥å¿ç¼å²åº |
| | | block_queue<char*> *m_log_queue; // é»å¡éå |
| | | bool m_is_async; // æ¯å¦å¼æ¥æ å¿ä½ |
| | | locker m_mutex; // äºæ¥é |
| | | int m_close_log; // å
³éæ¥å¿çæ å¿ |
| | | long max_size = 10 * 1024 * 1024; // å个æ¥å¿æä»¶çå¤§å° 10MB |
| | | |
| | | // æ°æ®åºç¸å
³ |
| | | sqlite3 *db; // SQLite æ°æ®åºæé |
| | | void openDatabase(const char *db_name); // æå¼æ°æ®åº |
| | | void closeDatabase(); // å
³éæ°æ®åº |
| | | }; |
| | | |
| | | #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 |