Distributed Tracing
Every outbound request from the SDK carries a traceparent header so server-side spans stitch directly into your distributed-tracing graph — whether you run Datadog, OpenTelemetry, Jaeger, Tempo, or Grafana Cloud Traces.
Available from SDK
1.2.0. No configuration is required — the header is added automatically, even without OpenTelemetry installed.#The header
The SDK emits the W3C Trace-Context format on every call:
traceparent: 00-<32-hex-trace-id>-<16-hex-span-id>-01
# example: 00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01#Resolution order
- Caller-supplied
traceparentwins. The SDK never overwrites a header that you passed inheaders=. Case-insensitive match, so bothtraceparentandTraceParentare detected. - OpenTelemetry active span. If
opentelemetryis importable and a recording span is live on the current context, the SDK delegates toopentelemetry.propagate.inject()— the header matches the runtime tracer's sampling decision and may also carry atracestate. - Standalone fallback. When no OTel context exists, the SDK synthesises a W3C-compliant traceparent with 128-bit random trace-id and 64-bit random span-id (via
secrets.token_hex). The server still gets a stable correlation id for its logs.
#Integrating with OpenTelemetry
No instrumentation library is required. Simply start a span before the SDK call — the SDK picks it up automatically.
from opentelemetry import trace
from radmah_sdk import RadMahClient
tracer = trace.get_tracer("my-app")
client = RadMahClient(api_key="sl_live_…")
with tracer.start_as_current_span("submit-synthesis-job") as span:
span.set_attribute("tenant.plan", "enterprise")
job = client.jobs.create(seal_id="seal_…", engine="mock", rows=10_000)
span.set_attribute("radmah.job_id", job.id)
# The server-side span for POST /v1/client/jobs/ is a child of
# submit-synthesis-job in your APM, no further wiring required.
#Supplying your own trace id
If your service has an existing correlation scheme and you want the server to log your id rather than OTel's, pass the header directly:
caller_tp = f"00-{your_trace_id}-{your_span_id}-01"
client._get("/v1/client/jobs/", headers={"traceparent": caller_tp})
Retry attempts reuse the same
traceparent so server-side logs can stitch all attempts of one logical call together.#Failure modes
- If
opentelemetryraises duringpropagate.inject()— a broken instrumentation install, a misconfigured SDK, a noop tracer — the SDK catches the exception silently and falls back to the standalone generator. Outbound requests are never blocked by OTel failures. - If the server rejects the header (shouldn't happen — the platform parses W3C format only), the request still proceeds. The header is informational, never load-bearing for authentication.