Build a Prometheus-style time-series database (12 scenes)
Scene 01 · What a metric point actually is
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.
Scene 01
What a metric point actually is
Diagram
Three horizontal lanes stacked top-to-bottom. Each lane is one series, labelled on the left as `metric{k=v,k=v}`. Points stream in left-to-right at a fixed 15 s cadence; each dot's float value floats above it. A scrub axis at the bottom marks 'now' — points to its right haven't arrived yet.
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.
Implementation
Point
the four-part tuple every scrape produces
1struct Point:2 metric_name: str # e.g. 'http_requests_total'3 labels: dict[str, str] # e.g. {method: GET, status: 200}4 ts: int # unix seconds, on a fixed cadence5 value: float64 # the sample reading67# (metric_name, labels) names the SERIES.8# (ts, value) is the per-sample payload.
seriesIdentity
the function that decides which stream a point belongs to
1def seriesIdentity(p: Point) -> SeriesKey:2 # ts and value are NOT part of the identity.3 # any change to metric_name or labels => different series.4 return (p.metric_name, frozenset(p.labels.items()))
TSDB.ingest
look up the series; create one if this identity is new
1def ingest(p: Point):2 key = seriesIdentity(p)3 series = index.get(key)4 if series is None:5 # brand-new identity => brand-new stream, starts now6 series = Series(key)7 index.put(key, series)8 series.append(p.ts, p.value)