#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_is_async = false;
|
}
|
|
Log::~Log()
|
{
|
if (m_fp != NULL)
|
{
|
fclose(m_fp);
|
}
|
}
|
|
bool Log::init(const char *file_name, int close_log, 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);
|
pthread_t tid;
|
pthread_create(&tid, NULL, flush_log_thread, NULL);
|
}
|
|
m_close_log = close_log;
|
m_log_buf_size = log_buf_size;
|
m_buf = new char[m_log_buf_size];
|
memset(m_buf, '\0', m_log_buf_size);
|
m_split_lines = split_lines;
|
|
time_t t = time(NULL);
|
struct tm *sys_tm = localtime(&t);
|
const char *p = strrchr(file_name, '/');
|
char log_full_name[256] = {0};
|
|
if (p == NULL)
|
{
|
snprintf(log_full_name, 255, "%d_%02d_%02d_%s", sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_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, sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday, log_name);
|
}
|
|
m_today = sys_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;
|
gettimeofday(&now, NULL);
|
time_t t = now.tv_sec;
|
struct tm *sys_tm = localtime(&t);
|
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;
|
}
|
|
m_mutex.lock();
|
m_count++;
|
|
if (m_today != sys_tm->tm_mday || m_count % m_split_lines == 0)
|
{
|
char new_log[256] = {0};
|
fflush(m_fp);
|
fclose(m_fp);
|
char tail[16] = {0};
|
snprintf(tail, 16, "%d_%02d_%02d_", sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday);
|
|
if (m_today != sys_tm->tm_mday)
|
{
|
snprintf(new_log, 255, "%s%s%s", dir_name, tail, log_name);
|
m_today = sys_tm->tm_mday;
|
m_count = 0;
|
}
|
else
|
{
|
snprintf(new_log, 255, "%s%s%s.%lld", dir_name, tail, log_name, m_count / m_split_lines);
|
}
|
m_fp = fopen(new_log, "a");
|
}
|
|
// 在写入之前检查日志文件大小
|
if (check_log_size())
|
{
|
rotate_logs(); // 如果超过最大文件大小,进行日志轮换
|
}
|
|
va_list valst;
|
va_start(valst, format);
|
|
string log_str;
|
int n = snprintf(m_buf, 48, "%d-%02d-%02d %02d:%02d:%02d.%06ld %s ",
|
sys_tm->tm_year + 1900, sys_tm->tm_mon + 1, sys_tm->tm_mday,
|
sys_tm->tm_hour, sys_tm->tm_min, sys_tm->tm_sec, now.tv_usec, s);
|
int m = vsnprintf(m_buf + n, m_log_buf_size - n - 1, format, valst);
|
m_buf[n + m] = '\n';
|
m_buf[n + m + 1] = '\0';
|
log_str = m_buf;
|
|
m_mutex.unlock();
|
|
if (m_is_async && !m_log_queue->full())
|
{
|
m_log_queue->push(log_str);
|
}
|
else
|
{
|
m_mutex.lock();
|
fputs(log_str.c_str(), m_fp);
|
m_mutex.unlock();
|
}
|
|
va_end(valst);
|
}
|
|
void Log::flush(void)
|
{
|
m_mutex.lock();
|
fflush(m_fp);
|
m_mutex.unlock();
|
}
|
|
// 添加的文件大小检查函数
|
bool Log::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 Log::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; // 重置日志计数
|
}
|