日志库考虑因素:
级别: 最好是 always, err, warn, notice, info, debug, verbos 几个级别.
性能: 如果设置级别低, 应该对程序性能没有任何影响.(不要先format)
不需要显示初始化.
打印代码行.
可以动态设置日志级别
因为标准库不支持日志级别, 所以造轮子的需求很强烈.
/usr/local/go/src/pkg/log/log.go
~/go/src/github.com/astaxie/beego/logs http://beego.me/docs/module/logs.md
遵守 RFC5424 log message levels:
const ( LevelEmergency = iota LevelAlert LevelCritical LevelError LevelWarning LevelNotice LevelInformational LevelDebug ) Numerical Severity Code 0 Emergency: system is unusable 1 Alert: action must be taken immediately 2 Critical: critical conditions 3 Error: error conditions 4 Warning: warning conditions 5 Notice: normal but significant condition 6 Informational: informational messages 7 Debug: debug-level messages
问题:
必须初始化并持有一个句柄才能打印日志:
log := NewLogger(10000) log.Trace("trace %s %s","param1","param2")
打日志先format再去判断级别, 性能差:
// Log WARNING level message. func (bl *BeeLogger) Warning(format string, v ...interface{}) { msg := fmt.Sprintf("[W] "+format, v...) bl.writerMsg(LevelWarning, msg) } func (bl *BeeLogger) writerMsg(loglevel int, msg string) error { if loglevel > bl.level { return nil }
为了兼容老代码, 代码中冗余函数较多.
File logging with rotation (size, linecount, daily) and custom output formats Console logging Network logging via JSON and TCP/UDP
级别很奇怪:
const ( FINEST level = iota FINE DEBUG TRACE INFO WARNING ERROR CRITICAL )
和常见的顺序是反的.. 没有NOTICE.
使用上也需要初始化一个实例再调用实例的方法.
级别差不多, 问题不大:
const ( LOG_FATAL = LogType(0x1) LOG_ERROR = LogType(0x2) LOG_WARNING = LogType(0x4) LOG_INFO = LogType(0x8) LOG_DEBUG = LogType(0x10) )
对几个库做了benchmark, (代码: https://github.com/idning/golog/blob/master/benchmark/log_benchmark.go )
结果如下:
go run benchmark/log_benchmark.go qps of dummy1: 2727908735 qps of dummy2: 552468326 qps of variadic: 6151799 qps of logging: 4003802 qps of golog: 5986678 qps of beelog: 1170780 <beego 性能确实较差>
测试发现, 使用变参形式就会导致性能很差:
Debug("hello %s", "world") // 1. 100w/s Debug("hello world") // 2. 1000w/s 性能好10倍.
对于变参写法, 通过profiling发现, 此时90%的时间都用于GC,
原因在于, 变参的这种写法, 每次要把参数转为 interface 构成的 slice, 产生了很多对象. 所以gc时间很重.
在benchmark里面我也加了 variadic测试, 对于一个空函数, 也只能达到600w/s 的性能.