// Package logging provides structured logging for the KnowFoolery application. package logging import ( "io" "os" "time" "github.com/rs/zerolog" ) // Config holds the configuration for the logger. type Config struct { Level string Environment string ServiceName string Version string Output io.Writer } // DefaultConfig returns a default configuration. func DefaultConfig() Config { return Config{ Level: "info", Environment: "development", ServiceName: "knowfoolery", Version: "0.0.0", Output: os.Stdout, } } // Logger wraps zerolog.Logger with application-specific methods. type Logger struct { logger zerolog.Logger } // NewLogger creates a new Logger. func NewLogger(config Config) *Logger { // Parse log level level, err := zerolog.ParseLevel(config.Level) if err != nil { level = zerolog.InfoLevel } // Set global level zerolog.SetGlobalLevel(level) zerolog.TimeFieldFormat = time.RFC3339Nano var logger zerolog.Logger output := config.Output if output == nil { output = os.Stdout } if config.Environment == "development" { // Human-readable console output for development logger = zerolog.New(zerolog.ConsoleWriter{ Out: output, TimeFormat: "15:04:05", }).With().Timestamp().Logger() } else { // JSON output for production logger = zerolog.New(output).With().Timestamp().Logger() } // Add service metadata logger = logger.With(). Str("service", config.ServiceName). Str("version", config.Version). Str("environment", config.Environment). Logger() return &Logger{logger: logger} } // Debug logs a debug message. func (l *Logger) Debug(msg string) { l.logger.Debug().Msg(msg) } // Info logs an info message. func (l *Logger) Info(msg string) { l.logger.Info().Msg(msg) } // Warn logs a warning message. func (l *Logger) Warn(msg string) { l.logger.Warn().Msg(msg) } // Error logs an error message. func (l *Logger) Error(msg string) { l.logger.Error().Msg(msg) } // Fatal logs a fatal message and exits. func (l *Logger) Fatal(msg string) { l.logger.Fatal().Msg(msg) } // WithError adds an error to the log entry. func (l *Logger) WithError(err error) *Logger { return &Logger{ logger: l.logger.With().Err(err).Logger(), } } // WithField adds a field to the log entry. func (l *Logger) WithField(key string, value interface{}) *Logger { return &Logger{ logger: l.logger.With().Interface(key, value).Logger(), } } // WithFields adds multiple fields to the log entry. func (l *Logger) WithFields(fields map[string]interface{}) *Logger { ctx := l.logger.With() for k, v := range fields { ctx = ctx.Interface(k, v) } return &Logger{ logger: ctx.Logger(), } } // GameEvent logs a game-related event. func (l *Logger) GameEvent(event string, gameSessionID, userID string, properties map[string]interface{}) { l.logger.Info(). Str("event_type", "game"). Str("event", event). Str("game_session_id", gameSessionID). Str("user_id", userID). Fields(properties). Msg("Game event occurred") } // APIRequest logs an API request. func (l *Logger) APIRequest(method, path string, statusCode int, duration time.Duration, userID string) { l.logger.Info(). Str("event_type", "api_request"). Str("method", method). Str("path", path). Int("status_code", statusCode). Dur("duration_ms", duration). Str("user_id", userID). Msg("API request processed") } // DatabaseOperation logs a database operation. func (l *Logger) DatabaseOperation(operation, table string, duration time.Duration, rowsAffected int64) { l.logger.Debug(). Str("event_type", "database"). Str("operation", operation). Str("table", table). Dur("duration_ms", duration). Int64("rows_affected", rowsAffected). Msg("Database operation completed") } // AuthenticationEvent logs an authentication event. func (l *Logger) AuthenticationEvent(event, userID, userType string, success bool, details map[string]string) { logEntry := l.logger.Info() if !success { logEntry = l.logger.Warn() } logEntry. Str("event_type", "authentication"). Str("event", event). Str("user_id", userID). Str("user_type", userType). Bool("success", success). Fields(details). Msg("Authentication event") } // SecurityEvent logs a security event. func (l *Logger) SecurityEvent(event, userID, ipAddress string, severity string, details map[string]interface{}) { l.logger.Warn(). Str("event_type", "security"). Str("event", event). Str("user_id", userID). Str("ip_address", ipAddress). Str("severity", severity). Fields(details). Msg("Security event detected") } // Zerolog returns the underlying zerolog.Logger for advanced usage. func (l *Logger) Zerolog() zerolog.Logger { return l.logger }