更新时间:

#go zap日志

如果是json格式的log。 有个更优秀的 zerolog

基础类型 不需要反射 /opt/go/src/fmt/print.go:659

// Some types can be done without reflection.
	switch f := arg.(type) {
	case bool:
		p.fmtBool(f, verb)
	case float32:
		p.fmtFloat(float64(f), 32, verb)
	case float64:
		p.fmtFloat(f, 64, verb)
	case complex64:
		p.fmtComplex(complex128(f), 64, verb)
	case complex128:
		p.fmtComplex(f, 128, verb)
	case int:
		p.fmtInteger(uint64(f), signed, verb)
	case int8:

#main.go

package main

import (
    "fmt"

    "demo-log/logs"

    "go.uber.org/zap"
)

func main() {

    log := logs.New(logs.Config{
        Module:   "MainService",
        Level:    "INFO",
        Handler:  "terminal",
        Filename: "xxxx.log",
        Color:    true,
    })
    name := "hello"
    age := 1
    for i := 0; i < 1; i++ {

        log.Info("this is a message", zap.String("name", name), zap.Int("age", age))
        log.Warn("this is a warn message", zap.String("name", name), zap.Int("age", age))
        log.Error("this is a warn message", zap.String("name", name), zap.Int("age", age))
        log.Debug("this is a warn message", zap.String("name", name), zap.Int("age", age))
        fmt.Println("----------")
        sugar := log.Sugar() // 性能比Logger低 50% 左右
        sugar.Infof("this is a message name %s, age %d", name, age)
        sugar.Warnf("this is a message name %s, age %d", name, age)
        sugar.Errorf("this is a message name %s, age %d", name, age)
        sugar.Debugf("this is a message name %s, age %d", name, age)

        fmt.Println("----------")
        sugar.Infow("this is a message ", "name", name, "age", age)
        sugar.Warnw("this is a message ", "name", name, "age", age)
        sugar.Errorw("this is a message ", "name", name, "age", age)
        sugar.Debugw("this is a message ", "name", name, "age", age)
    }
    fmt.Println("=====================")
   
    //log2 := logs.New(logs.Config{
    //    Module:   "XXXOOOO",
    //    Level:    "WARN",
    //    Handler:  "terminal",
    //    Filename: "xxxx.log",
    //    Color:    true,
    //})
    //
    //log.Info("this is a message", zap.String("name", name), zap.Int("age", age))
    //log.Warn("this is a warn message", zap.String("name", name), zap.Int("age", age))
    //log2.Info("this is a message", zap.String("name", name), zap.Int("age", age))
    //log2.Warn("this is a message", zap.String("name", name), zap.Int("age", age))

}

config

package logs

import (
    "os"
    "strings"

    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "gopkg.in/natefinch/lumberjack.v2"
)

const (
    FileLogger     = "file"
    TerminalLogger = "terminal"
)

type Logger struct {
    *zap.Logger
}

type Config struct {
    Module   string `json:"module" yaml:"module"`
    Level    string `json:"level" yaml:"level"`
    Handler  string `json:"handler" yaml:"handler"`
    Filename string `json:"filename" yaml:"filename"`
    Color    bool   `json:"color" yaml:"color"`
}

func New(conf Config) *Logger {
    logger := &Logger{
        Logger: nil,
    }

    atomicLevel := zap.NewAtomicLevel()
    atomicLevel.SetLevel(getLevel(conf.Level))

    zapConfig := zap.NewProductionEncoderConfig()
    zapConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05.000")
    var core zapcore.Core
    if conf.Color {
        zapConfig.EncodeLevel = zapcore.CapitalColorLevelEncoder
    }
    switch strings.ToLower(conf.Handler) {
    case FileLogger:
        if conf.Filename == "" {
            panic("you must refer logger file")
        }
        //zapConfig.EncodeLevel = zapcore.CapitalLevelEncoder

        hook := lumberjack.Logger{
            Filename:   conf.Filename, // ⽇志⽂件路径
            MaxSize:    1,             // megabytes 1M
            MaxBackups: 12,            // 最多保留3个备份
            MaxAge:     3,             // days
            Compress:   false,         // disabled by default
            LocalTime:  true,
        }
        core = zapcore.NewCore(
            //zapcore.NewJSONEncoder(zapConfig),
            zapcore.NewConsoleEncoder(zapConfig),
            zapcore.AddSync(&hook),
            //zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(&hook)), // 打印到控制台和文件
            atomicLevel,
        )
    case TerminalLogger:
        core = zapcore.NewCore(
            zapcore.NewConsoleEncoder(zapConfig),
            os.Stdout,
            atomicLevel,
        )
    default:
        panic("unknown logger handler" + conf.Handler)
    }

    if conf.Module != "" {
        //filed := zap.Fields(zap.String("Module", conf.Module))
        //logger.Logger = zap.New(core, zap.AddCaller(), zap.AddCallerSkip(0), filed)
        logger.Logger = zap.New(core)
    } else {
        logger.Logger = zap.New(core, zap.AddCaller(), zap.AddCallerSkip(0))
    }

    return logger
}

func SetLoggerModule(module string, conf Config) Config {
    if module == conf.Module {
        return conf
    }
    return Config{
        Module:   module,
        Level:    conf.Level,
        Handler:  conf.Handler,
        Filename: conf.Filename,
    }
}

func getLevel(level string) zapcore.Level {
    switch strings.ToUpper(level) {
    case "DEBUG":
        return zap.DebugLevel
    case "INFO":
        return zap.InfoLevel
    case "WARN", "WARNING":
        return zap.WarnLevel
    case "ERROR", "EROR":
        return zap.ErrorLevel
    case "FATAL", "CRITICAL":
        return zap.FatalLevel
    default:
        return zap.DebugLevel
    }
}

#go.mod

module demo-log

go 1.18

require (
	go.uber.org/zap v1.24.0
	gopkg.in/natefinch/lumberjack.v2 v2.2.1
)

require (
	github.com/pkg/errors v0.9.1 // indirect
	go.uber.org/atomic v1.7.0 // indirect
	go.uber.org/multierr v1.6.0 // indirect
)