Skip to content

Observability: Tracing, Logging, and Auditing

This document describes the observability architecture in Wanaku, covering distributed tracing, request ID propagation, and structured logging with traceability.

Overview

Wanaku integrates OpenTelemetry (OTel) for distributed tracing and Micrometer for metrics, providing end-to-end observability across the entire request chain:

  • MCP ClientRouter BackendDownstream MCP ServerDownstream Services

Every request flowing through the system carries:

  1. W3C traceparent header for distributed trace context propagation (automatic via OTel)
  2. x-wanaku-request-id for MCP request correlation (explicit propagation)

Architecture

Request Flow and Trace Propagation

text
┌──────────┐     HTTP/MCP      ┌────────────────┐                 ┌──────────────────┐
│ MCP Client │ ──────────────→ │ Router Backend  │ ─────────────→ │ Downstream MCP Srv│
│             │  traceparent    │                 │  traceparent   │                   │
│             │  x-wanaku-      │  MDC: requestId │  x-wanaku-     │  MDC: requestId   │
│             │  request-id     │  MDC: traceId   │  request-id    │  Span: requestId  │
└──────────┘                   └────────────────┘                 └──────────────────┘


                                 ┌──────────────┐
                                 │ OTel Collector│
                                 │  (4317 gRPC)  │
                                 └──────┬───────┘


                                 ┌──────────────┐
                                 │   Jaeger UI   │
                                 │  (16686 HTTP) │
                                 └──────────────┘

Components

ComponentRole
quarkus-opentelemetryAuto-instruments HTTP and Vert.x; creates spans; manages trace context
McpTracingInstrumenterBuilt into quarkus-mcp-server; auto-creates MCP spans with requestId, toolName, session_id attributes
McpHeadersSupplierPropagates W3C traceparent and x-wanaku-request-id from MDC to downstream MCP calls
quarkus-micrometer-registry-prometheusProvides Prometheus metrics export

Configuration

Router Backend

The router backend's application.properties configures OTel:

properties
# OpenTelemetry
quarkus.otel.exporter.otlp.endpoint=http://localhost:4317
quarkus.otel.exporter.otlp.traces.protocol=grpc
quarkus.otel.resource.attributes=service.name=wanaku-router,service.version=${quarkus.application.version}
quarkus.otel.traces.sampler=parentbased_always_on
quarkus.otel.propagators=tracecontext,baggage

Downstream MCP Servers

Downstream MCP servers use similar configuration:

properties
quarkus.otel.exporter.otlp.endpoint=http://localhost:4317
quarkus.otel.exporter.otlp.traces.protocol=grpc
quarkus.otel.resource.attributes=service.name=${wanaku.service.name:wanaku-mcp-server},service.version=${quarkus.application.version}
quarkus.otel.traces.sampler=parentbased_always_on
quarkus.otel.propagators=tracecontext,baggage

Each downstream MCP server must set wanaku.service.name to identify itself (e.g., wanaku-file-resource, wanaku-http-tool).

Log Format

All log profiles include trace and request context:

text
%d{yyyy-MM-dd HH:mm:ss} %-5p [%c] (%t) [traceId=%X{traceId}, requestId=%X{requestId}] %s%e%n

MDC keys available in log output:

MDC KeySourceDescription
traceIdOTel (automatic)W3C trace ID for distributed tracing
requestIdMCP requestMCP protocol request ID for correlation
connectionIdMCP connectionMCP connection/session identifier

How Request ID Propagation Works

1. MCP Request Arrives

When an MCP request arrives, quarkus-mcp-server's McpTracingInstrumenter automatically creates a span with requestId and toolName attributes.

2. Downstream MCP Calls

When outbound MCP calls are made, ClientUtil.createClient() uses McpHeadersSupplier to propagate:

  • W3C traceparent (from OTel context propagation)
  • x-wanaku-request-id (from MDC)

OTel Span Attributes

The following custom span attributes are set:

AttributeSet ByDescription
wanaku.mcp.request_idRouter request handlingMCP request ID
wanaku.mcp.connection_idRouter request handlingMCP connection/session ID
wanaku.mcp.tool_nameRouter tool routingName of the tool being invoked
wanaku.mcp.resource_nameRouter resource routingName of the resource being acquired

These attributes are searchable in Jaeger/Grafana for quick request correlation.

Deployment

Docker Compose

The docker-compose.yml and docker-compose-noauth.yml include:

  • OTel Collector (otel-collector:4317): Receives OTLP data from router and downstream MCP servers
  • Jaeger (jaeger:16686): UI for trace visualization; receives data from OTel Collector via OTLP

Environment variables set on services:

yaml
QUARKUS_OTEL_EXPORTER_OTLP_ENDPOINT: http://otel-collector:4317

OTel Collector Pipeline

The otel-collector-config.yaml configures:

yaml
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

exporters:
  otlp/jaeger:
    endpoint: jaeger:4317
    tls:
      insecure: true

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [otlp/jaeger]

Accessing Jaeger

After starting the stack with Docker Compose, Jaeger UI is available at:

text
http://localhost:16686

Search by:

  • Service: wanaku-router or the downstream MCP server name
  • Span attribute: wanaku.mcp.request_id=<request-id>
  • Operation: tool invocation or resource acquisition