A self-contained demo that illustrates the three pillars of observability:
| Pillar | Tool |
|---|---|
| Metrics | Prometheus + Grafana |
| Tracing | Jaeger |
| Logging | Structured JSON logs via Python's logging module |
All components are wired together with Docker Compose and instrumented using OpenTelemetry.
┌──────────────────────────────────────────────┐
│ Docker Compose stack │
│ │
│ ┌────────────┐ metrics ┌────────────┐ │
│ │ FastAPI │ ──────────► │ Prometheus │ │
│ │ app │ :8001 └─────┬──────┘ │
│ │ │ │ │
│ │ OTel SDK │ traces ┌────▼──────┐ │
│ │ │ ──────────► │ Grafana │ │
│ └─────┬──────┘ :6831 └────────────┘ │
│ │ │
│ │ traces ┌────────────┐ │
│ └───────────────────►│ Jaeger │ │
│ :6831 └────────────┘ │
└──────────────────────────────────────────────┘
Prerequisites: Docker + Docker Compose v2
# Clone and start everything
git clone https://github.com/alanthssss/observability.git
cd observability
docker compose up --build| Service | URL | Description |
|---|---|---|
| Sample app | http://localhost:8000 | FastAPI root |
Sample app /work |
http://localhost:8000/work | Simulates latency & errors |
| Prometheus metrics | http://localhost:8001 | Raw metric exposition |
| Prometheus UI | http://localhost:9090 | Query metrics |
| Grafana | http://localhost:3000 | Dashboards (admin / admin) |
| Jaeger UI | http://localhost:16686 | Distributed traces |
# Send 50 requests to /work to populate metrics & traces
for i in $(seq 1 50); do curl -s http://localhost:8000/work > /dev/null; doneThen open:
- Grafana → Observability Showcase dashboard for request rate, error rate, and latency percentiles.
- Jaeger → select service
observability-app→ Find Traces to explore spans.
observability/
├── app/
│ ├── Dockerfile
│ ├── main.py # FastAPI app with OTel instrumentation
│ └── requirements.txt
├── grafana/
│ ├── dashboards/
│ │ └── observability.json # Pre-built Grafana dashboard
│ └── provisioning/
│ ├── dashboards/
│ └── datasources/
├── prometheus/
│ └── prometheus.yml
├── docker-compose.yml
└── README.md
The app exposes a Prometheus-compatible /metrics endpoint on port 8001 via opentelemetry-exporter-prometheus.
Prometheus scrapes this endpoint every 15 s. Grafana queries Prometheus and renders the Observability Showcase dashboard automatically on startup.
Every request to /work creates an OpenTelemetry span that is exported to the Jaeger agent (UDP, port 6831) via the Jaeger Thrift exporter.
Open the Jaeger UI, select the observability-app service, and click Find Traces to explore distributed traces.
The app emits structured JSON logs to stdout. View them with:
docker compose logs -f appdocker compose down -v # -v also removes the Grafana volume