// Package logger provides a configured slog.Logger with TTY // detection for development vs production output. package logger import ( "log/slog" "os" "sneak.berlin/go/netwatch/internal/globals" "go.uber.org/fx" ) // Params defines the dependencies for Logger. type Params struct { fx.In Globals *globals.Globals } // Logger wraps slog.Logger with dynamic level control. type Logger struct { log *slog.Logger level *slog.LevelVar params Params } // New creates a Logger with TTY-aware output formatting. func New(_ fx.Lifecycle, params Params) (*Logger, error) { l := new(Logger) l.level = new(slog.LevelVar) l.level.Set(slog.LevelInfo) l.params = params tty := false if fileInfo, _ := os.Stdout.Stat(); fileInfo != nil { if (fileInfo.Mode() & os.ModeCharDevice) != 0 { tty = true } } var handler slog.Handler if tty { handler = slog.NewTextHandler( os.Stdout, &slog.HandlerOptions{ Level: l.level, AddSource: true, }, ) } else { handler = slog.NewJSONHandler( os.Stdout, &slog.HandlerOptions{ Level: l.level, AddSource: true, }, ) } l.log = slog.New(handler) return l, nil } // EnableDebugLogging sets the log level to debug. func (l *Logger) EnableDebugLogging() { l.level.Set(slog.LevelDebug) l.log.Debug("debug logging enabled", "debug", true) } // Get returns the underlying slog.Logger. func (l *Logger) Get() *slog.Logger { return l.log } // Identify logs the application's build-time metadata. func (l *Logger) Identify() { l.log.Info("starting", "appname", l.params.Globals.Appname, "version", l.params.Globals.Version, "buildarch", l.params.Globals.Buildarch, ) }