🐍 Python Integration Guide
Learn how to instrument your Python applications with OpenTelemetry to send distributed traces to TraceKit.
90% Automatic Tracing!
With the right libraries, most of your application will be traced automatically with minimal setup. No need to manually instrument every function.
Prerequisites
- • Python 3.8 or higher
- • An active TraceKit account
- • A generated API key from the API Keys page
🔍 What Gets Traced Automatically?
With proper setup, these operations are traced automatically with zero manual instrumentation:
| Component | Setup | Auto-Traced? |
|---|---|---|
| HTTP Endpoints | Auto-instrument Flask/Django/FastAPI | ✓ Yes |
| Database Queries | SQLAlchemy, psycopg2, pymongo auto-instrumentation | ✓ Yes |
| HTTP Client Calls | requests, httpx, aiohttp instrumentation | ✓ Yes |
| Redis Operations | redis-py instrumentation | ✓ Yes |
| Celery Tasks | Celery instrumentation | ✓ Yes |
| Custom Business Logic | Manual spans (optional) | Manual |
📦 Installation
Install the required OpenTelemetry packages:
pip install opentelemetry-api opentelemetry-sdk
pip install opentelemetry-exporter-otlp-proto-http
pip install opentelemetry-instrumentation-flask # or django, fastapi⚙️ Basic Setup
Create a tracing initialization module in your application:
Create tracing.py
# tracing.py
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.sdk.resources import Resource
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.semconv.resource import ResourceAttributes
def init_tracer(service_name: str, endpoint: str, api_key: str):
"""Initialize OpenTelemetry tracer for TraceKit"""
# Create resource with service name
resource = Resource(attributes={
ResourceAttributes.SERVICE_NAME: service_name,
ResourceAttributes.SERVICE_VERSION: "1.0.0",
})
# Create tracer provider
provider = TracerProvider(resource=resource)
# Configure OTLP exporter
otlp_exporter = OTLPSpanExporter(
endpoint=f"{endpoint}/v1/traces",
headers={"X-API-Key": api_key}
)
# Add span processor
provider.add_span_processor(BatchSpanProcessor(otlp_exporter))
# Set as global tracer provider
trace.set_tracer_provider(provider)
return provider🚀 Framework Integration
TraceKit works seamlessly with popular Python web frameworks through OpenTelemetry instrumentation.
Flask
# app.py
from flask import Flask
from opentelemetry.instrumentation.flask import FlaskInstrumentor
import os
from tracing import init_tracer
# Initialize tracing
init_tracer(
service_name="my-flask-app",
endpoint=os.getenv("TRACEKIT_ENDPOINT", "{ appURL }"),
api_key=os.getenv("TRACEKIT_API_KEY")
)
# Create Flask app
app = Flask(__name__)
# Auto-instrument Flask (all routes will be traced automatically!)
FlaskInstrumentor().instrument_app(app)
@app.route("/api/users")
def get_users():
return {"users": ["alice", "bob", "charlie"]}
if __name__ == "__main__":
app.run(port=5000)Django
# settings.py
from tracing import init_tracer
import os
# Initialize tracing at Django startup
init_tracer(
service_name="my-django-app",
endpoint=os.getenv("TRACEKIT_ENDPOINT", "{ appURL }"),
api_key=os.getenv("TRACEKIT_API_KEY")
)
# Add Django instrumentation to INSTALLED_APPS (not required but recommended)
# Then use:
# opentelemetry-instrument python manage.py runserver
# Or instrument manually in your WSGI/ASGI file:
from opentelemetry.instrumentation.django import DjangoInstrumentor
DjangoInstrumentor().instrument()FastAPI
# main.py
from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
import os
from tracing import init_tracer
# Initialize tracing
init_tracer(
service_name="my-fastapi-app",
endpoint=os.getenv("TRACEKIT_ENDPOINT", "{ appURL }"),
api_key=os.getenv("TRACEKIT_API_KEY")
)
# Create FastAPI app
app = FastAPI()
# Auto-instrument FastAPI
FastAPIInstrumentor.instrument_app(app)
@app.get("/api/users")
async def get_users():
return {"users": ["alice", "bob", "charlie"]}
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)⚡ Automatic Instrumentation Libraries
These libraries automatically create child spans for common operations. Set them up once, and every call is traced automatically.
Database Queries
Automatically trace all database operations:
SQLAlchemy
from sqlalchemy import create_engine
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
# Create engine
engine = create_engine("postgresql://user:pass@localhost/mydb")
# Instrument SQLAlchemy (one line!)
SQLAlchemyInstrumentor().instrument(engine=engine)
# Now all queries are automatically traced
from sqlalchemy.orm import Session
with Session(engine) as session:
users = session.query(User).all() # This query is traced!HTTP Client Calls
Automatically trace all outgoing HTTP requests:
from opentelemetry.instrumentation.requests import RequestsInstrumentor
import requests
# Instrument requests library (one line!)
RequestsInstrumentor().instrument()
# Now all HTTP requests are automatically traced
response = requests.get("https://api.example.com/users") # Traced!Redis Operations
Trace Redis commands automatically:
from redis import Redis
from opentelemetry.instrumentation.redis import RedisInstrumentor
# Instrument Redis
RedisInstrumentor().instrument()
# Create Redis client
redis_client = Redis(host='localhost', port=6379)
# All operations are now traced!
redis_client.set("key", "value") # Traced!
value = redis_client.get("key") # Traced!🔧 Manual Instrumentation (Optional)
For custom business logic that isn't covered by auto-instrumentation libraries, you can manually create spans. This is optional and only needed for specific operations you want to measure.
from opentelemetry import trace
def process_order(order_id: str):
tracer = trace.get_tracer(__name__)
# Start a parent span
with tracer.start_as_current_span("process_order") as span:
span.set_attribute("order.id", order_id)
span.set_attribute("order.status", "processing")
# Child spans automatically link to parent
with tracer.start_as_current_span("validate_order") as child_span:
child_span.set_attribute("order.id", order_id)
# Validation logic here
with tracer.start_as_current_span("charge_payment") as child_span:
child_span.set_attribute("order.id", order_id)
# Payment logic here
span.set_attribute("order.status", "completed")🔐 Environment Variables
Best practice: Store sensitive configuration in environment variables:
# .env
TRACEKIT_API_KEY=ctxio_your_generated_api_key_here
TRACEKIT_ENDPOINT={ appURL }
SERVICE_NAME=my-python-app🏭 Production Configuration
Production Checklist
- • Use HTTPS/TLS for the OTLP endpoint
- • Store API keys in a secrets manager (AWS Secrets Manager, HashiCorp Vault)
- • Set appropriate service names and versions
- • Configure resource attributes (deployment.environment, host.name, etc.)
- • Adjust sampling rates if needed for high-traffic services
🔧 Troubleshooting
Traces Not Appearing?
- Verify your API key is correct and not revoked
- Check the endpoint URL matches your TraceKit instance
- Ensure all required packages are installed
- Check application logs for OpenTelemetry errors
- Verify TraceKit is running and accessible
✅ Complete Example
Here's a complete working example with Flask:
# Complete Flask example
from flask import Flask
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
import os
from tracing import init_tracer
# Initialize tracing
init_tracer(
service_name=os.getenv("SERVICE_NAME", "flask-api"),
endpoint=os.getenv("TRACEKIT_ENDPOINT", "{ appURL }"),
api_key=os.getenv("TRACEKIT_API_KEY")
)
# Create Flask app
app = Flask(__name__)
# Auto-instrument Flask and requests
FlaskInstrumentor().instrument_app(app)
RequestsInstrumentor().instrument()
@app.route("/api/users")
def get_users():
return {"users": ["alice", "bob", "charlie"]}
@app.route("/api/users/<int:user_id>")
def get_user(user_id):
return {"id": user_id, "name": "Alice"}
if __name__ == "__main__":
print("Flask app starting with TraceKit tracing enabled")
app.run(host="0.0.0.0", port=5000)You're all set!
Your Python application is now sending traces to TraceKit. Visit the Dashboard to see your traces.
🚀 Next Steps
- • Add auto-instrumentation libraries for components you use (Redis, Celery, MongoDB, etc.)
- • Explore your traces on the Traces page to identify performance bottlenecks
- • Optionally add custom spans for specific business logic you want to measure
- • Configure sampling for high-traffic services to reduce overhead
- • Set up alert rules to get notified when issues occur