What it measures

Two numbers, what they are counted from, and the three places you can read them.

The two numbers

One is GPU time: tokens your GPUs computed more than once. One is GPU memory: the same tokens sitting in more than one cache at the same moment. They measure different resources, so they are never added together.

NumberResourceWhat it counts
Recomputed prefill GPU time Tokens that were stored, then evicted or cleared, then stored again on the same engine. Prefill you paid for twice
Duplicate KV footprint GPU memory The same content resident on more than one rank at the same instant. Copies across engines count here and are never added to the row above

Both are counted per rank, meaning one engine, one data parallel worker, one cache group. A node average cannot show you that one rank behaves differently from its siblings, and once you have taken the average you cannot get that back.

Why a miss gets a label

A miss on a prompt nobody had sent before and a miss on a block you evicted an hour ago cost the same GPU time, but you would fix them differently. So each miss is labelled when it is classified, and the labels are never merged back together. In the API they come through as the short names in the middle column.

LabelIn the APIMeans
evicted, then recomputed ETR Stored, evicted, stored again on the same engine.
recomputed after cache clear post_clear Same shape, but the cache was flushed rather than evicting under pressure. Usually a restart or a config change.
first compute (cold) cold Nothing to hit. Computed once, and not counted as recompute.
re-admitted re_admit Came back to a tier it had left.
engine-labelled reuse RE The engine said it was a reuse.
unclassifiable indeterminate Not enough in the stream to say. Counted as its own thing rather than folded into a neighbour.

What comes attached to every number

Four things, always. There is no way to get a bare number out of this system.

  • What it measures, in plain terms.
  • How it was computed, naming what went into it.
  • Its coverage, which is how much of the window was actually seen.
  • Its bound, which is what it is a floor or a ceiling on.

Figures are floors. If telemetry was missing for part of a window, that mass is not counted and it is not guessed at either, so the real number is somewhere above the one you are reading. A stretch nothing was seen for is drawn as unexamined rather than as a zero.

Coverage means two different things

Token-weighted answers "of the tokens this number is about, how many did we see". It qualifies every token figure. Observed time answers "was the tap sending at all". It qualifies none of them.

A fleet can look fully covered on one and sit at 40 percent on the other, in either direction. That is why both are labelled everywhere they appear.

Three places to read a number

All three come off the same query layer, so they cannot disagree with each other.

The dashboard

Fleet overview, each number's trend over time, which ranks are behind it, and a drill down to the individual store records the number came from. The records are the bottom level, and the page says so rather than implying there is more underneath.

An HTTP API

The dashboard is just a client. Figures, ranks, coverage, evidence, the difference between two windows, the fleet roster and delivery accounting are all addressable, and every response says which analysis version produced it.

Your own Prometheus

The numbers on the dashboard are also on the analyzer's /metrics, so you can alert on them with what you already run. If you want to be paged when recompute goes past five percent, that is a rule in your Alertmanager, not a feature request to us.

They appear once an analysis pass has run, and refresh each pass after that. Before the first pass they are absent rather than zero.

MetricWhat it is
infertap_fleet_recompute_tokens Tokens recomputed, over the window.
infertap_fleet_stored_tokens Tokens stored over the same window. The denominator below.
infertap_fleet_recompute_fraction Recompute as a share of tokens stored.
infertap_fleet_duplicate_kv_tokens Tokens held in more than one cache at once.
infertap_fleet_coverage_fraction How much of the window the figures above actually saw.
infertap_fleet_capture_fraction How many of the segments your taps wrote actually arrived.
infertap_fleet_segments_missing_unexplained Segments that never arrived and were never declared lost.
infertap_fleet_frontier_timestamp_seconds How far the analysis has got. Alert on this, not on scrape time.
infertap_fleet_meaning_info Carries the analysis version, so you can join on it. Numbers from either side of a version change are not the same quantity.

Which taps are reporting

Counted per tap run rather than per tap, because a tap that restarts is a new run. A single fleet wide freshness number is useless at scale: one busy tap keeps it green while ninety nine others sit dark.

MetricWhat it is
infertap_fleet_producer_runs_reporting Taps currently sending.
infertap_fleet_producer_runs_silent_unexplained Gone quiet past their own deadline, with no stop record. Page on this one.
infertap_fleet_producer_runs_departed Stopped cleanly. A rolling deploy lands here, so it will not wake anyone.
infertap_fleet_producer_runs_ungradeable Not enough information to judge either way.

It tells you when it could not measure something

infertap_analyzer_metrics_unmeasured counts how many of the figures above this scrape failed to produce. A partly blind scrape says so on the same endpoint, rather than dropping the metric or sending a zero.

That one, plus coverage_fraction and capture_fraction, is what to check during a trial. They tell you how much of the picture you are actually getting.

What you will not find here

Nothing tells you a number is good, bad or worrying, and no number is converted into money. Whether a figure warrants action depends on what your fleet is for, which we do not know. You can set thresholds, and they are drawn as your line across the measured data, labelled as yours.