golang 日志 zap的使用

簡介:

日志是我們開發(fā)程序必不可少的一部分河狐,go官方的提供的日志包默認(rèn)功能很簡潔当犯,但是滿足不了生產(chǎn)環(huán)境的全部需求(例如:更精細(xì)的日志級別垢村、日志文件分割,以及日志分發(fā)等)嚎卫。雖然Go是新興語言嘉栓,但是go的生態(tài)圈還是很活躍的,目前比較流行的第三方開源log包有seelog拓诸,zap侵佃,logrus,還有beego中的日志框架部分奠支。今天我們就著重講一下uber的zap包馋辈,本文中難免會有錯(cuò)誤的地方,如有請聯(lián)系本人倍谜,本人會及時(shí)更正迈螟。

zap是uber開源的Go高性能日志庫
Lumberjack用于將日志寫入滾動文件。zap 不支持文件歸檔尔崔,如果要支持文件按大小或者時(shí)間歸檔答毫,需要使用lumberjack,lumberjack也是zap官方推薦的季春。

怎么使用

下載安裝這些步驟就不在贅述烙常,講zap的用法之前,我們先來看一下zap的配置鹤盒,下面是我常用的配置

    zap.Config{
        Level:             zap.NewAtomicLevelAt(zap.DebugLevel),
        Development:       false,
        DisableCaller:     false,
        DisableStacktrace: false,
        Sampling:          nil,
        Encoding:          "json",
        EncoderConfig: zapcore.EncoderConfig{
            MessageKey:     "msg",
            LevelKey:       "level",
            TimeKey:        "time",
            NameKey:        "logger",
            CallerKey:      "file",
            StacktraceKey:  "stacktrace",
            LineEnding:     zapcore.DefaultLineEnding,
            EncodeLevel:    zapcore.LowercaseLevelEncoder,
            EncodeTime:     zapcore.ISO8601TimeEncoder,
            EncodeDuration: zapcore.SecondsDurationEncoder,
            EncodeCaller:   zapcore.ShortCallerEncoder,
            EncodeName:     zapcore.FullNameEncoder,
        },
        OutputPaths:      []string{"/tmp/zap.log"},
        ErrorOutputPaths: []string{"/tmp/zap.log"},
        InitialFields: map[string]interface{}{
            "app": "test",
        },
    }

    lumberjack.Logger{
            Filename:   logPath, // 日志文件路徑
            MaxSize:    128,     // 每個(gè)日志文件保存的大小 單位:M
            MaxAge:     7,       // 文件最多保存多少天
            MaxBackups: 30,      // 日志文件最多保存多少個(gè)備份
            Compress:   false,   // 是否壓縮
        }

  • zap配置說明
    Level:日志級別,只不過它需要的類型是AtomicLevel蚕脏。所以需要使用zap.NewAtomicLevelAt

    func NewAtomicLevelAt(l zapcore.Level) AtomicLevel {
        a := NewAtomicLevel()
        a.SetLevel(l)
        return a
    }
    
    DebugLevel Level = iota - 1
    // InfoLevel 默認(rèn)級別
    InfoLevel
    // WarnLevel
    WarnLevel
    // 項(xiàng)目運(yùn)行中侦锯,錯(cuò)誤的日志
    ErrorLevel
    // 記錄一條消息后驼鞭,如果是開發(fā)環(huán)境,則調(diào)用panic
    DPanicLevel
    // 記錄一條消息后尺碰,則調(diào)用panic
    PanicLevel
    // 記錄一條消息后調(diào)用 os.Exit(1).
    FatalLevel
    

    Development:是否是開發(fā)環(huán)境挣棕。如果是開發(fā)模式,對DPanicLevel進(jìn)行堆棧跟蹤
    DisableCaller: 不顯示調(diào)用函數(shù)的文件名稱和行號亲桥。默認(rèn)情況下洛心,所有日志都顯示。
    DisableStacktrace:是否禁用堆棧跟蹤捕獲题篷。默認(rèn)對Warn級別以上和生產(chǎn)error級別以上的進(jìn)行堆棧跟蹤词身。
    Sampling:抽樣策略。設(shè)置為nil禁用采樣番枚。(我自己沒用過法严,有需求的朋友可以研究下)
    Encoding:編碼方式损敷,支持json, console, 也支持自定義(需要通過RegisterEncoder注冊)
    EncoderConfig: 生成格式的一些配置,后面詳細(xì)介紹
    OutputPaths: 是url或文件路徑列表深啤,用于寫入日志輸出拗馒。
    ErrorOutputPaths:內(nèi)部日志程序錯(cuò)誤路徑列表。默認(rèn)為標(biāo)準(zhǔn)錯(cuò)誤溯街。
    InitialFields:加入一些初始的字段數(shù)據(jù)诱桂,比如項(xiàng)目名

    EncoderConfig配置說明:

    MessageKey:輸入信息的key名  
    LevelKey:輸出日志級別的key名  
    TimeKey:輸出時(shí)間的key名  
    NameKey CallerKey StacktraceKey跟以上類似,看名字就知道  
    LineEnding:每行的分隔符呈昔』拥龋基本zapcore.DefaultLineEnding 即"\\n"  
    EncodeLevel:基本zapcore.LowercaseLevelEncoder。將日志級別字符串轉(zhuǎn)化為小寫  
    EncodeTime:輸出的時(shí)間格式  
    EncodeDuration:一般zapcore.SecondsDurationEncoder,執(zhí)行消耗的時(shí)間轉(zhuǎn)化成浮點(diǎn)型的秒  
    EncodeCaller:一般zapcore.ShortCallerEncoder韩肝,以包/文件:行號 格式化調(diào)用堆棧  
    EncodeName:可選值触菜。
    
  • 真實(shí)例子

    需求:希望日志文件按照一定的大小分隔,備份哀峻,并且希望涡相,在開發(fā)的時(shí)候,日志可以在文件和控制臺上都有輸出剩蟀,只需要通過配置就能控制

