1
+ #include < pthread.h>
2
+ #include < string.h>
3
+ #include < time.h>
4
+ #include < sys/time.h>
5
+ #include < stdarg.h>
6
+
7
+ #include " log.h"
8
+
9
+ Log::Log ()
10
+ {
11
+ m_count = 0 ;
12
+ m_is_async = false ;
13
+ }
14
+
15
+ Log::~Log ()
16
+ {
17
+ if (NULL != m_fp)
18
+ {
19
+ fclose (m_fp);
20
+ }
21
+ }
22
+
23
+ /* 异步需要设置阻塞队列的长度,同步不需要设置 */
24
+ bool Log::init (const char * file_name, int log_buf_size,
25
+ int split_lines, int max_queue_size)
26
+ {
27
+ if (max_queue_size >= 1 )
28
+ {
29
+ m_is_async = true ;
30
+ m_log_queue = new block_queue<string>(max_queue_size);
31
+ pthread_t tid;
32
+ /* 创建线程异步写日志 */
33
+ pthread_create (&tid, NULL , flush_log_thread, NULL );
34
+ }
35
+
36
+ /* 输出内容的长度 */
37
+ m_log_buf_size = log_buf_size;
38
+ m_buf = new char [m_log_buf_size];
39
+ memset (m_buf, ' \0 ' , sizeof (m_buf));
40
+ m_split_lines = split_lines;
41
+
42
+ time_t t = time (NULL );
43
+ struct tm *sys_tm = localtime (&t);
44
+ struct tm my_tm = *sys_tm;
45
+
46
+ /* 从后往前找第一个 / 的位置 */
47
+ const char *p = strrchr (file_name, ' /' );
48
+ char log_full_name[256 ] = {0 };
49
+
50
+ /* 若输入的文件名没有 /,则直接将时间+文件名作为日志名 */
51
+ if (NULL == p)
52
+ {
53
+ snprintf (log_full_name, 255 , " %d_%02d_%02d_%s" ,
54
+ my_tm.tm_year + 1900 , my_tm.tm_mon + 1 , my_tm.tm_mday , file_name);
55
+ }
56
+ else
57
+ {
58
+ strcpy (log_name, p + 1 );
59
+ strncpy (dir_name, file_name, p - file_name + 1 );
60
+
61
+ snprintf (log_full_name, 255 , " %s%d_%02d_%02d_%s" , dir_name,
62
+ my_tm.tm_year + 1900 , my_tm.tm_mon + 1 , my_tm.tm_mday , log_name);
63
+ }
64
+
65
+ m_today = my_tm.tm_mday ;
66
+
67
+ m_fp = fopen (log_full_name, " a" ); /* a: 追加 */
68
+ if (NULL == m_fp)
69
+ {
70
+ return false ;
71
+ }
72
+ return true ;
73
+ }
74
+
75
+ void Log::write_log (int level, const char * format, ...)
76
+ {
77
+ struct timeval now = {0 , 0 };
78
+ gettimeofday (&now, NULL );
79
+ time_t t = now.tv_sec ;
80
+ struct tm *sys_tm = localtime (&t);
81
+ struct tm my_tm = *sys_tm;
82
+ char s[16 ] = {0 };
83
+
84
+ /* 日志分级 */
85
+ switch (level)
86
+ {
87
+ case 0 :
88
+ strcpy (s, " [debug]" );
89
+ break ;
90
+ case 1 :
91
+ strcpy (s, " [info]" );
92
+ break ;
93
+ case 2 :
94
+ strcpy (s, " [warn]" );
95
+ break ;
96
+ case 3 :
97
+ strcpy (s, " [erro]" );
98
+ break ;
99
+ default :
100
+ strcpy (s, " [info]" );
101
+ break ;
102
+ }
103
+
104
+ m_mutex.lock ();
105
+
106
+ /* 更新现有行数 */
107
+ m_count++;
108
+
109
+ /* 日志不是今天或写入的日志行数是最大行的倍数 */
110
+ if (m_today != my_tm.tm_mday || m_count % m_split_lines == 0 )
111
+ {
112
+ char new_log[256 ] = {0 };
113
+ /* 强迫将缓冲区内的数据写回参数stream 指定的文件中 */
114
+ fflush (m_fp);
115
+ fclose (m_fp);
116
+ char tail[16 ] = {0 };
117
+
118
+ /* 格式化日志名中的时间部分 */
119
+ snprintf (tail, 16 , " %d_%02d_%02d" ,
120
+ my_tm.tm_year + 1900 , my_tm.tm_mon + 1 , my_tm.tm_mday );
121
+
122
+ /* 如果时间不是今天,则创建今天的日志 */
123
+ if (m_today != my_tm.tm_mday )
124
+ {
125
+ snprintf (new_log, 255 , " %s%s%s" , dir_name, tail, log_name);
126
+ }
127
+ else
128
+ {
129
+ snprintf (new_log, 255 , " %s%s%s.%lld" ,
130
+ dir_name, tail, log_name, m_count / m_split_lines);
131
+ }
132
+
133
+ m_fp = fopen (new_log, " a" );
134
+ }
135
+
136
+ m_mutex.unlock ();
137
+
138
+ va_list valst;
139
+ va_start (valst, format);
140
+
141
+ string log_str;
142
+ m_mutex.lock ();
143
+
144
+ /* 写入内容格式:时间+内容 */
145
+ /* 时间格式化 */
146
+ int n = snprintf (m_buf, 48 , " %d-%02d-%02d %02d:%02d:%02d.%06ld %s " ,
147
+ my_tm.tm_year + 1900 , my_tm.tm_mon + 1 , my_tm.tm_mday ,
148
+ my_tm.tm_hour , my_tm.tm_min , my_tm.tm_sec , now.tv_usec , s);
149
+ /* 内容格式化 */
150
+ int m = vsnprintf (m_buf + n, m_log_buf_size - 1 , format, valst);
151
+ m_buf[n + m] = ' \n ' ;
152
+ m_buf[n + m + 1 ] = ' \0 ' ;
153
+
154
+ log_str = m_buf;
155
+
156
+ m_mutex.unlock ();
157
+
158
+ if (m_is_async && !m_log_queue->full ())
159
+ {
160
+ m_log_queue->push (log_str);
161
+ }
162
+ else
163
+ {
164
+ m_mutex.lock ();
165
+ fputs (log_str.c_str (), m_fp);
166
+ m_mutex.unlock ();
167
+ }
168
+
169
+ va_end (valst);
170
+ }
171
+
172
+ void Log::flush (void )
173
+ {
174
+ m_mutex.lock ();
175
+ fflush (m_fp);
176
+ m_mutex.unlock ();
177
+ }
0 commit comments