先上Github地址: lumberjack。
本篇博文中的示例为logrus + lumberjack。
因为没有找到很好的中文示例,我只能读文档了。所以本篇文章中的内容不会很高级,但会将其github上README文档中的内容简略写出。有时你可能会发现我完全是在翻译文档,请不要感到意外。
注意
这个包是v2.0版本的lumberjack,因此应该用 gopkg.in导入。[博主注: 不是很明白这里有什么因果关系]
1 | import "gopkg.in/natefinch/lumberjack.v2" |
Lumberjack故意把自己设计成日志基础的一部分,它不是一个集全面于一体的解决方案,相反,它是在日志底层可插拔的组件,它可以简单的控制日志写入的文件。 [博主: 有机翻那味儿了]
Lumberjack在任何使用io.Writer作为写入的日志库中都表现良好,包括标准库中的log包。
Lumberjack假设只有一个进程在写入到输出文件,在同一台机器上多进程使用相同的lumberjack配置将会造成lumberjack出现不当的行为。[博主注: 因为不加锁的多进程/线程对同一文件进行读写是不安全的]
示例
标准库中的log包只需要在应用启动时调用SetOutput函数就可以使用lumberjack。
代码:
1 | log.SetOutput(&lumberjack.Logger{ |
logger类型
1 | type Logger struct { |
Logger是一个写入指定文件名的io.WriteCloser类型。
Logger会打开日志文件,如果是第一次打开(即文件此时不存在),则会创建文件。如果文件已经存在并且文件大小小于MaxSize规定的MB,lumberjack将会打开文件并且向这个文件中添加内容。如果文件已经存在了并且文件大小>=MaxSize MB,这个文件会立即被重命名,lumberjack会添加当前时间的时间戳在文件名的扩展名之前(如果没有扩展名 时间戳将会添加在文件名之后),然后一个新的文件会以原来文件的文件名被创建。[博主注: 就是传入Logger的Filename]
当一次写入会造成当前文件的大小超过MaxSize MB时,当前的文件将会被关闭,重命名,然后一个新的日志文件将会被以原来的文件名被创建。因此,传入Logger的文件名将总是”当前”文件名。
麻了,README中关于文件名的解释的太多了,我眼睛看酸了,不翻译了。剩下的内容看原文吧:
1 | Backups use the log file name given to Logger, in the form name-timestamp.ext where name is the filename without the extension, timestamp is the time at which the log was rotated formatted with the time.Time format of 2006-01-02T15-04-05.000 and the extension is the original extension. For example, if your Logger.Filename is /var/log/foo/server.log, a backup created at 6:30pm on Nov 11 2016 would use the filename /var/log/foo/server-2016-11-04T18-30-00.000.log |
清除旧文件
当一个新的日志文件被创建时,旧的日志文件就有可能被删除。根据时间戳,最近创建的文件将会被保留,保留的文件的数量等于MaxBackups,如果MaxBackups为0,则全部都会被保留。根据时间戳,所有比MaxAge规定的天数旧的文件都会被删除,不管是否达到了MaxBackups规定的最大保留数。注意,时间戳中编码的时间是轮转时间,可能与文件最后一次写入的时间有所不同。
如果MaxAge和MaxBackups都为0,那么旧文件将不会被删除。
func (*Logger) Close
1 | func (l *Logger) Close() error |
Close实现了io.Closer,它会关掉当前的日志文件。
func (*Logger) Rotate
1 | func (l *Logger) Rotate() error |
Rotate会使Logger关闭当前存在的日志文件并且立即创建一个新的日志文件。这个函数在想要在轮转规则之外发起日志轮转时是相当有用的,例如响应SIGHUP。在轮转之后,它会根据正常的轮转规则清除旧文件。
示例
这个示例演示了如何在响应SIGHUP时轮转。
1 | l := &lumberjack.Logger{} |
func (*Logger) Write
1 | func (l *Logger) Write(p []byte) (n int, err error) |
Write实现了io.Writer。如果一次写入将会造成日志文件大于MaxSize,那么这个文件将会被关闭,并以文件名中包含当前时间时间戳的方式重命名,之后将会以原来的文件名创建一个新的文件。如果一次写入的字节大于MaxSize,那么这个函数将会返回错误。
logrus+lumberjack示例
我翻译了这么长的文档,就为了等这一刻。我给logrus的logger添加了一个钩子,这个钩子会在使用Info级别输出时使用SetOutput函数将lumberjack的logger传入logrus的logger,之后logrus的logger就会调用这个lumberjack的logger的Write方法。
示例:
1 | // main.go |
“gray-ice.com/test/hooks”的定义:
1 | // gray-ice.com/test/hooks/hooks.go |
运行程序后,log文件夹中多出了两个文件:
1 | ~/codeSet/goCode/test » cd log |