A monorepo for OpenTelemetry instrumentation packages targeting OpenStack-related Python libraries.
opentelemetry-instrumentation-taskflow— traces TaskFlow engine runs. Records a roottaskflow.flow.runspan per engine execution and child spans for every task/retryexecute/revert, using TaskFlow's native listener API.opentelemetry-instrumentation-oslo-log— enrichesoslo.logrecords with the active trace context.opentelemetry-instrumentation-oslo-messaging— propagates trace context acrossoslo.messagingRPC and notifications and records consumer spans.opentelemetry-instrumentation-oslo-service— keeps the active trace alive acrossoslo.service's concurrency primitives (native threads,futuristpools, and eventlet greenthreads), so spans and logs created in spawned work stay on the request's trace. Also selects theoslo.servicebackend.opentelemetry-instrumentation-openstacksdk— records aCLIENTspan for every OpenStack SDK REST call (wrappingopenstack.proxy.Proxy.request) and injects trace context into the outgoing request headers.opentelemetry-instrumentation-keystoneauth1— records aCLIENTspan for every HTTP call the sharedkeystoneauth1session makes (service calls, token fetches, discovery), injecting trace context into the outgoing headers. Sits below the SDK proxy, so it also captures the token/discovery calls the SDK instrumentation leaves untraced.opentelemetry-instrumentation-keystonemiddleware— the server-side entry point. Wraps theauth_tokenWSGI middleware to open aSERVERspan for the whole request (continuing the trace from the incoming headers) with a nestedINTERNALspan for token validation and the resolved identity.
The packages are designed to hand a single trace off to one another end to end.
Every seam uses the global propagator (W3C traceparent by default), so
injection and extraction always agree:
client process service process (e.g. nova-api)
────────────── ───────────────────────────────
openstacksdk Proxy.request CLIENT
keystoneauth1 Session.request CLIENT ──HTTP traceparent──▶ keystonemiddleware
__call__ SERVER
authenticate INTERNAL
handler work…
oslo.messaging
_send PRODUCER
│ ctxt traceparent
▼
another service
RPCDispatcher CONSUMER
- Client → HTTP → server: the SDK proxy and keystoneauth1 client spans nest in one trace and inject the innermost context onto the wire; keystonemiddleware extracts it and continues the trace on the server.
- Server request scope: keystonemiddleware's
SERVERspan stays active for the entire WSGI request, so everything the service handler does while serving it —oslo.messagingsends,taskflowruns, andoslo.logrecords (which carry the activeotelTraceID) — joins the same trace instead of starting a disconnected one. - RPC / notifications:
oslo.messaginginjects context into the on-the-wire message and the consumer opens a span parented to the producer. - Nesting with standard instrumentors: if an upstream WSGI/framework
instrumentor already opened the server span, keystonemiddleware nests under it
as
INTERNALrather than opening a second server span.
The repository also publishes a Python auto-instrumentation image,
daipham3213/otel-autoinstrumentation-openstack, built from
autoinstrumentation/Dockerfile. It is a
drop-in replacement for the upstream
autoinstrumentation-python
image: it bundles opentelemetry-distro, the standard contrib
instrumentations, and the six OpenStack packages above, so OpenStack
services get traced without changing the application image.
Tags follow the release version ({{version}}, {{major}}.{{minor}},
sha-<commit>, and latest on a published release).
Point the Instrumentation resource at this image instead of the default, then
annotate the workloads you want instrumented:
apiVersion: opentelemetry.io/v1alpha1
kind: Instrumentation
metadata:
name: openstack
spec:
exporter:
endpoint: http://otel-collector:4318
python:
image: daipham3213/otel-autoinstrumentation-openstack:latest# On the pod/deployment template:
metadata:
annotations:
instrumentation.opentelemetry.io/inject-python: "true"The operator injects an init container that copies the bundled packages into
the application container and sets PYTHONPATH, so the OpenStack
instrumentations load automatically at startup — no code or image changes
required.
This repository uses:
uvfor workspace and dependency managementhatchlingfor package buildspytestfor testsrufffor linting and formattingprekfor pre-commit hook executiontoxwithtox-uvfor repeatable test/lint environments
uv sync --all-packagesRun a single package's tests:
tox -e taskflow
tox -e oslo.log
tox -e oslo.messaging
tox -e openstacksdk
tox -e keystonemiddleware
tox -e keystoneauth1Run every package's tests:
tox -e allLint, format, and pre-commit hooks:
tox -e ruff
tox -e ruff-format
tox -e prek