Golang日志入門與技術(shù)選型

參考文檔:https://liwenzhou.com/posts/Go/zap/

無論是軟件開發(fā)的調(diào)試階段還是軟件上線之后的運行階段肺素,日志一直都是非常重要的一個環(huán)節(jié)恨锚,我們也應該養(yǎng)成在程序中記錄日志的好習慣。
Go 語言內(nèi)置的log包實現(xiàn)了簡單的日志服務倍靡。本文介紹了標準庫log的基本使用和第三日志庫的選型和使用猴伶。

1、原生Logger

log 包定義了 Logger 類型,該類型提供了一些格式化輸出的方法他挎。本包也提供了一個預定義的 “標準”logger筝尾,可以通過調(diào)用函數(shù)Print系列(Print|Printf|Println)、Fatal系列(Fatal|Fatalf|Fatalln)办桨、和Panic系列(Panic|Panicf|Panicln)來使用筹淫,比自行創(chuàng)建一個 logger 對象更容易使用。

例如呢撞,我們可以像下面的代碼一樣直接通過log包來調(diào)用上面提到的方法损姜,默認它們會將日志信息打印到終端界面:

package main

import (
    "log"
)

func main() {
    log.Println("這是一條很普通的日志。")
    v := "很普通的"
    log.Printf("這是一條%s日志殊霞。\n", v)
    log.Fatalln("這是一條會觸發(fā)fatal的日志摧阅。")
    log.Panicln("這是一條會觸發(fā)panic的日志。")
}

編譯并執(zhí)行上面的代碼會得到如下輸出:

2017/06/19 14:04:17 這是一條很普通的日志绷蹲。
2017/06/19 14:04:17 這是一條很普通的日志棒卷。
2017/06/19 14:04:17 這是一條會觸發(fā)fatal的日志。

logger 會打印每條日志信息的日期祝钢、時間比规,默認輸出到系統(tǒng)的標準錯誤。Fatal 系列函數(shù)會在寫入日志信息后調(diào)用 os.Exit(1)太颤。Panic 系列函數(shù)會在寫入日志信息后 panic苞俘。

1.1 配置 logger配置

默認情況下的 logger 只會提供日志的時間信息盹沈,但是很多情況下我們希望得到更多信息龄章,比如記錄該日志的文件名和行號等。log標準庫中為我們提供了定制這些設置的方法乞封。
log標準庫中的Flags函數(shù)會返回標準 logger 的輸出配置做裙,而SetFlags函數(shù)用來設置標準 logger 的輸出配置。

func Flags() int
func SetFlags(flag int)

1.1.1 flag 選項

log標準庫提供了如下的 flag 選項肃晚,它們是一系列定義好的常量锚贱。

const (
    // 控制輸出日志信息的細節(jié),不能控制輸出的順序和格式关串。
    // 輸出的日志在每一項后會有一個冒號分隔:例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
    Ldate         = 1 << iota     // 日期:2009/01/23
    Ltime                         // 時間:01:23:23
    Lmicroseconds                 // 微秒級別的時間:01:23:23.123123(用于增強Ltime位)
    Llongfile                     // 文件全路徑名+行號: /a/b/c/d.go:23
    Lshortfile                    // 文件名+行號:d.go:23(會覆蓋掉Llongfile)
    LUTC                          // 使用UTC時間
    LstdFlags     = Ldate | Ltime // 標準logger的初始值
)

下面我們在記錄日志之前先設置一下標準 logger 的輸出選項如下:

func main() {
    log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
    log.Println("這是一條很普通的日志拧廊。")
}

編譯執(zhí)行后得到的輸出結(jié)果如下:

2017/06/19 14:05:17.494943 .../log_demo/main.go:11: 這是一條很普通的日志。

1.1.2 配置日志前綴

log標準庫中還提供了關(guān)于日志信息前綴的兩個方法:

func Prefix() string
func SetPrefix(prefix string)

其中Prefix函數(shù)用來查看標準 logger 的輸出前綴晋修,SetPrefix函數(shù)用來設置輸出前綴吧碾。

func main() {
    log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
    log.Println("這是一條很普通的日志。")
    log.SetPrefix("[小王子]")
    log.Println("這是一條很普通的日志墓卦。")
}

上面的代碼輸出如下:

[小王子]2017/06/19 14:05:57.940542 .../log_demo/main.go:13: 這是一條很普通的日志倦春。

這樣我們就能夠在代碼中為我們的日志信息添加指定的前綴,方便之后對日志信息進行檢索和處理。

1.1.3 配置日志輸出位置

func SetOutput(w io.Writer)

SetOutput函數(shù)用來設置標準 logger 的輸出目的地睁本,默認是標準錯誤輸出尿庐。

