Skip to content

11. Observability

What You'll Learn

  • How to enable Prometheus metrics for DBWarden
  • How to use structured JSON logging
  • How to add query tracing middleware to FastAPI
  • How to monitor connection pool health

Prerequisites

  • examples/observability/ directory
  • Docker (for optional Prometheus + Grafana)

Step 1: Enable Prometheus Metrics

Install with metrics support:

uv add "dbwarden[metrics]"

DBWarden exposes six Prometheus metric families:

Metric Type Labels Description
dbwarden_migrations_total Counter database, status Migration count
dbwarden_migration_duration_seconds Histogram database Execution time
dbwarden_schema_version Gauge database Current version
dbwarden_pending_migrations Gauge database Pending count
dbwarden_errors_total Counter database, error_type Error count
dbwarden_seed_version Gauge database Current seed version

Step 2: Add Metrics to FastAPI

from dbwarden.fastapi import MetricsMiddleware, MetricsRouter

# Middleware captures request duration and counts
app.add_middleware(MetricsMiddleware)

# Router exposes /metrics endpoint
app.include_router(MetricsRouter(), prefix="/metrics")
curl http://localhost:8000/metrics

Output:

# HELP dbwarden_migrations_total Total number of migrations
# TYPE dbwarden_migrations_total counter
dbwarden_migrations_total{database="primary",status="applied"} 5

# HELP dbwarden_pending_migrations Number of pending migrations
# TYPE dbwarden_pending_migrations gauge
dbwarden_pending_migrations{database="primary"} 0

Step 3: Structured Logging

import os
os.environ["DBWARDEN_LOG_JSON"] = "1"

Or via environment variable:

DBWARDEN_LOG_JSON=1 uvicorn app.main:app

This switches from colored human-readable output to JSON:

{"timestamp": "2025-01-15T10:30:00Z", "level": "INFO", "event": "migration_applied", "database": "primary", "duration_ms": 42, "version": "0005"}

JSON logs are easier to ingest into ELK, Datadog, or other log aggregators.

Step 4: Query Tracing

from dbwarden.fastapi import QueryTracingMiddleware

app.add_middleware(QueryTracingMiddleware)

This logs every SQL query with its duration:

{"event": "query", "duration_ms": 3, "database": "primary", "statement": "SELECT ..."}

Useful for: - Identifying slow queries in development - Building a query performance baseline - Debugging N+1 query patterns

Step 5: Pool Metrics Collector

from dbwarden.fastapi import PoolMetricsCollector

This monitors SQLAlchemy connection pool health and exposes:

  • Pool size (current/total)
  • Connections in use
  • Connections overflow
  • Pool timeouts

Step 6: Full Setup

from contextlib import asynccontextmanager
from fastapi import FastAPI
from dbwarden.fastapi import (
    DBWardenHealthRouter,
    dbwarden_lifespan,
    MetricsMiddleware,
    MetricsRouter,
    QueryTracingMiddleware,
)


@asynccontextmanager
async def lifespan(app: FastAPI):
    async with dbwarden_lifespan(app, mode="check"):
        yield


app = FastAPI(
    title="DBWarden Observability Example",
    lifespan=lifespan,
)

app.add_middleware(QueryTracingMiddleware)
app.add_middleware(MetricsMiddleware)
app.include_router(MetricsRouter(), prefix="/metrics")
app.include_router(DBWardenHealthRouter(), prefix="/health")

Step 7: Prometheus + Grafana (Optional)

services:
  prometheus:
    image: prom/prometheus:latest
    ports:
      - "9090:9090"
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml

  grafana:
    image: grafana/grafana:latest
    ports:
      - "3000:3000"
docker compose up -d
  • Prometheus: http://localhost:9090
  • Grafana: http://localhost:3000

In Grafana, add Prometheus data source (http://prometheus:9090) and create dashboards using the dbwarden_* metrics.

Key Takeaways

  • Metrics are opt-in via uv add "dbwarden[metrics]"
  • Six metric families cover migration, schema, and error tracking
  • DBWARDEN_LOG_JSON=1 switches to structured JSON logging
  • QueryTracingMiddleware logs every SQL query with duration
  • PoolMetricsCollector monitors connection pool health
  • Metrics are compatible with standard Prometheus + Grafana setup