logrus学习笔记

栏目: Go · 发布时间: 6年前

1.logrus.Entry结构

1.1 类型

type Entry struct {
    Logger *Logger          // 指向Logger对象
    
    Data Fields             // 包含用户设置的所有字段,Fields结构:type Fields map[string]interface{}
    
    Time time.Time          // log entry创建时间
    
    Level Level             // 可以记录的日志级别为Trace, Debug, Info, Warn, Error, Fatal or Panic
    
    Caller *runtime.Frame   // 带包名的调用时方法,每条日志中记录文件名、函数和行号
    
    Message string          // 要记录的消息
    
    Buffer *bytes.Buffer    // 当在entry.log方法中调用formatter接口实现的方法,Buffer才会被使用到
    
    err string              // 用于记录字段格式化错误
}

1.2 方法

1. func NewEntry(logger *Logger) *Entry
  • 功能说明:创建一个新的Entry对象,接口对包外开放

  • 流程分析:传入Logger对象,初始化Entry.Logger和Entry.Data成员

2. func (entry *Entry) String() (string, error)
  • 功能说明:将Entry中的数据序列化成string,并返回

  • 流程分析:调用entry.Logger.Formatter.Format方法,其中Formatter是一个接口,类型定义如下:

    type Formatter interface {  
          Format(*Entry) ([]byte, error)
      }

    Logger.Formatter在logrus/logger.go中默认初始化为TextFormatter,见方法“func New() *Logger”,或者

    使用方法Logger.SetFormatter初始化,常用的Formatter有:TextFormatter、JSONFormatter,也可自定义实现Formatter接口

3. func (entry *Entry) WithError(err error) *Entry
  • 功能说明:添加err字段到Entry.Data中,返回一个新的entry对象

  • 流程分析:详解见Entry.WithField

4. func (entry *Entry) WithField(key string, value interface{}) *Entry
  • 功能说明:向Entry.Data字段追加{key, value}字段,并返回一个新的Entry对象

  • 流程分析:详解见Entry.WithFields

5. func (entry *Entry) WithFields(fields Fields) *Entry
  • 功能说明:向Entry.Data中依次追加fields中包含的若干个字段,其中Fields结构为type Fields map[string]interface{}

  • 流程分析:

    1.先将Entry.Data中原有的元素添加至临时的data变量中

    2.循环添加fields中元素至data中,若添加失败,则将添加的失败信息追加到Entry.err

    3.返回一个新的Entry对象

6. func (entry *Entry) WithTime(t time.Time) *Entry
  • 功能说明:修改Entry.Time,并返回一个新的Entry对象

  • 流程分析:无

7. func (entry Entry) log(level Level, msg string)
  • 功能说明:日志处理的核心部分

  • 流程分析:

    1.初始化entry的Time、Level、Message字段

    2.如果entry.Logger.ReportCaller为true,则获取运行时调用者信息,初始化entry.Caller字段

    3.调用entry.fireHooks方法,处理所有entry.Logger上注册的Hook,详解见entry.fireHooks方法

    4.给entry.Buffer初始化一个*bytes.Buffer对象,以备entry.write中间隔使用,详解见entry.write方法

    Entry.Caller类型为*runtime.Frame,保存运行时调用者信息,包括文件名、方法名、方法行号等。

    • 系统默认的logger为std,Logger.ReportCaller字段默认为false,可使用Logger.SetReportCaller打开  
8. func (entry *Entry) fireHooks()
  • 功能说明:处理当前一条日志所有的Hook

  • 流程分析:调用entry.Logger.Hooks.Fire方法,实际是处理entry.Level级别对应的所有Hook,详解见Logger.Hooks.Fire方法

9. func (entry *Entry) write()
  • 功能说明:没有Hook的情况下,日志默认处理流程

  • 流程分析:

    1.使用entry.Logger.Formatter.Format格式化日志,返回一个序列化的日志数据

    2.使用entry.Logger.Out.Write写日志,系统默认Logger使用os.Stderr写日志

10. func (entry *Entry) Log(level Level, args ...interface{})
  • 功能说明:不同级别日志fmt.Sprint方式的通用处理方法

  • 流程分析:

    1.如果当前待写的日志级别小于Logger的级别,才会调用entry.log 2.使用fmt.Sprint格式化用户的日志

11. func (entry *Entry) Trace(args ...interface{})
  • 功能说明:entry的TraceLevel级别以fmt.Sprint方式写日志方法,其它级别雷同

  • 流程分析:无

