Windows, buckets, and refresh intervals
The screen passes the window and bucket size explicitly, so you can reproduce any tile by calling the same procedure with the same arguments.
Two consequences worth internalising:
- The chart is coarser than the KPI. The viewer series uses 600-second
buckets over 24 hours. The “Concurrent viewers” KPI is a current
reading from
overviewKpis. A spike shorter than a bucket shows up in the KPI and is flattened in the chart. - The refresh intervals are staggered. The glass-to-glass KPI in the
strip refreshes on the 30 s
overviewKpiscycle; the histogram beside it refreshes on its own 60 s cycle. The P50 in the strip and the P50 under the histogram come from different queries (overviewKpisvsqoeKpis) and can be up to one refresh interval apart.
viewerSeries returns one row per bucket with bucket, viewers, and
g2g_p50 — i.e. the series carries a per-bucket latency median
alongside the viewer count, even though the Overview chart only plots
viewers.
Viewer counts: concurrent, unique, and how they are sampled
Two different viewer numbers appear on the screen. Org-wide concurrent viewers comes fromoverviewKpis.viewers_now.
It is a current reading, not an average over the refresh interval: the
tile re-reads it every 30 s and replaces the displayed value.
Per-stream concurrent viewers comes from each live input row’s
viewers_now field in liveInputs.list, rendered in the “Live now”
list next to that stream’s g2g_p50_ms. A row with no reading is
displayed as 0.
The 24-hour chart plots viewers per 600-second bucket from
viewerSeries. Because it is a bucketed rollup, each plotted point is
one value for a ten-minute span, not a continuous trace. The chart
renders “No viewer samples yet.” rather than a flat line whenever
fewer than two buckets have arrived, or when every bucket in the window
is zero — a relay rollup that has not produced two buckets yet cannot be
drawn as a line.
Live stream counts and the trailing ”+”
The “Live streams” KPI and the “across N live streams” hint both come from client-side filtering, and both can be a floor rather than an exact count. The Overview fetches one page of inputs (perPage: 100) without a
status filter, then keeps the rows where is_live is true or status
is active. The status filter is deliberately omitted because the
relay-derived is_live reconcile happens server-side after the
Postgres status filter — filtering in the query would drop rows the
reconcile would have marked live.
That client-side filter can only see the rows on the page it fetched. So
when total from the response exceeds the number of rows returned, the
count is a lower bound and the console appends a +:
7+ as “at least 7 of the inputs on the first page are live; there
are more inputs than were inspected.” The denominator (/ 213) is the
org’s total input count, taken from a separate perPage: 1 query that
exists only to read total. If you need an exact live count for an org
with many inputs, page through streams.liveInputs.list yourself and
apply the same is_live || status === 'active' predicate across all
pages.
Glass-to-glass: the target line and the percentiles
Glass-to-glass latency is surfaced three ways:overviewKpis.g2g_p50_ms— the single number in the KPI strip.qoeKpis.g2g_p50_ms/g2g_p95_ms/g2g_p99_ms— percentiles over the trailing 60 minutes, shown under the histogram.g2gHistogram.buckets— the distribution over the same 60-minute window, drawn as the bar chart. The Overview renders the first 14 buckets, with axis labels at80,180,280,420, and600+milliseconds, and places a marker at the bucket derived from the current P50.
250ms shown on the KPI card is a display target, not a quota or
a service commitment. The card renders in its “ok” state when P50 is
greater than zero and at or below that target; above it, the card simply
loses the ok styling. Nothing is throttled, rejected, or billed
differently on either side of the line.
A reported value of 0 means “no reading”, not “zero latency” — every
tile treats g2g_p50_ms > 0 as the precondition for rendering a value,
and shows — otherwise.
Egress and cache hit
overviewKpis carries two delivery-side numbers:
Note the window mismatch: egress in the KPI strip is a rolling 24-hour
figure, while the egress meter in the This billing cycle panel covers
the billing period. They are not the same measurement and should not be
expected to match.
The cache hit card renders its “ok” state at 95% or above. As with the
glass-to-glass target, that is a threshold for the card’s colour only.
Metered usage vs plan pools
The billing panel draws three meters, and each one prefers the plan pool over raw metered bytes when a pool exists.streams.analytics.usage returns raw meters:
streams.analytics.billing returns pools, keyed by meter, where each
pool has a limit and a remaining. The Overview uses two pools:
stream_egress_gb and vod_storage_gb.
The resolution rule for the egress and storage meters is:
- If the pool exists, used =
limit − remaining, clamped at zero, and the meter’s limit is the pool’slimit. - If the pool is absent, fall back to the raw meter from
usage(egress_bytesorstorage_bytes, converted to GB), and the meter is drawn with no limit.
remaining briefly
exceeds its limit (for example after a credit) shows as 0 rather than
a negative number.
Delivery minutes has no pool. It is drawn straight from
usage.delivery_minutes with no limit, so it reports consumption only —
it is not a progress bar against an allowance.
When a number is stale or incomplete
Work through these in order when a tile disagrees with what you expect:—instead of a value. The query has not resolved, or the underlying field is zero/absent. Every KPI on this screen prints—when its source is missing, and the glass-to-glass tiles additionally print—when the value is0.- “No viewer samples yet.” Fewer than two buckets in the series, or all buckets zero. Not an error — a stream that started less than two buckets ago cannot be plotted.
- “No active inputs”.
liveInputs.listresolved with nothing matchingis_live || status === 'active'. The first encoder publish populates the list. - A trailing
+on a count. The count is a floor computed from one page. See Live stream counts and the trailing ”+”. - Two tiles showing different latency. Different queries, different refresh intervals. Compare only after both have refreshed.
- Egress in the KPI strip ≠ egress in the billing panel. Different windows (24 h vs billing cycle) and, when a pool exists, a different derivation (pool subtraction vs raw bytes).
- A telemetry health banner at the top of the screen. The Overview renders one above the KPIs. When it is showing, treat every number on the page as suspect until it clears.
Reproducing these numbers from the SDK
Every tile is a plain tRPC call against the same control-plane origin the console uses, so you can pull the same figures into your own dashboard with the ClutchCall SDK or over HTTPS. Pass the samewindowMinutes
and bucketSeconds the console passes if you want the values to line up
with what the screen shows.
Related
- Telemetry — gateway-side metric families, traces, and CDRs
- Telephony Metrics — standard definitions for latency, jitter, and MOS
- SDK methods

