Observability
Every response from /v1/* carries two correlation headers. If
you wire them through your logging and tracing, debugging a
streaming chat across three machines stops being a guessing game.
Headers
X-Request-ID: req_3f2a7c8e1b4d5e6f
traceparent: 00-<trace_id>-<parent_id>-<flags>
tracestate: rojo=00f067aa0ba902b7
Three things they let you do:
- Correlate a server-side log line with a specific HTTP exchange the bridge made.
- Stitch a distributed trace across iOS → cloud → bridge → agent.
- Pass through opaque vendor state (Honeycomb, Sentry, Datadog…) without us inspecting it.
X-Request-ID
Identifies one HTTP exchange. Format when server-generated:
req_<16 lowercase hex> e.g. req_3f2a7c8e1b4d5e6f
Clients may supply their own value ([A-Za-z0-9._:-]{1,64});
the server echoes it back unchanged.
The recommended pattern: every error your bridge logs should
include the X-Request-ID of the failing call. When you file a
bug or open a support ticket, paste it. The server has the same
id in its logs and can find your exact request in seconds.
const r = await fetch(url, { ... })
if (!r.ok) {
const reqId = r.headers.get('X-Request-ID')
log.error({ reqId, status: r.status }, 'sophon POST failed')
}traceparent (W3C Trace Context)
Format:
<version>-<trace_id>-<parent_id>-<flags>
00-4bf92f3577b34da6a3ce929d0e0e4736-00f067aa0ba902b7-01
version: always00for v1.trace_id: 32 hex chars, identifies the distributed trace.parent_id: 16 hex chars, identifies this server's span inside the trace. Agents stitching their own spans below this useparent_idas their parent reference.flags:01= sampled,00= not sampled.
If your bridge sends a valid inbound traceparent (you already
have a span), the server keeps your trace_id and mints a new
parent_id (the server is now a child of your inbound caller).
If you don't send one, the server generates a fresh trace
with flags=01.
tracestate
Comma-delimited list of opaque vendor state, per the W3C spec. The server passes it through verbatim — never inspects, never rewrites. If you're using Honeycomb / Datadog / Lightstep / a homegrown tracer, this is where their per-vendor context rides along.
OpenTelemetry pass-through
If your bridge already runs an OTel SDK, you get distributed traces for free. The HTTP client should:
- Inject
traceparent/tracestateoutbound on every Sophon request. - Extract the returned
traceparentand attach it as a span link on the outgoing request span.
Most OTel HTTP instrumentations do both automatically. With Pino,
Sentry, or a homegrown logger, just thread the
X-Request-ID and traceparent into your structured log record
and you're done.
Server-side logging hooks
Server logs include the same request_id and trace_id on
every line that handled the request. When you ping the team with
a bug:
Bridge call to
/v1/bridge/createTaskreturned 500.X-Request-ID: req_3f2a7c8e1b4d5e6f,traceparent: 00-4bf9…-00f0…-01.
…we have everything we need to find the line and the upstream context.
What we don't do
- We do not sniff your
tracestate. - We do not persist
X-Request-IDbeyond the standard log retention window. - We do not require
traceparentto be present — you're perfectly fine sending none, you just lose the cross-system view.