DEV Community

Kaushikcoderpy
Kaushikcoderpy

Posted on • Originally published at logicandlegacy.blogspot.com

FastAPI Observability with Prometheus, Loki & Grafana (Complete 2026 Guide)

Building a Scalable Observability Stack

When dealing with complex microservice architectures, traditional debugging methods can become cumbersome and inefficient. As systems grow, the need for a robust observability stack becomes increasingly important. This involves implementing a combination of tools to monitor, log, and visualize data in real-time.

The Limitations of Traditional Debugging

Traditional debugging methods, such as SSH-ing into production servers and running grep across text files, are no longer effective in modern Kubernetes environments. Containers are ephemeral, and logs can be lost forever when a pod is terminated. To combat this, a more scalable approach is needed.

Introducing the Observability Trinity

The "Holy Trinity" of microservices observability consists of Prometheus, Loki, and Grafana. Each tool plays a crucial role in the observability stack:

  • Prometheus: A time-series database that pulls metrics from applications, providing insights into system performance and behavior.
  • Loki: A centralized logging solution that indexes metadata and compresses raw log text, making it efficient and cost-effective.
  • Grafana: A visualization layer that correlates data from Prometheus and Loki, enabling real-time monitoring and alerting.

Implementing Prometheus

Prometheus is a pull-based system that scrapes metrics from applications at regular intervals. When instrumenting a FastAPI application for Prometheus, it's essential to avoid high-cardinality data in labels, as this can lead to performance issues. Instead, use bounded lists for labels, such as status_code or method.

from fastapi import FastAPI
from prometheus_fastapi_instrumentator import Instrumentator

app = FastAPI()

# Auto-instrument all HTTP routes and expose the /metrics endpoint
Instrumentator().instrument(app).expose(app)
Enter fullscreen mode Exit fullscreen mode

Centralized Logging with Loki

Loki offers a cost-effective alternative to traditional logging solutions like ELK. By indexing only metadata and compressing raw log text, Loki reduces storage costs and improves query performance. Promtail, a lightweight Go agent, is used to ship logs from containers to Loki.

Visualizing Data with Grafana

Grafana provides a visualization layer for correlating data from Prometheus and Loki. By sharing the same label system, Grafana can automatically fetch logs for a specific time range, enabling real-time monitoring and alerting. Essential PromQL and LogQL queries can be used to create alerts and dashboards.

# PromQL example: High-Level Error Rate Alert
sum(rate(http_requests_total{status=~"5.."}[2m])) > 0

# LogQL example: Find all logs for the FastAPI app containing "ERROR"
{app="fastapi"} |= "ERROR"
Enter fullscreen mode Exit fullscreen mode

Deploying the Observability Stack

To deploy the observability stack, a docker-compose.yml file can be used to orchestrate the services. This includes configuring Prometheus, Loki, and Grafana, as well as setting up persistent volumes and socket mounting for Promtail.

version: '3.8'

volumes:
  prometheus-data:
  grafana-data:
  loki-data:

services:
  api:
    build: .
    restart: unless-stopped
    ports:
      - "8000:8000"
    labels:
      logging_job: fastapi

  prometheus:
    image: prom/prometheus:v2.45.0
    restart: unless-stopped
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
      - prometheus-data:/prometheus
    ports:
      - "9090:9090"

  loki:
    image: grafana/loki:2.9.0
    restart: unless-stopped
    volumes:
      - ./loki-config.yml:/etc/loki/local-config.yaml:ro
      - loki-data:/loki
    ports:
      - "3100:3100"
    command: -config.file=/etc/loki/local-config.yaml

  promtail:
    image: grafana/promtail:2.9.0
    restart: unless-stopped
    volumes:
      - /var/lib/docker/containers:/var/lib/docker/containers:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
Enter fullscreen mode Exit fullscreen mode

Top comments (0)