如何在 uber/zap 记录器中动态更改日志级别

How to dynamically change log level in uber/zap logger

我的项目结构如下:

在我的记录器包中,我有以下和平代码,它只是创建一个记录器并替换了 zap 的全局记录器

var logger *zap.Logger
var atomicLevel zap.AtomicLevel

func init() {
    lmb := config.NewLumberjack()
    atomicLevel = newAtomicLevel()
    logger = newLogger(lmb, atomicLevel)
    zap.ReplaceGlobals(logger)
    setRotation(lmb)
    onLogLevelChange()
}

func SetLevel(l string) {
    atomicLevel.SetLevel(config.ParseLevel(l))
}

在我的 app package 主代码库中放置业务逻辑的地方我有时应该更改日志记录级别,我是这样做的

logger.SetLevel("debug")
zap.L().Debug("Message", zap.Duration("exec_time", time.Second))

问题是我不想从另一个包调用函数来更改完全位于不同包中的对象的行为。 有没有其他更好的方法来解决这个问题?

我认为在这种情况下,当你不想从另一个包切换记录器本身或用高级别包装它时setter,你可以集中切换日志记录级别:

1) 为记录器注册 ServeHTTP,您应该在其中传递记录器的 AtomicLevel。这个 part of the docs will help in this case. Also this link 也可能有帮助。在这里您可以使用 PUT http 请求切换您的记录器级别。

2) 与第 1) 点方法相同,但使用系统信号(例如 USR2)切换电平。您需要放置代码,在无限循环中等待信号(SIGKILL、SIGTERM 和 USR2)select,如下所示:

for {
    select {
    case usrSig := <-WaitForOsUser2Signal():
        // here you can switch your global logger level with atomicLevel
        atomicLevel.SetLevel(zap.ErrorLevel)
    case sig := <-WaitForOsStopProcessSignals():
        // here you should handle graceful shutdown of your app
        return
    }
}

以及select块的功能实现:

func WaitForOsStopProcessSignals() <-chan os.Signal {
    sigCh := make(chan os.Signal, 1)
    signal.Notify(sigCh, syscall.SIGINT, syscall.SIGTERM)

    return sigCh
}

func WaitForOsUser2Signal() <-chan os.Signal {
    usr2Ch := make(chan os.Signal, 1)
    signal.Notify(usr2Ch, syscall.SIGUSR2)

    return usr2Ch
}

希望这会有所帮助。