golang log4go的日誌輸出優化詳解

2022-09-27 09:00:11 字數 2784 閱讀 7669

前言

在go語言中,自身已經整合了一定log模組,開發者可以使用go語言自身的log包(im 「log」)。也有不少對自身log的開源封裝。對於一些簡單的開發www.cppcns.com,自身的log模組就已經足夠應付。但是對一些大型,複雜的開發,log需要分門別類的輸出,或者通過網路進行輸出,自身log模組將難以應對。

當前也有一些比較重量級的log模組,比如logrus,可以實現比較複雜的功能。這裡介紹乙個輕量級的log模組——log4go

最近又看了一些golang的日誌包和相關的文章,仔細閱讀了go 1.9.2系統提供的log和go-log,產生了對log4go的日誌輸出進行優化的想法。

結構化與multiwriter程式設計客棧

log使用multiwriter支援多個日誌輸出,用 mutex 加鎖解決多執行緒日誌輸出的衝突。log4go 則採用結構化程式設計用 channel 傳遞 logrecord 日誌記錄。

原來以為 channel 的效率比較高……其實這是乙個偽命題。channel 是乙個全域性加鎖的佇列,可以用來加鎖,但效率比較低。因為它多了傳遞資料、協調順序處理、timout等功能,並不僅僅是加鎖。跟mutex不是一回事兒。

log4go 將螢幕日誌輸出 termlog 放在了結構裡,這帶來乙個小問題。當我們用log4go除錯小程式時,執行的太快,termlog 的 goroutine 還沒有執行起來,程式就退出了。結果螢幕上沒有顯示日誌。這個問題只能通過在close()時加延時,等待 goroutine 啟動來解決。然後還要檢查 channel ……

func (f *filter) close()

// sleep at most one second and let go routine running

// drain the log channel before closing

for i := 10; i 程式設計客棧》 0; i--

} // block write channel

f.closed = true

defer f.logwriter.close()

close(f.rec)

if len(f.rec) <= 0

// drain the log channel and write driect

for rec := range f.rec

}log直接將格式化日誌資訊輸出到螢幕,簡單多了。

試著兼顧兩者,在 log4go 中增加了 writer,直接輸出到螢幕。擬將filelog,socketlog作為backend,仍然放在結構裡。這樣,除錯小程式和生產程式可以使用同乙個日誌庫。實測效率略有降低。不知道 windows 下的 colorlog 如何,以後再說。

在log4go中可以通過呼叫setoutput(nil),使out = nil來關閉螢幕輸出。

determine caller func - it's expensive

這句話注釋在 log 原始檔中,log4go也要呼叫runtime.caller(skip int)函式來獲取源檔名和行號。它是昂貴的——消耗了cpu。建議在生產環境中關閉,log.setskip(-1)。如果要對log4go進行封裝,設定log.setskip(log.getskip()+1)。

format優化

其實,這才是文章的主題。

日誌輸出避免不了列印日期和時間,linux 環境下還要列印微秒,說不定還要列印時區。log4go的pattlog.go就是完成這些工作的。

在log裡邊自備了乙個cheap的itoa函式。

// cheap integer to fixed-width decimal ascii. give a negative width to **oid zero-padding.

func itoa(buf *byte, i int, wid int)

// i < 10

b[bp] = byte('0' + i)

*buf = append(*buf, b[bp:]...)

}用這個函式替換日期和時間的字串格式化函式。用byte代替string。

優化前,log4go 的 benchmark。

benchmarkformatlogrecord-4 300000 4480 ns/op

benchmarkconsolelog-4 1000000 1748 ns/op

benchmarkconsolenotlogged-4 20000000 97.5 ns/op

benchmarkconsoleutillog-4 300000 3496 ns/op

benchmarkconsoleutilnotlog-4 20000000 104 ns/op

優化後:

benchmarkformatlogrecord-4 1000000 1443 ns/op

benchmarkconsolelog-4 2000000 982 ns/op

benchmarkconsoleutillog-4 500000 3242 ns/op

benchmarkconsoleutilnotlog-4 30000000 48.4 ns/op

格式化日期時間所花的時間是原來的1/3。

列印無格式化資訊所花的時間是原來的1/2。

benchmarkconsoleutillog呼叫了runtime.caller,格式化資訊,且新增了輸出資訊到螢幕的時間。

字串格式化——比較昂貴。

總結本文標題: golang log4go的日誌輸出優化詳解

本文位址: /jiaoben/golang/216111.html

go開發屬於自己的日誌庫 日誌切分

在檔案日誌中,還存在乙個問題,就是在日誌寫檔案時間長了以後,日誌檔案肯定會非常大,內容非常多,這個時候如果我們需要去定位乙個錯誤,會耗費很長的時間。所以我們需要將日誌檔案進行分割,分割檔案我們可以採用一天分割一次,或者檔案大小達到乙個體積進行分割。log const.go const logspli...

go語言中日誌第三方包log4go的使用

文中通重載入配置檔案使用log4go。二 配置檔案log4go.xml stdout console info file file debug test client.log d t l s m true 10m0k false xmllog xmltrace trace.xml true 100m...

go開發屬於自己的日誌庫 日誌庫需求分析

go的第三方框架中已經有很多日誌庫了,為什麼還要自己寫一遍。俗話說,好記性不如爛筆頭,更何況是程式語言呢。多寫多練才能使自己技術進步。一般來說,日誌庫支援檔案寫入和console顯示,還有的支援寫入在網路服務中,這次的日誌庫,只需要實現檔案寫入和console就可以了。debug 除錯程式,日誌最詳...