美文网首页
Go常用库-日志Logrus

Go常用库-日志Logrus

作者: 沉寂之舟 | 来源:发表于2020-02-23 10:53 被阅读0次

    写在前面:

    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

          本文链接:https://www.haomeiwen.com/subject/zygdqhtx.html