Exporters
Exporters bridge the gap between systems that don’t natively expose Prometheus metrics and Prometheus itself. An exporter runs alongside (or inside) a target, collects metrics, and exposes them on a /metrics endpoint.
Node Exporter (Host Metrics)
Section titled “Node Exporter (Host Metrics)”The most commonly used exporter — provides CPU, memory, disk, network, and filesystem metrics for Linux hosts.
Install and Run
Section titled “Install and Run”# Downloadwget https://github.com/prometheus/node_exporter/releases/download/v1.7.0/node_exporter-1.7.0.linux-amd64.tar.gztar xzf node_exporter-*.tar.gz./node_exporterOr as a systemd service:
[Unit]Description=Node ExporterAfter=network.target
[Service]ExecStart=/usr/local/bin/node_exporterRestart=always
[Install]WantedBy=multi-user.targetKey Metrics
Section titled “Key Metrics”| Metric | Type | What It Measures |
|---|---|---|
node_cpu_seconds_total | Counter | CPU time per mode (user, system, idle, iowait) |
node_memory_MemAvailable_bytes | Gauge | Available memory |
node_memory_MemTotal_bytes | Gauge | Total memory |
node_filesystem_avail_bytes | Gauge | Available disk space |
node_filesystem_size_bytes | Gauge | Total disk space |
node_network_receive_bytes_total | Counter | Network bytes received |
node_network_transmit_bytes_total | Counter | Network bytes sent |
node_load1 / node_load5 / node_load15 | Gauge | System load averages |
node_disk_io_time_seconds_total | Counter | Disk I/O time |
Useful Queries
Section titled “Useful Queries”These are PromQL queries you’d run in the Prometheus UI (http://prometheus:9090/graph) or use in Grafana dashboard panels to visualize Node exporter data:
# CPU usage percentage100 - (avg by (instance) (rate(node_cpu_seconds_total{mode="idle"}[5m])) * 100)
# Memory usage percentage(1 - node_memory_MemAvailable_bytes / node_memory_MemTotal_bytes) * 100
# Disk usage percentage(1 - node_filesystem_avail_bytes{mountpoint="/"} / node_filesystem_size_bytes{mountpoint="/"}) * 100
# Network throughput (bytes/sec)rate(node_network_receive_bytes_total{device="eth0"}[5m])Scrape Config
Section titled “Scrape Config”To tell Prometheus to scrape your Node exporters, add this to the Prometheus server’s prometheus.yml under scrape_configs. Each target is a host:port where Node exporter is running:
# prometheus.yml — on the Prometheus serverscrape_configs: - job_name: "node" static_configs: - targets: ["node1:9100", "node2:9100", "node3:9100"]Prometheus will scrape http://node1:9100/metrics, http://node2:9100/metrics, and http://node3:9100/metrics at the global scrape_interval.
Blackbox Exporter (Probing)
Section titled “Blackbox Exporter (Probing)”Probes endpoints from the outside — HTTP, TCP, DNS, ICMP. Tests what users experience:
Use Cases
Section titled “Use Cases”- Is my website returning 200?
- Is my API responding within 500ms?
- Is my DNS resolving correctly?
- Is port 5432 (PostgreSQL) open?
Configuration
Section titled “Configuration”modules: http_2xx: prober: http timeout: 5s http: valid_status_codes: [200, 201, 202] method: GET follow_redirects: true
http_post: prober: http http: method: POST headers: Content-Type: application/json body: '{"check": true}'
tcp_connect: prober: tcp timeout: 5s
dns_lookup: prober: dns dns: query_name: example.com query_type: A
icmp_ping: prober: icmp timeout: 5sScrape Config (Multi-Target)
Section titled “Scrape Config (Multi-Target)”scrape_configs: - job_name: "blackbox-http" metrics_path: /probe params: module: [http_2xx] static_configs: - targets: - https://example.com - https://api.example.com/health - https://staging.example.com relabel_configs: - source_labels: [__address__] target_label: __param_target - source_labels: [__param_target] target_label: instance - target_label: __address__ replacement: blackbox-exporter:9115Key Metrics
Section titled “Key Metrics”# Is the endpoint up? (1 = success, 0 = failure)probe_success{instance="https://example.com"}
# Response timeprobe_duration_seconds{instance="https://example.com"}
# SSL certificate expiry (days until expiration)(probe_ssl_earliest_cert_expiry - time()) / 86400Application Instrumentation (Client Libraries)
Section titled “Application Instrumentation (Client Libraries)”Instead of using an exporter, instrument your own application to expose metrics directly.
Python (prometheus_client)
Section titled “Python (prometheus_client)”from prometheus_client import Counter, Histogram, start_http_server
REQUEST_COUNT = Counter( 'http_requests_total', 'Total HTTP requests', ['method', 'status'])REQUEST_LATENCY = Histogram( 'http_request_duration_seconds', 'Request latency in seconds', ['method'])
@app.route('/api/data')def get_data(): with REQUEST_LATENCY.labels(method='GET').time(): # ... handle request ... REQUEST_COUNT.labels(method='GET', status='200').inc() return data
# Expose /metrics on port 8000start_http_server(8000)Go (prometheus/client_golang)
Section titled “Go (prometheus/client_golang)”import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp")
var requestCount = prometheus.NewCounterVec( prometheus.CounterOpts{ Name: "http_requests_total", Help: "Total HTTP requests", }, []string{"method", "status"},)
func init() { prometheus.MustRegister(requestCount)}
func main() { http.Handle("/metrics", promhttp.Handler()) http.ListenAndServe(":8080", nil)}Node.js (prom-client)
Section titled “Node.js (prom-client)”const client = require('prom-client');
const requestCount = new client.Counter({ name: 'http_requests_total', help: 'Total HTTP requests', labelNames: ['method', 'status'],});
app.get('/metrics', async (req, res) => { res.set('Content-Type', client.register.contentType); res.end(await client.register.metrics());});Naming Conventions
Section titled “Naming Conventions”| Pattern | Example | Rule |
|---|---|---|
<namespace>_<name>_<unit> | http_request_duration_seconds | Always include the unit |
| Counter suffix | _total | Counters should end in _total |
| Histogram suffix | _bucket, _sum, _count | Auto-generated |
| Unit suffixes | _bytes, _seconds, _total | Use base units (bytes not KB, seconds not ms) |
Other Common Exporters
Section titled “Other Common Exporters”| Exporter | Metrics From |
|---|---|
| mysqld_exporter | MySQL queries, connections, buffer pool |
| postgres_exporter | PostgreSQL queries, connections, replication |
| redis_exporter | Redis memory, keys, commands/sec |
| mongodb_exporter | MongoDB connections, operations, replication |
| nginx_exporter | Nginx connections, requests |
| cadvisor | Container CPU, memory, network (Docker/K8s) |
| kube-state-metrics | Kubernetes object states (pods, deployments, nodes) |
Custom Exporters
Section titled “Custom Exporters”When no existing exporter fits, write your own. The pattern:
- Collect data from your system (API, file, database).
- Map it to Prometheus metric types (Counter, Gauge, Histogram).
- Expose on
/metrics.
from prometheus_client import Gauge, start_http_serverimport requests, time
queue_depth = Gauge('queue_depth', 'Number of items in the job queue', ['queue_name'])
def collect(): while True: resp = requests.get('http://internal-api/queues') for queue in resp.json(): queue_depth.labels(queue_name=queue['name']).set(queue['depth']) time.sleep(15)
start_http_server(9200)collect()Key Takeaways
Section titled “Key Takeaways”- Node exporter for host metrics (CPU, memory, disk, network) — install on every machine.
- Blackbox exporter for probing endpoints from the outside (HTTP, TCP, DNS, ICMP).
- Instrument your apps with client libraries to expose request counts, latency histograms, and business metrics.
- Follow naming conventions:
_totalfor counters,_seconds/_bytesfor units. - Use existing exporters for databases, caches, and web servers before writing custom ones.