[W3C Trace Context end-to-end]

Observability and tracing

Argus adopts W3C Trace Context across every request. Send a `traceparent` header to anchor the trace in your own observability backend, or let Argus generate one for you. Every response carries `X-Argus-Trace-ID` and `X-Argus-Span-ID` so you can correlate operator activity with your own logs and dashboards.

Observability and tracing

Incoming headers

Argus accepts the standard W3C `traceparent` header in the form `00-<trace-id-32hex>-<span-id-16hex>-<flags-2hex>`. The optional `tracestate` header is propagated as opaque vendor state. If `traceparent` is missing or malformed, Argus generates a fresh trace and span ID for the request so every operation is observable. Inbound trace context applies uniformly to all routes; there is no opt-in.

Outgoing headers

Every Argus response, success or error, carries `X-Argus-Trace-ID` (32-hex trace ID) and `X-Argus-Span-ID` (16-hex span ID for that request). A complete `traceparent` is also re-emitted in standard W3C form for downstream services that consume it. Response headers are emitted unconditionally; client SDKs treat them as optional and never raise on absence.

Propagation to partner connectors

Argus propagates the active trace context to every partner connector call through a single `traced_http` factory. Outbound HTTP requests to integrations carry `traceparent` and `tracestate` so a single trace ID stitches the operator action to your downstream system. Jobs, provenance records, and audit entries that originate from a request stamp the same `trace_id` for end-to-end correlation.

Trace lookup endpoint

`GET /v1/observability/traces/{trace_id}` returns the recorded span tree for a 32-hex W3C trace ID. The endpoint requires the `argus:observability:read` scope on a bearer token. A 200 response includes the trace ID, the tenant ID, an array of spans (each with span ID, parent span ID, name, start time in unix nanoseconds, duration in nanoseconds, status code, and attributes), and an `ingestion: stored` marker. If the OpenTelemetry backend is briefly unreachable, the endpoint returns 503 with `ingestion: recorded` and `query_hint: use_your_backend` so your tooling can fall back to your own OTEL store. The trace was still recorded.

Tenant isolation

Trace lookups are filtered by the tenant resource attribute (`tenant.id`) and the OpenTelemetry `service.namespace` attribute set to `argus-{tenant_id}`. A bearer token issued for tenant A cannot read tenant B span data: a cross-tenant lookup returns 404. Span attributes that carry sensitive markers are filtered against the caller’s clearance. Every call to the trace lookup endpoint writes an audit entry capturing the user, organization, tenant, the trace ID read, and whether the OTEL backend was reachable at read time.

SDK usage

All four official SDKs (`@argus/connector-sdk`, `argus-connector-sdk`, `@argus/client`, `argus-client`) expose `client.getLastResponseHeaders()` so callers can read `X-Argus-Trace-ID` and `X-Argus-Span-ID` after any operation. Use `client.withTraceparent("00-<trace-id>-<span-id>-01")` on a request builder to anchor a call in an existing trace from your own backend. The trace headers are treated as optional metadata; an SDK call never raises if they are missing from a response.

Round-trip with traceparent

# Round-trip a request with an existing traceparent
curl -i \
  -H "traceparent: 00-0af7651916cd43dd8448eb211c80319c-b7ad6b7169203331-01" \
  -H "Authorization: Bearer $TOKEN" \
  https://api.knogin.com/v1/profiles/abc

# Response excerpt
# HTTP/1.1 200 OK
# X-Argus-Trace-ID: 0af7651916cd43dd8448eb211c80319c
# X-Argus-Span-ID: <fresh 16-hex>
# traceparent: 00-0af7651916cd43dd8448eb211c80319c-<server-span>-01

# Look up the recorded trace
curl -H "Authorization: Bearer $TOKEN" \
  https://api.knogin.com/v1/observability/traces/0af7651916cd43dd8448eb211c80319c

Trace lookup response

{
  "trace_id": "0af7651916cd43dd8448eb211c80319c",
  "tenant_id": "tnt_123",
  "spans": [
    {
      "span_id": "b7ad6b7169203331",
      "parent_span_id": null,
      "name": "POST /v1/profiles/{id}/enrich",
      "start_unix_nano": 1746715200000000000,
      "duration_ns": 412000000,
      "status_code": "OK",
      "attributes": { "http.status_code": 200, "tenant.id": "tnt_123" }
    }
  ],
  "ingestion": "stored"
}

Ready to wire trace IDs into your dashboards?

Open the API reference for the public contract, or talk to Knogin if you need help instrumenting partner connectors.