1. 日志目錄結果
└── 01_zap_log
├── log
│ └── test.log
├── logger.go
└── logger_test.go
logger.go 文件
package zap_log
// 安裝以下依賴庫
// go get -u go.uber.org/zap
// go get -u github.com/natefinch/lumberjack
// go get gopkg.in/alecthomas/kingpin.v2
import (
"github.com/natefinch/lumberjack"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/alecthomas/kingpin.v2"
"os"
"path/filepath"
"strconv"
)
const (
defaultlogpath = "/var/log/test" // 【默認】日志文件路徑
defaultlogfilename = "test.log" // 【默認】日志文件名稱
defaultloglevel = "info" // 【默認】日志打印級別 debug info warning error
defaultlogfilemaxsize = 5 // 【日志分割】 【默認】單個日志文件最多存儲量 單位(mb)
defaultlogfilemaxbackups = 10 // 【日志分割】 【默認】日志備份文件最多數量
logmaxage = 1000 // 【默認】日志保留時間,單位: 天 (day)
logcompress = false // 【默認】是否壓縮日志
logstdout = false // 【默認】是否輸出到控制台
)
var logger *zap.sugaredlogger // 定義日志打印全局變量
var (
// kingpin 可以在啟動時通過輸入參數,來修改日志參數
level = kingpin.flag("log.level", "only log messages with the given severity or above. one of: [debug, info, warn, error]").default(defaultloglevel).string()
format = kingpin.flag("log.format", "output format of log messages. one of: [logfmt, json]").default("logfmt").string()
logpath = kingpin.flag("log.path", "output log path").default(defaultlogpath).string()
logfilename = kingpin.flag("log.filename", "output log filename").default(defaultlogfilename).string()
logfilemaxsize = kingpin.flag("log.file-max-size", "output logfile max size, unit mb").default(strconv.itoa(defaultlogfilemaxsize)).int()
logfilemaxbackups = kingpin.flag("log.file-max-backups", "output logfile max backups").default(strconv.itoa(defaultlogfilemaxbackups)).int()
)
// 初始化 logger
func initlogger() error {
loglevel := map[string]zapcore.level{
"debug": zapcore.debuglevel,
"info": zapcore.infolevel,
"warn": zapcore.warnlevel,
"error": zapcore.errorlevel,
}
writesyncer, err := getlogwriter() // 日志文件配置 文件位置和切割
if err != nil {
return err
}
encoder := getencoder() // 獲取日志輸出編碼
level, ok := loglevel[*level] // 日志打印級別
if !ok {
level = loglevel["info"]
}
core := zapcore.newcore(encoder, writesyncer, level)
logger := zap.new(core, zap.addcaller()) // zap.addcaller() 輸出日志打印文件和行數如: logger/logger_test.go:33
logger = logger.sugar()
return nil
}
// 編碼器(如何寫入日志)
func getencoder() zapcore.encoder {
encoderconfig := zap.newproductionencoderconfig()
encoderconfig.encodetime = zapcore.iso8601timeencoder // looger 時間格式 例如: 2021-09-11t20:05:54.852+0800
encoderconfig.encodelevel = zapcore.capitallevelencoder // 輸出level序列化為全大寫字符串,如 info debug error
//encoderconfig.encodecaller = zapcore.fullcallerencoder
//encoderconfig.encodelevel = zapcore.capitalcolorlevelencoder
if *format == "json" {
return zapcore.newjsonencoder(encoderconfig) // 以json格式寫入
}
return zapcore.newconsoleencoder(encoderconfig) // 以logfmt格式寫入
}
// 獲取日志輸出方式 日志文件 控制台
func getlogwriter() (zapcore.writesyncer, error) {
// 判斷日志路徑是否存在,如果不存在就創建
if exist := isexist(*logpath); !exist {
if *logpath == "" {
*logpath = defaultlogpath
}
if err := os.mkdirall(*logpath, os.modeperm); err != nil {
*logpath = defaultlogpath
if err := os.mkdirall(*logpath, os.modeperm); err != nil {
return nil, err
}
}
}
// 日志文件 與 日志切割 配置
lumberjacklogger := &lumberjack.logger{
filename: filepath.join(*logpath, *logfilename), // 日志文件路徑
maxsize: *logfilemaxsize, // 單個日志文件最大多少 mb
maxbackups: *logfilemaxbackups, // 日志備份數量
maxage: logmaxage, // 日志最長保留時間
compress: logcompress, // 是否壓縮日志
}
if logstdout {
// 日志同時輸出到控制台和日志文件中
return zapcore.newmultiwritesyncer(zapcore.addsync(lumberjacklogger), zapcore.addsync(os.stdout)), nil
} else {
// 日志只輸出到控制台
return zapcore.addsync(lumberjacklogger), nil
}
}
// 判斷文件或者目錄是否存在
func isexist(path string) bool {
_, err := os.stat(path)
return err == nil || os.isexist(err)
}
3. logger_test.go 文件
package zap_log
import (
"errors"
"go.uber.org/zap"
"gopkg.in/alecthomas/kingpin.v2"
"testing"
)
func testinitlogger(t *testing.t) {
if _, err := kingpin.commandline.parse([]string{
"--log.level", "debug",
"--log.format", "logfmt",
"--log.path", "../01_zap_log/log",
"--log.filename", "test.log",
"--log.file-max-size", "3",
"--log.file-max-backups", "2"}); err != nil {
t.fatal(err)
}
if err := initlogger(); err != nil {
t.fatal(err)
}
var logger *zap.sugaredlogger
logger = logger
logger.infof("測試一下啊:%s", "111") // logger infof 用法
logger.debugf("測試一下啊:%s", "111") // logger debugf 用法
logger.errorf("測試一下啊:%s", "111") // logger errorf 用法
logger.warnf("測試一下啊:%s", "111") // logger warnf 用法
logger.infof("測試一下啊:%s, %d, %v, %f", "111", 1111, errors.new("collector returned no data"), 3333.33)
logger = logger.with("collector", "cpu", "name", "主機") // logger with 用法
}
4. 輸出日志文件 test.log
2021-09-11t20:24:07.938+0800 info 01_zap_log/logger_test.go:26 測試一下啊:111
2021-09-11t20:24:07.939+0800 debug 01_zap_log/logger_test.go:27 測試一下啊:111
2021-09-11t20:24:07.939+0800 error 01_zap_log/logger_test.go:28 測試一下啊:111
2021-09-11t20:24:07.939+0800 warn 01_zap_log/logger_test.go:29 測試一下啊:111
2021-09-11t20:24:07.939+0800 info 01_zap_log/logger_test.go:30 測試一下啊:111, 1111, collector returned no data, 3333.330000