user1028741
user1028741

Reputation: 2815

Change zap log level dynamically for some of the code

I'm used to work with java and log4j, in which I could dynamically change the log level for a single class without any additional (coding) effort.

Now, when I work with golang (zap for logging) – I seek the same functionality, but cannot find it.

Is there an easy way to change log level dynamically for a file or a package or a part of the code?

Upvotes: 0

Views: 2861

Answers (1)

colm.anseo
colm.anseo

Reputation: 22037

zap supports log.Logger wrapping via constructors like NewStdLog, so if you want to keep using zap then the following technique will work:


If you don't want to use a third-party loggers, the following technique is quite simple, using go's standard library log.Logger:

Define some default app loggers:

var (
    pkgname = "mypkgname"
    Info  = log.New(os.Stdout, "[INFO:"+pkgname+"] ", log.LstdFlags)
    Debug = log.New(ioutil.Discard, "[DBUG:"+pkgname+"] ", log.LstdFlags|log.Lshortfile)
    Trace = log.New(ioutil.Discard, "[TRCE:"+pkgname+"] ", log.LstdFlags|log.Lmicroseconds|log.Lshortfile)
)

so by default Info will write to Stdout - but Debug & Trace will go be "off" by default.

One can then, safely (i.e. goroutine-safe) turn these log.Loggers on/off either at start time:

func init() {
    if v, ok := os.LookupEnv("DEBUG"); ok && v != "" {
        Info.Println("ENV VAR 'DEBUG' set: enabling debug-level logging")
        Debug.SetOutput(os.Stderr)
    }
}

or during runtime:

func httpServiceHandler(r *req) {
    if r.TraceingOn {
        Trace.SetOutput(os.Stderr)
    } else {
        Trace.SetOutput(ioutil.Discard)
    }
}

Logging at pkg level is just like any other log method:

Debug.Printf("http request: %+v", r)

And if there's an expensive log event that you don't want to generate - if say the logger is set to discard - you can safely check the state of the logger like so:

if Trace.Writer() != ioutil.Discard {
    // do expensive logging here

    // e.g. bs, _ = ioutil.ReadAll(resp.Body);  Trace.Println("RESP: RAW-http response:", string(bs))
}

Upvotes: 3

Related Questions