End-to-end OpenTelemetry: every envelope on the wire (in either
direction) emits a span, and W3C trace context (traceparent /
tracestate) rides along inside envelope.extensions["x.otel"] so
the spans link into one distributed trace.
The middleware MUST be wired on both sides. If only one side wires it, that side's spans are correct in isolation, but the peer creates fresh root spans instead of linking — the trace splits.
In one terminal:
pnpm tsx examples/tracing/server.tsIn a second terminal:
pnpm tsx examples/tracing/client.tsBoth processes use ConsoleSpanExporter, so spans land on stdout.
On the client:
arcp.send job.submit(PRODUCER)arcp.recv job.accepted(CONSUMER), parent of the corresponding server-sidearcp.send job.accepted- One
arcp.recv job.eventper event arcp.recv job.result
On the server:
arcp.recv job.submit(CONSUMER), parent of the server's own delegation chainarcp.send job.accepted, then onearcp.send job.eventper emitted event, thenarcp.send job.result- The same span tree spans the CHILD job —
trace_idis inherited through delegation per §10.3, so the child'sarcp.send job.acceptedshares the same trace as the parent'sarcp.send job.submit.
Each span carries arcp.* attributes — arcp.session_id,
arcp.job_id, arcp.agent, arcp.event_seq, arcp.lease.capabilities
— so the trace is searchable by ARCP identity in whatever backend you
ship them to.
The client also prints each event's trace_id so you can confirm at a
glance that the parent and child events share one trace id.
ConsoleSpanExporter is for demos. In production, swap the
SimpleSpanProcessor(new ConsoleSpanExporter()) for a
BatchSpanProcessor(new OTLPTraceExporter({ url })) pointing at Jaeger,
Tempo, Honeycomb, or any OTLP receiver.
| Env var | Default | Used by |
|---|---|---|
ARCP_DEMO_PORT |
7895 |
server |
ARCP_DEMO_URL |
ws://127.0.0.1:7895/arcp |
client |
ARCP_DEMO_TOKEN |
demo-token |
both |
- §11 Trace propagation (W3C context via
extensions["x.otel"]) - §10.3 trace inheritance on delegation