package logger

   import (
       " xxx/config"
       "os"

       "github.com/natefinch/lumberjack"
       "go.uber.org/zap"
       "go.uber.org/zap/zapcore"
   )

   var ZapLogger *zap.Logger

   func InitLogger() {
       // 此處的配置是從我的項(xiàng)目配置文件讀取的催蝗,讀者可以根據(jù)自己的情況來設(shè)置
       logPath := config.Cfg.Section("app").Key("logPath").String()
       name := config.Cfg.Section("app").Key("name").String()
       debug, err := config.Cfg.Section("app").Key("debug").Bool()
       if err != nil {
           debug = false
       }
       hook := lumberjack.Logger{
           Filename:   logPath, // 日志文件路徑
           MaxSize:    128,     // 每個(gè)日志文件保存的大小 單位:M
           MaxAge:     7,       // 文件最多保存多少天
           MaxBackups: 30,      // 日志文件最多保存多少個(gè)備份
           Compress:   false,   // 是否壓縮
       }
       encoderConfig := zapcore.EncoderConfig{
           MessageKey:     "msg",
           LevelKey:       "level",
           TimeKey:        "time",
           NameKey:        "logger",
           CallerKey:      "file",
           StacktraceKey:  "stacktrace",
           LineEnding:     zapcore.DefaultLineEnding,
           EncodeLevel:    zapcore.LowercaseLevelEncoder,
           EncodeTime:     zapcore.ISO8601TimeEncoder,
           EncodeDuration: zapcore.SecondsDurationEncoder,
           EncodeCaller:   zapcore.ShortCallerEncoder, // 短路徑編碼器
           EncodeName:     zapcore.FullNameEncoder,
       }
       // 設(shè)置日志級別
       atomicLevel := zap.NewAtomicLevel()
       atomicLevel.SetLevel(zap.DebugLevel)
       var writes = []zapcore.WriteSyncer{zapcore.AddSync(&hook)}
       // 如果是開發(fā)環(huán)境,同時(shí)在控制臺上也輸出
       if debug {
           writes = append(writes, zapcore.AddSync(os.Stdout))
       }
       core := zapcore.NewCore(
           zapcore.NewJSONEncoder(encoderConfig),
           zapcore.NewMultiWriteSyncer(writes...),
           atomicLevel,
       )

       // 開啟開發(fā)模式育特,堆棧跟蹤
       caller := zap.AddCaller()
       // 開啟文件及行號
       development := zap.Development()

       // 設(shè)置初始化字段
       field := zap.Fields(zap.String("appName", name))

       // 構(gòu)造日志
       ZapLogger = zap.New(core, caller, development, field)
       ZapLogger.Info("log 初始化成功")
   }

從上面的例子中我們分幾步來看

  1. 首先先通過配置lumberjack.Logger丙号,來設(shè)置日志文件的切割
  2. 通過配置zapcore.EncoderConfig,來設(shè)置日志的格式
  3. 通過zapcore.NewMultiWriteSyncer(writes...)來設(shè)置多個(gè)輸出缰冤,和io.MultiWriter很像犬缨。
  4. 通過zapcore.NewCore創(chuàng)建一個(gè)core
  5. 通過zap.New創(chuàng)建日志實(shí)例

當(dāng)然本文沒有介紹zap的其他基本用法,只是講解了本人經(jīng)常用到的方法棉浸,其他方法如果有時(shí)間怀薛,我也會一一列出。謝謝大家觀看迷郑,比心~~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末枝恋,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子嗡害,更是在濱河造成了極大的恐慌焚碌,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霸妹,死亡現(xiàn)場離奇詭異十电,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進(jìn)店門摆出,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朗徊,“玉大人首妖,你說我怎么就攤上這事偎漫。” “怎么了有缆?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵象踊,是天一觀的道長。 經(jīng)常有香客問我棚壁,道長杯矩,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任袖外,我火速辦了婚禮史隆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘曼验。我一直安慰自己泌射,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布鬓照。 她就那樣靜靜地躺著熔酷,像睡著了一般。 火紅的嫁衣襯著肌膚如雪豺裆。 梳的紋絲不亂的頭發(fā)上拒秘,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天,我揣著相機(jī)與錄音臭猜,去河邊找鬼躺酒。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蔑歌,可吹牛的內(nèi)容都是我干的羹应。 我是一名探鬼主播,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼丐膝,長吁一口氣:“原來是場噩夢啊……” “哼量愧!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起帅矗,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤偎肃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后浑此,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體累颂,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了紊馏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片料饥。...
    茶點(diǎn)故事閱讀 39,722評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖朱监,靈堂內(nèi)的尸體忽然破棺而出岸啡,到底是詐尸還是另有隱情,我是刑警寧澤赫编,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布巡蘸,位于F島的核電站,受9級特大地震影響擂送,放射性物質(zhì)發(fā)生泄漏悦荒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一嘹吨、第九天 我趴在偏房一處隱蔽的房頂上張望搬味。 院中可真熱鬧,春花似錦蟀拷、人聲如沸碰纬。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽嘀趟。三九已至,卻和暖如春愈诚,著一層夾襖步出監(jiān)牢的瞬間她按,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工炕柔, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留酌泰,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓匕累,卻偏偏與公主長得像陵刹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子欢嘿,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,614評論 2 353