Is it possible to update the log level of a zap logger at runtime?


I created a logger with kubebuilder, it is based on zap logger:

import (
    uzap ""
    // Import all Kubernetes client auth plugins (e.g. Azure, GCP, OIDC, etc.)
    // to ensure that exec-entrypoint and run can make use of them.
    _ ""

    utilruntime ""
    clientgoscheme ""
    ctrl ""


var (
    scheme   = runtime.NewScheme()
    setupLog = ctrl.Log.WithName("setup")

var zapOpts []uzap.Option
    zapOpts = append(zapOpts, uzap.AddCaller())
    zapOpts = append(zapOpts, uzap.AddCallerSkip(1))
    zapOpts = append(zapOpts, uzap.AddStacktrace(uzap.DebugLevel))

    opts := zap.Options{
        Development:     developmentFlag,
        StacktraceLevel: stacktraceLevel,
        Level:           level,
        Encoder:         encoder,
        ZapOpts:  zapOpts,



Now I want to change the log level to zapcore.InfoLevel at run time. I didn’t find any SetLogLevel or similar API.

Do I need to create new opts and then set the new level?

Also I need to set the logger with library. The interface of the logger is from go-logr and it implements logr.Logger interface. If I tried to change it to zapcore.NewCore than I can’t set the logger with ctrl.SetLogger anymore.

I want to keep the options to update all the options of zap.Options and also to change the log level, and still to use the zap from

Is it possible to do it with


Better answer: as suggested by @Oliver Dain, use zap.AtomicLevel. See their answer for details.

Another option is to create a core with a custom LevelEnabler function. You can use zap.LevelEnablerFunc to convert a closure to a zapcore.LevelEnabler.

The relevant docs:

LevelEnabler decides whether a given logging level is enabled when logging a message.

LevelEnablerFunc is a convenient way to implement zapcore.LevelEnabler with an anonymous function.

That function may then return true or false based on some other variable that changes at runtime:

    // will be actually initialized and changed at run time 
    // based on your business logic
    var infoEnabled bool 

    errorUnlessEnabled := zap.LevelEnablerFunc(func(level zapcore.Level) bool {
        // true: log message at this level
        // false: skip message at this level
        return level >= zapcore.ErrorLevel || infoEnabled

    core := zapcore.NewCore(
    logger := zap.New(core)

    logger.Info("foo") // not logged
    infoEnabled = true

    logger.Info("foo again") // logged

PS: this code is contrived. Your program will have to implement initialization, value change at run-time and proper synchronization (if needed) over the infoEnabled variable.

You can run this example in the playground:

Answered By – blackgreen

Answer Checked By – Candace Johnson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.