Home  >  Article  >  Backend Development  >  Change log level of Go lang slog at runtime

Change log level of Go lang slog at runtime

王林
王林forward
2024-02-09 10:18:08336browse

在运行时更改 Go lang slog 的日志级别

php editor Strawberry is here to introduce a method to change the log level of Go lang slog at runtime. Go lang slog is a commonly used logging library, but during development, we may need to change the level of the log without restarting the application. This article will introduce a simple and effective method that allows you to easily change the log level at runtime to meet different needs. Whether you are a beginner or an experienced developer, this tip will help your projects.

Question content

Using the Go slog logging package ("log/slog"), I'm looking for a way to change the logger log level at runtime?

Is it possible? I've spent hours playing with it but can't find a way to do this.

Update 1 - Running app with 3 loggers and changing level using HTTP

Below is the code I wrote based on Peter's answer. I make HTTP calls http://localhost:8080/changeLogLevel?logger=TCP&level=ERROR.

package main

import (
    "log"
    "log/slog"
    "net/http"
    "os"
    "strings"
    "time"
)

func main() {
    // Create a LevelVar variable and initialize it to DEBUG.

    // Create the template logger with info
    tcpLvl := new(slog.LevelVar)
    tcpLvl.Set(slog.LevelDebug)

    dbLvl := new(slog.LevelVar)
    dbLvl.Set(slog.LevelDebug)

    mqLvl := new(slog.LevelVar)
    mqLvl.Set(slog.LevelDebug)

    tcpLogger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
        Level: tcpLvl,
    }))

    mqLogger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
        Level: mqLvl,
    }))


    // Create the MQLogger.
    dbLogger :=  slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
        Level: dbLvl,
    }))

    // Create a goroutine that prints debug messages to the 3 loggers.
    go func() {
        levels := map[string]slog.Level{
            "DEBUG":  slog.LevelDebug,
            "WARN": slog.LevelWarn,
            "INFO": slog.LevelInfo,
            "ERROR": slog.LevelError,
        }
        for {
            for levelStr, numericLevel := range levels {
                log.Printf("Is: %s enabled for tcpLogger? %v \n", levelStr, tcpLogger.Enabled(nil, numericLevel))
            }
            dbLogger.Debug("This is a debug message from the DBLogger.")
            tcpLogger.Debug("This is a debug message from the TCPLogger.")
            mqLogger.Debug("This is a debug message from the MQLogger.")
            log.Println("----------------------------------------------------")
            time.Sleep(10 * time.Second)
        }
    }()
    // Create an HTTP server.
    http.HandleFunc("/changeLogLevel", func(w http.ResponseWriter, r *http.Request) {
        // Get the logger name from the request.
        log.Println("----- Got HTTP call -------")
        loggerName := r.URL.Query().Get("logger")

        // Get the new log level from the request.
        newLogLevelStr := r.URL.Query().Get("level")
        var level slog.Level
        log.Printf("Incoming log level  is %v\n", newLogLevelStr)
        switch strings.ToUpper(newLogLevelStr) {
        case "DEBUG":
            level = slog.LevelDebug
        case "WARNING":
            level = slog.LevelWarn
        case "ERROR":
            level = slog.LevelError
        case "INFO":
            level = slog.LevelInfo
        default:
            {
                w.WriteHeader(http.StatusBadRequest)
                w.Write([]byte("Invalid level name"))
                return
            }

        }

        log.Printf("Incoming logger name is %v\n", loggerName)
        switch strings.ToUpper(loggerName) {
        case "DB":
            dbLvl.Set(level)
        case "TCP":
            log.Printf("Going to set the TCP logger level to %v\n", level)
            tcpLvl.Set(level)
        case "MQ":
            mqLvl.Set(level)
        default:
            w.WriteHeader(http.StatusBadRequest)
            w.Write([]byte("Invalid logger name"))
            return
        }

        w.WriteHeader(http.StatusOK)
    })

    // Start the HTTP server.
    http.ListenAndServe(":8080", nil)
}

Update 2 - Basic Example

The code below works as expected.

package main

import (
    "log"
    "log/slog"
    "os"
)

func main() {
    log.Println("slog chaqnge level demo")
    lvl := new(slog.LevelVar)
    lvl.Set(slog.LevelInfo)

    logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
        Level: lvl,
    }))
    logger.Info("Info msg")
    logger.Debug("Debug msg - you will NOT see me")
    lvl.Set(slog.LevelDebug)
    logger.Debug("Debug msg - you will see me")

}

Output

2009/11/10 23:00:00 slog chaqnge level demo
time=2009-11-10T23:00:00.000Z level=INFO msg="Info msg"
time=2009-11-10T23:00:00.000Z level=DEBUG msg="Debug msg - you will see me"

Solution

The constructors of built-in handlers all take the HandlerOptions parameter. HandlerOptions has a Level field that you can use to dynamically change the level.

type HandlerOptions struct {
    // Level reports the minimum record level that will be logged.
    // The handler discards records with lower levels.
    // If Level is nil, the handler assumes LevelInfo.
    // The handler calls Level.Level for each record processed;
    // to adjust the minimum level dynamically, use a LevelVar.
    Level Leveler

    // ...
}

So just set a LevelVar when creating the logger:

lvl := new(slog.LevelVar)
lvl.Set(slog.LevelInfo)

logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
    Level: lvl,
}))

// later ...

lvl.Set(slog.LevelDebug)

If you are implementing your own handler, the Enabled method determines the log level, you can also easily use LevelVar:

type MyHandler struct {
    level slog.Leveler
}

func (h *MyHandler) Enabled(_ context.Context, level slog.Level) bool {
    return level >= h.level.Level()
}

The above is the detailed content of Change log level of Go lang slog at runtime. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:stackoverflow.com. If there is any infringement, please contact admin@php.cn delete