日志

背景

封装日志API供平时代码学习使用,顺便学习一下相关的知识点:

  • 变参函数
  • 时间的格式化输出

c语言版本

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 ", log_output); return nWrittenBytes; } #endif

测试

#include "log.h"
 
int main()
{
    if(LogInit(LOG_INFOR, "forever.log"))
    {   
        printf("log init failed.
");
        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

c++版本

log.h

#ifndef _LOG_H_                                                                                                                                                                                                                                                                
#define _LOG_H_

enum LogLevel {
    ALL = 0,
    INFO,
    WARN,
    ERR 
};

class LOG {

public:
    static void INFO(const char *msg, ...);
    static void WARN(const char *msg, ...);
    static void ERR(const char *msg, ...);
    static void SetLogLevel(LogLevel level) { logLevel = level; }
private:
    static void write(const char *msg);
    static LogLevel logLevel;
};

#endif

log.cc

#include "log.h"                                                                                                                                                                                                                                                               
#include <stdarg.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <stdio.h>

LogLevel LOG::logLevel = LogLevel::ALL;

void LOG::write(const char *msg)
{
    struct timeval tv; 
    struct tm tm_time;
    long mseconds, useconds;
    static char cur_timestr[32] = ""; 
    gettimeofday(&tv, NULL);
    gmtime_r(&tv.tv_sec, &tm_time);
    mseconds = tv.tv_usec / 1000;
    useconds = tv.tv_usec % 1000;
    sprintf(cur_timestr, "%d/%d/%d %d:%d:%d:%ld:%ld", 
            tm_time.tm_year +1900, tm_time.tm_mon, tm_time.tm_mday, 
            tm_time.tm_hour +8, tm_time.tm_min, tm_time.tm_sec, 
            mseconds, useconds);

    printf("%s %s", cur_timestr, msg);
}
void LOG::INFO(const char *msg, ...)
{
    if (logLevel > LogLevel::INFO) {return;}
    if (!msg) {return;}
    char pTemp[1024] = { 0 };
    va_list arg_ptr;
    va_start(arg_ptr, msg);
    vsprintf(pTemp + strlen(pTemp), msg, arg_ptr);
    va_end(arg_ptr);

    LOG::write(pTemp);
}
void LOG::WARN(const char *msg, ...)
{
    if (logLevel > LogLevel::WARN)
        return;

    if (!msg) {return;}
    char pTemp[1024] = { 0 };
    va_list arg_ptr;
    va_start(arg_ptr, msg);
    vsprintf(pTemp + strlen(pTemp), msg, arg_ptr);
    va_end(arg_ptr);

    LOG::write(pTemp);
}
void LOG::ERR(const char *msg, ...)
{
    if (!msg) {return;}
    char pTemp[1024] = { 0 };
    va_list arg_ptr;
    va_start(arg_ptr, msg);
    vsprintf(pTemp + strlen(pTemp), msg, arg_ptr);
    va_end(arg_ptr);

    LOG::write(pTemp);
}

测试

#include "log.h"
#include <iostream>
int main()                                                                                                                                                                                                                                                                     
{
    LOG::SetLogLevel(LogLevel::ERR);

    LOG::INFO("%s
", "久旱逢甘露");
    LOG::WARN("%s
", "他乡遇故知");
    LOG::ERR("%s
", "洞房花烛夜");
    LOG::ERR("%s
", "金榜题名时");
}

日志输出

orejia@debian9:log$ ./demo 
2019/11/29 15:1:49:255:949 洞房花烛夜
2019/11/29 15:1:49:256:25 金榜题名时

参考资料

简洁版 https://blog.csdn.net/iw1210/article/details/53591565 

纯C日志函数库zlog使用手册 http://hardysimpson.github.io/zlog/UsersGuide-CN.html#htoc1

C-log https://www.cnblogs.com/prophet-ss/p/8025825.html

日志切割 https://www.cnblogs.com/areyouready/p/9334872.html

日志切割之logrotate https://www.cnblogs.com/clsn/p/8428257.html

原文地址:https://www.cnblogs.com/orejia/p/12114806.html