Skip to content

Signals

Signals

telemetryd stores three signals. They share one storage engine and differ only in their Arrow schema — which is the whole reason adding traces and metrics was a schema and a query layer rather than two more storage engines.

Logs Traces Metrics
Ingest POST /v1/logs POST /v1/traces POST /v1/metrics, POST /api/v1/write
Query API Loki Tempo Prometheus
Query language LogQL subset TraceQL subset PromQL subset
Default retention 7 days 7 days 30 days
Indexed by event time span start time sample time

Streams and series are the same idea

Every record belongs to a stream — a bounded set of labels that identifies it. In Prometheus terms that is a series; in Loki terms a stream. telemetryd treats them identically, which is why label discovery works the same way for all three signals and why the metric name is stored as just another label (__name__).

A stream is deliberately small: app, level, and a configured list of promoted resource attributes. Everything else is an attribute — stored, queryable, but not part of the stream's identity. Putting high-cardinality values in the stream is how a telemetry store dies, so the line is drawn in configuration rather than left to chance.

app is always present

Every record carries an app label. If a producer sends neither app nor service.name, telemetryd assigns unknown rather than storing an unattributed record — so retention, quotas and queries never need a special case for a missing tenant.

app is a query namespace, not a security boundary. A holder of the ingest token can write any app value. See Security.

Metrics retention is longer, on purpose

Metrics default to 30 days where logs and traces default to 7. They cost far less per unit of time, and week-over-week comparison is most of what dashboards are for. The disk budget is still the hard cap across all three, so this cannot cause an unbounded footprint.