一、日志库的特点
该项目是基于C++实现的简单日志库系统,代码方面大约200多行,比较简单,封装的接口很容易看懂,使用起来也十分方便,通过定义的宏来实现打印输出到日志文件中。
二、日志库的需求
- 日志库的存储:文本文件。
- 日志存储的内容:时间、日志级别、文件名、行号、日志内容。
- 日志级别:debug<info<warn<erro<fatal。
- 日志翻滚:通过设置日志文件最大可以存储内容的字节,若文件存储超过当前最大字节数,则重新创建一个新的日志文件用来存储日志内容。
三、日志库的实现
该日志库使用了单例模式来创建日志库对象,从而调用接口,如下是单例模式的代码:
//创建Logger对象
Logger *Logger::getInstance()
{
if(m_instance==nullptr)
{
std::mutex mtx;
mtx.lock();
m_instance=new Logger();
mtx.unlock();
}
return m_instance;
}
日志打印的接口是该日志库的重要部分,如下是日志打印的代码:
/**
* @brief:打印日志
* @param:参数一:日志级别,参数二:打印日志的的文件名,参数三:打印日志所在的行号,参数四:打印格式,参数5:C++中的不定参数
*/
void Logger::log(Level level,const char *fileName,int line,const char *format,...)
{
//过滤低级别日志
if(levels>level)
{
return;
}
if (m_fout.fail())
{
throw std::logic_error("open file failed "+m_fileName);
}
//获取当前时间戳
auto timeTicks=time(nullptr);
//将当前时间戳转化为时间结构体
auto ptns=localtime(&timeTicks);
//存储格式化后的时间
char timeArray[32];
//初始化字符数组
memset(timeArray,0,sizeof(timeArray));
//格式化时间结构体
strftime(timeArray,sizeof(timeArray),"[%Y-%m-%d %H:%M:%S]",ptns);
//日志格式化的结果(日期 日志级别 日志打印位置:日志打印的行号位置)
const char *fmt="%s %s %s:%d ";
//获取格式化后的字符串长度
int size=snprintf(nullptr,0,fmt,timeArray,m_Level[level],fileName,line);
if(size>0)
{
char *buffer=new char[size+1];
memset(buffer,0,size+1);
snprintf(buffer,size+1,fmt,timeArray,m_Level[level],fileName,line);
std::cout<<buffer<<std::endl;
//将字符串写入日志中
m_fout<<buffer;
m_len+=size;
delete []buffer;
}
//获取写入日志内容
va_list arg_ptr;
va_start(arg_ptr,format);
size=vsnprintf(nullptr,0,format,arg_ptr);
va_end(arg_ptr);
if(size>0)
{
char *content=new char[size+1];
va_start(arg_ptr,format);
vsnprintf(content,size+1,format,arg_ptr);
va_end(arg_ptr);
std::cout<<content<<std::endl;
m_fout<<content;
m_len+=size;
delete []content;
}
m_fout<<"\n";
//刷新文件内容
m_fout.flush(

该文章介绍了一个基于C++实现的简单日志库,包括其特点、需求、实现方式和完整代码。日志库使用了单例模式,提供不同级别的日志打印,并实现了日志翻滚功能。此外,还通过宏定义简化了日志打印的调用方式。


被折叠的 条评论
为什么被折叠?



