package middleware import ( "crypto/rand" "encoding/hex" "regexp" "strings" "github.com/gin-gonic/gin" "github.com/google/uuid" ) var traceParentPattern = regexp.MustCompile(`^00-([0-9a-f]{32})-([0-9a-f]{16})-[0-9a-f]{2}$`) func randomHex(bytes int) string { value := make([]byte, bytes) _, _ = rand.Read(value) return hex.EncodeToString(value) } func RequestMeta() gin.HandlerFunc { return func(c *gin.Context) { requestID := c.GetHeader("X-Request-Id") if requestID == "" || len(requestID) > 128 || strings.ContainsAny(requestID, "\r\n") { requestID = uuid.NewString() } traceID, parentSpanID := "", "" if match := traceParentPattern.FindStringSubmatch(strings.ToLower(c.GetHeader("traceparent"))); len(match) == 3 { traceID, parentSpanID = match[1], match[2] } else if candidate := c.GetHeader("X-Trace-Id"); len(candidate) <= 128 && !strings.ContainsAny(candidate, "\r\n") { traceID = candidate } if traceID == "" { traceID = randomHex(16) } spanID := randomHex(8) c.Header("X-Request-Id", requestID) c.Header("X-Trace-Id", traceID) if len(traceID) == 32 { c.Header("traceparent", "00-"+traceID+"-"+spanID+"-01") } c.Set("request_id", requestID) c.Set("trace_id", traceID) c.Set("span_id", spanID) c.Set("parent_span_id", parentSpanID) c.Next() } }