Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Use when naming the metrics and labels a service exposes to Prometheus: snake_case names with a single-word application prefix, base-unit suffixes (seconds/bytes/ratio, never milliseconds or megabytes), a _total suffix on counters, dimensions as labels rather than name fragments, and low-cardinality snake_case label keys (never a user id, email, or full path as a label). Do NOT use for writing PromQL queries, configuring scrape intervals or alerting rules, choosing a metrics backend, or naming general code identifiers.
.claude/skills/prometheus-metric-naming/SKILL.md| Model | Eval pass | Runs |
|---|---|---|
| gemini-3.6-flash | 100% | 6 |
| Model | Lift | Δ tokens | Δ turns | Cases | Verified |
|---|---|---|---|---|---|
| gemini-3.6-flashbest | +5% | +66% | 0% | 22 | 53d ago |
| gemini-3.5-flash | pending re-run | — | |||
| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | — | — |
| case-10 | ✗→✗ | = Same ✗ | — | — |
| case-11 | ✗→✗ | = Same ✗ | — | — |
| case-22 | ✗→✗ | = Same ✗ | — | — |
| case-04 | ✗→✗ | = Same ✗ | — | — |
Enforces the Prometheus naming best-practices on every metric and label a service exposes: snake_case names, a single-word application prefix, a base-unit suffix, _total on counters, dimensions expressed as labels, and low-cardinality snake_case label keys. Apply when defining or reviewing instrumentation a Prometheus-compatible scraper reads; not for queries, alerting rules, or scrape configuration.
single underscores. Never camelCase (httpRequests), never hyphens, never dots inside a name. A metric name matches [a-z_][a-z0-9_]*.
word naming the subsystem it belongs to — http_, process_, queue_, db_. A bare requests_total with no prefix is unnamespaced; give it one.
and that unit is the SI base unit — _seconds (never _ms, _milliseconds, _millis), _bytes (never _kb, _mb, _kilobytes, _megabytes), _ratio for a 0.0–1.0 fraction (never _percent on a 0–100 scale). Convert the value; don't rename the unit.
_total. A counter — a value that only ever increases —carries the _total suffix (http_requests_total, errors_total). A gauge — a value that goes up and down, like a queue depth or a temperature — never carries _total.
no _gauge, _counter, _histogram, _summary. And _sum, _count, and _bucket are RESERVED — the histogram/summary machinery emits them automatically — so they are never a suffix you choose for your own metric.
method, status, region, outcome — is a label on ONE metric, never spliced into the name. One name (http_requests_total) with a method label beats a name per method (http_get_requests_total, http_post_requests_total).
lowercase, underscores, no camelCase (status_code, not statusCode).
no user id, email address, full URL or request path, request id, session id, or raw timestamp. Every distinct label-value combination is a new stored time series, so an unbounded label explodes storage. Bound the set (a normalized route template, an outcome enum) or leave the value out of the metric entirely.
A request counter — camelCase, milliseconds, and a missing suffix become conforming:
BEFORE httpRequestsMs # a counter, camelCase, and it names a unit it is not measuring
AFTER http_requests_total # counter: snake_case, prefix, _total
http_request_duration_seconds # the latency histogram: base unit secondsA size gauge — megabytes and a type suffix become base units and a clean name:
BEFORE memoryUsageMb_gauge
AFTER process_resident_memory_bytes # base unit bytes, no _gauge, no _totalA fraction — a 0–100 percentage becomes a 0–1 ratio:
BEFORE cacheHitPercent # 0..100
AFTER cache_hit_ratio # 0.0..1.0, suffix _ratioA dimension baked into the name becomes a label:
BEFORE http_get_requests_total
http_post_requests_total
AFTER http_requests_total{method="get"}
http_requests_total{method="post"}A high-cardinality label is dropped; a bounded one stays:
BEFORE http_requests_total{user_id="u-99381", path="/orders/48213"}
AFTER http_requests_total{route="/orders/{id}", status_code="200"}_total:network_transmit_bytes_total, process_cpu_seconds_total.
..._timestamp_seconds, never amillisecond timestamp.
unit suffix — but it is a gauge, so it still takes no _total either.
..._info gauge fixed at value 1with the metadata as labels — not smuggled into a name.
as a normalized template label (/orders/{id}), never as the raw high-cardinality value.
http_requests_total. Don't write httpRequests, HTTPRequests, or requests._total. Don't add _total to a gauge._seconds. Don't record _ms / _milliseconds._bytes. Don't record _mb / _kb._ratio on 0..1. Don't use _percent on 0..100.statusCode or userId as a label key._sum / _count / _bucket.httpRequestDurationMs)._total, so a counter looks like a gauge to every tool that keys on the suffix.user_id, email, session_id, or full-path label — each unique value is a new series._gauge / _counter type suffixes, or reusing the reserved _count / _sum / _bucket._seconds not ms, _bytes not mb, _ratio (0..1) not percent._total on counters only; gauges take neither _total nor a type suffix._gauge/_counter type suffix; _sum/_count/_bucket reserved, never yours.| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-10 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-11 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-22 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-04 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-05 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-01 | fail→pass | — | — | — | — | — | — | — | — | — | — | — | — |
case-19 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-17 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-13 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-14 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-08 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-07 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-12 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-03 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-18 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-20 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-02 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-06 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-09 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-15 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-16 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
case-21 | fail→fail | — | — | — | — | — | — | — | — | — | — | — | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +5 percentage points is the difference between those two pass rates over the 22 comparable cases.
The per-case answers from this run were removed by the retention sweep, so the case table below shows the verdicts without the text either arm produced. The counts above were recorded at the time and are unaffected. Answers are now kept for 180 days.
| Model | Method | Date | Lift |
|---|---|---|---|
| gemini-3.5-flash | verified | 7/10/2026 | +27% |
Other measured skills in the registry, with their headline benchmark lift.