go
46 lines · 7 steps
Correlation ID tracing middleware in Gin
A Gin middleware that tags every request with a correlation ID and threads it through the logger and request context.
Explained by
highlit
1package middleware
2
3import (
4 "context"
5
6 "github.com/gin-gonic/gin"
7 "github.com/google/uuid"
8 "github.com/rs/zerolog"
9 "github.com/rs/zerolog/log"
10)
11
12const (
13 CorrelationIDKey = "correlation_id"
14 correlationIDHeader = "X-Correlation-ID"
15)
16
17func CorrelationID() gin.HandlerFunc {
18 return func(c *gin.Context) {
19 cid := c.GetHeader(correlationIDHeader)
20 if cid == "" {
21 cid = uuid.NewString()
22 }
23
24 c.Set(CorrelationIDKey, cid)
25 c.Header(correlationIDHeader, cid)
26
27 logger := log.With().Str("correlation_id", cid).Logger()
28 ctx := logger.WithContext(c.Request.Context())
29 c.Request = c.Request.WithContext(ctx)
30
31 c.Next()
32 }
33}
34
35func FromContext(ctx context.Context) string {
36 if c, ok := ctx.(*gin.Context); ok {
37 if cid := c.GetString(CorrelationIDKey); cid != "" {
38 return cid
39 }
40 }
41 return zerolog.Ctx(ctx).GetLevel().String()
42}
43
44func LoggerFrom(c *gin.Context) *zerolog.Logger {
45 return log.Ctx(c.Request.Context())
46}
01 / 01
STEP 01
‹ swipe to step through ›
Walkthrough
Space play
←→ step
click any line
Three takeaways
- 1Reusing an inbound correlation header lets a single ID follow a request across service boundaries.
- 2Attaching the ID to a request-scoped logger gives every downstream log line automatic traceability.
- 3Storing shared state in both the Gin context and the request context makes it reachable from handlers and plain context.Context consumers alike.
Related explainers
ruby
module RequestTagging class Middleware def initialize(app) @app = app
Per-request context with CurrentAttributes in Rails
middleware
thread-safety
logging
Intermediate
7 steps
go
package hashring import ( "hash/crc32"
How consistent hashing works in Go
consistent-hashing
load-balancing
concurrency
Intermediate
8 steps
typescript
type Middleware<TIn, TOut> = (ctx: TIn) => Promise<TOut> | TOut; class Pipeline<TIn, TOut> { private constructor(private readonly run: Middleware<TIn, TOut>) {}
A type-safe async middleware pipeline
generics
type-safety
middleware
Advanced
9 steps
go
package middleware import ( "net/http"
Wrapping Gin requests in a DB transaction
middleware
transactions
error-handling
Intermediate
8 steps
php
<?php namespace App\Http\Middleware;
Caching HTTP responses with Laravel middleware
middleware
caching
http
Intermediate
8 steps
go
package handlers import ( "encoding/base64"
Cursor pagination in a Gin handler
pagination
cursor
rest-api
Intermediate
8 steps
Share this explainer
Here's the card — post it anywhere.
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code
Embed this explainer
Drop the interactive walkthrough into a blog or docs. Views never cost a credit.
<iframe src="https://highlit.co/explainers/correlation-id-tracing-middleware-in-gin-explained-go-9526/embed?autoplay=1" width="100%" height="520" loading="lazy" style="border:0"></iframe>
Autoplay is on by default — add ?autoplay=0 to start paused.