调用时包含hhl_log.h文件后使用宏替代函数进行写入日志操作
// eg:
FATAL("a:%d b:%s", a, b);
ALERT("a:%d b:%s", a, b);
CRITICAL("a:%d b:%s", a, b);
ERROR("a:%d b:%s", a, b);
WARNING("a:%d b:%s", a, b);
NOTICE("a:%d b:%s", a, b);
INFO("a:%d b:%s", a, b);
DEBUG("a:%d b:%s", a, b);
//CheckErrorReturn等价为
//if( (a == 1) )
//{
// ERROR("a is 1, return 0 msg:%s\n", msg);
// return 0;
//}
CheckErrorReturn(a == 1, 0, "a is 1, return 0 msg:%s\n", msg);
write_log.h
#ifndef __WRITE_LOG_H__
#define __WRITE_LOG_H__
#define _GNU_SOURCE
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdarg.h>
#include <time.h>
#include <pthread.h>
#include <sys/syscall.h>//Linux system call for thread id
/* exps is true, return ret */
#define CheckErrorReturn(exps, ret, msg, ...) \
do \
{ \
if ((exps)) \
{ \
ERROR(msg, ##__VA_ARGS__); \
return (ret); \
} \
} \
while(0) \
/* exps is true, return */
#define CheckErrorReturnVoid(exps, msg, ...) \
do \
{ \
if ((exps)) \
{ \
ERROR(msg, ##__VA_ARGS__); \
return ; \
} \
} \
while(0) \
/* exps is true, goto label */
#define CheckErrorGoto(exps, label, msg, ...) \
do \
{ \
if ((exps)) \
{ \
ERROR(msg, ##__VA_ARGS__); \
goto label; \
} \
} \
while(0) \
/* system is unusable */
#define FATAL(msg, ...) PrintLog("Fatal", msg, ##__VA_ARGS__)
/* action must be taken immediately */
#define ALERT(msg, ...) PrintLog("Alert", msg, ##__VA_ARGS__)
/* critical conditions */
#define CRITICAL(msg, ...) PrintLog("Critical", msg, ##__VA_ARGS__)
/* error conditions */
#define ERROR(msg, ...) PrintLog("Error", msg, ##__VA_ARGS__)
/* warning conditions */
#define WARNING(msg, ...) PrintLog("Warning", msg, ##__VA_ARGS__)
/* normal but significant condition */
#define NOTICE(msg, ...) PrintLog("Notice", msg, ##__VA_ARGS__)
/* informational */
#define INFO(msg, ...) PrintLog("Info", msg, ##__VA_ARGS__)
/* debug-level messages */
#define DEBUG(msg, ...) PrintLog("Debug", msg, ##__VA_ARGS__)
#define PrintLog(level_str, msg, ...) \
do { \
printf("[%s][%s][%s][%d] "msg, level_str, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
write_log("[%s][%s][%s][%d] "msg, level_str, __FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__); \
} while (0)
void write_log(const char* format, ...);
#endif
write_log.c
// log.cpp: 定义应用程序的入口点。
//
#include "write_log.h"
static pthread_mutex_t fileMutex = PTHREAD_MUTEX_INITIALIZER;
int safe_check_vasprintf(char** strp, const char* fmt, va_list ap)
{
int retval;
retval = vasprintf(strp, fmt, ap);
if (retval == -1)
{
printf("Failed to vasprintf: %s. Bailing out\n", strerror(errno));
return 1;
}
return retval;
}
int safe_asprintf(char** strp, const char* fmt, ...)
{
va_list ap;
int retval;
va_start(ap, fmt);
retval = safe_check_vasprintf(strp, fmt, ap);
va_end(ap);
return retval;
}
void write_log(const char* format, ...)
{
pthread_mutex_lock(&fileMutex);
FILE* fp = NULL;
va_list vlist;
char* fmt = NULL;
// Open debug info output file.
if (!(fp = fopen("log.txt", "a+")))
{
pthread_mutex_unlock(&fileMutex);
return;
}
va_start(vlist, format);
safe_check_vasprintf(&fmt, format, vlist);
va_end(vlist);
if (!fmt)
{
pthread_mutex_unlock(&fileMutex);
return;
}
time_t timep;
struct tm* ptm = NULL;
time(&timep);
ptm = localtime(&timep);
fprintf(fp, "[%04d-%02d-%02d-%02d:%02d:%02d][pid:%ld]%s",
ptm->tm_year + 1900,
ptm->tm_mon + 1,
ptm->tm_mday,
ptm->tm_hour,
ptm->tm_min,
ptm->tm_sec,
syscall(SYS_gettid),
fmt);
free(fmt);
fsync(fileno(fp));
fclose(fp);
pthread_mutex_unlock(&fileMutex);
}