1. 程式人生 > >簡單的C/C++日誌模塊實現

簡單的C/C++日誌模塊實現

oca 線程 sca log4cxx void case ## div flush

諸如log4cxx之類的日誌庫還是有些復雜,自己實現了一個簡單的日誌模塊。

支持文件設置、日誌級別、非原子打印,還附加了常用的線程鎖相關宏,如下:

sys_logger.h

  1 #ifndef __sys_logger_h_
  2 #define __sys_logger_h_
  3 
  4 #include <stdio.h>
  5 #include <iostream>
  6 #include <cstring>
  7 #include <stdarg.h>
  8 #include <time.h>
  9 #include <unistd.h>
 10
#include <pthread.h> 11 #include <sys/time.h> 12 #include <sys/syscall.h> 13 14 #define gettid() syscall(SYS_gettid) 15 16 #define LEVEL_SOCKET_DEBUG 0 17 #define LEVEL_DEBUG 1 18 #define LEVEL_INFO 2 19 #define LEVEL_WARNING 3 20 #define LEVEL_ERROR 4 21
22 #define LOG_BUF_SIZE 2048 23 #define MAX_FILENAME_LEN 256 24 25 26 using namespace std; 27 28 #define LOG_INFO_NOLOCK(format, ...) 29 SysLogger::GetInstance()->WriteLogNoLock(LEVEL_INFO, 30 __FILE__, __LINE__, gettid(), 31 format, ##__VA_ARGS__)
32 33 #define SOCKET_DEBUG(format, ...) 34 SysLogger::GetInstance()->WriteLog(LEVEL_SOCKET_DEBUG, 35 __FILE__, __LINE__, gettid(), 36 format, ##__VA_ARGS__) 37 38 #define LOG_DEBUG(format, ...) 39 SysLogger::GetInstance()->WriteLog(LEVEL_DEBUG, 40 __FILE__, __LINE__, gettid(), 41 format, ##__VA_ARGS__) 42 43 #define LOG_INFO(format, ...) 44 SysLogger::GetInstance()->WriteLog(LEVEL_INFO, 45 __FILE__, __LINE__, gettid(), 46 format, ##__VA_ARGS__) 47 48 #define LOG_WARNING(format, ...) 49 SysLogger::GetInstance()->WriteLog(LEVEL_WARNING, 50 __FILE__, __LINE__, gettid(), 51 format, ##__VA_ARGS__) 52 53 #define LOG_ERROR(format, ...) 54 SysLogger::GetInstance()->WriteLog(LEVEL_ERROR, 55 __FILE__, __LINE__, gettid(), 56 format, ##__VA_ARGS__) 57 58 // Pthread trylock, lock, unlock 59 #define MUTEX_LOCK(mutex) {int oldstate; 60 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 61 pthread_mutex_lock(mutex); 62 pthread_setcancelstate(oldstate, NULL); 63 } 64 65 #define MUTEX_UNLOCK(mutex) {int oldstate; 66 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 67 pthread_mutex_unlock(mutex); 68 pthread_setcancelstate(oldstate, NULL); 69 } 70 71 inline int MutexTryLock(pthread_mutex_t* mutex) 72 { 73 int ret = 0; 74 int oldstate; 75 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 76 ret = pthread_mutex_trylock(mutex); 77 pthread_setcancelstate(oldstate, NULL); 78 return ret; 79 } 80 81 inline void MutexLock(pthread_mutex_t* mutex) 82 { 83 int oldstate; 84 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 85 pthread_mutex_lock(mutex); 86 pthread_setcancelstate(oldstate, NULL); 87 } 88 89 inline void MutexUnlock(pthread_mutex_t* mutex) 90 { 91 int oldstate; 92 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate); 93 pthread_mutex_unlock(mutex); 94 pthread_setcancelstate(oldstate, NULL); 95 } 96 97 class SysLogger 98 { 99 public: 100 SysLogger(); 101 ~SysLogger(); 102 103 static SysLogger* GetInstance(); 104 105 bool InitLogger(const char* file_name, int min_level); 106 void WriteLog(int level, const char* exec_file, int exec_line, int tid, const char* format, ...); 107 void WriteLogNoLock(int level, const char* exec_file, int exec_line, int tid, const char* format, ...); 108 109 private: 110 void set_log(int level, const char* exec_file, int exec_line, int tid, const char* format, va_list valst); 111 112 public: 113 static SysLogger* instance_; 114 115 private: 116 int min_level_; 117 char* log_file_; 118 char* log_buf_; 119 FILE* log_fp_; 120 pthread_mutex_t* mutex_; 121 }; 122 123 #endif

sys_logger.cpp

  1 #include "sys_logger.h"
  2 
  3 SysLogger* SysLogger::instance_ = NULL;
  4 
  5 SysLogger* SysLogger::GetInstance()
  6 {
  7     if (instance_ == NULL) {
  8         instance_ = new SysLogger();
  9     }
 10 
 11     return instance_;
 12 }
 13 
 14 SysLogger::SysLogger()
 15 {
 16     min_level_ = 0;
 17     log_fp_ = NULL;
 18     log_file_ = new char[MAX_FILENAME_LEN];
 19     memset(log_file_, 0, MAX_FILENAME_LEN);
 20     log_buf_ = new char[LOG_BUF_SIZE];
 21     mutex_ = new pthread_mutex_t;
 22     pthread_mutex_init(mutex_, NULL);
 23 }
 24 
 25 SysLogger::~SysLogger()
 26 {
 27     if (log_file_ != NULL) {
 28         delete[] log_file_;
 29         log_file_ = NULL;
 30     }
 31     
 32     if (log_buf_ != NULL) {
 33         delete[] log_buf_;
 34         log_buf_ = NULL;
 35     }
 36     
 37     if (log_fp_ != NULL) {
 38         fclose(log_fp_);
 39         log_fp_ = NULL;
 40     }
 41     
 42     pthread_mutex_destroy(mutex_);
 43 
 44     if (mutex_ != NULL) {
 45         delete mutex_;
 46     }
 47 }
 48 
 49 bool SysLogger::InitLogger(const char* file_name, int min_level)
 50 {
 51     strncpy(log_file_, file_name, MAX_FILENAME_LEN - 1);
 52     
 53     if (min_level >=0 && min_level <= 4) {
 54         min_level_ = min_level;
 55     }
 56     
 57     log_fp_ = fopen(log_file_, "a");
 58     
 59     if (log_fp_ == NULL) {
 60         return false;
 61     }
 62 
 63     return true;
 64 }
 65 
 66 void SysLogger::WriteLog(int level, const char* exec_file, int exec_line, int tid, const char* format, ...)
 67 {
 68     if (level < min_level_) {
 69         return;
 70     }
 71     
 72     pthread_mutex_lock(mutex_);
 73     va_list valst;
 74     va_start(valst, format);
 75     set_log(level, exec_file, exec_line, tid, format, valst);
 76     va_end(valst);
 77     
 78     fputs(log_buf_, log_fp_);
 79     fflush(log_fp_);
 80     
 81     // if (log_fp_ != NULL) {
 82         // fclose(log_fp_);
 83         // log_fp_ = NULL;
 84     // }
 85     
 86     pthread_mutex_unlock(mutex_);
 87 }
 88 
 89 // Used for mod exit
 90 void SysLogger::WriteLogNoLock(int level, const char* exec_file, int exec_line, int tid, const char* format, ...)
 91 {
 92     if (level < min_level_) {
 93         return;
 94     }
 95     
 96     va_list valst;
 97     va_start(valst, format);
 98     set_log(level, exec_file, exec_line, tid, format, valst);
 99     va_end(valst);
100     fputs(log_buf_, log_fp_);
101     fflush(log_fp_);
102     
103     // if (log_fp_ != NULL) {
104         // fclose(log_fp_);
105         // log_fp_ = NULL;
106     // }
107 }
108 
109 void SysLogger::set_log(int level, const char* exec_file, int exec_line, int tid, const char* format, va_list valst)
110 {
111     char exec_filename[MAX_FILENAME_LEN];
112     memset(exec_filename, 0, MAX_FILENAME_LEN);
113     const char* pch = strrchr(exec_file, /);
114     
115     if (pch == NULL) {
116         strncpy(exec_filename, exec_file, MAX_FILENAME_LEN - 1);
117     } else {
118         strncpy(exec_filename, pch + 1, MAX_FILENAME_LEN - 1);
119     }
120     
121     char levstr[16];
122     memset(levstr, 0, 16);
123     
124     switch (level) {
125         case LEVEL_SOCKET_DEBUG:
126         case LEVEL_DEBUG:
127             strcpy(levstr, "DEBUG");
128             break;
129         case LEVEL_INFO:
130             strcpy(levstr, "INFO");
131             break;
132         case LEVEL_WARNING:
133             strcpy(levstr, "WARN");
134             break;
135         case LEVEL_ERROR:
136             strcpy(levstr, "ERROR");
137             break;
138         default:
139             strcpy(levstr, "INFO");
140             break;
141     }
142     
143     if (log_fp_ == NULL) {
144         log_fp_ = fopen(log_file_, "a");
145     }
146     
147     memset(log_buf_, 0, LOG_BUF_SIZE);
148     struct timeval now = {0, 0};
149     gettimeofday(&now, NULL);
150     struct tm* sys_tm = localtime(&(now.tv_sec));
151     
152     int n = snprintf(log_buf_, 128, "\n%d-%02d-%02d %02d:%02d:%02d,%03d <%s> [%s:%d] [%d] ",
153                         sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday,
154                         sys_tm->tm_hour, sys_tm->tm_min, sys_tm->tm_sec, now.tv_usec / 1000, 
155                         levstr, exec_filename, exec_line, tid);
156     vsnprintf(log_buf_ + n, LOG_BUF_SIZE - n, format, valst);
157 }

簡單的C/C++日誌模塊實現