【问题标题】:What is the correspondence between go-logr and uber's zap verbosity levels?go-logr 和 uber 的 zap 详细程度有什么对应关系?
【发布时间】:2021-12-16 05:28:50
【问题描述】:

我看到 Uber Zap 实现中有日志级别:

    const (
            // DebugLevel logs are typically voluminous, and are usually disabled in
            // production.
            DebugLevel Level = iota - 1
            // InfoLevel is the default logging priority.
            InfoLevel
            // WarnLevel logs are more important than Info, but don't need individual
            // human review.
            WarnLevel
            // ErrorLevel logs are high-priority. If an application is running smoothly,
            // it shouldn't generate any error-level logs.
            ErrorLevel
            // DPanicLevel logs are particularly important errors. In development the
            // logger panics after writing the message.
            DPanicLevel
            // PanicLevel logs a message, then panics.
            PanicLevel
            // FatalLevel logs a message, then calls os.Exit(1).
            FatalLevel
        ) 

当我在 sigs.k8s.io/controller-runtime/pkg/log/zap 记录器中设置级别时使用它,它在引擎盖下使用 go-logr

func determineLogLevel(verbosityLevel string) zapcore.Level {
    var zapLevel zapcore.Level
    verbosityLevel = strings.ToLower(verbosityLevel)
    switch verbosityLevel {
    case ERROR:
        zapLevel = zapcore.ErrorLevel
    case WARNING:
        zapLevel = zapcore.WarnLevel
    case INFO:
        zapLevel = zapcore.InfoLevel
    case DEBUG:
        zapLevel = zapcore.DebugLevel
    default:
        zapLevel = zapcore.InfoLevel
    }
    return zapLevel
}

// here zap is "sigs.k8s.io/controller-runtime/pkg/log/zap"
opts := zap.Options{
    StacktraceLevel: ... ,
    Level:           determineLogLevel("ERROR"),
    Encoder:         ... ,
    ZapOpts:         ...,
}

但也可以选择使用logr.Logger.V

这里的level值和Uber Zap的常量一样吗? (DebugLevel, InfoLevel, WarnLevel, ....)

我也看到了:

flag --zap-log-level:Zap 级别,用于配置日志记录的详细程度。可以是“调试”、“信息”、“错误”或任何大于 0 的整数值之一,对应于增加详细程度的自定义调试级别”

此标志值是否与sigs.k8s.iozap.Options 中的zapcore.Level 相同?

logr.Logger.V 的文档

    // V returns an Logger value for a specific verbosity level, relative to
    // this Logger.  In other words, V values are additive.  V higher verbosity
    // level means a log message is less important.  It's illegal to pass a log
    // level less than zero.
    V(level int) Logger

【问题讨论】:

  • 您是在问传递给Vint 和优步的zap 自己的关卡之间是否存在对应关系?
  • @blackgreen - 是的,还有关于 V ,level 和 zap-log-level 之间的区别

标签: go logging go-zap


【解决方案1】:

go-logrgo.uber.org/zap日志级别的对应关系如下:

zapLevel = -1 * logrLevel

换句话说,go-logr 级别是zap 级别的。此信息可在 go-logr/zapr 包文档中找到:

logr 中的级别对应于 Zap 中的自定义调试级别。 logr 中的任何给定级别都由其在 zap (zapLevel = -1*logrLevel) 中的倒数表示。例如 V(2) 相当于 Zap 中的日志级别 -2,而 V(1) 相当于 Zap 的 DebugLevel。

您还可以通过查看zapr 包的logr.Logger.V 实现来查看关卡如何初始化的具体示例:

func (zl *zapLogger) V(level int) logr.Logger {
    return &zapLogger{
        lvl: zl.lvl - zapcore.Level(level),
        l:   zl.l,
    }
}

方法zapr.NewLogger 构造了一个zapr.zapLogger,其中lvl 字段设置为zap.InfoLevel(你知道它是0),所以每次你在这个实现上调用V,它都会减去给定的int值,从而得到它的负数。


--zap-log-level 标志从命令行(或 k8s yaml 配置)传递的字符串值映射到 Uber Zap 的级别,基于此:

var levelStrings = map[string]zapcore.Level{
    "debug": zap.DebugLevel,
    "info":  zap.InfoLevel,
    "error": zap.ErrorLevel,
}

然后将数值乘以-1,然后设置为logr.Logger 实现,如上面引用的文档所要求的那样。

【讨论】:

  • 并且 zap-log-level 标志用于 V 计算?
  • 我怎样才能控制打印什么不打印?我可以控制 V levek testLog.V(0).Info("This is a test0") testLog.V(1).Info("This is a test1") testLog.V(2).Info("This is a test2") testLog.V(3).Info("This is a test3") testLog.V(-1).Info("This is a test-1") testLog.V(-2).Info( "这是一个测试 2")
  • @user1365697 我更新了答案。该标志只是将日志级别设置为 k8s logr logger 的另一种方式。
  • @@user1365697 - 如果我将记录器设置为 info LEVEL,我如何获取带有 V(1)、V(2)、V(3) 的消息.....
  • @user1365697 如果 Uber zap 记录器设置为 InfoLevel,您使用带有负值的 V 来打印警告、错误、dpanic 等。 logger.V(0).Info("foo")info 打印foo,在logger.V(-1).Info("foo")warn 打印foo,因为-1 乘以-1 = 1,在zap 中是@987654>3@4