日志是服务端开发必不可少的模块,工作过几个公司,基本每个公司或者项目组都有自己的日志模块,有使用开源的,也有自己写的,这是自己写的一个日志模块,经过线上大并发的测试,性能良好,使用也较方便。该日志采用的是单例模式,支持自动按天分文件,按日志行数自动分文件,是多线程安全的单例模式,没有外部依赖,linux操作系统均可以使用。
- /********************************************************
- function:log class
- version:1.0
- date:2013.4.19
- modify:2014.12.21
- *********************************************************/
- #ifndef LOG_H
- #define LOG_H
- #include <stdio.h>
- #include <iostream>
- #include <stdarg.h>
- #include <pthread.h>
- using namespace std;
- class Log
- {
- public:
- static Log* get_instance()
- {
- static Log instance;
- return &instance;
- }
- bool init(const char* file_name, int log_buf_size = 8192, int split_lines = 5000000);
- void write_log(int level, const char* format, ...);
- void flush(void);
- private:
- Log();
- virtual ~Log();
- private:
- pthread_mutex_t *m_mutex;
- 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;
- };
- #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
/********************************************************
function:log class
version:1.0
date:2013.4.19
modify:2014.12.21
*********************************************************/
#ifndef LOG_H
#define LOG_H
#include <stdio.h>
#include <iostream>
#include <stdarg.h>
#include <pthread.h>
using namespace std;
class Log
{
public:
static Log* get_instance()
{
static Log instance;
return &instance;
}
bool init(const char* file_name, int log_buf_size = 8192, int split_lines = 5000000);
void write_log(int level, const char* format, ...);
void flush(void);
private:
Log();
virtual ~Log();
private:
pthread_mutex_t *m_mutex;
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;
};
#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
- /********************************************************
- function:log class
- version:1.0
- date:2013.4.19
- modify:2014.12.21
- *********************************************************/
- #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;
- pthread_mutex_init(m_mutex, NULL);
- }
- Log::~Log()
- {
- if(m_fp != NULL)
- {
- fclose(m_fp);
- }
- 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)
- {
- 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;
- 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;
- }
- 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);
- 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);
- pthread_mutex_lock(m_mutex);
- int m = vsnprintf(m_buf + n, m_log_buf_size-1, format, valst);
- m_buf[n + m - 1] = '\n';
- fputs(m_buf, 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);
- }
/********************************************************
function:log class
version:1.0
date:2013.4.19
modify:2014.12.21
*********************************************************/
#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;
pthread_mutex_init(m_mutex, NULL);
}
Log::~Log()
{
if(m_fp != NULL)
{
fclose(m_fp);
}
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)
{
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;
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;
}
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);
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);
pthread_mutex_lock(m_mutex);
int m = vsnprintf(m_buf + n, m_log_buf_size-1, format, valst);
m_buf[n + m - 1] = '\n';
fputs(m_buf, 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);
}
- #include "log.h"
- void *f(void* args)
- {
- for(int i = 0;i < 100000; 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);
- 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", i,'a',"log", 1.000);
- LOG_INFO("%d", 123456789);
- LOG_ERROR("%d", 123456789);
- LOG_DEBUG("%d", 123456789);
- LOG_WARN("%d", 123456789);
- pthread_t id;
- for(int i = 0; i < 10; i++)
- {
- pthread_create(&id, NULL, f, NULL);
- pthread_join(id,NULL);
- }
- for(;;)
- {
- sleep(5);
- Log::get_instance()->flush();
- }
- return 0;
- }