3. Writing your first rules #
The syntax, a full example and group options.
A rules file #
Declare the file in prometheus.yml, then write the rules. These examples use Prometheus's own metrics, so you can try them straight away:
global:
scrape_interval: 5s
evaluation_interval: 15s
rule_files:
- /etc/prometheus/rules.yml
scrape_configs:
- job_name: prometheus
static_configs:
- targets: ["localhost:9090"]groups:
- name: http_prometheus
rules:
- record: job_handler:prometheus_http_requests:rate5m
expr: sum by (job, handler) (rate(prometheus_http_requests_total[5m]))
- record: job:prometheus_http_requests:rate5m
expr: sum by (job) (job_handler:prometheus_http_requests:rate5m)
- record: job:prometheus_http_requests_errors:rate5m
expr: sum by (job) (rate(prometheus_http_requests_total{code=~"5.."}[5m]))
- record: job:prometheus_http_requests_errors:ratio_rate5m
expr: |
(job:prometheus_http_requests_errors:rate5m or job:prometheus_http_requests:rate5m * 0)
/ job:prometheus_http_requests:rate5m
- record: job:prometheus_http_request_duration_seconds:p95_rate5m
expr: |
histogram_quantile(0.95,
sum by (job, le) (rate(prometheus_http_request_duration_seconds_bucket[5m])))In Grafana, the query becomes very simple:
# Before: recomputed on every refresh of every panel
sum by (job) (rate(http_requests_total[5m]))
# After: simple read of the recorded series
job:http_requests:rate5mGroup options #
groups:
- name: http_aggregates
interval: 30s # otherwise: the global evaluation_interval
query_offset: 30s # evaluates slightly in the past if data arrives late
limit: 1000 # the rule fails if it produces more than 1000 series
labels:
team: platform # added to all rules of the group
rules:
- record: job:http_requests:rate5m
expr: sum by (job) (rate(http_requests_total[5m]))4. Naming your rules well #
The level:metric:operations convention.
The official convention #
The Prometheus documentation recommends the level:metric:operations format. The name then says what the series contains, without opening the rules file. Colons are reserved for this purpose: exporters must not use them.
| Part | Meaning | Example |
|---|---|---|
| level | Labels kept by the aggregation | job, instance_path |
| metric | Original name, without the _total suffix after a rate | http_requests |
| operations | Applied operations, newest first | rate5m, ratio_rate5m, p95_rate5m |
5. Pitfalls to avoid #
Ratios, missing series, order of operations.
Never average ratios #
A service at 10 requests per second with 50% errors and another at 1000 requests per second with 0% do not average 25% errors, but about 0.5%. So record the numerator and denominator, then divide their sums:
# Wrong: average of ratios, a small service weighs as much as a big one
avg by (job) (instance:http_requests_errors:ratio_rate5m)
# Right: aggregate the numerator and denominator separately
sum by (job) (instance:http_requests_errors:rate5m)
/ sum by (job) (instance:http_requests:rate5m)The ratio that disappears when all is well #
This is the sneakiest pitfall, observed while preparing this chapter. If no 5xx series exists, the filter returns nothing, and dividing by an empty result gives an empty result, not 0. The dashboard shows “No data”: you can then no longer tell “no errors” from a collection outage.
# Empty as long as no 5xx error has been seen
job:requests_errors:rate5m / job:requests:rate5m
# Equals 0 when there is no error
(job:requests_errors:rate5m or job:requests:rate5m * 0) / job:requests:rate5mOther frequent mistakes #
ratefirst,sumsecond:sum(rate(x[5m])). Adding counters beforeratebreaks the detection of their resets.- Histograms: keep the
lelabel insum by, orhistogram_quantilecannot compute anything. - Too many labels: a rule keeping
instanceorpodkeeps almost all the cardinality. - Changing a rule: if the expression changes meaning, change the name too, or the old and new logic mix in the same series.
My progress
Sign in to track your progress and take notes. Sign in
Course Glossary
Alerting
The process of notifying teams (via email, Slack, Teams) when a specific event, threshold breach, or anomaly is detected.
Architecture
The overall structural design of an IT system, defining its various components, their relationships, and the principles guiding its evolution.
OpenTelemetry
An open source framework providing standards, APIs, and SDKs to collect and export observability data (traces, metrics, logs) in an agnostic way.
Recommended Articles
Prometheus : alerter avec Alertmanager (règles, routage, silences)
Mettre en place l'alerting Prometheus : règles d'alerte, Alertmanager, routage, regroupement, inh...
Grafana Alloy: Syntax and Configuration (Alloy Language: River)
As part of a Grafana training or observability training, master the declarative syntax of Grafana...
Les types de métriques dans Prometheus
Découvrez en détail les quatre types de métriques supportés par Prometheus (Counter, Gauge, Histo...
Prometheus sur Kubernetes et l'interface web de Prometheus
Déployer Prometheus sur Kubernetes avec kube-prometheus-stack (Prometheus Operator, ServiceMonito...
Mimir : le chemin de lecture (query-frontend, querier, store-gateway et caches)
Comment Mimir répond à une requête PromQL : découpage et cache du query-frontend, file d'attente,...
Prometheus dans le monde Kubernetes (Operator, ServiceMonitor, kube-prometheus-stack)
Superviser Kubernetes avec Prometheus : service discovery, kube-prometheus-stack, Prometheus Oper...
Grafana : maîtriser les requêtes (PromQL, LogQL, SQL et expressions)
Construire des requêtes efficaces dans Grafana : éditeur de requêtes, Query Inspector, PromQL, Lo...
Exploring data in OpenObserve: SQL, PromQL and VRL
Search with SQL, query metrics with PromQL, optimize a stream (indexes, partitions, retention) an...
Kibana avancé : data views, Lens, dashboards, alerting et reporting
Exploiter Kibana en profondeur : data views et champs runtime, Discover, Lens et formules, dashbo...