# Metrics Exposition

> Use when adding or reviewing a /metrics endpoint, choosing metric labels, or diagnosing a monitoring system that is growing without bound: which labels are cardinality decisions, capping high-cardinality views, exporting the fact that you truncated, and provisioning dashboards from the repository.

- Skill: `konradcinkusz/metrics-exposition` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add konradcinkusz/metrics-exposition`
- Raw SKILL.md: https://api.skillmd.com/api/skills/konradcinkusz/metrics-exposition/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: konradcinkusz (https://skillmd.com/u/konradcinkusz)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/konradcinkusz/metrics-exposition

---


# Metrics exposition: bounded cardinality, and truncation you can see

**Read [`references/METRICS-EXPOSITION.md`](references/METRICS-EXPOSITION.md) before applying any of this.**
That file is the standard; everything below it is a summary to help you decide
whether this skill applies and to check your work afterwards.

Reference-architecture principles: P15.

## What this standard covers

- Every label is a cardinality decision
- High-cardinality dimensions are opt-in and capped
- Export the fact that you truncated
- Emit sums and counts, not averages
- The endpoint is a surface; it can be closed
- Dashboards are provisioned, not clicked

## Failure modes

| Symptom | Cause |
|---|---|
| Prometheus memory climbs steadily and never recovers | A label carrying ids from your data — session, user, request, a path with an id in it. Each distinct value is a permanent series (§1) |
| Monitoring costs more than the service it monitors | The same, discovered on a bill rather than in a graph |
| A panel's numbers are confidently wrong, and nothing looks broken | The exporter truncated and never said so, so the dashboard is rendering a capped view as if it were complete (§3) |
| A rollup across instances disagrees with the per-instance panels | Pre-averaged gauges being averaged again — an average of averages (§4) |
| Cardinality is fine in staging and explodes in production | The high-cardinality view is default-on; staging simply never had enough distinct values to show it (§2) |
| An error-type label grows without bound | `type` sourced from an exception name or a remote error string: bounded by what dependencies say, which is not a bound you hold (§1) |
| Nobody can rebuild the dashboard after the monitoring stack is recreated | It was clicked together in a UI and never provisioned from the repository (§6) |

## Checklist

- [ ] Every label answers "what bounds its distinct values, and who enforces that bound?" — a label bounded only by your data does not ship as it stands
- [ ] High-cardinality views are off by default, with the reason written at the switch
- [ ] Each such view has a configured ceiling and a stated rule for which entries win when it is reached
- [ ] Open-ended label values (error types, and anything sourced from a dependency's strings) are top-N capped by volume
- [ ] The exporter emits its own ceiling **and** its own drop count as series, so a truncated view is visible on the dashboard built from it
- [ ] Scores and latencies are exported as `_sum`/`_count` pairs rather than pre-averaged gauges
- [ ] Serving `/metrics` is a configuration decision with an off switch
- [ ] Datasource, dashboard JSON and scrape config are provisioned from the repository, not assembled in a UI

---

Generated from [`docs/guides/METRICS-EXPOSITION.md`](https://github.com/konradcinkusz/architecture-standards/blob/main/docs/guides/METRICS-EXPOSITION.md) by `scripts/build-marketplace.mjs`. Do not edit this file: change the source document, or its entry in `catalog/marketplace.catalog.json`, and re-run the generator.

