Saphan StudioDocs
Integrations

Metrics export: what you get

Three metrics from the record to any OTLP collector you run, the rule that governs every label on them, and the metrics a monitoring team usually asks for that this deliberately refuses.

For whoever builds the dashboard a fleet is watched from.

After reading it you can say which series exist, which labels you may group by, and which metrics you will not get and why.

Before you start: nothing. Read this before you design a dashboard, not after.

Saphan can publish a small, deliberately narrow set of metrics from its own record to any OTLP/HTTP collector you run — Prometheus behind the OpenTelemetry Collector, Grafana Alloy, Datadog's OTLP intake, or anything else that speaks the protocol.

It never sends recorded content, never runs automatically, and is not on the run path. An export cannot slow a run down, because no run ever triggers one — see running an export.

Three metrics, and each one has a column behind it

The exporter reads and never computes. A metric exists only because a column in the record answers it directly.

metricunitwhat backs it
saphan.run.cost_usdUSDthe quote and the actual cost of a run, told apart by a saphan.cost.kind attribute
saphan.review.roundscountthe review round ordinal
saphan.account.usage_pctpercenta seat's session and week usage readings

The rule that governs every label

An attribute is attached only when the record column carried a value. An empty column does not produce an empty label — it produces no label at all, and the series simply does not have that dimension.

That is deliberate, and the reason is worth reading before you build a query:

An attribute with an empty value is not a neutral default. An empty string here means this build did not answer, and a dashboard grouping on it invents a cohort that does not exist.

Do not assume a label is always present. Only the two marked always below are unconditional.

metricattributepresent
saphan.run.cost_usdsaphan.cost.kind (quoted or actual)always
saphan.streamwhen the record has it
gen_ai.system — the backendwhen the record has it
gen_ai.request.model — the modelwhen the record has it
saphan.rolewhen the record has it
saphan.trackwhen the run has a track
saphan.pricing_refwhen the record has it
saphan.review.roundssaphan.streamwhen the record has it — and nothing else
saphan.account.usage_pctsaphan.usage.windowalways
saphan.machinewhen the record has it
saphan.seat.statewhen the record has it

Two of the cost labels use OpenTelemetry's own convention names rather than the saphan. prefix — the backend is gen_ai.system and the model is gen_ai.request.model. A query filtering on saphan.* alone will not see them.

No attribute is common to all three metrics. Seat usage carries no stream: it is a property of a seat, not of a run, so a dashboard cannot join the three on one dimension.

The name you give a collector rides the exporter's own health points, under an endpoint attribute — not the record metrics above. Use it to tell two collectors apart in the exporter's self-reporting; do not expect it as a filter on cost or usage. The collector's URL never reaches the wire at all.

What is deliberately not exported

You will not find these, and each absence is a decision rather than a gap. Each is refused by name, and the export command prints the reason — so you never have to guess whether a missing metric is a bug.

what a monitoring team usually asks forwhy it is refused
a count of runsno column counts runs
a gate decisionno column carries one as a value
a review verdictno column, and no review table at all
egress dials and refusalsno column in the egress facts
a run's durationno elapsed-time column. The one column that looks like an answer is a configured cap — what a run was allowed, not what it took. Publishing a cap under a duration's name would be a lie, and deriving elapsed time would be a computation this exporter does not perform

A metric with no row behind it is not registered. If you need one of the above, the answer is a new column in the record first — never a number derived at export time.

Privacy

Identifiers and fingerprints only. Prompts, transcripts, file contents, credentials and free text never leave the record. The collector's URL is not published on the wire either — only the name you choose for it.

⇒ Next: running an export — the three keys, the egress admission the address does not grant you, and the limit to read before you schedule anything.

On this page