Skip to content

Commit 0be06d8

Browse files
committed
ADD: log.cpp
1 parent d3d3083 commit 0be06d8

File tree

2 files changed

+185
-3
lines changed

2 files changed

+185
-3
lines changed

log/log.cpp

+177
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,177 @@
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+
}

log/log.h

+8-3
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,26 @@ class Log
1818
return &instance;
1919
}
2020

21+
bool init(const char* file_name, int log_buf_size = 8192,
22+
int split_lines = 5000000, int max_queue_size = 0);
23+
24+
/* 异步写日志公有方法 */
2125
static void* flush_log_thread(void *args)
2226
{
2327
Log::get_instance()->async_write_log();
2428
}
2529

26-
bool init(const char* file_name, int log_buf_size = 8192,
27-
int split_lines = 5000000, int max_queue_size = 0);
28-
30+
/* 将输出内容按照标准格式整理 */
2931
void write_log(int level, const char* format, ...);
3032

33+
/* 强制刷新缓冲区 */
3134
void flush(void);
3235

3336
private:
3437
Log();
3538
virtual ~Log();
39+
40+
/* 异步写日志方法 */
3641
void* async_write_log()
3742
{
3843
string single_log;

0 commit comments

Comments
 (0)