Trace-based tests
A trace test calls your service, then asserts on the response and on the spans the call produced. The runner sends a W3C traceparent it generated, so it knows the trace id, waits until the trace can be queried (poll every 2 s, up to wait_for_trace_s, default 30), and evaluates each trace selector with the trace query language.
Spec
{
"trigger": {"http": {"method": "POST", "url": "https://shop.example/buy", "headers": {}, "body": ""}},
"variables": {"env": "prod", "order": {"from_response": "[BODY].id"}},
"wait_for_trace_s": 30,
"assertions": [
{"on": "response", "status": 200, "jsonpath": {"$.id": "abc"}},
{"on": "trace", "selector": "{ resource.service.name = \"db\" && duration > 100ms }",
"expect": {"count_gte": 1}}
]
}{{var.NAME}}is replaced in the trigger and in selectors. Literal variables exist from the start;from_responseones (any[BODY],[HEADER]placeholder path) after the trigger answered.expecttakes one ofcount_gte,count_eq(0 means "no such span"),max_duration_ms(every matched span),attr: {key, eq}(some matched span has that attribute value).Only HTTP triggers run today;
trigger.grpcis rejected.A selector that matches more than 100 traces in the last minute can hide the test's own trace.
Triggers
Manual:
POST /v1/projects/{p}/trace-tests/{id}/runs, or a suite:POST …/trace-test-suites/{id}/runs.Schedule: a monitor of kind
trace_testwith the spec as its config, so locations, retries, alerts, history and private probes apply. Public locations refuse private targets.CI:
wtctl test run --suite <id> --wait --junit out.xmlexits 0 (all passed), 1 (a test failed) or 2 (could not start or finish). The JUnit file has one case per assertion and can be uploaded withwtctl ci upload-junit.
Runs: GET …/trace-test-runs?ref= (a suite run's ref), GET …/trace-test-runs/{id}.