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:
@@ -118,8 +118,6 @@ func New(lc fx.Lifecycle, params ConfigParams) (*Config, error) {
|
||||
|
||||
if s.Debug {
|
||||
params.Logger.EnableDebugLogging()
|
||||
s.log = params.Logger.Get()
|
||||
log.Debug("Debug mode enabled")
|
||||
}
|
||||
|
||||
// Log configuration summary (without secrets)
|
||||
|
||||
@@ -18,6 +18,7 @@ type LoggerParams struct {
|
||||
|
||||
type Logger struct {
|
||||
logger *slog.Logger
|
||||
levelVar *slog.LevelVar
|
||||
params LoggerParams
|
||||
}
|
||||
|
||||
@@ -26,16 +27,17 @@ 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
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
opts := &slog.HandlerOptions{
|
||||
Level: slog.LevelInfo,
|
||||
ReplaceAttr: func(_ []string, a slog.Attr) slog.Attr { // nolint:revive // groups unused
|
||||
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 {
|
||||
@@ -43,7 +45,12 @@ func New(lc fx.Lifecycle, params LoggerParams) (*Logger, error) {
|
||||
}
|
||||
}
|
||||
return a
|
||||
},
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
opts := &slog.HandlerOptions{
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user