12. func (entry *Entry) Logf(level Level, format string, args ...interface{})
  • 功能说明:不同级别日志以fmt.Sprintf方式的通用处理方法

  • 流程分析:

    1.如果当前待写的日志级别小于Logger的级别,才会调用entry.log 2.使用fmt.Sprintf格式化用户的日志

13. func (entry *Entry) Tracef(args ...interface{})
  • 功能说明:entry的TraceLevel级别以fmt.Sprintf方式写日志方法,其它级别雷同

  • 流程分析:无

14. func (entry *Entry) Logln(level Level, format string, args ...interface{})
  • 功能说明:不同级别日志以fmt.Sprintln并且没有新行的通用处理方法

  • 流程分析:

    1.如果当前待写的日志级别小于Logger的级别,才会调用entry.log 2.调用entry.sprintlnn方法,处理用户日志

15. func (entry *Entry) Traceln(args ...interface{})
  • 功能说明:entry的TraceLevel级别写日志方法,其它级别雷同

  • 流程分析:

15. func (entry *Entry) sprintlnn(args ...interface{}) string
  • 功能说明:试图在每个参数之间加空格,并且去掉fmt.Sprintln多加的新行

  • 流程分析:调用fmt.Sprintln处理用户日志,然后去掉多加的新行

2.logrus.Logger结构

2.1 类型

type Logger struct {
    Out io.Writer           // Logger默认输出位置,系统默认为os.Stderr,可以设置可以更灵活,如:Kafka
                            // 使用Logger.SetOutput()方法设置
    
    Hooks LevelHooks        // 挂载在Logger上Hook集合,二维数组结构,每个日志级别对应一个Hook数组切片
                            // 类型为 type LevelHooks map[Level][]Hook,使用Logger.AddHook()添加
                            
    Formatter Formatter     // 所有日志在输出到Out上之前,都会经过formatter处理,默认为TextFormatter,
                            // 也可以设置为JSONFormatter,当输出为TTY设备,日志会用不同颜色显示,文件不行
                            // 使用Logger.SetFormatter()添加

    ReportCaller bool       // 日志是否记录调用者信息,默认关闭,可以使用Logger.SetReportCaller()设置

    Level Level             // 所有日志是否要经过默认的Out还是Hook,都有Level等级决定,默认为logrus.InfoLevel
                            // 那么只允许Info(), Warn(), Error() and Fatal()处理日志,使用Logger.SetLevel()设置
                            
    mu MutexWrap            // 互斥锁包装,默认打开,可以使用Logger.SetNoLock关闭
    
    entryPool sync.Pool     // 存放临时的Entry对象,减少GC对Entry对象的内存回收,提高Entry对象复用,提高效率
    
    ExitFunc exitFunc       // 日志退出回调函数,默认为os.Exit
}

2.2 方法

1. func New() *Logger
  • 功能说明:创建一个Logger对象
  • 流程分析:无,见类型说明部分
2. func (logger *Logger) newEntry() *Entry
  • 功能说明:创建一个Entry对象

  • 流程分析:先尝试从entryPool中取一个Entry对象。若失败,调用NewEntry创建一个,并返回

3. func (logger *Logger) releaseEntry(entry *Entry)
  • 功能说明:暂时回收Entry对象

  • 流程分析:

    1.entry.Data设置为空map,等待GC下一次运行回收

    2.将entry放入entryPool中,等待GC下一次运行回收

4.  WithField/WithFields/WithError/WithTime
  • 功能说明:这4个方法都是往日志中添加字段,返回一个Entry对象

  • 流程分析:

    1.先创建一个Entry对象

    2.然后分别调用Entry对象的方法,前3个方法是往Entry.Data中添加字段,WithTime是更新Entry写日志时间

    3.通过defer释放创建的Entry对象

5. func (logger *Logger) Logf(level Level, format string, args ...interface{})
  • 功能说明:以fmt.Sprintf格式写日志

  • 流程分析:

    1.若level<= logger.Level,才会处理日志 2.newEntry创建entry对象 3.entry.Logf()处理日志 4.releaseEntry回收entry对象

6. Tracef/Debugf/Infof/Printf/Warnf/Warningf/Errorf/Fatalf
  • 功能说明:以fmt.Sprintf格式格式化用户日志,并写入对应级别的日志

  • 流程分析:

7. func (logger *Logger) Log(level Level, args ...interface{})
  • 功能说明:以fmt.Sprint格式写日志

  • 流程分析:

    1.若level<= logger.Level,才会处理日志 2.newEntry创建entry对象 3.entry.Log()处理日志 4.releaseEntry回收entry对象

8. Trace/Debug/Info/Print/Warn/Warning/Error/Fatal
  • 功能说明:以fmt.Sprint格式格式化用户日志,并写入对应级别的日志

  • 流程分析:

