如何在Go中使用slog包编程获取当前日志级别?
在Go的slog包中编程获取当前日志级别
slog标准库本身并没有提供直接获取当前日志级别的API,但可以通过自定义或包装Handler的方式实现这一需求——核心是利用slog Handler的Enabled方法逻辑:日志是否输出由Handler的级别判断决定,我们可以在Handler中维护当前级别并暴露获取方法。
方式一:包装默认Handler实现级别获取
通过包装slog内置的TextHandler/JSONHandler,添加级别存储和获取方法:
import ( "log/slog" "os" ) type LevelHandler struct { level slog.Level handler slog.Handler } func NewLevelHandler(level slog.Level, handler slog.Handler) *LevelHandler { return &LevelHandler{ level: level, handler: handler, } } // 实现slog.Handler接口的Enabled方法 func (h *LevelHandler) Enabled(lvl slog.Level) bool { return h.level <= lvl } // 委托其他Handler接口方法给内部handler func (h *LevelHandler) Handle(r slog.Record) error { return h.handler.Handle(r) } func (h *LevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler { return NewLevelHandler(h.level, h.handler.WithAttrs(attrs)) } func (h *LevelHandler) WithGroup(name string) slog.Handler { return NewLevelHandler(h.level, h.handler.WithGroup(name)) } // 暴露获取当前日志级别的方法 func (h *LevelHandler) GetLogLevel() slog.Level { return h.level } // 使用示例 func main() { baseHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelInfo}) levelHandler := NewLevelHandler(slog.LevelInfo, baseHandler) logger := slog.New(levelHandler) // 获取并打印当前级别 currentLevel := levelHandler.GetLogLevel() logger.Info("当前日志级别", "level", currentLevel.String()) }
方式二:支持动态调整级别的线程安全实现
如果需要在运行时动态修改日志级别,需要添加同步锁保证并发安全:
import ( "log/slog" "os" "sync" ) type LevelHandler struct { mu sync.RWMutex level slog.Level handler slog.Handler } func NewLevelHandler(level slog.Level, handler slog.Handler) *LevelHandler { return &LevelHandler{ level: level, handler: handler, } } func (h *LevelHandler) Enabled(lvl slog.Level) bool { h.mu.RLock() defer h.mu.RUnlock() return h.level <= lvl } func (h *LevelHandler) Handle(r slog.Record) error { return h.handler.Handle(r) } func (h *LevelHandler) WithAttrs(attrs []slog.Attr) slog.Handler { return NewLevelHandler(h.level, h.handler.WithAttrs(attrs)) } func (h *LevelHandler) WithGroup(name string) slog.Handler { return NewLevelHandler(h.level, h.handler.WithGroup(name)) } // 获取当前日志级别(线程安全) func (h *LevelHandler) GetLogLevel() slog.Level { h.mu.RLock() defer h.mu.RUnlock() return h.level } // 修改当前日志级别(线程安全) func (h *LevelHandler) SetLogLevel(level slog.Level) { h.mu.Lock() defer h.mu.Unlock() h.level = level } // 使用示例 func main() { baseHandler := slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{}) levelHandler := NewLevelHandler(slog.LevelInfo, baseHandler) logger := slog.New(levelHandler) logger.Info("初始级别", "level", levelHandler.GetLogLevel().String()) // 动态调整级别 levelHandler.SetLogLevel(slog.LevelDebug) logger.Debug("调整后级别生效", "level", levelHandler.GetLogLevel().String()) }
注意事项
- 若使用第三方slog Handler(如各种适配器),优先查看其是否自带级别获取方法;若没有,同样可以用上述包装方式实现。
- 不要直接访问slog内部的私有字段来获取级别,这会导致代码依赖未公开的实现细节,版本更新时极易出错。
内容的提问来源于stack exchange,提问作者Fabrice Jammes
相关产品推荐
相关产品推荐

