1. 日志要求
对于一个日志来说,我们任认为其应该具有以下的内容
1. 日志时间
2. 日志等级
3. 日志内容
4. 文件名称与行号
在此基础上我们对不同的日志做出分级,即
info: 常规信息
warning: 报警信号
error: 严重信号,可能需要立即处理
fatal: 致命信号
Debug: 调试信息
2. 代码实现
#pragma once
#include <iostream>
#include <time.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#define SIZE 1024
#define Info 0
#define Debug 1
#define Warning 2
#define Error 3
#define Fatal 4
#define Screen 1
#define Onefile 2
#define Classfile 3
#define LogFile "log.txt"
class Log
{
public:
// 构造函数
Log()
{
// 设置默认日志模式为向屏幕打印
printMethod = Screen;
path = "./log/";
}
// 调整日志模式
void Enable(int method)
{
printMethod = method;
}
// 返回分级字符串
std::string levelToString(int level)
{
switch (level)
{
case Info:
return "Info";
case Debug:
return "Debug";
case Warning:
return "Warning";
case Error:
return "Error";
case Fatal:
return "Fatal";
default:
return "None";
}
}
// 根据不同模式,向不同位置打印日志
void printLog(int level, const std::string &logtxt)
{
switch (printMethod)
{
case Screen:
std::cout << logtxt;
break;
case Onefile:
printOneFile(LogFile, logtxt);
break;
case Classfile:
printClassFile(level, logtxt);
break;
default:
break;
}
}
// 向一个文件中写入日志
void printOneFile(const std::string &logname, const std::string &logtxt)
{
std::string _logname = path + logname;
int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); // "log.txt"
if (fd < 0)
return;
write(fd, logtxt.c_str(), logtxt.size());
close(fd);
}
// 向一个文件夹中写入日志
void printClassFile(int level, const std::string &logtxt)
{
std::string filename = LogFile;
filename += ".";
filename += levelToString(level); // "log.txt.Debug/Warning/Fatal"
printOneFile(filename, logtxt);
}
~Log()
{}
// 运算符重载 便于直接使用
void operator()(int level, const char *format, ...)
{
time_t t = time(nullptr);
struct tm *ctime = localtime(&t);
// leftbuffer - 存储等级信息与日期信息
char leftbuffer[SIZE];
snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(),
ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday,
ctime->tm_hour, ctime->tm_min, ctime->tm_sec);
// 将可变参数中传入的参数写入到rightbuffer中
// rightbuffer - 存储用户提示
va_list s;
va_start(s, format);
char rightbuffer[SIZE];
vsnprintf(rightbuffer, sizeof(rightbuffer), format, s);
va_end(s);
// 格式:默认部分+自定义部分
char logtxt[SIZE * 2];
snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer);
printLog(level, logtxt);
}
private:
int printMethod;
std::string path;
};
3. 使用测试
#include "Log.hpp"
int main()
{
// 创建Log对象
Log lg;
lg(Info, "启动成功");
sleep(1);
lg(Debug, "这是一个调试信息");
sleep(1);
lg(Warning, "这是一个警告信息");
sleep(1);
lg(Error, "这是一个错误信息");
sleep(1);
lg(Fatal, "这是一个致命错误信息");
return 0;
}
测试效果