例如,下面的代碼會把日志輸出到同目錄下的xx.log文件中呢堰。

func main() {
    logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        fmt.Println("open log file failed, err:", err)
        return
    }
    log.SetOutput(logFile)
    log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
    log.Println("這是一條很普通的日志抄瑟。")
    log.SetPrefix("[小王子]")
    log.Println("這是一條很普通的日志。")
}

如果你要使用標準的 logger暮胧,我們通常會把上面的配置操作寫到init函數(shù)中锐借。

func init() {
    logFile, err := os.OpenFile("./xx.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
    if err != nil {
        fmt.Println("open log file failed, err:", err)
        return
    }
    log.SetOutput(logFile)
    log.SetFlags(log.Llongfile | log.Lmicroseconds | log.Ldate)
}

1.2 創(chuàng)建 logger

log標準庫中還提供了一個創(chuàng)建新 logger 對象的構(gòu)造函數(shù)–New,支持我們創(chuàng)建自己的 logger 示例往衷。New函數(shù)的簽名如下:

func New(out io.Writer, prefix string, flag int) *Logger

New 創(chuàng)建一個 Logger 對象钞翔。其中,參數(shù) out 設置日志信息寫入的目的地席舍。參數(shù) prefix 會添加到生成的每一條日志前面布轿。參數(shù) flag 定義日志的屬性(時間、文件等等)来颤。

舉個例子:

func main() {
    logger := log.New(os.Stdout, "<New>", log.Lshortfile|log.Ldate|log.Ltime)
    logger.Println("這是自定義的logger記錄的日志汰扭。")
}

將上面的代碼編譯執(zhí)行之后,得到結(jié)果如下:

<New>2017/06/19 14:06:51 main.go:34: 這是自定義的logger記錄的日志福铅。

1.3 總結(jié)

Go 內(nèi)置的 log 庫功能有限萝毛,例如無法滿足記錄不同級別日志的情況,我們在實際的項目中根據(jù)自己的需要選擇使用第三方的日志庫滑黔,如 logrus笆包、zap 等。

2略荡、第三方日志庫

2.1 日志選型需求整理

  1. 日志寫入性能
  2. 日志級別分離庵佣,并且可分離成多個日志文件
  3. 可讀性與結(jié)構(gòu)化,Json格式或有分隔符汛兜,方便后續(xù)的日志采集巴粪、監(jiān)控等
  4. 能夠打印基本信息,如調(diào)用文件 / 函數(shù)名和行號粥谬,日志時間等
  5. 日志書寫友好肛根,支持通過context自動log trace等
  6. 文件切割,可按小時漏策、天進行日志拆分派哲,或者按文件大小
  7. 文件定時刪除
  8. 開源性,與其他開源框架支持較好
  9. 多輸出 - 同時支持標準輸出哟玷,文件等

2.2 日志比對

2.2.1 功能比對

參考文檔:

搜看的許多日志框架狮辽,最后剩下兩款目前明顯性能比較好的Uber開源的Zap和ZeroLog一也,參考github中開源項目日志引用情況和日志周邊框架支持最終選用Zap。

需求點 go.uber.org/zap(國內(nèi)一些開源項目見得比較多喉脖、性能也不錯椰苟、推薦) github.com/rs/zerolog
日志寫入性能 較高
日志級別分離 支持 支持
可讀性 (Json格式或有分隔符,方便后續(xù)的日志采集树叽、監(jiān)控等) json格式 json格式
易用性:接入方便舆蝴,書寫方便(格式化),可Hook注入trace_id等 自動接入時間题诵、代碼信息洁仗、日志級別,支持Hook 可支持接入時間性锭、代碼信息赠潦、日志級別等,支持Hook
文件切割 (可按時間草冈、文件大小日志拆分) 不支持她奥,可通過lumberjack實現(xiàn) 支持
定時刪除 支持 支持
多輸出 - 同時支持標準輸出,文件等 支持 支持

2.2.3 性能數(shù)據(jù)比對

根據(jù)Uber-go Zap的文檔怎棱,它的性能比類似的結(jié)構(gòu)化日志包更好——也比標準庫更快哩俭。 以下是Zap發(fā)布的基準測試信息

記錄一條消息和10個字段:
image.png

記錄一個靜態(tài)字符串,沒有任何上下文或printf風格的模板:
image.png

下一篇我們會來講講高性能日志框架Zap的使用拳恋,以及如何滿足我們對于日志框架豐富的使用需求凡资,我們下期見,Peace??

我是簡凡谬运,一個勵志用最簡單的語言隙赁,描述最復雜問題的新時代農(nóng)民工判帮。求點贊,求關(guān)注凹炸,如果你對此篇文章有什么疑惑耐亏,歡迎在我的微信公眾號中留言,我還可以為你提供以下幫助:

  • 幫助建立自己的知識體系
  • 互聯(lián)網(wǎng)真實高并發(fā)場景實戰(zhàn)講解
  • 不定期分享Golang妇萄、Java相關(guān)業(yè)內(nèi)的經(jīng)典場景實踐

我的博客:https://besthpt.github.io/
我的微信:bestbear666
微信公眾號:"簡凡丶"

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子滑废,更是在濱河造成了極大的恐慌,老刑警劉巖袜爪,帶你破解...
    沈念sama閱讀 211,194評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蠕趁,死亡現(xiàn)場離奇詭異,居然都是意外死亡辛馆,警方通過查閱死者的電腦和手機俺陋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,058評論 2 385
  • 文/潘曉璐 我一進店門豁延,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人腊状,你說我怎么就攤上這事诱咏。” “怎么了缴挖?”我有些...
    開封第一講書人閱讀 156,780評論 0 346
  • 文/不壞的土叔 我叫張陵袋狞,是天一觀的道長。 經(jīng)常有香客問我映屋,道長苟鸯,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,388評論 1 283
  • 正文 為了忘掉前任棚点,我火速辦了婚禮早处,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘瘫析。我一直安慰自己陕赃,他們只是感情好,可當我...
    茶點故事閱讀 65,430評論 5 384
  • 文/花漫 我一把揭開白布颁股。 她就那樣靜靜地躺著么库,像睡著了一般。 火紅的嫁衣襯著肌膚如雪甘有。 梳的紋絲不亂的頭發(fā)上诉儒,一...
    開封第一講書人閱讀 49,764評論 1 290
  • 那天,我揣著相機與錄音亏掀,去河邊找鬼忱反。 笑死,一個胖子當著我的面吹牛滤愕,可吹牛的內(nèi)容都是我干的温算。 我是一名探鬼主播,決...
    沈念sama閱讀 38,907評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼间影,長吁一口氣:“原來是場噩夢啊……” “哼注竿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起魂贬,我...
    開封第一講書人閱讀 37,679評論 0 266
  • 序言:老撾萬榮一對情侶失蹤巩割,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后付燥,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體宣谈,經(jīng)...
    沈念sama閱讀 44,122評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,459評論 2 325
  • 正文 我和宋清朗相戀三年键科,在試婚紗的時候發(fā)現(xiàn)自己被綠了闻丑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片漩怎。...
    茶點故事閱讀 38,605評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖嗦嗡,靈堂內(nèi)的尸體忽然破棺而出扬卷,到底是詐尸還是另有隱情,我是刑警寧澤酸钦,帶...
    沈念sama閱讀 34,270評論 4 329
  • 正文 年R本政府宣布怪得,位于F島的核電站,受9級特大地震影響卑硫,放射性物質(zhì)發(fā)生泄漏徒恋。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,867評論 3 312
  • 文/蒙蒙 一欢伏、第九天 我趴在偏房一處隱蔽的房頂上張望入挣。 院中可真熱鬧,春花似錦硝拧、人聲如沸径筏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,734評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽滋恬。三九已至,卻和暖如春抱究,著一層夾襖步出監(jiān)牢的瞬間恢氯,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,961評論 1 265
  • 我被黑心中介騙來泰國打工鼓寺, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留勋拟,地道東北人。 一個月前我還...
    沈念sama閱讀 46,297評論 2 360
  • 正文 我出身青樓妈候,卻偏偏與公主長得像敢靡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子苦银,可洞房花燭夜當晚...
    茶點故事閱讀 43,472評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 一墓毒、log日志包 log支持并發(fā)操作吓揪。其結(jié)構(gòu)定義如下: log基本日志格式 (1)Golang's log模塊主要...
    學生黃哲閱讀 10,538評論 3 35
  • 簡介: 日志是我們開發(fā)程序必不可少的一部分亲怠,go官方的提供的日志包默認功能很簡潔所计,但是滿足不了生產(chǎn)環(huán)境的全部需求(...
    JiBadBoy閱讀 5,996評論 0 5
  • 本文作者:陳進堅個人博客:https://jian1098.github.io[https://jian1098....
    不能吃的堅果j閱讀 6,237評論 0 5
  • 一、介紹 在許多Go語言項目中团秽,我們需要一個好的日志記錄器能夠提供下面這些功能: 1主胧、能夠?qū)⑹录涗浀轿募邪仁祝?..
    梁帆閱讀 714評論 0 1
  • 本文轉(zhuǎn)載自姜總 golang日志庫 golang標準庫的日志框架非常簡單,僅僅提供了print踪栋,panic和fat...
    哆啦在這A夢在哪閱讀 7,906評論 4 9