A comprehensive boilerplate project for learning and implementing OpenTelemetry (OTEL) with FastAPI, featuring the Grafana LGTM Stack for full observability.
otel_test/
├── server/ # FastAPI application with OTEL instrumentation
├── observability/ # Grafana LGTM Stack (Loki, Grafana, Tempo, Mimir)
└── README.md # This file
- FastAPI Server with CRUD operations
- OpenTelemetry Instrumentation:
- Automatic FastAPI instrumentation
- Custom traces, spans, and span events
- Custom metrics (counters, histograms)
- Structured logging with trace correlation
- Semantic attributes
- Grafana LGTM Stack:
- Loki: Log aggregation
- Grafana: Unified observability UI
- Tempo: Distributed tracing
- Mimir: Prometheus-compatible metrics storage
- OTEL Collector: Central telemetry data pipeline
- Development Tools:
- VS Code Dev Containers
- uv for package management
- ruff for linting and formatting
- pytest with full coverage
- Docker and Docker Compose
- VS Code with Dev Containers extension (optional, for development)
- Python 3.14+ (if running locally without Docker)
cd observability
docker-compose up -dThis starts:
- Grafana on http://localhost:3000 (admin/admin)
- OTEL Collector on ports 4317 (gRPC) and 4318 (HTTP)
- Tempo, Loki, and Mimir (accessed via Grafana)
cd server
docker-compose up --build- Open the
serverfolder in VS Code - Click "Reopen in Container" when prompted
- Run:
uv run uvicorn src.main:app --reload --host 0.0.0.0
cd server
uv sync
uv run uvicorn src.main:app --reload- FastAPI: http://localhost:8000
- API Docs: http://localhost:8000/docs
- Grafana: http://localhost:3000
curl -X POST http://localhost:8000/items \
-H "Content-Type: application/json" \
-d '{"name": "Test Item", "description": "A test item"}'curl http://localhost:8000/itemscurl http://localhost:8000/items/1curl -X PUT http://localhost:8000/items/1 \
-H "Content-Type: application/json" \
-d '{"name": "Updated Item", "description": "Updated description"}'curl -X DELETE http://localhost:8000/items/1- Open Grafana at http://localhost:3000
- Go to Explore → Select "Tempo" datasource
- Search for traces or use TraceQL queries
- Go to Explore → Select "Loki" datasource
- Use LogQL to query logs:
{service_name="otel-fastapi-server"} - Logs are automatically correlated with traces
- Go to Explore → Select "Mimir" datasource
- Query custom metrics like
items_created_totaloritems_deleted_total - Pre-configured dashboards are available
cd server
uv run pytestcd server
uv run pytest --cov=src --cov-report=htmlcd server
uv run ruff check .
uv run ruff format .The project follows a clean architecture pattern:
- API Layer (
src/api/): HTTP endpoints - Service Layer (
src/services/): Business logic - Models (
src/models/): Data models - Telemetry (
src/telemetry/): OTEL configuration and instrumentation
- Automatic Instrumentation: FastAPI requests/responses
- Custom Spans: Service layer operations with parent-child relationships
- Span Attributes: Custom and semantic attributes
- Span Events: Marking significant operations
- Custom Metrics: Counters and histograms
- Structured Logging: JSON logs with trace context
- Context Propagation: Trace IDs across service boundaries
MIT