2

I saw that there is log level in Uber Zap implementation:

    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
        ) 

I use this when I set the level in a sigs.k8s.io/controller-runtime/pkg/log/zap logger, which uses go-logr under the hood:

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:         ...,
}

But there is also the option of using logr.Logger.V.

Is the level value here the same as in Uber Zap's constants? ( DebugLevel, InfoLevel, WarnLevel, ....)

I also saw this:

flag --zap-log-level: Zap Level to configure the verbosity of logging. Can be one of ‘debug’, ‘info’, ‘error’, or any integer value > 0 which corresponds to custom debug levels of increasing verbosity”

Is this flag value the same as zapcore.Level in the sigs.k8s.io's zap.Options?

The documentation for 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
blackgreen
  • 34,072
  • 23
  • 111
  • 129
user1365697
  • 5,819
  • 15
  • 60
  • 96

1 Answers1

2

The correspondence between go-logr and go.uber.org/zap log levels is given by:

zapLevel = -1 * logrLevel

In other words, the go-logr level is the inverse of zap level. This information is available in go-logr/zapr package docs:

Levels in logr correspond to custom debug levels in Zap. Any given level in logr is represents by its inverse in zap (zapLevel = -1*logrLevel). For example V(2) is equivalent to log level -2 in Zap, while V(1) is equivalent to Zap's DebugLevel.

You can also see a concrete example of how the level is initialized by looking at the implementation of logr.Logger.V by zapr package:

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

The method zapr.NewLogger constructs a zapr.zapLogger with lvl field set to zap.InfoLevel (which you know is 0), so each time you call V on this implementation, it subtracts the given int value, thus obtaining its negative.


The flag --zap-log-level is mapped from the string value passed on the command line (or k8s yaml config) to the Uber Zap's level as-is, based on this:

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

The numerical value is then multiplied by -1 and then set to the logr.Logger implementation, as required by the documentation quoted above.

blackgreen
  • 34,072
  • 23
  • 111
  • 129
  • and the zap-log-level flag is for the V calculation ? – user1365697 Nov 01 '21 at 14:36
  • How I can control what will be print and what is not ? where i can control on 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("This is a test-2") – user1365697 Nov 01 '21 at 14:39
  • 1
    @user1365697 I updated the answer. the flag is just another way to set the log level to the k8s `logr` logger. – blackgreen Nov 01 '21 at 14:42
  • @@user1365697 - If i set the logger to info LEVEL how I can get the messages with V(1),V(2),V(3) ..... – user1365697 Nov 01 '21 at 14:44
  • @user1365697 If the Uber zap logger is set to `InfoLevel` you use `V` with negative values to print warn, error, dpanic, etc. E.g. `logger.V(0).Info("foo")` prints `foo` at `info`, `logger.V(-1).Info("foo")` prints `foo` at `warn`, because `-1` is multiplied by `-1` = `1`, which in zap is `WarnLevel` – blackgreen Nov 01 '21 at 14:51
  • @user1365697 and therefore zap logger initialized with `DebugLevel` will print `V(1).Info` at `debug` level, because `1` becomes `-1` – blackgreen Nov 01 '21 at 14:52