What a metric point actually is

A metric point is a four-part tuple — (metric_name, label_set, timestamp, value) — and the (metric_name, label_set) pair identifies a series that emits one value per scrape forever.

Scene 01

What a metric point actually is

  1. Watch
  2. Try it
  3. Predict
  4. Capture
S1http_requests_total{method=GETstatus=200}100.0101.5103.0S2http_requests_total{method=GETstatus=500}2.002.003.00S3http_requests_total{method=POSTstatus=200}86.587.287.9t=-1t=7t=15t=23t=31now t=30Three series, each emitting one point every 15 s. The float above each dot is the value at that timestamp.
What to watch for

Three running services emit one value every 15 seconds. Watch the dots stream into each lane — the float above each dot is the value at that timestamp. Notice that the three lanes share the same metric name but differ in their label set.

Continue unlocks when the animation finishes.
Implementation

Highlighted lines are the ones running in the diagram right now.

Point
the four-part tuple every scrape produces
struct Point:
metric_name: str # e.g. 'http_requests_total'
labels: dict[str, str] # e.g. {method: GET, status: 200}
ts: int # unix seconds, on a fixed cadence
value: float64 # the sample reading
# (metric_name, labels) names the SERIES.
# (ts, value) is the per-sample payload.
seriesIdentity
the function that decides which stream a point belongs to
def seriesIdentity(p: Point) -> SeriesKey:
# ts and value are NOT part of the identity.
# any change to metric_name or labels => different series.
return (p.metric_name, frozenset(p.labels.items()))
TSDB.ingest
look up the series; create one if this identity is new
def ingest(p: Point):
key = seriesIdentity(p)
series = index.get(key)
if series is None:
# brand-new identity => brand-new stream, starts now
series = Series(key)
index.put(key, series)
series.append(p.ts, p.value)

Where this sits in Build a Prometheus-style time-series database

Scene 01 of 12. A point is (metric, label_set, ts, value). The first two parts are the series identity — change one label and you've named a different stream.

Up next. If every scrape is one of these four-part tuples, the obvious move is to drop them in a SQL row — let's see why that obvious move is catastrophic.

All 12 scenes in Build a Prometheus-style time-series database · Every curriculum

Built with Arqly
Every scene in Build a Prometheus-style time-series database builds on the one before it.All 12 Build a Prometheus-style time-series database scenes