Zipkin
Send spans from any Zipkin tracer (Brave, zipkin-js, Sleuth, Micrometer Tracing) straight to the gateway. Needs an ingestion key with ingest:traces, sent as Authorization: Bearer <key> (or x-watchtower-key).
POST /api/v2/spansThe body is Zipkin v2 JSON (Content-Type: application/json) or protobuf zipkin.proto3.ListOfSpans (application/x-protobuf). The answer is 202 Accepted.
Mapping: localEndpoint.serviceName becomes service.name (spans without one go to unknown_service), remoteEndpoint.serviceName becomes peer.service, kind becomes the span kind, tags become attributes (a tag named error marks the span as failed), annotations become span events, and shared is ignored. Trace and parent ids are left-padded with zeros to 16 and 8 bytes, so 64-bit ids work. Timestamps and durations are microseconds and are stored as nanoseconds.
B3 and W3C traceparent header propagation happen inside your services, not in the gateway: keep your tracer's propagation setting (B3 or W3C) consistent across services so the spans join into one trace.
Spring Boot example (application.yml):
management.zipkin.tracing.endpoint=https://ingest.example.com/api/v2/spansZipkin tracers cannot set an auth header from the endpoint URL alone; use a reporter with a custom header, or an OpenTelemetry Collector with the zipkin receiver and an otlphttp exporter in front.
Delivery is at-least-once: tracers retry failed reports, so duplicates are possible. Do not set wt.* tags; the gateway deletes them.
Status: unit-tested against hand-built payloads, not yet run against a real tracer.