OpenTelemetry Integration
Distributed tracing with span-per-task — exporters, customization, composition.
Distributed tracing with span-per-task — exporters, customization, composition.
flexiq provides optional OpenTelemetry support for distributed tracing of task execution.
Install with the otel extra:
pip install flexiq[otel]This installs opentelemetry-api and opentelemetry-sdk as
dependencies. It does not install an exporter — for the OTLP example
below, also run pip install opentelemetry-exporter-otlp (or whichever
exporter package matches your backend).
Add OpenTelemetryMiddleware to your queue:
from flexiq import Queue
from flexiq.contrib.otel import OpenTelemetryMiddleware
queue = Queue(middleware=[OpenTelemetryMiddleware()])Each task execution produces a span (a timed unit of work in a distributed trace) with:
flexiq.execute.<task_name> (customizable)flexiq.job_id — the job IDflexiq.task_name — the registered task nameflexiq.queue — the queue nameflexiq.retry_count — current retry attemptOK on success, ERROR on failure (with exception recorded)retry event is added when a task is about to be retriedOpenTelemetryMiddleware uses the standard OpenTelemetry API, so configure
exporters as you normally would:
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.otlp.proto.grpc.trace_exporter import OTLPSpanExporter
# Set up the tracer provider with an OTLP exporter
provider = TracerProvider()
provider.add_span_processor(BatchSpanProcessor(OTLPSpanExporter()))
trace.set_tracer_provider(provider)
# Now create your queue — spans will be exported automatically
from flexiq import Queue
from flexiq.contrib.otel import OpenTelemetryMiddleware
queue = Queue(middleware=[OpenTelemetryMiddleware()])OpenTelemetryMiddleware accepts several options to customize how spans
are created:
OpenTelemetryMiddleware(
tracer_name="my-service",
span_name_fn=lambda ctx: f"task/{ctx.task_name}",
attribute_prefix="myapp",
extra_attributes_fn=lambda ctx: {"deployment.env": "prod"},
task_filter=lambda name: not name.startswith("internal."),
)| Parameter | Type | Default | Description |
|---|---|---|---|
tracer_name | str | "flexiq" | OpenTelemetry tracer name. |
span_name_fn | Callable[[JobContext], str] | None | None | Custom span name builder. Receives JobContext, returns a string. Defaults to <prefix>.execute.<task_name>. |
attribute_prefix | str | "flexiq" | Prefix for all span attribute keys. |
extra_attributes_fn | Callable[[JobContext], dict] | None | None | Returns extra attributes to add to each span. Receives JobContext. |
task_filter | Callable[[str], bool] | None | None | Predicate that receives a task name. Return True to trace, False to skip. None traces all tasks. |
OpenTelemetryMiddleware is a standard TaskMiddleware, so it composes
with other middleware:
queue = Queue(middleware=[
OpenTelemetryMiddleware(),
MyLoggingMiddleware(),
])OpenTelemetryMiddleware is thread-safe and can be used with
multi-worker configurations. Internal span tracking is protected by a
lock.
See the Middleware guide for more on combining middleware.