Modern QA2026Instrumenting a Python Service — tiles
Log inJoin
31 / 67 · 06 Observability-Driven Testing · Distributed Tracing with OpenTelemetry← prev⊞ allnext →☰ Read as one page

5.4Instrumenting a Python Service

Automatic Instrumentation Setup

# otel_setup.py -- OpenTelemetry configuration for a Flask service
from opentelemetry import trace, metrics
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
from opentelemetry.sdk.metrics import MeterProvider
from opentelemetry.sdk.metrics.export import PeriodicExportingMetricReader
from opentelemetry.exporter.otlp.proto.grpc.metric_exporter import OTLPMetricExporter
from opentelemetry.sdk.resources import Resource
from opentelemetry.instrumentation.flask import FlaskInstrumentor
from opentelemetry.instrumentation.requests import RequestsInstrumentor
from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor

def setup_telemetry(service_name: str, service_version: str):
    """Initialize OpenTelemetry with OTLP export."""
    resource = Resource.create({
        "service.name": service_name,
        "service.version": service_version,
        "deployment.environment": "production",
    })

    # Traces
    trace_provider = TracerProvider(resource=resource)
    trace_provider.add_span_processor(
        BatchSpanProcessor(OTLPSpanExporter(endpoint="http://otel-collector:4317"))
    )
    trace.set_tracer_provider(trace_provider)

    # Metrics
    metric_reader = PeriodicExportingMetricReader(
        OTLPMetricExporter(endpoint="http://otel-collector:4317"),
        export_interval_millis=10000,
    )
    metrics.set_meter_provider(MeterProvider(
        resource=resource, metric_readers=[metric_reader]
    ))

    # Auto-instrument frameworks
    FlaskInstrumentor().instrument()
    RequestsInstrumentor().instrument()
    SQLAlchemyInstrumentor().instrument()

Manual Spans for Business Logic

# app.py -- Adding manual spans for business-critical operations
from opentelemetry import trace

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

def process_order(order_data):
    with tracer.start_as_current_span("process_order") as span:
        span.set_attribute("order.id", order_data["id"])
        span.set_attribute("order.item_count", len(order_data["items"]))
        span.set_attribute("order.total_cents", order_data["total"])

        with tracer.start_as_current_span("validate_order"):
            validate(order_data)

        with tracer.start_as_current_span("charge_payment") as payment_span:
            result = charge(order_data["payment"])
            payment_span.set_attribute("payment.method", result.method)
            payment_span.set_attribute("payment.processor", result.processor)

        with tracer.start_as_current_span("reserve_inventory"):
            reserve(order_data["items"])

        span.set_attribute("order.status", "completed")