ARCP uses W3C Trace Context (spec §11). The SDK exposes instrumentation via
System.Diagnostics.ActivitySource — no OpenTelemetry SDK dependency in the
core library. Arcp.Otel provides the transport wrapper and attribute
constants.
-
Add the
Arcp.Otelpackage:dotnet add package Arcp.Otel
-
Wrap your transport with
WithTracing():using Arcp.Otel; // Server side: _ = server.AcceptAsync(serverTransport.WithTracing()); // Client side: await using var client = await ArcpClient.ConnectAsync( clientTransport.WithTracing(), options);
-
Register the
ActivitySourcenames with your OTel SDK consumer:using var tracerProvider = Sdk.CreateTracerProviderBuilder() .AddSource(ArcpDiagnostics.TransportSourceName) // "Arcp.Transport" .AddSource(ArcpDiagnostics.RuntimeSourceName) // "Arcp.Runtime" .AddOtlpExporter() .Build();
| Name | Purpose |
|---|---|
Arcp.Transport |
One span per envelope (send and receive). |
Arcp.Runtime |
Runtime-internal spans (dispatch, agent run). |
For each envelope, the wrapper:
- Starts an
Activitynamedarcp.send {type}(producer) orarcp.recv {type}(consumer). - Sets the attribute keys listed below.
- On send: injects a W3C
traceparent(andtracestateif present) intoenvelope.extensions["x-vendor.opentelemetry.tracecontext"]. - On receive: extracts the same field and restores it as the parent
ActivityContextbefore starting the consumer span.
| Attribute | Source field |
|---|---|
arcp.direction |
"in" / "out" |
arcp.type |
envelope type |
arcp.id |
envelope id |
arcp.session_id |
envelope session_id |
arcp.job_id |
envelope job_id |
arcp.trace_id |
envelope trace_id |
arcp.event_seq |
envelope event_seq |
arcp.agent |
payload.agent (on submit / accept) |
arcp.lease.capabilities |
comma-joined lease keys |
arcp.lease.expires_at |
ISO 8601 string (v1.1) |
arcp.budget.remaining |
JSON-stringified currency map (v1.1) |
When hosting via Arcp.AspNetCore, call WithTracing() on the transport
returned by MapArcp:
app.MapArcp(server, o =>
{
o.Path = "/arcp";
o.TransportFilter = t => t.WithTracing(); // wrap each new connection
});// Pass the parent's trace ID when delegating:
var child = await childClient.SubmitAsync("research", traceId: ctx.TraceId);This ensures the child's spans attach to the same distributed trace root. See Delegation for the full pattern.
See samples/Tracing/ for a runnable sample
that exports spans to an OTLP collector.