簡介:
日志是我們開發(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 初始化成功")
}
從上面的例子中我們分幾步來看
- 首先先通過配置
lumberjack.Logger
丙号,來設(shè)置日志文件的切割 - 通過配置
zapcore.EncoderConfig
,來設(shè)置日志的格式 - 通過
zapcore.NewMultiWriteSyncer(writes...)
來設(shè)置多個(gè)輸出缰冤,和io.MultiWriter
很像犬缨。 - 通過
zapcore.NewCore
創(chuàng)建一個(gè)core - 通過
zap.New
創(chuàng)建日志實(shí)例
當(dāng)然本文沒有介紹zap的其他基本用法,只是講解了本人經(jīng)常用到的方法棉浸,其他方法如果有時(shí)間怀薛,我也會一一列出。謝謝大家觀看迷郑,比心~~