Go常用库-日志Logrus

写在前面:

Logrus版本: v1.4.2

logrus相当于标准库log包的加强版,是目前最流行的日志库.它在完全兼容原生方法的基础上,增加了格式化日志的能力,简单易用,使得日志更为工整.其源码代码量并不大,通读一下便于后续理解使用.

time="2015-03-26T01:27:38-04:00" level=debug msg="Started observing beach" animal=walrus number=8
time="2015-03-26T01:27:38-04:00" level=info msg="A group of walrus emerges from the ocean" animal=walrus size=10
time="2015-03-26T01:27:38-04:00" level=warning msg="The group's number increased tremendously!" number=122 omg=true
time="2015-03-26T01:27:38-04:00" level=debug msg="Temperature changes" temperature=-4
time="2015-03-26T01:27:38-04:00" level=panic msg="It's over 9000!" animal=orca size=9009

一. Logrus官网-并没有

Logrus的特点就是使用简单,并不需要特别搭个网站说明,文档就是项目的readme.
sirupsen/logrus: Structured, pluggable logging for Go. - GitHub
中文版的简单介绍:
Logrus日志框架

二. 使用+说明:

logrus日志使用详解
Go进阶10:logrus日志使用教程
源码中 example_**.go, 和readme中说明的一样的,只是更加完整.

三. Logrus源码(v1.4.2)

1. exported.go

这是包的入口,在这里定义了包级变量std(实际是logger)作为标准库log替代,并声明了包方法WithField(),Debug()等供外部调用.实际就是调用logger结构的方法.

2. logrus.go和logger.go

logrus.go是包的类型说明文件,定义了Fields是map[string]interface{}类型;Level的枚举;StdLogger和FieldLogger两个接口.
logger.go是整个包的核心,当我们调用日志方法时候,就是它在工作.当然它作为包级变量也不是自己去实干,而是根据参数newEntry出来,让Entry实际完成写日志的动作.

3. entry.go

Entry结构是真正干活的,它保持需要记录日志的要素,包括通用(Time,Level)和自定义(Data)

type Entry struct {
    Logger *Logger

    // Contains all the fields set by the user.
    Data Fields

    // Time at which the log entry was created
    Time time.Time

    // Level the log entry was logged at: Trace, Debug, Info, Warn, Error, Fatal or Panic
    // This field will be set on entry firing and the value will be equal to the one in Logger struct field.
    Level Level

    // Calling method, with package name
    Caller *runtime.Frame

    // Message passed to Trace, Debug, Info, Warn, Error, Fatal or Panic
    Message string

    // When formatter is called in entry.log(), a Buffer may be set to entry
    Buffer *bytes.Buffer

    // Contains the context set by the user. Useful for hook processing etc.
    Context context.Context

    // err may contain a field formatting error
    err string
}

其核心方法是log(),里面把打印的内容放入buffer,然后调用entry.write(),写入Logger.Out.(由于Logger.Out(通常是日志文件)可能会并冲突,因而write()方法是有进行加锁的.)

P.S.1. 从log()方法可以看出,entry至少有Time,Level,Message三部分,这样就能格式化出基本的格式.
P.S.2. GO并没有java的Trace()机制,要实现打印调用栈就要用到runtime.Frame,Logrus使用getCaller()方法跟踪函数的调用情况,从而实现调用栈的打印.

4. formatter.go以及son_formatter.go和text_formatter.go实现

formatter是logrus扩展处,它从Entry构造出需要打印的data(实际就是Map)结构,再转换为实际输出的[]byte

Logrus提供了两种标准实现:

  • JSON主要就是用Encoder完成Json的序列化
  • Text复杂点,特别如果设置corlored,还要调用printColored()实现彩色字体.(这个真没细看...)

5. hooks.go和hooks目录

logrus实现了Hook机制,在entry的log()方法的write方法前,会调用entry.fireHooks()执行钩子函数.这个时候会把entry传递给Hook,让钩子进行自定义操作.
hooks.go定义了包变量LevelHooks(根据日志级别登记所有Hooks),和Hook接口:

type Hook interface {
    Levels() []Level
    Fire(*Entry) error
}

hooks目录定义了一个系统钩子,其writer为*syslog.Writer,这样使用这个Hook,就会在各种日志级别也写一份日志到这个Writer中.Logrus官方整理了各种Hook:
https://github.com/sirupsen/logrus/wiki/Hooks
例如KafkaLogrus可以同步Log到kafaka,Logstash可以同步Log到ELK

6. 其他

  • terminal_check_*.go: 检测各种操作系统是否有控制台.
  • writter.go: 对io.Writer的实现,使得Logrus能够传给其他Lib用,如http.Server或者替换系统的标准输出:
log.SetOutput(logger.Writer())

四.其他推荐阅读文章

Logrus -- Go 的结构化 logger

Golang logrus的高级配置(hook, logrotate)

Logrus源码阅读(1)--基本用法

Logrus源码阅读(2)--logrus生命周期

你可能感兴趣的:(Go常用库-日志Logrus)