zoukankan      html  css  js  c++  java
  • log4go的一些改进设想

    log4go 的 4.0.2 版本(https://github.com/ccpaging/log4go/tree/4.0.2)发布以后,
    看了看别的 go 语言日志文件设计。发现了一篇好文:

    log4go 和 logrus 的对比与分析
    https://www.doraemonext.com/archives/783.html

    顺藤摸瓜,找了一窝关于日志的设计。链接如下(含老的链接):

    1. https://github.com/alecthomas/log4go/
      这是log4go项目的“鼻祖”
    2. https://github.com/ngmoco/timber
      实现了结构化,写文件缓冲,热配置等。把log4go重构的面目全非
    3. https://github.com/siddontang/go/tree/master/log
    4. https://github.com/sirupsen/logrus
    5. https://github.com/YoungPioneers/blog4go
    6. https://github.com/YoungPioneers/blog4go-benchmark 各种 go log 的benchmark对比
    7. https://github.com/cihub/seelog

    异步写入日志

    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
    }
    

    扩展程序只要做:

    1. NewXXXLogWrite,初始化扩展要使用的资源。
    2. LogWrite(rec *LogRecord),输出日志记录
    3. Close()中关闭或释放资源
    4. 在应用程序中调用 AddFilter 把新的日志扩展加入到log4go日志结构中

    大功告成了。

    其中,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。

    可扩展的日志接口包括:

    • Send error messages as a mail

    • Make TCP/UDP server and let client pull the messages

    • websocket

    • nanomsg pub/sub

    • Store log messages in MySQL

    自扩展日志配置接口

    log4go 4.0.2 支持 xml 和 json 配置。日志文件的配置有三种方式:

    1. 在应用程序中配置
    2. 单独的配置文件
    3. 存于主程序配置文件中

    日志系统作为一个辅助功能,常常面临的是第三种情况。而配置文件的格式多种多样。例如:

    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
    

    Rotate 的改进设想

    log4go 自带 rotate。

    linux 系统本来是有 logrotate 的,用 cron 定时执行。非常棒的设计。
    简单说,就是写日志文件归写日志文件,不要去做任何转储的判断。程序员可根据系统的实际运行情况,
    自行设置转储的时间间隔。转储时:

    • 加锁。使 log4go 暂时停止写日志,这可能是在 linux 系统中 log4go 没有使用 logrotate 的原因之一。

    • 当前日志文件进行处理。

    • 解锁。尽快恢复 log4go,继续写日志到当前日志文件。

    • 另开 go routine 对历史日志文件进行处理。


    好吧。暂时就想到这么多了。很多有趣的工作正在进行……

    再次感谢 doraemonext@gmail.com 童鞋的好文:log4go 和 logrus 的对比与分析

    请关注:

    https://github.com/ccpaging/log4go

  • 相关阅读:
    git基础教程(三)
    Struts2_day04
    Struts2_day03
    Struts2_day02
    Struts2_day01
    Spring 学习02
    Spring 学习01
    Kafka 温故(五):Kafka的消费编程模型
    Kafka 温故(四):Kafka的安装
    Kafka 温故(三):Kafka的内部机制深入(持久化,分布式,通讯协议)
  • 原文地址:https://www.cnblogs.com/ccpaging/p/7205226.html
Copyright © 2011-2022 走看看