package logger import ( "bytes" "io" "strings" "time" "github.com/gin-gonic/gin" "github.com/google/uuid" ) // RequestLoggerMiddleware creates a Gin middleware for request logging func RequestLoggerMiddleware(logger *Logger) gin.HandlerFunc { return func(c *gin.Context) { // Generate request ID if not present requestID := c.GetHeader("X-Request-ID") if requestID == "" { requestID = uuid.New().String() c.Header("X-Request-ID", requestID) } // Get correlation ID correlationID := c.GetHeader("X-Correlation-ID") if correlationID == "" { correlationID = uuid.New().String() c.Header("X-Correlation-ID", correlationID) } // Create request-scoped logger reqLogger := logger. WithRequestID(requestID). WithCorrelationID(correlationID) // Store logger in context c.Set("logger", reqLogger) c.Set("request_id", requestID) c.Set("correlation_id", correlationID) // Capture request body for logging if needed var requestBody []byte if c.Request.Body != nil && strings.HasPrefix(c.ContentType(), "application/json") { requestBody, _ = io.ReadAll(c.Request.Body) c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody)) } // Start timer start := time.Now() // Log request start reqLogger.Info("Request started", map[string]interface{}{ "method": c.Request.Method, "path": c.Request.URL.Path, "query": c.Request.URL.RawQuery, "remote_addr": c.Request.RemoteAddr, "user_agent": c.Request.UserAgent(), "content_type": c.ContentType(), "body_size": len(requestBody), }) // Process request c.Next() // Calculate duration duration := time.Since(start) // Get response status status := c.Writer.Status() responseSize := c.Writer.Size() // Log level based on status code var logLevel LogLevel switch { case status >= 500: logLevel = ERROR case status >= 400: logLevel = WARN default: logLevel = INFO } // Log request completion fields := map[string]interface{}{ "method": c.Request.Method, "path": c.Request.URL.Path, "status": status, "duration": duration.String(), "duration_ms": duration.Milliseconds(), "response_size": responseSize, "client_ip": c.ClientIP(), "user_agent": c.Request.UserAgent(), "content_type": c.ContentType(), "content_length": c.Request.ContentLength, } // Add query parameters if present if c.Request.URL.RawQuery != "" { fields["query"] = c.Request.URL.RawQuery } // Add error information if present if len(c.Errors) > 0 { errors := make([]string, len(c.Errors)) for i, err := range c.Errors { errors[i] = err.Error() } fields["errors"] = errors } reqLogger.log(logLevel, "Request completed", &duration, fields) } } // GetLoggerFromContext retrieves the logger from Gin context func GetLoggerFromContext(c *gin.Context) *Logger { if logger, exists := c.Get("logger"); exists { if l, ok := logger.(*Logger); ok { return l } } return globalLogger } // GetRequestIDFromContext retrieves the request ID from Gin context func GetRequestIDFromContext(c *gin.Context) string { if requestID, exists := c.Get("request_id"); exists { if id, ok := requestID.(string); ok { return id } } return "" } // GetCorrelationIDFromContext retrieves the correlation ID from Gin context func GetCorrelationIDFromContext(c *gin.Context) string { if correlationID, exists := c.Get("correlation_id"); exists { if id, ok := correlationID.(string); ok { return id } } return "" } // DatabaseLoggerMiddleware creates middleware for database operation logging func DatabaseLoggerMiddleware(logger *Logger, serviceName string) gin.HandlerFunc { return func(c *gin.Context) { reqLogger := GetLoggerFromContext(c).WithService(serviceName) c.Set("db_logger", reqLogger) c.Next() } } // GetDBLoggerFromContext retrieves the database logger from Gin context func GetDBLoggerFromContext(c *gin.Context) *Logger { if logger, exists := c.Get("db_logger"); exists { if l, ok := logger.(*Logger); ok { return l } } return GetLoggerFromContext(c) } // ServiceLogger creates a service-specific logger func ServiceLogger(serviceName string) *Logger { return globalLogger.WithService(serviceName) } // AuthServiceLogger returns a logger for auth service func AuthServiceLogger() *Logger { return ServiceLogger("auth-service") } // BPJSServiceLogger returns a logger for BPJS service func BPJSServiceLogger() *Logger { return ServiceLogger("bpjs-service") } // RetribusiServiceLogger returns a logger for retribusi service func RetribusiServiceLogger() *Logger { return ServiceLogger("retribusi-service") } // DatabaseServiceLogger returns a logger for database operations func DatabaseServiceLogger() *Logger { return ServiceLogger("database-service") } // MiddlewareServiceLogger returns a logger for middleware operations func MiddlewareServiceLogger() *Logger { return ServiceLogger("middleware-service") }