DEV Community

Alex Spinov
Alex Spinov

Posted on

Prometheus Has a Free API — Monitor Everything with PromQL

TL;DR

Prometheus is the industry-standard open-source monitoring system. It collects metrics from your applications via a pull model, stores them in a time-series database, and provides PromQL for powerful querying — all completely free.

What Is Prometheus?

Prometheus is a CNCF graduated project for monitoring:

  • Pull-based — scrapes metrics from HTTP endpoints
  • Time-series DB — efficient storage with compression
  • PromQL — powerful query language for metrics
  • Alerting — built-in alertmanager for notifications
  • Service discovery — auto-find targets in Kubernetes, Docker, EC2
  • Free — Apache 2.0, self-hosted

Quick Start

# prometheus.yml
global:
  scrape_interval: 15s

scrape_configs:
  - job_name: "my-app"
    static_configs:
      - targets: ["localhost:8080"]

  - job_name: "node-exporter"
    static_configs:
      - targets: ["localhost:9100"]
Enter fullscreen mode Exit fullscreen mode
# Run with Docker
docker run -p 9090:9090 \
  -v ./prometheus.yml:/etc/prometheus/prometheus.yml \
  prom/prometheus

# Access UI at http://localhost:9090
Enter fullscreen mode Exit fullscreen mode

Instrumenting Your App

Node.js

import { Registry, Counter, Histogram, collectDefaultMetrics } from "prom-client";
import express from "express";

const register = new Registry();
collectDefaultMetrics({ register });

// Custom counter
const httpRequests = new Counter({
  name: "http_requests_total",
  help: "Total HTTP requests",
  labelNames: ["method", "path", "status"],
  registers: [register],
});

// Request duration histogram
const httpDuration = new Histogram({
  name: "http_request_duration_seconds",
  help: "HTTP request duration in seconds",
  labelNames: ["method", "path"],
  buckets: [0.01, 0.05, 0.1, 0.5, 1, 5],
  registers: [register],
});

const app = express();

// Middleware to track metrics
app.use((req, res, next) => {
  const end = httpDuration.startTimer({ method: req.method, path: req.path });
  res.on("finish", () => {
    httpRequests.inc({ method: req.method, path: req.path, status: res.statusCode });
    end();
  });
  next();
});

// Metrics endpoint
app.get("/metrics", async (req, res) => {
  res.set("Content-Type", register.contentType);
  res.end(await register.metrics());
});

app.listen(8080);
Enter fullscreen mode Exit fullscreen mode

Python

from prometheus_client import Counter, Histogram, start_http_server
import time

REQUESTS = Counter("http_requests_total", "Total requests", ["method", "endpoint"])
LATENCY = Histogram("request_latency_seconds", "Request latency")

@LATENCY.time()
def process_request():
    REQUESTS.labels(method="GET", endpoint="/api").inc()
    time.sleep(0.1)

# Expose metrics on port 8000
start_http_server(8000)
Enter fullscreen mode Exit fullscreen mode

Essential PromQL Queries

# Request rate (requests per second)
rate(http_requests_total[5m])

# 95th percentile latency
histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))

# Error rate percentage
sum(rate(http_requests_total{status=~"5.."}[5m])) /
sum(rate(http_requests_total[5m])) * 100

# Top 5 endpoints by request count
topk(5, sum by (path) (rate(http_requests_total[1h])))

# Memory usage in MB
process_resident_memory_bytes / 1024 / 1024

# CPU usage
rate(process_cpu_seconds_total[5m]) * 100
Enter fullscreen mode Exit fullscreen mode

Alerting

# alerts.yml
groups:
  - name: app-alerts
    rules:
      - alert: HighErrorRate
        expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "Error rate above 5%"

      - alert: HighLatency
        expr: histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m])) > 1
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "P95 latency above 1 second"
Enter fullscreen mode Exit fullscreen mode

Prometheus + Grafana Stack

# docker-compose.yml
version: "3"
services:
  prometheus:
    image: prom/prometheus
    ports: ["9090:9090"]
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana
    ports: ["3000:3000"]
    environment:
      - GF_SECURITY_ADMIN_PASSWORD=admin
Enter fullscreen mode Exit fullscreen mode

Resources


Monitoring your data pipelines? My Apify scraping tools extract web data at scale — instrument them with Prometheus for full observability. Questions? Email spinov001@gmail.com

Top comments (0)