Prometheus Concepts
debt(d9/e7/b7/t7)
Closest to 'silent in production until users hit it' (d9), high-cardinality labels don't trigger errors at code time — Prometheus itself only shows strain when series counts explode in production. detection_hints.automated is 'no'.
Closest to 'cross-cutting refactor across the codebase' (e7), removing high-cardinality labels means finding every metric emission site, redesigning label schemes, and potentially migrating dashboards/alerts that depend on those labels.
Closest to 'strong gravitational pull' (b7), metrics design applies across web/cli/queue-worker contexts (per applies_to) and every service emits metrics — label schema choices shape observability across the whole system.
Closest to 'serious trap' (t7), the misconception that Prometheus handles high-cardinality data like a logging system contradicts how developers think about other stores (databases, ES) — labels look free but each unique combination is a new time series.
TL;DR
Explanation
Metric types: Counter (monotonically increasing, e.g. requests total), Gauge (up/down, e.g. memory), Histogram (bucketed distribution, e.g. latency), Summary (client-side quantiles). Labels: dimensions for filtering (method='GET', status='200'). Cardinality: high-cardinality labels (user_id) cause performance issues — use sparingly. PromQL: sum(rate(http_requests_total[5m])) by (route). Scrape: Prometheus pulls /metrics every 15-60s. Alertmanager: evaluates rules, routes alerts. PHP: promphp/prometheus_client_php, default Laravel integration. Push gateway: for short-lived jobs that don't live long enough to be scraped.
Common Misconception
Why It Matters
Common Mistakes
- High-cardinality labels — user_id, request_id in labels = millions of time series.
- Not using histograms for latency — use Histogram, not Gauge, for percentile queries.
- Scraping too frequently — default 15s is fine; 1s creates unnecessary load.
Code Examples
// High cardinality — one series per user:
$counter->labels(['user_id' => $userId])->inc(); // Millions of series
// Low cardinality — aggregate labels:
$counter->labels(['route' => $route, 'method' => $method, 'status' => $statusCode])->inc();
// Histogram for latency:
$histogram = new Histogram($registry, 'http_duration_seconds', 'Request duration',
['route'], [.005, .01, .025, .05, .1, .25, .5, 1, 2.5, 5]);
$histogram->labels([$route])->observe($duration);