opentelemetry-instrumentation-absurd
OpenTelemetry instrumentation for the Absurd
durable-task SDK (absurd-sdk).
Absurd (absurd_sdk.AsyncAbsurd) is a Postgres-backed durable task queue: a producer
spawn()s a task and a worker work_batch() claims and runs the registered handler, possibly
in a different process. Without instrumentation the two halves live in separate traces, so a
task's execution cannot be linked back to whatever spawned it.
This instrumentor follows the standard producer/consumer span shape for a task queue:
AsyncAbsurd.spawn()is wrapped to open aCLIENTspan named after the task and inject the current trace context into the task'sheaders. Absurd persists headers on the task row and hands them back to the handler viactx.headers.AsyncAbsurd.register_task()is wrapped so every registered handler runs inside arunning:<task>SERVERspan whose parent is extracted from those headers.
The two spans share one trace, so a task's execution is linked back to whatever spawned it — even when the spawner and the worker run in different processes.
trigger (your span)
└── report CLIENT ← spawn() (process A)
└── running:report SERVER ← handler (process B)
Installation
pip install opentelemetry-instrumentation-absurd
# or
uv add opentelemetry-instrumentation-absurd
Usage
Install the instrumentor once per process, on both the spawn side and the worker side:
from opentelemetry.instrumentation.absurd import AbsurdInstrumentor
AbsurdInstrumentor().instrument()
That is all — no changes to your spawn() calls or task handlers are required. Only
AsyncAbsurd is instrumented.
You can pass an explicit TracerProvider:
AbsurdInstrumentor().instrument(tracer_provider=my_tracer_provider)
Because this package ships an
opentelemetry_instrumentor entry point,
it is also picked up automatically by opentelemetry-instrument:
opentelemetry-instrument python your_app.py
Producer / consumer example
import asyncio
from absurd_sdk import AsyncAbsurd
from opentelemetry.instrumentation.absurd import AbsurdInstrumentor
AbsurdInstrumentor().instrument()
app = AsyncAbsurd('postgresql://localhost/absurd', queue_name='workflows')
@app.register_task(name='report')
async def report(params, ctx):
# Runs inside a `running:report` SERVER span parented to the spawner.
return {'value': params['value'] * 2}
async def main() -> None:
# Opens a `report` CLIENT span and injects the trace context into the task headers.
await app.spawn('report', {'value': 7}, queue='workflows')
asyncio.run(main())
Span attributes
Both spans carry these attributes (set when available):
| Attribute | Span | Description |
|---|---|---|
absurd.task.name |
CLIENT + SERVER | The registered task name. |
absurd.queue |
CLIENT + SERVER | The queue the task was spawned on. |
absurd.task.id |
CLIENT + SERVER | The task UUID (stringified). |
absurd.run.id |
CLIENT | The run UUID assigned by spawn(). |
absurd.task.attempt |
SERVER | The current attempt number of the run. |
absurd.task.idempotency_key |
CLIENT | Set only when an idempotency key is given. |
The trace context is propagated through the task headers under the
otel.absurd.context key using the globally configured OpenTelemetry propagator (W3C
traceparent by default), so any caller headers you pass are preserved.
How it works
spawn() and the registered handler are wrapped with wrapt.
On spawn() the current context is injected into a fresh carrier nested under a single header
key; the worker extracts that carrier and parents its SERVER span to the spawner's CLIENT
span. If a task was spawned before instrumentation (no carrier present), the handler still runs
in its own SERVER span — it just starts a new trace.
Compatibility
- Python 3.10+
absurd-sdk >= 0.4.0opentelemetry-api >= 1.0
Development
make install # uv sync --all-groups
make test # uv run pytest
make check # ruff check + ruff format --check
AI disclaimer
This code was written with the help of AI.
License
Metadata
Release files for opentelemetry-instrumentation-absurd 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| opentelemetry_instrumentation_absurd-0.1.0.tar.gz | 6.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| opentelemetry_instrumentation_absurd-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 14.8 kB
Release files / opentelemetry_instrumentation_absurd-0.1.0.tar.gz
| Download URL | opentelemetry_instrumentation_absurd-0.1.0.tar.gz |
|---|---|
| Size | 6.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6c5086707b0c24e1d53c562134504db8fbe8454476ca4ecfb27fe2829a644d3f
|
|
BLAKE2b-256 checksum How to use checksums |
743484b4ccdb2d00a905b044e4a6acaf25efbd40de314c8b8047a7757979d1b5
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency logRelease files / opentelemetry_instrumentation_absurd-0.1.0-py3-none-any.whl
| Download URL | opentelemetry_instrumentation_absurd-0.1.0-py3-none-any.whl |
|---|---|
| Size | 8.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8df44d213a3e8248a3e7b7ac192936bd43516ddf43d5a0fc4a85b78153652ece
|
|
BLAKE2b-256 checksum How to use checksums |
9ec7ffd1454d1bd1899061531096c159c9f0509bafcedd78104772de00505d0f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 30, 2026.
Transparency log