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()
    }
}
posted @ 2020-08-21 12:32  fanzou  阅读(905)  评论(0编辑  收藏  举报