1. 程式人生 > >自己寫的C++日誌類log

自己寫的C++日誌類log

主要功能是在伺服器執行的時候可以列印日誌到日誌檔案中,主要運用到的知識點有執行緒, 執行緒鎖,條件變數,STL的deque。大致思路是這樣的:
            這個類提供一個介面,可以直接呼叫他,並且可以列印日誌到日誌檔案中。但是不能影響到伺服器的正常執行,也就是說不能進行大量的檔案操作;

大致 實現流程:
    物件初始化時候建立一個執行緒在後臺讀取佇列,並將讀到的資料寫入到日誌檔案中,並在佇列中刪除這一資料;
    介面處,每次寫日誌時,其實是將日誌存到佇列中去。交由後臺執行緒寫入到檔案中。

整個程式難點:對於臨界區的控制,即執行緒鎖,條件變數的使用。
                        對deque的理解與使用。
                        在C++類內部實現類例項化;
下邊上程式碼
    log.h #ifndef
 LOG_H   #define LOG_H   #include <stdio.h> #include <iostream> #include <string> #include <stdarg.h> #include <pthread.h> #include <deque> using namespace std; class Log {     public:     static Log* get_instance()     {     static Log instance;     return &instance
;     }     static void *flush_log_thread(void* args)     {     Log::get_instance()->async_write_log();     }     bool init(const char* file_name, int log_buf_size = 8192, int split_lines = 5000000, int max_queue_size = 0);     void write_log(int level, const char* format, ...);     void flush(void);     private
:     Log();     virtual ~Log();   void *async_write_log()     {     string single_log;     while(1){     printf("%d\n",!m_log_queue.size());     if(!m_log_queue.size() )     {     pthread_mutex_lock(m_mutex);     {     pthread_cond_wait(m_cond, m_mutex);     single_log=m_log_queue.front();     fputs(single_log.c_str(), m_fp);     m_log_queue.pop_front();     pthread_mutex_unlock(m_mutex);     }     }else{     pthread_mutex_lock(m_mutex);     single_log=m_log_queue.front();     fputs(single_log.c_str(), m_fp);     m_log_queue.pop_front();     pthread_mutex_unlock(m_mutex);     }     }     printf("end\n");     }     private:     pthread_mutex_t *m_mutex;     pthread_cond_t  *m_cond;     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;     char *m_buf;     deque<string> m_log_queue;     bool m_is_async; }; #define LOG_DEBUG(format, ...) Log::get_instance()->write_log(0, format, __VA_ARGS__)   #define LOG_INFO(format, ...) Log::get_instance()->write_log(1, format, __VA_ARGS__)   #define LOG_WARN(format, ...) Log::get_instance()->write_log(2, format, __VA_ARGS__)   #define LOG_ERROR(format, ...) Log::get_instance()->write_log(3, format, __VA_ARGS__)   #endif  
log.cpp
 *********************************************************/ #include <string.h> #include <time.h> #include <sys/time.h> #include <stdarg.h> #include "log.h" #include <pthread.h> using namespace std; Log::Log() {     m_count = 0;     m_mutex = new pthread_mutex_t;  m_cond = new pthread_cond_t;     m_is_async = false;     pthread_mutex_init(m_mutex, NULL); } Log::~Log() {     if(m_fp != NULL)     {     fclose(m_fp);     }     pthread_cond_destroy(m_cond);       if(m_cond != NULL)      {     delete m_cond;      }     pthread_mutex_destroy(m_mutex);     if(m_mutex != NULL)     {     delete m_mutex;     } } bool Log::init(const char* file_name, 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);       deque<string>(max_queue_size);     pthread_t tid;     pthread_create(&tid, NULL, flush_log_thread, NULL);     }     m_log_buf_size = log_buf_size;     m_buf = new char[m_log_buf_size];     memset(m_buf, '\0', sizeof(m_buf));     m_split_lines = split_lines;     time_t t = time(NULL);     struct tm* sys_tm = localtime(&t);     struct tm my_tm = *sys_tm;     const char *p = strrchr(file_name, '/');     char log_full_name[256] = {0};     if(p == NULL)     {     snprintf(log_full_name, 255, "%d_%02d_%02d_%s",my_tm.tm_year+1900, my_tm.tm_mon+1, my_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, my_tm.tm_year+1900, my_tm.tm_mon+1, my_tm.tm_mday, log_name );     }     m_today = my_tm.tm_mday;     m_fp = fopen(log_full_name, "a");     if(m_fp == NULL)     {     return false;     }     return true; } void Log::write_log(int level, const char* format, ...) {     struct timeval now = {0,0};     gettimeofday(&now, NULL);     time_t t = now.tv_sec;     struct tm* sys_tm = localtime(&t);     struct tm my_tm = *sys_tm;     char s[16] = {0};     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;     }     pthread_mutex_lock(m_mutex);     m_count++;     if(m_today != my_tm.tm_mday || m_count % m_split_lines == 0) //everyday log       {     char new_log[256] = {0};     fflush(m_fp);     fclose(m_fp);     char tail[16] = {0};     snprintf(tail, 16,  "%d_%02d_%02d_", my_tm.tm_year+1900, my_tm.tm_mon+1, my_tm.tm_mday);     if(m_today != my_tm.tm_mday)     {     snprintf(new_log, 255, "%s%s%s", dir_name, tail, log_name);     m_today = my_tm.tm_mday;     m_count = 0;     }     else     {     snprintf(new_log, 255, "%s%s%s.%d", dir_name, tail, log_name, m_count/m_split_lines);     }     m_fp = fopen(new_log, "a");     }     pthread_mutex_unlock(m_mutex);     va_list valst;     va_start(valst, format);     string log_str;     pthread_mutex_lock(m_mutex);     int n = snprintf(m_buf, 48, "%d-%02d-%02d %02d:%02d:%02d.%06d %s ",     my_tm.tm_year+1900, my_tm.tm_mon+1, my_tm.tm_mday,     my_tm.tm_hour, my_tm.tm_min, my_tm.tm_sec, now.tv_usec, s);     int m = vsnprintf(m_buf + n, m_log_buf_size-1, format, valst);  m_buf[n + m - 1] = '\n';     log_str = m_buf;     pthread_mutex_unlock(m_mutex);     if(m_is_async)// && !m_log_queue->full())       {  pthread_mutex_lock(m_mutex);  m_log_queue.push_back(log_str);  pthread_cond_broadcast(m_cond);  pthread_mutex_unlock(m_mutex);     }     else     {     pthread_mutex_lock(m_mutex);     fputs(log_str.c_str(), m_fp);     pthread_mutex_unlock(m_mutex);     }     va_end(valst); } void Log::flush(void) {     pthread_mutex_lock(m_mutex);     fflush(m_fp);     pthread_mutex_unlock(m_mutex); } 測試檔案 main.cpp
#include "log.h" void *f(void* args) {     for(int i = 0;i < 10000; i++)     {     Log::get_instance()->write_log(1, "d=%d,c=%c,s=%s,f=%f", i,'a',"log", 1.000);     Log::get_instance()->write_log(2, "d=%d,c=%c,s=%s,f=%f", i,'a',"log", 1.000);     Log::get_instance()->write_log(3, "d=%d,c=%c,s=%s,f=%f", i,'a',"log", 1.000);     LOG_INFO("%d", 123456789);     LOG_ERROR("%d", 123456789);     LOG_DEBUG("%d", 123456789);     LOG_WARN("%d", 123456789);     } } int main() {     Log::get_instance()->init("./mylog.log", 100, 2000000, 10);     //Log::get_instance()->init("./mylog.log", 100, 2000000, 0);//synchronization model   //  printf("11111111111111\n"); //  sleep(1);       int i = 0;     Log::get_instance()->write_log(1, "d=%d,c=%c,s=%s,f=%f", i,'a',"log", 1.000);     Log::get_instance()->write_log(2, "d=%d,c=%c,s=%s,f=%f", i,'a',"log", 1.000);     Log::get_instance()->write_log(3, "d=%d,c=%c,s=%s,f=%f"