logrus源碼:https://github.com/sirupsen/logrusgit
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. 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處理用戶日誌,而後去掉多加的新行
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 }
1. func New() *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寫入日誌
流程分析:
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. 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
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鉤子機制,能夠作到多級別輸出、格式化輸出、多樣化輸出(不一樣輸出目的地)。