The data model: metrics, labels and series

Prometheus · Essentials · 10 min

Every query and every performance problem in Prometheus comes back to series and their labels.

Every time series is identified by a metric name and a set of labels (key-value pairs):

http_requests_total{method="GET", path="/api/users", status="200"}

Each distinct combination of label values is a separate series. A series is a list of samples: a float64 value and a millisecond timestamp. Prometheus adds two labels to every scraped series: job (from the scrape configuration) and instance (the target's host:port).

Labels make queries powerful: you can sum all requests, or break them down by method or status, with one metric. But they have a cost. The number of series is the product of the label values used. Adding user_id as a label creates a series per user, the classic cardinality explosion that makes Prometheus slow and memory-hungry. Keep label values bounded: HTTP method, status class, route template, never IDs, emails or full URLs.

Naming conventions from the Prometheus docs:

  • snake_case, prefixed with the application or domain: myapp_jobs_processed_total.
  • Include the base unit as a suffix: _seconds, _bytes, not milliseconds or megabytes.
  • Counters end in _total.

Label names starting with __ are reserved for internal use.

Example

# Exposition format: one line per series, # HELP and # TYPE describe the metric
# HELP http_requests_total Total HTTP requests.
# TYPE http_requests_total counter
http_requests_total{method="GET",status="200"} 1027
http_requests_total{method="GET",status="404"} 3
http_requests_total{method="POST",status="200"} 112
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 2.4576e+07

# After scraping, each series also gets job and instance labels:
# http_requests_total{instance="10.0.0.5:8000",job="api",method="GET",status="200"}

Remember

  • A series = metric name + unique label set; each holds float samples
  • job and instance are added at scrape time
  • Keep label values bounded; base units and _total in names

Watch out for

  • Putting user IDs, request IDs or raw URLs into labels, creating millions of series.

Check yourself

  1. A metric has labels method (4 values), status (10 values) and instance (5 targets). How many series can it have at most?

Sign in to answer, see the explanations, and get this lesson back as a quick review later.

Official docs: prometheus.io/docs/concepts/data_model/

The data model: metrics, labels and series · Prometheus · Topolearn