zap日志庫


一、默認版log庫

1.配置日志輸出文件

func SetupLogger() {
    logFileLocation, _ := os.OpenFile("/Users/q1mi/test.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0744)
    log.SetOutput(logFileLocation)
}

2.使用logger

func simpleHttpGet(url string) {
    resp, err := http.Get(url)
    if err != nil {
        log.Printf("Error fetching url %s : %s", url, err.Error())
    } else {
        log.Printf("Status Code for %s : %s", url, resp.Status)
        resp.Body.Close()
    }
}
  1. 三個打印函數Print 、Panic 、Fatal
  • 對每一類接口其提供了3中調用方式,分別是 "Xxxx 、 Xxxxln 、Xxxxf",基本和fmt中的相關函數類似
  • log.Fatal 接口,打印輸出后,接着調用系統的 os.exit(1) 接口
  • log.Panic接口,該函數把日志內容刷到標准錯誤后,調用 panic 函數

log包存在的劣勢

  • 僅限基本的日志級別
  • 但是它缺少一個ERROR日志級別,這個級別可以在不拋出panic或退出程序的情況下記錄錯誤
  • 但是它缺少一個ERROR日志級別,這個級別可以在不拋出panic或退出程序的情況下記錄錯誤
  • 不提供日志切割的能力,如日志文件大小,存儲管理

二、go.uber.org/zap 又快又好用的日志包

安裝 go get -u go.uber.org/zap

1)配置Zap Logger

Zap提供了兩種類型的日志記錄器 SugaredLoggerLogger
相對來說,SugaredLogger比 Logger封裝更高級,支持結構化和printf風格,
但是Logger,適用於每一微秒和每一次內存分配都很重要的上下文中,因為只支持強類型的結構化日志記錄,比SugaredLogger更快,內存分配次數也更少,

2)簡單調用

  • zap.NewProduction()、zap.NewDevelopment()、zap.Example()創建一個Logger
  • 上面每一個函數都將創建一個logger。唯一的區別在於它將記錄的信息不同。例如production logger默認記錄調用函數信息、日期和時間等
  • Logger調用Info/Error等,默認日志打印到console
var logger *zap.Logger

func main() {
    InitLogger()
    defer logger.Sync()  //zap底層設置了緩存,sync將緩存同步到文件中
    simpleHttpGet("www.google.com")
    simpleHttpGet("http://www.google.com")
}

func InitLogger() {
    logger, _ = zap.NewProduction()
    sugarLogger = logger.Sugar()   //升級為sugar
}

func simpleHttpGet(url string) {
    resp, err := http.Get(url)
    if err != nil {
        logger.Error(
            "Error fetching url..",
            zap.String("url", url),  // 輸出 url: XXXX,
            zap.Error(err))
    } else {
        logger.Info("Success..",
            zap.String("statusCode", resp.Status),  //zap.type() 強類型,寫入日志,zap.StringP,輸出記錄指針,zap.StringL 輸出記錄字符串數組
            zap.String("url", url))
        resp.Body.Close()
    }
}

輸出結果 默認有caller

{"level":"error","ts":1572159149.923002,"caller":"logic/temp2.go:27","msg":"Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme \"\"","stacktrace":"main.simpleHttpGet\n\t/Users/q1mi/zap_demo/logic/temp2.go:27\nmain.main\n\t/Users/q1mi/zap_demo/logic/temp2.go:14\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:203"}
{"level":"info","ts":1572159150.192585,"caller":"logic/temp2.go:29","msg":"Success! statusCode = 200 OK for URL http://www.sogo.com"}

3)定制化調用

func New(core zapcore.Core, options ...Option) *Logger
其中zapcore.Core需要三個配置——Encoder,WriteSyncer,LogLevel

  • Encoder 編碼器(如何寫入日志),使用json編碼NewsJSONEncoder(),再使用預先設置的ProductionEncoderConfig()。
    zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())

  • WriterSyncer :指定日志將寫到哪里去。我們使用zapcore.AddSync()函數並且將打開的文件句柄傳進去

file, _ := os.Create("./test.log") 
writeSyncer := zapcore.AddSync(file)
  • Log Level:哪種級別的日志將被寫入
func InitLogger() {
    file, _ := os.Create("./test.log") 

    writeSyncer := zapcore.AddSync(file)
    encoder := zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()) //json輸出格式
    core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)

    logger := zap.New(core)
    sugarLogger = logger.Sugar()
}

輸出結果,無caller,需額外配置

{"level":"debug","ts":1572160754.994731,"msg":"Trying to hit GET request for www.sogo.com"}
{"level":"error","ts":1572160754.994982,"msg":"Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme \"\""}
{"level":"debug","ts":1572160754.994996,"msg":"Trying to hit GET request for http://www.sogo.com"}
{"level":"info","ts":1572160757.3755069,"msg":"Success! statusCode = 200 OK for URL http://www.sogo.com"}

添加調用詳細信息,即那行代碼出錯

logger := zap.New(core, zap.AddCaller())

修改時間格式

大寫記錄日志級別

通過修改core

    encoderConfig := zap.NewProductionEncoderConfig()
    encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
    encoder := zapcore.NewConsoleEncoder(encoderConfig)
019-10-27T15:33:29.855+0800    DEBUG   logic/temp2.go:47   Trying to hit GET request for www.sogo.com
2019-10-27T15:33:29.855+0800    ERROR   logic/temp2.go:50   Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme ""
2019-10-27T15:33:29.856+0800    DEBUG   logic/temp2.go:47   Trying to hit GET request for http://www.sogo.com
2019-10-27T15:33:30.125+0800    INFO    logic/temp2.go:52   Success! statusCode = 200 OK for URL http://www.sogo.com

三、使用Lumberjack進行日志切割歸檔

go get -u github.com/natefinch/lumberjack

  • 使用lumberjack 修改WriterSyncer
lumberJackLogger := &lumberjack.Logger{
        Filename:   "./test.log",
        MaxSize:    10,  //日志文件最大存儲大小(MB)
        MaxBackups: 5, //保留舊文件最大個數
        MaxAge:     30, //保留舊文件最大天數
        Compress:   false, //是否壓縮
    }
WriterSyncer := zapcore.AddSync(lumberJackLogger)

最終完整zap/lumberjack代碼示例如下:

package main

import (
    "net/http"

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

var sugarLogger *zap.SugaredLogger

func main() {
    InitLogger()
    defer sugarLogger.Sync()
    simpleHttpGet("www.sogo.com")
    simpleHttpGet("http://www.sogo.com")
}

func InitLogger() {
    writeSyncer := getLogWriter()
    encoder := getEncoder()
    core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)

    logger := zap.New(core, zap.AddCaller())
    sugarLogger = logger.Sugar()
}

func getEncoder() zapcore.Encoder {
    encoderConfig := zap.NewProductionEncoderConfig()
    encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
    encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
    return zapcore.NewConsoleEncoder(encoderConfig)
}

func getLogWriter() zapcore.WriteSyncer {
    lumberJackLogger := &lumberjack.Logger{
        Filename:   "./test.log",
        MaxSize:    1,
        MaxBackups: 5,
        MaxAge:     30,
        Compress:   false,
    }
    return zapcore.AddSync(lumberJackLogger)
}

func simpleHttpGet(url string) {
    sugarLogger.Debugf("Trying to hit GET request for %s", url)
    resp, err := http.Get(url)
    if err != nil {
        sugarLogger.Errorf("Error fetching URL %s : Error = %s", url, err)
    } else {
        sugarLogger.Infof("Success! statusCode = %s for URL %s", resp.Status, url)
        resp.Body.Close()
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM