自己写一些小代码的时候总是用fprintf来写log,感觉这样不太科学,还是写一个通用的简单带log level的log类,以后就拿来复用吧。这个类实现了非常简单的功能:如果指定了log文件path和name创建一个log文件,并将各种level的写入文件中,否则都打印到屏幕,其使用方式也和printf一样,比如log.msg("xxx%d %s", xx,xxx)。
代码:
//--------------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)
{
vsnprintf(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");
int i = 1;
const char* s = "string";
char c = 'a';
log.debug("debuging %d, %s\n",i, s);
log.warn("warning\n");
log.msg("msging %c\n", c);
return 0;
}
$cat logfile
[DUBUG] : debuging 1, string
[WARN ] : warning
[MSG ] : msging a