JustAnalytics for FastAPI
Step-by-step guide to add analytics, error tracking, and APM to your FastAPI app
JustAnalytics for FastAPI
Add distributed tracing, error tracking, structured logging, and infrastructure metrics to your FastAPI application.
Time to data: 3 minutesPrerequisites#
- FastAPI 0.100+
- Python 3.9+
- A JustAnalytics account with a Site ID and API key
Install the SDK
pip install justanalytics-python[fastapi]
Initialize and add middleware
# main.py
import os
import justanalytics
from fastapi import FastAPI
from justanalytics.integrations.fastapi import JustAnalyticsMiddleware
# Initialize the SDK
justanalytics.init(
site_id=os.environ.get("JA_SITE_ID"),
api_key=os.environ.get("JA_API_KEY"),
service_name="fastapi-app",
environment=os.environ.get("ENV", "development"),
)
app = FastAPI()
# Add middleware — traces all incoming requests automatically
app.add_middleware(JustAnalyticsMiddleware)
Add your endpoints
All endpoints are automatically traced. Each request creates a span named after the route pattern:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
class CreateUserRequest(BaseModel):
name: str
email: str
@app.get("/api/users/{user_id}")
async def get_user(user_id: int):
# Automatically traced as "GET /api/users/{user_id}"
user = await db.users.find_one(user_id)
if not user:
raise HTTPException(status_code=404, detail="User not found")
return user
@app.post("/api/users", status_code=201)
async def create_user(data: CreateUserRequest):
user = await db.users.create(data.dict())
return user
Add error handling
FastAPI HTTPException responses are tagged on the span. For capturing unexpected errors:
from fastapi import Request
from fastapi.responses import JSONResponse
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
justanalytics.capture_exception(exc, tags={
"path": request.url.path,
"method": request.method,
})
return JSONResponse(
status_code=500,
content={"detail": "Internal server error"},
)
Verify data is flowing
Start your server and make a test request:
uvicorn main:app --reload
curl http://localhost:8000/api/users/1
Verify Your Setup
After making a request, check the Traces tab. You should see spans with FastAPI route patterns like 'GET /api/users/{user_id}'.
Open DashboardAdvanced Features#
Custom spans#
@app.get("/api/reports/{report_id}")
async def get_report(report_id: str):
with justanalytics.start_span("generate-report") as span:
span.set_attribute("report.id", report_id)
with justanalytics.start_span("fetch-data"):
data = await fetch_report_data(report_id)
with justanalytics.start_span("render-pdf"):
pdf = await render_pdf(data)
return Response(content=pdf, media_type="application/pdf")
Dependency injection with tracing#
from fastapi import Depends
@justanalytics.span(op="db.query")
async def get_db_user(user_id: int):
return await db.users.find_one(user_id)
@app.get("/api/users/{user_id}/orders")
async def get_user_orders(user: dict = Depends(get_db_user)):
return await db.orders.find_many({"user_id": user["id"]})
User identification#
from fastapi import Depends, Security
from fastapi.security import HTTPBearer
security = HTTPBearer()
async def get_current_user(credentials = Security(security)):
user = await verify_token(credentials.credentials)
justanalytics.set_user(id=str(user.id), email=user.email)
return user
Structured logging#
justanalytics.log("info", "Order placed", {"order_id": "o123", "total": 99.99})
justanalytics.log("error", "Payment failed", {"user_id": "u456", "reason": "card_expired"})
Background task tracing#
from fastapi import BackgroundTasks
async def send_welcome_email(user_id: str):
with justanalytics.start_span("send-welcome-email") as span:
span.set_attribute("user.id", user_id)
await email_service.send(user_id, template="welcome")
@app.post("/api/users")
async def create_user(data: CreateUserRequest, background_tasks: BackgroundTasks):
user = await db.users.create(data.dict())
background_tasks.add_task(send_welcome_email, str(user.id))
return user
Outgoing HTTP tracing#
from justanalytics.integrations.requests import RequestsIntegration
RequestsIntegration(service_name="fastapi-app").enable()
Lifecycle events for clean shutdown#
@app.on_event("shutdown")
async def shutdown_event():
justanalytics.flush()
justanalytics.close()
Custom metrics#
justanalytics.record_metric("custom.queue_depth", await get_queue_depth())
justanalytics.record_metric("custom.cache_hit_ratio", 0.87, {"cache": "redis"})
Environment variables#
| Variable | Description | Required |
|----------|-------------|----------|
| JA_SITE_ID | Your site ID from the dashboard | Yes |
| JA_API_KEY | API key (starts with ja_sk_) | Yes |
| ENV | Deployment environment | No |