diff --git a/internal/config/config.go b/internal/config/config.go index b78eae2..ee4eb86 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -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) diff --git a/internal/logger/logger.go b/internal/logger/logger.go index 687b241..61ead7f 100644 --- a/internal/logger/logger.go +++ b/internal/logger/logger.go @@ -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) }