package logger import ( "os" "time" "github.com/gin-gonic/gin" "github.com/sirupsen/logrus" ) var Logger *logrus.Logger // InitLogger initializes the logger func InitLogger() { Logger = logrus.New() // Set log level based on environment logLevel := os.Getenv("LOG_LEVEL") if logLevel == "" { logLevel = "info" } level, err := logrus.ParseLevel(logLevel) if err != nil { level = logrus.InfoLevel } Logger.SetLevel(level) // Set formatter Logger.SetFormatter(&logrus.JSONFormatter{ TimestampFormat: time.RFC3339, }) // Set output to stdout by default Logger.SetOutput(os.Stdout) } // GetLogger returns the logger instance func GetLogger() *logrus.Logger { if Logger == nil { InitLogger() } return Logger } // GinLogger returns a gin middleware for logging func GinLogger() gin.HandlerFunc { return func(c *gin.Context) { // Start timer start := time.Now() path := c.Request.URL.Path raw := c.Request.URL.RawQuery // Process request c.Next() // Stop timer end := time.Now() latency := end.Sub(start) // Get client IP clientIP := c.ClientIP() // Get method method := c.Request.Method // Get status code statusCode := c.Writer.Status() // Get error message if any var errorMessage string if len(c.Errors) > 0 { errorMessage = c.Errors.String() } // Get body size bodySize := c.Writer.Size() // Get request ID if available requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = c.GetString("requestID") } // Get user ID if available userID := c.GetString("userID") // Log the request entry := GetLogger().WithFields(logrus.Fields{ "request_id": requestID, "user_id": userID, "client_ip": clientIP, "method": method, "path": path, "query": raw, "status_code": statusCode, "body_size": bodySize, "latency": latency, "latency_human": latency.String(), "error_message": errorMessage, }) if statusCode >= 500 { entry.Error() } else if statusCode >= 400 { entry.Warn() } else { entry.Info() } } } // WithRequestID adds a request ID to the logger func WithRequestID(requestID string) *logrus.Entry { return GetLogger().WithField("request_id", requestID) } // WithUserID adds a user ID to the logger func WithUserID(userID string) *logrus.Entry { return GetLogger().WithField("user_id", userID) } // WithError adds an error to the logger func WithError(err error) *logrus.Entry { return GetLogger().WithError(err) } // WithField adds a custom field to the logger func WithField(key string, value interface{}) *logrus.Entry { return GetLogger().WithField(key, value) } // WithFields adds multiple custom fields to the logger func WithFields(fields logrus.Fields) *logrus.Entry { return GetLogger().WithFields(fields) } // Info logs an info message func Info(args ...interface{}) { GetLogger().Info(args...) } // Infof logs a formatted info message func Infof(format string, args ...interface{}) { GetLogger().Infof(format, args...) } // Warn logs a warning message func Warn(args ...interface{}) { GetLogger().Warn(args...) } // Warnf logs a formatted warning message func Warnf(format string, args ...interface{}) { GetLogger().Warnf(format, args...) } // Error logs an error message func Error(args ...interface{}) { GetLogger().Error(args...) } // Errorf logs a formatted error message func Errorf(format string, args ...interface{}) { GetLogger().Errorf(format, args...) } // Fatal logs a fatal message and exits func Fatal(args ...interface{}) { GetLogger().Fatal(args...) } // Fatalf logs a formatted fatal message and exits func Fatalf(format string, args ...interface{}) { GetLogger().Fatalf(format, args...) } // Debug logs a debug message func Debug(args ...interface{}) { GetLogger().Debug(args...) } // Debugf logs a formatted debug message func Debugf(format string, args ...interface{}) { GetLogger().Debugf(format, args...) } // Panic logs a panic message and panics func Panic(args ...interface{}) { GetLogger().Panic(args...) } // Panicf logs a formatted panic message and panics func Panicf(format string, args ...interface{}) { GetLogger().Panicf(format, args...) } // LogDatabaseOperation logs a database operation func LogDatabaseOperation(operation string, table string, duration time.Duration, err error) { entry := GetLogger().WithFields(logrus.Fields{ "operation": operation, "table": table, "duration": duration, }) if err != nil { entry.WithError(err).Error("Database operation failed") } else { entry.Info("Database operation completed") } } // LogAIInteraction logs an AI interaction func LogAIInteraction(model string, promptLength int, responseLength int, duration time.Duration, success bool, err error) { entry := GetLogger().WithFields(logrus.Fields{ "ai_model": model, "prompt_length": promptLength, "response_length": responseLength, "duration": duration, "success": success, }) if err != nil { entry.WithError(err).Error("AI interaction failed") } else { entry.Info("AI interaction completed") } } // LogWebSocketEvent logs a WebSocket event func LogWebSocketEvent(event string, clientID string, roomID string, err error) { entry := GetLogger().WithFields(logrus.Fields{ "event": event, "client_id": clientID, "room_id": roomID, }) if err != nil { entry.WithError(err).Error("WebSocket event failed") } else { entry.Info("WebSocket event completed") } } // LogAuthEvent logs an authentication event func LogAuthEvent(event string, userID string, clientIP string, success bool, err error) { entry := GetLogger().WithFields(logrus.Fields{ "event": event, "user_id": userID, "client_ip": clientIP, "success": success, }) if err != nil { entry.WithError(err).Error("Authentication event failed") } else { entry.Info("Authentication event completed") } }