日志模块设计思路图,日志模块设计思路是什么
私人物品的实际分享
模块设计思路日志系统是一个项目不可或缺的一部分,它的存在意义在于可以为我们输出一些关键信息,因为作为开发工程师,我们可以在项目不在线的时候使用本地调试工具调试程序,也可以在调试工具或者控制台上输出一些关键信息定位bug。但是一旦我们开发的程序投入使用,我唯一能依靠的就是log。
设计日志类的必要条件:
存储日志输出的路径(或者指向这个打开文件的文件指针)一个静态输出函数(用来输出一个字符串到一个文件)判断路径中包含的文件是否成功打开。文件打不开的原因有很多,比如文件被占用,文件权限不够等等。在C语言中,我们不能在构造函数中抛出异常(见有效C),所以我们有必要在文件打开失败时,使用这个标志来判断文件是否打开成功,并在后续的日志写入或其他操作之前进行判断和处理。
班级可以锦上添花:
设置不同的日志级别。比如在Ratel后端网络框架中,我简单的把日志分为了四个级别:调试、信息、警告和错误级别都在不断上升。用宏定义简化输出(如果不理解会在下面的代码中体现)。使用singleton模式,保证全世界只有一个日志,方便输出和设计日志锁。写日志时锁定日志的设计大致可以分为多线程锁定机制和单线程池异步排队两种设计思路。
日志输出时要设计的尽量详细,比如包括线程号、文件名、行号、打印时间等相关信息,更有利于定位和解决问题。
现在我们有了大概的思路,其他细节看源代码就知道了。接下来,我们来详细说说输出函数。
我认为日志系统的输出函数最好用可变参数设计,并且可以格式化字符串,因为这是日志所必需的,否则字符串在被传入日志系统的输出函数之前必须被格式化。这样的设计很不友好,最好留给日志系统来处理。
void CLog:output(Log_level级别,char* fmt,){
如果(!Isok_open) assert(日志文件打开失败);
//获取变量参数以开始
va _ list va
va_start(va,fmt);
int strlength=vsn printf((char *)nullptr,0,fmt,va);//用于计算所需长度
va _ end(va);
STD:string stroutput;
str output . resize(strlength 1);//添加结尾\0
va _ list vb
va_start(vb,fmt);
vsnprintf((char *)stroutput . data()、stroutput.capacity()、fmt、VB);//将格式化的放入变量中
va _ end(VB);
//获取变量参数结束
STD:string strhead=make head(level);//根据传入日志的级别构造必要的日志头。
strhead=stroutput \ n//添加日志头和日志内容。
fp.write(strhead.c_str()、strhead . size());
FP . flush();
返回;
}文中提到的日志的分类和宏定义设计。
枚举类Log_level{
LOG_DEBUG,//调试输出
LOG_INFO,//信息输出
LOG_WARNING,//警告信息
LOG_ERROR //错误信息
};
//使用宏定义来简化调用,使用起来更方便。
#定义日志(级别、)CLOG: OUTPUT (level,_ _ va _ args _ _)//一般的日志输出方便下面的宏定义。
# definelogd(.)log (log _ level: log _ debug,_ _ va _ args _ _)//对应调试输出打印。
# definelogi(.)log (log _ level: log _ info,_ _ va _ args _ _)//对应信息输出和打印。
#定义logw(.)log (log _ level: log _ warning,_ _ va _ args _ _)//打印对应的警告信息。
#定义日志(.)log (log _ level: log _ error,_ _ va _ args _ _)//错误信息对应的日志打印系统是一个比较核心的模块,要尽可能考虑全面,为以后定位和调试在线问题提供方便。不能说一劳永逸,但是以后可以节省很多时间和精力。
,
郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。