Skip to main content

Overview

The trace middleware propagates distributed tracing context (trace ID, span ID) across service boundaries for observability. Use it when you need:
  • Distributed tracing
  • Request correlation
  • Service observability

Installation

import "github.com/go-mizu/mizu/middlewares/trace"

Quick Start

app := mizu.New()

app.Use(trace.New())

app.Get("/api", func(c *mizu.Ctx) error {
    traceID := trace.ID(c)
    log.Printf("Trace: %s", traceID)
    return c.JSON(200, data)
})

Configuration

Options

OptionTypeDefaultDescription
TraceHeaderstring"X-Trace-ID"Trace ID header
SpanHeaderstring"X-Span-ID"Span ID header
ParentHeaderstring"X-Parent-ID"Parent span header
Generatorfunc() stringUUIDID generator

Examples

Basic Tracing

app.Use(trace.New())

W3C Trace Context

app.Use(trace.W3C())
// Uses traceparent header

Custom Headers

app.Use(trace.WithOptions(trace.Options{
    TraceHeader:  "X-Request-ID",
    SpanHeader:   "X-Span-ID",
    ParentHeader: "X-Parent-Span-ID",
}))

Access Trace Info

app.Get("/", func(c *mizu.Ctx) error {
    traceID := trace.ID(c)
    spanID := trace.SpanID(c)
    parentID := trace.ParentID(c)

    // Include in logs
    log.Printf("[%s] Request processed", traceID)

    return c.JSON(200, data)
})

Propagate to Downstream

app.Get("/", func(c *mizu.Ctx) error {
    // Create HTTP client with trace context
    req, _ := http.NewRequest("GET", "http://service-b/api", nil)
    trace.Inject(c, req.Header)

    resp, _ := http.DefaultClient.Do(req)
    // ...
})

API Reference

Functions

// New creates trace middleware
func New() mizu.Middleware

// W3C creates W3C trace context middleware
func W3C() mizu.Middleware

// WithOptions creates with configuration
func WithOptions(opts Options) mizu.Middleware

// Context access
func ID(c *mizu.Ctx) string
func SpanID(c *mizu.Ctx) string
func ParentID(c *mizu.Ctx) string

// Propagation
func Inject(c *mizu.Ctx, headers http.Header)

Technical Details

Implementation Architecture

The trace middleware implements distributed tracing through:
  1. Context Propagation: Uses Go’s context.Context to store span information throughout the request lifecycle
  2. Span Generation: Creates unique trace and span IDs using cryptographic randomness (16 bytes encoded as hex)
  3. Header-based Propagation: Extracts and injects trace context via HTTP headers for cross-service communication

Core Components

Span Structure
  • TraceID: Unique identifier for the entire trace across services
  • SpanID: Unique identifier for this specific operation
  • ParentID: Reference to the parent span for hierarchy
  • StartTime/EndTime: Timing information for duration calculation
  • Status: Enumerated status (Unset, OK, Error)
  • Tags: Key-value metadata for context
  • Events: Timestamped events within the span
ID Generation Uses crypto/rand to generate 16-byte random values, encoded as 32-character hexadecimal strings, ensuring globally unique identifiers with negligible collision probability. Span Lifecycle
  1. Extract or generate trace ID from request headers
  2. Create new span with generated span ID
  3. Store span in request context
  4. Set response headers for downstream propagation
  5. Execute handler chain
  6. Calculate duration and set final status
  7. Invoke OnSpan callback if configured
Collector Pattern The Collector provides a simple way to aggregate spans for testing or custom backends:
  • Thread-safe span collection
  • In-memory storage
  • Clear method for test isolation

Configuration Defaults

FieldDefault ValuePurpose
ServiceName"mizu-service"Identifies the service in traces
TraceHeader"X-Trace-ID"HTTP header for trace ID
ParentHeader"X-Parent-ID"HTTP header for parent span ID
OnSpannilOptional callback for completed spans
SamplernilWhen nil, all requests are traced

Best Practices

  • Use consistent format across services
  • Include trace ID in all logs
  • Propagate to all downstream calls
  • Consider W3C standard for interoperability

Testing

The trace middleware includes comprehensive test coverage for all features:
Test CaseDescriptionExpected Behavior
TestNewBasic middleware creationCreates span with trace ID and span ID for each request
TestWithOptions_ServiceNameCustom service name configurationSets service tag to configured value
TestWithOptions_PropagateTraceIDExisting trace ID propagationPreserves incoming trace ID from request headers
TestWithOptions_ParentIDParent span ID propagationExtracts and stores parent span ID from request headers
TestWithOptions_OnSpanSpan completion callbackInvokes OnSpan callback with completed span including duration
TestWithOptions_SamplerSampling controlSkips span creation when sampler returns false
TestAddTagCustom tag additionAdds custom key-value tags to span
TestAddEventEvent loggingRecords timestamped events with metadata in span
TestTraceIDTrace ID retrievalReturns current trace ID from context
TestSpanIDSpan ID retrievalReturns current span ID from context
TestCollectorSpan collectionCollects multiple spans and supports clearing
TestResponseHeaderResponse header propagationSets X-Trace-ID header in response
TestHTTPHeadersDownstream header generationGenerates headers for propagating trace context to downstream services