refactor: use slog.LevelVar for dynamic log levels

Replace the pattern of recreating the logger handler when enabling debug
logging. Now use slog.LevelVar which allows changing the log level
dynamically without recreating the handler or logger instance.

closes #8
This commit is contained in:
clawbot
2026-03-01 15:49:21 -08:00
committed by user
parent d4eef6bd6a
commit 3e3d44a168
2 changed files with 20 additions and 42 deletions

View File

@@ -17,8 +17,9 @@ type LoggerParams struct {
}
type Logger struct {
logger *slog.Logger
params LoggerParams
logger *slog.Logger
levelVar *slog.LevelVar
params LoggerParams
}
// nolint:revive // lc parameter is required by fx even if unused
@@ -26,24 +27,30 @@ func New(lc fx.Lifecycle, params LoggerParams) (*Logger, error) {
l := new(Logger)
l.params = params
// Use slog.LevelVar for dynamic log level changes
l.levelVar = new(slog.LevelVar)
l.levelVar.Set(slog.LevelInfo)
// Determine if we're running in a terminal
tty := false
if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
tty = true
}
replaceAttr := func(_ []string, a slog.Attr) slog.Attr { // nolint:revive // groups unused
// Always use UTC for timestamps
if a.Key == slog.TimeKey {
if t, ok := a.Value.Any().(time.Time); ok {
return slog.Time(slog.TimeKey, t.UTC())
}
}
return a
}
var handler slog.Handler
opts := &slog.HandlerOptions{
Level: slog.LevelInfo,
ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { // nolint:revive // groups unused
// Always use UTC for timestamps
if a.Key == slog.TimeKey {
if t, ok := a.Value.Any().(time.Time); ok {
return slog.Time(slog.TimeKey, t.UTC())
}
}
return a
},
Level: l.levelVar,
ReplaceAttr: replaceAttr,
}
if tty {
@@ -63,34 +70,7 @@ func New(lc fx.Lifecycle, params LoggerParams) (*Logger, error) {
}
func (l *Logger) EnableDebugLogging() {
// Recreate logger with debug level
tty := false
if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 {
tty = true
}
var handler slog.Handler
opts := &slog.HandlerOptions{
Level: slog.LevelDebug,
ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { // nolint:revive // groups unused
// Always use UTC for timestamps
if a.Key == slog.TimeKey {
if t, ok := a.Value.Any().(time.Time); ok {
return slog.Time(slog.TimeKey, t.UTC())
}
}
return a
},
}
if tty {
handler = slog.NewTextHandler(os.Stdout, opts)
} else {
handler = slog.NewJSONHandler(os.Stdout, opts)
}
l.logger = slog.New(handler)
slog.SetDefault(l.logger)
l.levelVar.Set(slog.LevelDebug)
l.logger.Debug("debug logging enabled", "debug", true)
}