首页 > 代码库 > 一个简单实用的log类

一个简单实用的log类

    自己写一些小代码的时候总是用fprintf来写log,感觉这样不太科学,还是写一个通用的简单带log level的log类,以后就拿来复用吧。这个类实现了非常简单的功能:如果指定了log文件path和name创建一个log文件,并将各种level的写入文件中,否则都打印到屏幕,格式如下:

[DEBUG] : xxxxx

[WARN] : xxxx

[MSG] : xxxxx

代码:

//--------------log.h----------------------
#ifndef __LOG_H__
#define __LOG_H__

#include <cstdarg>
#include <cstdio>
static const char* log_str[] = {
    "DUBUG",
    "MSG",
    "WARN",
    "ERR",
    "FATAL"
};
class Log {
public:
    enum LogLevel {
        DEBUG   = 0,
        MSG     = 1,
        WARN    = 2,
        ERR     = 3,
        FATAL   = 4,
        LOG_LEVEL_CNT,
    };
  
    Log();
    Log(const char* path, const char* name);
public:
    //for the sake of this pointer __attribute__ must shift 1 if not static
   void debug(const char* fmt, ...) 
        __attribute__((format(printf, 2, 3)));
   void msg(const char* fmt, ...) 
        __attribute__((format(printf, 2, 3)));
   void warn(const char* fmt, ...) 
        __attribute__((format(printf, 2, 3)));
   void err(int eval, const char* fmt, ...) 
        __attribute__((format(printf, 3, 4)));
    //void fatal(int eval, const char* fmt, ...) __attribute__((format(printf, 2, 3)));
private:
    void set_log_file(const char* path, const char* name);
    void log_helper(int severity, int log_errno, const char* fmt, va_list ap);
private:
    FILE* _log_file;
};

#endif // __LOG_H__
//----------log.cc------------------------------
#include "log.h"
#include <cstdlib>
#include <cstdio>
#include <errno.h>
#include <string.h>
#include <cassert>
#include <unistd.h>

Log::Log() : _log_file(NULL) 
{

}

Log::Log(const char* path, const char* name)
{
    set_log_file(path, name);

}

void Log::set_log_file(const char* path, const char* name)
{
    assert(path);
    assert(name);
    char file_name[512];//FIXME:hard code
    if ((strlen(path) + strlen(name)) >= 512)
    {
        fprintf(stderr, "\ninvalid file name:%s/%s too long",path,name);
    }
    sprintf(file_name, "%s/%s", path, name);
    _log_file = fopen(file_name, "w+");
    if (!_log_file) 
    {
        printf("seting log file failed use stderr instread");
        return;
    }
}

void Log::debug(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    log_helper(DEBUG, -1, fmt, ap);
    va_end(ap);
}

void Log::msg(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    log_helper(MSG, -1, fmt,ap);
    va_end(ap);
}

void Log::warn(const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    log_helper(WARN, -1, fmt, ap);
    va_end(ap);
}

void Log::err(int eval, const char* fmt, ...)
{
    va_list ap;
    va_start(ap, fmt);
    log_helper(ERR, eval, fmt, ap);
    va_end(ap);
}

void Log::log_helper(int severity, int log_errno, const char* fmt, va_list ap)
{
    char buf[1024];
    size_t len;

    snprintf(buf, sizeof(buf), "[%-5s] : ", log_str[severity]);
    len = strlen(buf);

    if (fmt != NULL)
    {
        snprintf(buf+len, sizeof(buf)-len, fmt, ap);
    }

    if (!_log_file)
    {
        write(STDOUT_FILENO, buf, strlen(buf));
    }
    else
    {
        write(fileno(_log_file), buf, strlen(buf));
    }
    
    if (log_errno >= 0) 
    {
        len = strlen(buf);
        if (len < sizeof(buf) - 3)
        {
            snprintf(buf+len, sizeof(buf) - len, ": %s", strerror(log_errno));
            write(STDERR_FILENO, buf, strlen(buf));
            abort();
        }
    } 
}

int main()
{
    Log log("./", "logfile");
    log.debug("debuging\n");
    log.warn("warning\n");
    log.msg("msging\n");
    return 0;
}
$cat logfile
[DUBUG] : debuging
[WARN ] : warning
[MSG  ] : msging


一个简单实用的log类