49 lines
1.3 KiB
Go
49 lines
1.3 KiB
Go
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()
|
|
}
|
|
}
|