CtrlK
BlogDocsLog inGet started
Tessl Logo

testland/jaeger-trace-tests

Author integration tests that query a tracing backend for cross-service trace verification - Jaeger, Zipkin, or Grafana Tempo, same run-query-assert workflow. Jaeger all-in-one Docker for CI (OTLP gRPC :4317 + HTTP :4318 ingest, query API on :16686), `/api/traces?service=X&operation=Y` query patterns, span set + parent-child + duration assertions; Zipkin (:9411 REST API, B3 single/multi-header propagation tests, dependency graph) in references/zipkin.md; Tempo (TraceQL span selectors + structural operators, /api/search, single-binary Docker) in references/tempo.md. Use when verifying that a request produces the expected spans across service boundaries in a running Jaeger, Zipkin, or Tempo backend.

74

Quality

93%

Does it follow best practices?

Run evals on this skill

Adds up to 20 points to the overall score

View guide

SecuritybySnyk

Low

Low-risk findings worth noting

Overview
Quality
Evals
Security
Files

zipkin.mdreferences/

Zipkin backend - same run-query-assert workflow

Zipkin is the original distributed-tracing system (predates OpenTelemetry); still common in Java shops via Spring Cloud Sleuth heritage, and these tests protect a Zipkin → Jaeger/OTel cutover. The workflow is identical to Jaeger's: run the backend in CI, ship spans, force_flush(), query the REST API, assert on the span set.

Run in CI

Per the Zipkin quickstart:

docker run -d -p 9411:9411 openzipkin/zipkin
services:
  zipkin:
    image: openzipkin/zipkin
    ports: ["9411:9411"]

REST API

Per the Zipkin API spec:

EndpointReturns
GET /api/v2/servicesService names
GET /api/v2/spans?serviceName=XOperations
GET /api/v2/traces?serviceName=X&spanName=Y&lookback=300000&limit=10Traces (lookback in ms)
GET /api/v2/trace/{traceId}Single trace
GET /api/v2/dependencies?endTs=...&lookback=...Service dependency graph
POST /api/v2/spansSubmit spans (V2 JSON)

Ship + query + assert

from opentelemetry.exporter.zipkin.json import ZipkinExporter
# BatchSpanProcessor(ZipkinExporter(endpoint="http://localhost:9411/api/v2/spans"))

def test_order_trace_in_zipkin():
    with use_tracer():
        create_order(items=[item])
    trace.get_tracer_provider().force_flush(timeout_millis=5000)
    time.sleep(0.5)

    traces = requests.get(
        "http://localhost:9411/api/v2/traces",
        params={"serviceName": "orders", "spanName": "order.create",
                "lookback": 60000, "limit": 1},
    ).json()                       # list of lists of spans
    assert len(traces) == 1
    span = next(s for s in traces[0] if s["name"] == "order.create")
    assert span["tags"]["order.item_count"] == "1"   # Zipkin V2 tags are ALL strings

Zipkin V2 stores tag values as strings (vs Jaeger's typed tags) - cast in assertions accordingly.

B3 propagation header tests

Per the B3 propagation spec:

  • Multi-header: X-B3-TraceId (32/16 lower-hex), X-B3-SpanId (16), X-B3-ParentSpanId (absent on root), X-B3-Sampled (1/0), X-B3-Flags (1 debug).
  • Single-header: b3: {TraceId}-{SpanId}-{SamplingState}-{ParentSpanId}, sampling 1 accept / 0 deny / d debug / absent defer.

Test both forms - modern services increasingly send only the single-header form:

def test_b3_single_header_propagates():
    headers = {"b3": f"{trace_id}-{span_id}-1-{parent_id}"}
    requests.get("http://localhost:8080/orders", headers=headers)
    time.sleep(0.5)
    spans = requests.get(f"http://localhost:9411/api/v2/trace/{trace_id}").json()
    assert any(s["traceId"] == trace_id for s in spans)

Dependency-graph assertion

Zipkin computes service dependencies from observed traces; aggregation is lazy (in-memory computes inline; Cassandra uses Spark batch) - allow

=2s:

deps = requests.get("http://localhost:9411/api/v2/dependencies",
                    params={"endTs": int(time.time() * 1000), "lookback": 60000}).json()
pair = next((d for d in deps if d["parent"] == "orders" and d["child"] == "payments"), None)
assert pair and pair["callCount"] >= 1

Zipkin-specific anti-patterns

Anti-patternWhy it failsFix
Assert tag values as integersV2 tags are all stringsCompare as string
Test only multi-header B3Single-header form is commonTest both
Expect the dependency graph immediatelyAggregation is lazyAllow ≥2s delay

References

SKILL.md

tile.json