Dashboard Get started

Python Instrumentation

Instrument Flask, FastAPI, Django, requests, SQLAlchemy, and more automatically using the OpenTelemetry bootstrap tool. No config file. No import order to manage.

1. Install

bash
pip install opentelemetry-distro opentelemetry-exporter-otlp

# Auto-install instrumentation packages for your dependencies
opentelemetry-bootstrap -a install
opentelemetry-bootstrap -a install scans your installed packages and installs the matching OTel instrumentation — e.g. if you have FastAPI installed, it addsopentelemetry-instrumentation-fastapi automatically.

2. Set environment variables

.env
OTEL_SERVICE_NAME=my-python-service
OTEL_EXPORTER_OTLP_ENDPOINT=https://la-ingest-gateway.lightarch.workers.dev
OTEL_EXPORTER_OTLP_HEADERS=x-la-dsn=la_live_YOUR_TOKEN_HERE
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf
OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf is required — the Python distro defaults to gRPC, which Lightarch doesn't accept.

3. Run your app

Prefix your normal start command with opentelemetry-instrument:

bash
# FastAPI
opentelemetry-instrument uvicorn main:app --host 0.0.0.0 --port 8000

# Flask
opentelemetry-instrument flask run

# Django
opentelemetry-instrument python manage.py runserver

# Any Python script
opentelemetry-instrument python your_script.py

No changes to your application code required.

Screenshot needed

Traces page showing Python service spans with service='my-python-service', environment='production', waterfall showing FastAPI routes.

Verify it's working

bash
la query "SELECT service, severity, body, duration_ms FROM recent_spans WHERE service = 'my-python-service' ORDER BY timestamp DESC LIMIT 10"

la logs tail --service my-python-service

Custom spans

python
from opentelemetry import trace

tracer = trace.get_tracer("my-service")

def process_payment(order_id: str):
    with tracer.start_as_current_span("payment.process") as span:
        span.set_attribute("order.id", order_id)
        try:
            result = charge_card(order_id)
            span.set_attribute("payment.status", result["status"])
            return result
        except Exception as e:
            span.record_exception(e)
            span.set_status(trace.StatusCode.ERROR, str(e))
            raise
Advanced: manual config file (for custom resource attributes or fine-grained control)
eo_config.py
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.http.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.resources import Resource
import os

LA_DSN = os.environ["LA_DSN"]

resource = Resource.create({
    "service.name": "my-python-service",
    "deployment.environment": os.getenv("ENVIRONMENT", "production"),
})

provider = TracerProvider(resource=resource)
exporter = OTLPSpanExporter(
    endpoint="https://la-ingest-gateway.lightarch.workers.dev/v1/traces",
    headers={"x-la-dsn": LA_DSN},
)
provider.add_span_processor(BatchSpanProcessor(exporter))
trace.set_tracer_provider(provider)
main.py
import eo_config  # must be first import

from fastapi import FastAPI
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor

app = FastAPI()
FastAPIInstrumentor.instrument_app(app)
Import eo_config as the first import — before FastAPI, requests, or any other library you want traced.