linux下c语言简单实现写日志函数(多线程安全)

14 篇文章 1 订阅

调用时包含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);
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值