package middleware import ( "time" "github.com/gin-gonic/gin" "github.com/google/uuid" "go.uber.org/zap" ) const requestIDHeader = "X-Request-ID" func RequestID() gin.HandlerFunc { return func(c *gin.Context) { requestID := c.GetHeader(requestIDHeader) if requestID == "" { requestID = uuid.NewString() } c.Set("request_id", requestID) c.Header(requestIDHeader, requestID) c.Next() } } func AccessLog(log *zap.Logger) gin.HandlerFunc { return func(c *gin.Context) { start := time.Now() c.Next() requestID, _ := c.Get("request_id") log.Info("request", zap.String("method", c.Request.Method), zap.String("path", c.FullPath()), zap.Int("status", c.Writer.Status()), zap.Duration("duration", time.Since(start)), zap.String("client_ip", c.ClientIP()), zap.String("request_id", toString(requestID)), ) } } func Recovery(log *zap.Logger) gin.HandlerFunc { return gin.CustomRecovery(func(c *gin.Context, recovered any) { requestID, _ := c.Get("request_id") log.Error("panic recovered", zap.Any("panic", recovered), zap.String("request_id", toString(requestID)), ) c.AbortWithStatusJSON(500, gin.H{ "error": "internal server error", "requestId": toString(requestID), }) }) } func toString(value any) string { typed, ok := value.(string) if !ok { return "" } return typed }