版权声明:这里将不定期发布一些技术上分享,如对文章有任何意见或者建议,欢迎评论,转载请注明出处。 https://blog.csdn.net/goal_ff/article/details/90051323
说明:
- 使用时只需要包含log.h;
- 在变参列表读取解析位置有个小bug,vsnprintf()对不正确的格式匹配会出错,应该尽量在日志输出以避免;
- 日志输出原则:分级输出、信息列对齐、使用简单;
- 后续改进:添加配置读取(级别,输出位置);
功能文件 log.h
/* log.h */
#ifndef _LOG_H_
#define _LOG_H_
#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
#define LOG_DEBUG 0x01
#define LOG_INFOR 0x02
#define LOG_WARNING 0x03
#define LOG_ERROR 0x04
#define LOG_FATAL_ERROR 0x05
#define LOG_DBG(format, ...) \
WriteLog(LOG_DEBUG, "DEBUG ", __LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
#define LOG_INFO(format, ...) \
WriteLog(LOG_INFOR, "INFO ", __LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
#define LOG_WARN(format, ...) \
WriteLog(LOG_WARNING, "WARN ", __LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
#define LOG_ERR(format, ...) \
WriteLog(LOG_ERROR, "ERR ", __LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
#define LOG_FATAL(format, ...) \
WriteLog(LOG_FATAL_ERROR, "FATAL", __LINE__, __FUNCTION__, __FILE__, format, ##__VA_ARGS__)
FILE *log_file;
int log_level;
int LogInit(const int level, const char *path)
{
log_level = level;
log_file = fopen(path, "a");
if (NULL == log_file)
{
return -1;
}
setvbuf(log_file, NULL, _IOLBF, 0); /* 行缓冲 */
return 0;
}
int WriteLog(int v_level,const char *level, int line, const char *func, const char *file, const char * format, ...)
{
if (log_level > v_level){return -1;}
/* ---文件名---行号---函数名---- */
char log_pos[64] = {0};
sprintf(log_pos, " %s %s:%d [%s] ", level, file, line, func);
/* ---时间戮--- */
char log_time[64] = {0};
time_t t = time(NULL);
struct tm ptm;
localtime_r(&t, &ptm);
sprintf(log_time, "%4d-%02d-%02d %02d:%02d:%02d",
ptm.tm_year + 1900, ptm.tm_mon + 1, ptm.tm_mday, ptm.tm_hour, ptm.tm_min, ptm.tm_sec);
/* ---日志内容--- */
char log_msg[5*1024] = {0};
va_list arg_ptr;
va_start(arg_ptr, format);
int nWrittenBytes = vsnprintf(log_msg,sizeof(log_msg), format, arg_ptr);
if (nWrittenBytes < 0)
{
perror("vsnprintf");
return -1;
}
va_end(arg_ptr);
/* ---完整日志拼接--- */
char log_output[6*1024] = {0};
strcat(log_output, log_time);
strcat(log_output, log_pos);
strcat(log_output, log_msg);
fprintf(log_file, "%s\n", log_output);
return nWrittenBytes;
}
#endif
测试文件 main.c
/* main.c */
#include "log.h"
int main()
{
if(LogInit(LOG_INFOR, "forever.log"))
{
printf("log init failed.\n");
return -1;
}
int tmp = 123;
LOG_DBG("***********");
LOG_INFO("***********");
LOG_INFO("%d", tmp);
LOG_INFO("%s%p", "infor log", &tmp);
LOG_WARN("%s***%d", "warning log", tmp);
LOG_ERR("%s %d", "error log", tmp);
LOG_FATAL("%s %d", "fatal error log", tmp);
return 0;
}
测试结果
[root@localhost]# gcc main.c
[root@localhost]# ./a.out
[root@localhost]# tail -f forever.log
2019-05-09 13:40:06 INFO main.c:13 [main] ***********
2019-05-09 13:40:06 INFO main.c:14 [main] 123
2019-05-09 13:40:06 INFO main.c:15 [main] infor log0x7ffd443c729c
2019-05-09 13:40:06 WARN main.c:16 [main] warning log***123
2019-05-09 13:40:06 ERR main.c:17 [main] error log 123
2019-05-09 13:40:06 FATAL main.c:18 [main] fatal error log 123