Expert · Monitoring and logging · topic 39 of 53 · 35 min
Prometheus and Grafana
Explanation
What Prometheus is
Prometheus is a free, open-source monitoring system and time series database. A time series is a list of values with time stamps, like "requests so far" every 15 seconds. It started at SoundCloud and is now a graduated project of the CNCF (Cloud Native Computing Foundation), the same home as Kubernetes. It is the default choice for metrics in most Kubernetes setups.
The parts
- Prometheus server: scrapes targets on a schedule, stores samples in its local TSDB (time series database) and evaluates alert rules. Its web UI listens on port 9090.
- Targets: anything that serves metrics as plain text over HTTP, usually at /metrics. Many apps expose this with a client library.
- Exporters: small programs that translate metrics from things that cannot expose them themselves. node_exporter (port 9100) gives host metrics like CPU, memory, disk and network. There are exporters for MySQL, PostgreSQL, Redis and more, and blackbox_exporter for probing URLs from outside.
- Service discovery: Prometheus can find targets automatically from Kubernetes, cloud APIs or files, so new pods are scraped without editing config by hand.
- Alertmanager: receives alerts from Prometheus, removes duplicates, groups related ones, routes them to email, chat or a paging tool, and lets you silence them during maintenance. Port 9093.
- Pushgateway: only for short batch jobs that finish before Prometheus could scrape them. The job pushes its final numbers there and Prometheus scrapes the gateway. Do not use it for normal services.
Prometheus uses a pull model: it pulls metrics from targets, the targets do not push. A bonus is that a failed scrape is itself a signal: the built-in metric up is 1 when the last scrape worked and 0 when it did not.
# HELP http_requests_total Total HTTP requests handled.
# TYPE http_requests_total counter
http_requests_total{method="GET",route="/orders",status="200"} 10234
http_requests_total{method="POST",route="/orders",status="500"} 12
# HELP process_resident_memory_bytes Resident memory size in bytes.
# TYPE process_resident_memory_bytes gauge
process_resident_memory_bytes 5.24288e+07The four metric types
| Type | Behaviour | Examples |
|---|---|---|
| Counter | Only goes up; resets to 0 when the process restarts | Requests served, errors, bytes sent |
| Gauge | Goes up and down | Memory in use, queue length, temperature, active users |
| Histogram | Counts observations into buckets (_bucket with an le label, plus _sum and _count); percentiles are computed at query time and can be combined across servers | Request duration, response size |
| Summary | The client computes chosen quantiles itself; cheap to query, but the quantiles of many servers cannot be correctly combined | Request duration on a single process |
Labels and the cardinality trap
Labels are key-value pairs that split a metric into separate series, such as method="GET" or status="500". Every unique combination of name and labels is its own time series. Cardinality means how many series you end up with. Labels with a few fixed values are fine. A label like user_id, email, order_id or a full URL with IDs in it creates millions of series and can run Prometheus out of memory.
A scrape config
global:
scrape_interval: 15s # how often to scrape every target
evaluation_interval: 15s # how often to check alert rules
rule_files:
- "alerts.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
scrape_configs:
- job_name: "orders-api"
metrics_path: /metrics
static_configs:
- targets: ["orders-api:8080"]
- job_name: "node"
static_configs:
- targets: ["10.0.1.11:9100", "10.0.1.12:9100"]PromQL basics
PromQL is the query language of Prometheus. An instant vector is the latest value of each matching series, for example http_requests_total. A range vector is all samples in a time window, written with square brackets: http_requests_total[5m]. You cannot graph a range vector directly; you pass it to a function like rate().
rate(http_requests_total[5m])
sum by (status) (rate(http_requests_total[5m]))
sum(rate(http_requests_total{status=~"5.."}[5m]))
/ sum(rate(http_requests_total[5m]))
histogram_quantile(0.95, sum by (le) (rate(http_request_duration_seconds_bucket[5m])))rate() gives the average per-second increase of a counter over the window, and it handles counter resets when a pod restarts. sum by (status) adds up all series but keeps the status label separate. =~ means "matches this regular expression", so "5.." matches 500 to 599. histogram_quantile() estimates a percentile from histogram buckets; keep the le label when you sum.
Alert rules
groups:
- name: orders-api
rules:
- alert: OrdersHighErrorRate
expr: |
sum(rate(http_requests_total{job="orders-api",status=~"5.."}[5m]))
/ sum(rate(http_requests_total{job="orders-api"}[5m])) > 0.05
for: 10m
labels:
severity: page
annotations:
summary: "orders-api error rate is above 5%"
description: "Error rate is {{ $value | humanizePercentage }} for the last 10 minutes."
runbook_url: "https://wiki.example.com/runbooks/orders-high-error-rate"While the condition is true but for has not passed, the alert is "pending". Only after 10 minutes in a row does it "fire" and go to Alertmanager. This stops one bad scrape from waking someone up.
Grafana
Grafana is an open-source tool for dashboards. It does not store metrics itself; it connects to data sources such as Prometheus, Loki, Elasticsearch, PostgreSQL, MySQL, Amazon CloudWatch and Azure Monitor, and shows them as panels. Variables add drop-downs (choose the service or namespace) so one dashboard serves many services. Dashboards are saved as JSON, so you can keep them in Git.
On Kubernetes: kube-prometheus-stack
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
helm install monitoring prometheus-community/kube-prometheus-stack \
--namespace monitoring --create-namespaceWith the operator, you tell Prometheus what to scrape by creating a ServiceMonitor object next to your app, instead of editing prometheus.yml.
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Prometheus and Grafana · 1/8
In this lesson you will meet Prometheus and Grafana, the most common open-source pair for metrics and dashboards.
Prefer a video by a teacher? Find free videos on “prometheus grafana tutorial promql alertmanager for beginners” on YouTube ↗
In real life: A college fest ticket site
A student team runs the ticket site for an engineering college fest. They add a Prometheus client library to their Node.js app, run node_exporter on the two VMs, and install Prometheus and Grafana with Docker Compose. When ticket sales open at 6 pm, the Grafana panel built from sum by (status) (rate(http_requests_total[1m])) shows 500 errors climbing. The p95 panel from histogram_quantile shows the payment callback at 8 seconds. An alert rule with for: 5m pages the team lead, who finds the payment webhook timing out and raises its worker count.
sum by (route) (rate(http_requests_total{status=~"5.."}[1m]))Practice (0/3 done)
How does Prometheus normally get metrics from your orders API?
Write counter_rate(samples), a simplified PromQL rate(). samples is a list of (time_in_seconds, counter_value) tuples in time order. Add up the increase between each pair of neighbouring samples. If a value is LOWER than the one before, the counter was reset (the process restarted from 0), so the increase for that step is just the new value. Divide the total increase by the seconds between the first and last sample and round to 3 decimal places. With fewer than 2 samples return 0.0. (Real Prometheus also extrapolates to the window edges; ignore that here.)
Your team runs a "payments" service on port 9000 at payments:9000 and two Linux hosts at 10.0.2.21 and 10.0.2.22 with node_exporter. Write (a) the scrape_configs part of prometheus.yml, and (b) an alert rule that pages when the p95 latency of payments, from the histogram http_request_duration_seconds, is above 2 seconds for 10 minutes.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- Logging: structured, safe and centralisedMonitoring and logging · same module
- Alerting and on-callMonitoring and logging · same module
- Go in cloud and DevOps: Kubernetes, Terraform and PrometheusGo Programming (backend and cloud) · CLI tools and Go in cloud and DevOps
- Monitoring with CloudWatch, CloudTrail and ConfigCloud Computing (AWS, Azure, Google Cloud) · Serverless, monitoring and cost control
- Capstone project: from commit to monitored productionGitOps, platform engineering and DevOps careers
- Logging and monitoringBackend Development · Performance and reliability
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
Which metric type fits "number of items waiting in the email queue right now"?
Answer: Gauge
The queue length goes up and down, so it is a gauge.
What does rate(http_requests_total[5m]) return?
Answer: The average per-second increase of the counter over the last 5 minutes
rate() turns a counter into a per-second rate over the window and handles resets.
Which label is a cardinality danger?
Answer: user_id="9875512"
A user ID has millions of possible values, so it creates millions of time series.
When should you use the Pushgateway?
Answer: For a short nightly batch job that ends before it could be scraped
Pushgateway is only for short-lived batch jobs; long-running services should be scraped.
An alert rule has for: 10m. What does that mean?
Answer: The condition must stay true for 10 minutes before the alert fires
Until for has passed the alert is pending; it fires only if the condition holds the whole time.
How does Prometheus get metrics from a Go service?Related
Answer: Prometheus scrapes an HTTP endpoint such as /metrics
Prometheus pulls metrics over HTTP on a schedule.
From Go in cloud and DevOps: Kubernetes, Terraform and Prometheus
Why add for: 10m to an alert rule?Related
Answer: So a short spike does not page anyone; the condition must hold for 10 minutes
for prevents flapping alerts from brief spikes.
From Alerting and on-call
Your EC2 dashboard shows CPU but no memory use. Why?Related
Answer: EC2 cannot see inside the OS; install the CloudWatch agent
The hypervisor sees CPU, network and disk I/O, but not memory used inside the OS. The CloudWatch agent sends it as a custom metric.
Why should an alert include a runbook_url?Related
Answer: The person paged can follow written first steps instead of guessing at 3 a.m.
A runbook link turns an alert into a clear next action.
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “Monitoring and logging” before its exam: Logging: structured, safe and centralised, Alerting and on-call.
- Module 9 exam: Monitoring and logging · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
- Then the next module, SRE: reliability and incidents. 53 topics left in the course before the final exam.
← Previous: Monitoring and observability: metrics, logs and traces