logrus學習筆記

logrus源碼:https://github.com/sirupsen/logrusgit

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對象,接口對包外開放github

  • 流程分析:傳入Logger對象,初始化Entry.Logger和Entry.Data成員數組

2. func (entry *Entry) String() (string, error)
  • 功能說明:將Entry中的數據序列化成string,並返回服務器

  • 流程分析:調用entry.Logger.Formatter.Format方法,其中Formatter是一個接口,類型定義以下:app

    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.WithFieldspa

4. func (entry *Entry) WithField(key string, value interface{}) *Entry
  • 功能說明:向Entry.Data字段追加{key, value}字段,並返回一個新的Entry對象日誌

  • 流程分析:詳解見Entry.WithFieldscode

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.v二、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方法集:
    Add(hook)           給不一樣級別日誌Hook列表中添加hook,這些級別由hook.Levels()決定
    Fire(level, entry)  處理level對應的hook列表中的全部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

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鉤子機制,能夠作到多級別輸出、格式化輸出、多樣化輸出(不一樣輸出目的地)。

相關文章
相關標籤/搜索