// Package logger provides structured logging for the application. package logger import ( "log/slog" "os" "git.eeqj.de/sneak/chat/internal/globals" "go.uber.org/fx" ) // Params defines the dependencies for creating a Logger. type Params struct { fx.In Globals *globals.Globals } // Logger wraps slog with application-specific configuration. type Logger struct { log *slog.Logger level *slog.LevelVar params Params } // New creates a new Logger with appropriate handler // based on terminal detection. func New( _ fx.Lifecycle, params Params, ) (*Logger, error) { logger := new(Logger) logger.level = new(slog.LevelVar) logger.level.Set(slog.LevelInfo) tty := false if fileInfo, _ := os.Stdout.Stat(); (fileInfo.Mode() & os.ModeCharDevice) != 0 { tty = true } opts := &slog.HandlerOptions{ //nolint:exhaustruct // ReplaceAttr optional Level: logger.level, AddSource: true, } var handler slog.Handler if tty { handler = slog.NewTextHandler(os.Stdout, opts) } else { handler = slog.NewJSONHandler(os.Stdout, opts) } logger.log = slog.New(handler) logger.params = params return logger, nil } // EnableDebugLogging switches the log level to debug. func (logger *Logger) EnableDebugLogging() { logger.level.Set(slog.LevelDebug) logger.log.Debug( "debug logging enabled", "debug", true, ) } // Get returns the underlying slog.Logger. func (logger *Logger) Get() *slog.Logger { return logger.log } // Identify logs the application name and version at startup. func (logger *Logger) Identify() { logger.log.Info("starting", "appname", logger.params.Globals.Appname, "version", logger.params.Globals.Version, ) }