9. func (logger *Logger) Logln(level Level, args ...interface{})
  • 功能说明:不同级别日志以fmt.Sprintln,并且没有新行的通用处理方法

  • 流程分析:

    1.若level<= logger.Level,才会处理日志 2.newEntry创建entry对象 3.entry.Log()处理日志 4.releaseEntry回收entry对象

10. Traceln/Debugln/Infoln/Println/Warnln/Warningln/Errorln/Fatalln
  • 功能说明:以不同级别的方式使用Logln写入日志

  • 流程分析:

3.logrus.Hook结构

1.1 类型

type Hook interface {
	Levels() []Level        // 当前Hook可有效用于哪些级别的日志
	Fire(*Entry) error      // 当前Hook处理方法,将被LevelHooks.Fire方法执行
}

type LevelHooks map[Level][]Hook    // 每级日志对应一个Hook数组,有的写入本地磁盘,有的输送到日志服务器上,有的...

Hook是一个接口,每一个用户自定义的Hook,都必须实现Levels()方法和Fire()方法,

用户可以封装复杂的结构及方法,实现Hook接口,通过Fire()可以将特定格式的日志数据,记录到特定的目的地。
可参考:github.com/rifflock/lfshook、gopkg.in/sohlich/elogrus.v2、github.com/pkg/logrus_amqp

1.2 方法

1. func (hooks LevelHooks) Add(hook Hook)
  • 功能说明:给不同级别日志Hook列表中添加Hook,这些级别由用户实现的Hook.Levels()方法决定

  • 流程分析:以下是Add()方法代码

    for _, level := range hook.Levels() {
          hooks[level] = append(hooks[level], hook)

    循环往Levels()对应的Level列表中,分别添加Hook

2. func (hooks LevelHooks) Fire(level Level, entry *Entry) error
  • 功能说明:处理level级别下所有Hook

  • 流程分析:以下是Fire()方法代码

    for _, hook := range hooks[level] {
          if err := hook.Fire(entry); err != nil {
              return err
          }
      }

    循环处理level对应的hooks列表中的hook,调用每个hook中用户实现的Fire方法,并传入当前logging的entry对象

    * Hook接口:
      Levels()    决定当前Hook将作用于哪些级别的日志
      Fire()      处理当前日志的用户自定义回调处理方法
      
      * LevelHooks结构:
      type LevelHooks map[Level][]Hook,图示如下:
      
      PanicLevel  --> hook1 | hook2 | hook3 | hook4 | hook5 
      FatalLevel  --> hook2 | hook3 | hook4 | hook5   
      ErrorLevel  --> hook2 | hook3 | hook5 
      WarnLevel   --> hook4 | hook5
      InfoLevel   --> hook3
      DebugLevel  --> hook2
      TraceLevel  --> hook2 | hook4
      
      * LevelHooks方法集:
      Add(hook)           给不同级别日志Hook列表中添加hook,这些级别由hook.Levels()决定
      Fire(level, entry)  处理level对应的hook列表中的所有hook,即调用它们各自的Fire()方法

4.Entry与Logger的关系

  • Entry是每条日志记录的实体,每记录一条日志,都会创建一个Entry对象,里面包含具体日志记录的数据字段和方法集。包括:

    Message(用户记录原始数据),Time(日志时间),Level(记录级别),Data(自定义格式字段),Caller(运行时调用者信息),

    Buffer(经过Logger.Formatter处理后的序列化数据),err(日志记录出错记录),Logger(当前Entry所属的Logger)。

  • Logger是一个全局日志工具,包含:

    Out(默认日志记录的Writer),Hooks(Hook机制),Formatter(默认日志记录的格式化器),

    ReportCaller(默认日志记录,记录运行时调用者信息的开关),Level(所有日志记录的过滤级别,包括所有添加的Hook),

    mu(Logger操作互斥锁), entryPool(Entry对象缓冲池),ExitFunc(退出应用程序处理函数,默认为os.EXIT())。

  • 所有记录日志的上层操作接口是由Logger提供,Entry属于后台记录的实体,Logger每提交一条日志,都对应一个Entry对象,并最后交由它处理。

  • Logger可以高度定制,使用Hook钩子机制,可以做到多级别输出、格式化输出、多样化输出(不同输出目的地)。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Tagging

Tagging

Gene Smith / New Riders / 2007-12-27 / GBP 28.99

Tagging is fast becoming one of the primary ways people organize and manage digital information. Tagging complements traditional organizational tools like folders and search on users desktops as well ......一起来看看 《Tagging》 这本书的介绍吧!

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

MD5 加密
MD5 加密

MD5 加密工具

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器