Exporting RED metrics over OTLP
Spider can turn the traffic it captures into RED metrics — Rate, Errors, Duration — and push them to any OTLP/HTTP collector. The point is not to replace your observability stack but to feed it: Spider already sees every request on the wire, including the ones no application instruments, so it can produce service-level metrics for code you do not own and cannot change.
The feature requires an ENTERPRISE licence and must be enabled at install with
global.flips.otelExport.
What is exported
Two instruments, and nothing else:
| Metric | Type | Unit | Meaning |
|---|---|---|---|
spider.requests | Sum | 1 | Number of requests in the window |
spider.request.duration | Histogram | s | Request duration distribution |
Both are attributed with the protocol, the client and server identities Spider resolved, and the
response status. Errors are not a third instrument: they are spider.requests sliced by the status
attribute, which is what the "E" in RED means in practice.
Metrics only. Spans are out of scope by design. Spider observes each request from outside the process and has no propagated context to stitch a trace from — anything it emitted as a span would be a single-hop guess, and a wrong trace is worse than no trace. If you want traces, instrument the application; use Spider's metrics for what the application does not report.
Two objects: target and exporter
The split exists so that credentials never leave administrator hands.
An OtelTarget is a collector endpoint: a URL, an authentication mode, a credential, and the
list of teams allowed to use it. Only an administrator (or a user with the otelTargets.create
right) creates one. Find them under OTel targets in the left band.
An OtelExporter is a team's selection of traffic: which whisperers, which protocols, an optional
filter, and which of the shared targets to push to. A team member with the team's settings right
authors it, from the Metrics export tab of the team - see
Exporting metrics to your own stack
for the exporter forms, the Preview workflow, and how to read push status.
A team can therefore push to a collector without ever being able to read its credential, and an
administrator can revoke a whole team's access by removing it from the target's teams list.
The credential is write-only
It is sealed at rest with a key from global.otelExport.credentialKey and never returned by any
read: every response carries the literal *** and, by construction, cannot carry anything else —
the field's type holds no data, so redaction is not something a future change can forget to do. The
form always opens with the credential box empty and an unchanged placeholder: leaving it empty
keeps the stored secret, it does not clear it.
For the same reason, Test connection performs the collector handshake on the server. The browser only ever learns whether it worked, the status code and the latency.
That test is only safe because of one further rule: changing a target's endpoint clears its credential, so the same edit must supply a fresh one. A credential is scoped to the collector it was issued for. Without the rule, anyone who could edit a target could repoint it at a listener of their own and press Test connection to have Spider hand over the secret. The cost is small and deliberate: fixing a typo in an endpoint means re-entering the credential in that same save.
To rotate the encryption key, put the new key in global.otelExport.credentialKey, move the old one
into global.otelExport.credentialKeysPrevious, redeploy, then edit each target once to re-seal it.
A target's Sealed with key field tells you which key it still uses, so you can see when the
rotation is finished. Remove an old key from credentialKeysPrevious only once no target still
reports it.
Your collector must accept delta temporality
Spider pushes AGGREGATION_TEMPORALITY_DELTA: each push carries what happened in that one minute,
not a running total. This is not configurable, and it is the single most common reason an otherwise
correct setup receives nothing usable.
- Prometheus — its native OTLP endpoint accepts delta metrics directly.
- OpenTelemetry Collector — add the
deltatocumulativeprocessor to the pipeline if what sits behind it expects cumulative sums. - Anything else — check its temporality support before blaming the export.
Delta temporality is also why a failed push is never retried into a later window: replaying a delta would double-count it permanently, with nothing to reconcile against later. Spider prefers a visible gap over silent corruption.
Timing
Metrics lag two minutes behind real time. Spider aggregates whole one-minute windows, and a window is only pushed once late-arriving traffic for it has settled — pushing sooner would emit counts that are quietly too low.
If an exporter falls behind — a collector that has been down, for instance — it catches up window by
window, up to a bounded number of windows. Past that bound the missed windows are skipped rather
than backfilled, for the delta reason above. The otelExportStale alert probe tells you when this
is happening.
Cardinality: the endpoint label
The optional endpoint label adds spider.endpoint to every series. It is the most useful
attribute and the most dangerous one, because it multiplies your series count by the number of
distinct endpoints.
For HTTP and PostgreSQL, its value depends on the whisperer's configured request templates.
With templates, /orders/8213 and /orders/9147 both become /orders/{id} — one series. Without
them they are two, and a busy API becomes tens of thousands. Configure the templates before turning
the label on.
Each exporter is bounded by a per-window series budget. Past it, the overflow is dropped and
counted, not sampled — a truncated metric that looked complete would be worse than a missing one.
Use Preview before saving: it runs the real aggregation over the window the exporter would
process next, without saving anything, and tells you whether you are over budget. The
otelExportDropping alert probe tells you if a saved exporter starts overflowing later.
Scope is re-resolved on every run
An exporter's effective scope is its own whisperer list intersected with the team's whisperers, recomputed every time it runs. A whisperer removed from the team therefore stops being exported immediately, with no edit to the exporter and no redeploy. An exporter can only ever narrow over time, never widen.
When authoring, you can additionally only select whisperers you can already read yourself. An exporter must not be able to emit metrics for traffic its own author cannot see in the UI.
Only whisperers in INTERFACE capture mode can be selected: an UPLOAD whisperer holds imported
captures, not live traffic, and has no windows to roll up.
Monitoring the export itself
Two alert probes ship with the feature, both inactive on installs that do not use it:
| Probe | Fires when | Gauge |
|---|---|---|
otelExportStale | an enabled exporter's target is more than maxWindowsBehind windows behind | spider_otel_export_staleness_windows{exporter,target} |
otelExportDropping | an exporter overflowed its series budget | spider_otel_export_dropped_series{exporter} |
Push status is also visible per exporter and per target in the Metrics export tab: the last window pushed, the last error, and how many failures in a row. It is shown per target rather than per exporter on purpose — an exporter fanning out to three collectors can be current on two and stuck on the third.