Easylog一种简单的适合C++大工程的日志方式

最近在做项目时候,遇到了写日志比较麻烦的问题,需要考虑多线程而且不同类实例之间如果要写入同一个日志文件还有考虑线程安全问题,另外因为项目划分架构存在多级结构,一部分类要写入A 日志文件,另一部分要写入B日志文件.既要满足可以写多文件,又要满足写同一个文件线程安全.
  从网速上找了一些开源的代码,但是要么太过简单无法满足需求,要么太复杂,需要安装库,配置文件等,于是参考别人的经验,自己写了一个日志系统,实现了多文件日志,线程安全,日志分等级的功能.源代码在github上可以直接下载,只要easylog.cpp和easylog.h文件就可是了.在这里分享给大家,也希望大家多提意见.
  源代码下载:
  https://github.com/RedCrab1/Easylog
  
  该代码需要在编译时支持C++11和多线程,共200多行代码也可以根据自己需要进行修改比较容易.

先讲一下代码设计思想.
  1.首先采用单例的模式创建一个日志工厂类LogFactory. 这样可以保证在不同的类中引用该日志系统时保持唯一,不会被创建出多个实例导致不能实现日志的线程互斥.
  2.既然创建了工厂类,目的当然是批量生成日志类.之所以要批量生成日志类,也是为了实现多文件日志功能.根据设定的logID不同生成不同的日志文件,这样,通过指定不同的logID,可以将日志写入不同的文件中.当前还要设定要写入日志的文件夹位置.如过与已经创建的logID相同,也可以不指定日志文件夹路径.
  3.重点说日志类,考虑一个比较大成熟的项目,为了调试频繁的频繁的增加删除log,并不是一个很好的方式,因为一旦修改源代码重新编译可能要调试复现的bug就不再复现了(这个这实际情况中还是比较棘手的),所有我们考虑的是预先埋入log,对log分等级,这样根据实际需要是输出一部分log,还是全部输出进行最细化的调试.这里对log分了ERROR, WARN, INFO, DEBUG, TRACE五个等级.通过setRecordlevel()设置等级,高于设定等级的log才会被输出.而传入的参数完全可以通过配置文件设置,这样能保证可执行文件不动的情况下,输出不同的日志.
  4.考虑我自己项目的实际情况是在嵌入式环境中,有时候并不能及时的查看Log.所有对日志文件的处理是根据日期进行创建的.在开始传入的日志文件夹下根据日期创建日志文件.以日期命名的方式的话,可以保证文件不至于过大,也不会被覆盖,以后查看起来可以通过时间查找比较方便.我想这也是一个比较好的方式.

上面讲了那个多,也只是为加深对日志系统的理解.下面就直接讲如何使用.使用起来还是比较简单的.
在当前文件夹下创建举例
首先创建日志,设置日志等级:

shared_ptr<EasyLog> logger = LogFactory::instance()->getEasylog("Sample1", "./");
logger->setRecordlevel(INFO);

这样日志就创建完成了.如果想写入同一个日志文件直接把上面的代码复制到其他位置就可以,只要指定的第一个参数logID相同就会被写入同一个日志文件.如果想写入另一个文件,指定不同的另一个logID就可以了.如果想直接输出在屏幕上,那在第一次指定logID的位置,后面的第二个参数日志文件夹就不要指定了,空的化就会直接输出在屏幕上.
 设置等级的参数建议通过配置文件进行设定,这样对于较大的工程调试起来非常方便.初始化就这么简单两行就完成了.

接下来是如何写日志,由于一些原因,虽然代码是C++写的,但是写日志的方式还是保留了C的风格:

logger->WriteLog(ERROR, "this is a test error log: %s", str.c_str());

只需要这一行代码就搞定了.

上面说的有些简单,我自己写了一个测试代码进行了几种方式的测试:

int main()
{ 	
    //创建一个log文件,id为"Sample1", logid相同时会写入同一个log文件.
 	SampleA  a1("Sample1", "./");
 	//写入sample1.log中 	
 	a1.testfunc("a1");  	
 	
 	//创建一个对象a2,logid仍然为"Sample1", 该对象的log会写入同一个文件. 	
 	SampleA  a2("Sample1", "./"); 	
 	a2.testfunc("a2");  	
 	
 	//创建对象a3, logid仍然为"Sample1", 但是log文件不指定,此时仍会写入同一个文件 	
 	SampleA  a3("Sample1", " "); 	
 	a3.testfunc("a3");  	
 	
 	//使用SampleB创建对象b1, 仍指定logID为"Sample1", log会写入同一个文件 	
 	SampleB b1("Sample1", " "); 	
 	b1.testfunc("b1");  	
 	
 	//写log与id有关,id相同会写入同一个文件,如果不同会写入不同的文件 	
 	SampleB  b2("Sample2", "./"); 	
 	b2.testfunc("b2");  	
 	
 	//当第一次使用一个新的id, 并不指定文件路径时,直接输出在屏幕上 	
 	SampleB  b3("Sample3", " "); 	
 	b3.testfunc("b3");    	
 	return 0;
}

将测试代码编译后执行效果:
有输出到屏幕的Log,有输出到Sample1下的log, 有输出到Sample2下的log.

$:~/Desktop/sample/easylog$ ./test 
[2019-10-05 11:44:48] [ERROR] this is a test error log: b3
[2019-10-05 11:44:48] [INFO] this is a test INFO log: b3
$:~/Desktop/sample/easylog$ ls
easylog.cpp  easylog.h  main.cpp  Sample1  Sample2  test
$:~/Desktop/sample/easylog$ cd Sample1
$:~/Desktop/sample/easylog/Sample1$ ls
20191005.log
$:~/Desktop/sample/easylog/Sample1$ cat 20191005.log 
[2019-10-05 11:44:48] [ERROR] this is a test error log: a1
[2019-10-05 11:44:48] [INFO] this is a test INFO log: a1
[2019-10-05 11:44:48] [ERROR] this is a test error log: a2
[2019-10-05 11:44:48] [INFO] this is a test INFO log: a2
[2019-10-05 11:44:48] [ERROR] this is a test error log: a3
[2019-10-05 11:44:48] [INFO] this is a test INFO log: a3
[2019-10-05 11:44:48] [ERROR] this is a test error log: b1
[2019-10-05 11:44:48] [INFO] this is a test INFO log: b1
$:~/Desktop/sample/easylog/Sample1$ cd ../Sample2/
$:~/Desktop/sample/easylog/Sample2$ ls
20191005.log
$:~/Desktop/sample/easylog/Sample2$ cat 20191005.log 
[2019-10-05 11:44:48] [ERROR] this is a test error log: b2
[2019-10-05 11:44:48] [INFO] this is a test INFO log: b2

以上是日志系统的原理和使用,使用了两种设计模式,代码也比较简单,对于大神来说有点班门弄斧,不过对于初级程序员还有有一定借鉴意义的,希望大家支持.

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值