Fork me on GitHub

1.前言

在Java中我们常常会这样使用日志

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

class Main {
    final static Logger log = LoggerFactory.getLogger(Main.class);
    public static void main(String[] args) {
        log.info("info, hello {}", "slf4j");
        log.error("error");
    }
}

输出

6:30:03.350 [main] INFO  Main - info, hello slf4j
16:30:03.356 [main] ERROR Main - error

这里在每条日志中都有类名,可以很容易从文件中过滤出这个类相关的日志。

2.zap中使用name标识

zap中的玩法

package main

import (
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
    "time"
)

func main() {
    config := zap.NewProductionConfig()
    config.Encoding = "console"
    config.EncoderConfig.EncodeTime = zapcore.TimeEncoderOfLayout("2006-01-02 15:04:05")
    logger, _ := config.Build()
    defer logger.Sync()
    // 输出该条日志在代码文件中的行号
    logger = logger.WithOptions(zap.AddCaller())
    logger.Info("failed to fetch URL",
        zap.Int("attempt", 3),
        zap.Duration("backoff", time.Second),
    )
    go func() { // worker1
        // 携带name标识
        logger1 := logger.Named("worker1")
        for {
            time.Sleep(time.Millisecond * 200)
            logger1.Info("hello1")
        }
    }()
    go func() { // worker2
        logger2 := logger.Named("worker2")
        for {
            time.Sleep(time.Millisecond * 200)
            logger2.Info("hello2")
        }
    }()

    time.Sleep(3 * time.Second)
}

输出

每条日志都输出了logger的Name以及该条日志在代码文件中的行号

  • 输出日志在代码文件中的行号,可以帮助快速定位问题
  • 如果服务中包含多个在后台运行的协程(worker),萌叔建议给logger命名,并输出到日志中

3.zap中处理重复的Field

package main

import (
    "go.uber.org/zap"
    "time"
)

func main() {
    config := zap.NewProductionConfig()
    config.Encoding = "console"
    logger, _ := config.Build()
    defer logger.Sync()
    logger = logger.WithOptions(zap.AddCaller())
    logger.Info("failed to fetch URL",
        zap.Int("attempt", 3),
        zap.Duration("backoff", time.Second),
    )
    logger1 := logger.With(zap.String("duplicateKey", "duplicateValue"))
    for i := 0; i < 5; i++ {
        logger1.Info("record", zap.Int("i", i))
    }
    logger1.Info("I will exit.")
    time.Sleep(10 * time.Second)
}

上面的程序中,有个特殊的Field

zap.String("duplicateKey", "duplicateValue") 

需要在每条日志中携带, 那么你可以使用logger.With

输出

1.7284685624361799e+09  info    myotp2/main.go:14       failed to fetch URL     {"attempt": 3, "backoff": 1}
1.728468562436277e+09   info    myotp2/main.go:22       record  {"duplicateKey": "duplicateValue", "i": 0}
1.7284685624362822e+09  info    myotp2/main.go:22       record  {"duplicateKey": "duplicateValue", "i": 1}
1.728468562436285e+09   info    myotp2/main.go:22       record  {"duplicateKey": "duplicateValue", "i": 2}
1.728468562436287e+09   info    myotp2/main.go:22       record  {"duplicateKey": "duplicateValue", "i": 3}
1.728468562436289e+09   info    myotp2/main.go:22       record  {"duplicateKey": "duplicateValue", "i": 4}
1.728468562436291e+09   info    myotp2/main.go:24       I will exit.    {"duplicateKey": "duplicateValue"}

作者: vearne
文章标题: 玩转高性能日志库ZAP (7)-标识
发表时间: 2024年10月9日
文章链接:https://vearne.cc/archives/40167
版权说明: CC BY-NC-ND 4.0 DEED


微信公众号

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注