log4go 的 4.0.2 版本 (https://github.com/ccpaging/log4go/tree/4.0.2) 发布以后,
看了看别的 go 语言日志文件设计。发现了一篇好文:
log4go 和 logrus 的对比与分析
https://www.doraemonext.com/archives/783.html
顺藤摸瓜,找了一窝关于日志的设计。链接如下(含老的链接):
log4go 的特点之一是异步写入。格式化日志记录、写入文件、转储日志等,都会消耗 CPU 的时间,并可能因为错误处理而阻塞主线程。
但日志系统仅仅是一个辅助功能,所以,保证主线程的高效运行是首先要达到的设计要求。异步写入是可行的方案之一。
其实,log4go 是支持类似 logrus 的扩展特性的。
正好纠结于 color text term log 的设计如何处理的问题…… 因为这个功能使用了第三方包。放在 log4go 里增加了它的依赖性。但这确实又是我特别特别喜欢的一个功能。
不如把 color text term log 做成扩展日志接口。说干就干……
先搞清楚 log4go 中可用的扩展接口:
- type LogWriter interface {
- LogWrite(rec * LogRecord)
- // This should clean up anything lingering about the LogWriter, as it is called before
- // the LogWriter is removed. LogWrite should not be called after Close.
- Close()
- }
- type Filter struct {
- Level Level rec chan * LogRecord // write queue
- closed bool // true if Socket was closed at API level
- LogWriter
- }
- type Logger map[string] * Filter
- func(log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger {
- log[name] = NewFilter(lvl, writer) return log
- }
扩展程序只要做:
,初始化扩展要使用的资源。
- NewXXXLogWrite
,输出日志记录
- LogWrite(rec *LogRecord)
中关闭或释放资源
- Close()
把新的日志扩展加入到 log4go 日志结构中
- AddFilter
大功告成了。
其中,Add filter name 是 Logger map 的索引关键字,log4go 使用了:
"stdout", "file", "syslog"
如果新加的 Filter 的关键字已存在,log4go(4.0.2 以后的版本)将自动关闭原来的,再增加新的。代码如下:
- func(log Logger) AddFilter(name string, lvl Level, writer LogWriter) Logger {
- if filt,
- isExist: =log[name];
- isExist {
- filt.Close() delete(log, name)
- }
- log[name] = NewFilter(lvl, writer) return log
- }
借助扩展接口,log4go 的日志记录可以采用任何你希望的封装格式,例如 xml 和 json,这是已经实现的。
以后还可以扩展 csv(使日志文件导入到 Excel 中)或者 json 封装的 message。
可扩展的日志接口包括:
log4go 4.0.2 支持 xml 和 json 配置。日志文件的配置有三种方式:
日志系统作为一个辅助功能,常常面临的是第三种情况。而配置文件的格式多种多样。例如:
windows ini, linux config, json, xml ...
郁闷。log4go 不应当去支持所有的配置文件格式,而是提供接口,让用户可以根据自己的主程序的设计需要,自行扩展。
也许应该把 xml 和 json 配置文件支持都以扩展配置文件接口的方式实现,而不是跟 log4go 的主程序捆绑在一起。
已经测试了两层缓冲写文件。
第一层是格式化日志记录,一个单独的 go routine,另一个写文件,边格式化记录边写文件,消耗降低了 40%。
第二层是用 bufio。达到一定的缓冲数量如 4k、8k,一次写文件。消耗降低了 80%。
通过判断 Channel 中的记录长度来决定系统何时空闲。当长度为 0 时,后续没有新的日志记录,做一次 Flush()。
这种方案简单。
另外加上 rotate 的优化,效率提高了 5 倍。
- BenchmarkFileLog - 4 200000 10675 ns / op BenchmarkFileNotLogged - 4 20000000 106 ns / op BenchmarkFileUtilLog - 4 200000 10660 ns / op BenchmarkFileUtilNotLog - 4 5000000 239 ns / op BenchmarkCacheFileLog - 4 1000000 2191 ns / op BenchmarkCacheFileNotLogged - 4 20000000 106 ns / op BenchmarkCacheFileUtilLog - 4 500000 3680 ns / op BenchmarkCacheFileUtilNotLog - 4 5000000 240 ns / op
log4go 自带 rotate。
linux 系统本来是有 logrotate 的,用 cron 定时执行。非常棒的设计。
简单说,就是写日志文件归写日志文件,不要去做任何转储的判断。程序员可根据系统的实际运行情况,
自行设置转储的时间间隔。转储时:
好吧。暂时就想到这么多了。很多有趣的工作正在进行……
再次感谢 doraemonext@gmail.com 童鞋的好文:log4go 和 logrus 的对比与分析
请关注:
https://github.com/ccpaging/log4go
来源: http://www.cnblogs.com/ccpaging/p/7205226.html