Skip to main content
Pre-release

This release is a pre-release and may not be stable for production use.

acceldata-aio-tracer

The Acceldata AIO instrumentation SDK. OpenTelemetry-native: it does not replace your instrumentation, it completes it.

Installation

pip install acceldata-aio-tracer

Requires Python 3.10 or newer. FastAPI and httpx instrumentation ship as an optional extra:

pip install 'acceldata-aio-tracer[http]'

Quickstart

import acceldata_aio_tracer as aio

aio.init(
    service="my-app",
    tenant_id="...",
    project_id="...",
    endpoint="https://aio.example.com",
    access_key="...",
    secret_key="...",
)

with aio.root_span(conversation_id=conversation_id, input_preview=user_message):
    ...   # model calls, tools, MCP, outbound HTTP

That is the whole integration. init() runs once at startup, before you build any client; root_span() wraps each unit of work.

tenant_id must be nonblank. It is a claim rather than proof: the Collector checks it against the identity its gateway authenticated, and overwrites it from there.

Endpoints

endpoint is the AIO server. Telemetry goes to that same host unless you say otherwise, so a second endpoint is only needed when the Collector lives somewhere else:

aio.init(
    ...,
    endpoint="https://aio.example.com",
    aio_collector_endpoint="https://collector.example.com",
)

Both fall back to the environment when the argument is omitted — AIO_ENDPOINT and AIO_COLLECTOR_ENDPOINT — and the standard OTEL_EXPORTER_OTLP_ENDPOINT is honoured for the Collector as well.

Selecting a project

Pass exactly one selector. When the UUID is known, project_id is used unchanged and the SDK makes no request to the server.

Otherwise pass the name and let the SDK resolve it:

aio.init(
    service="my-app",
    tenant_id="...",
    project_name="customer-facing-agent",
    endpoint="https://aio.example.com",
    access_key="...",
    secret_key="...",
)

The name is matched exactly, and a project that does not exist is created with only {"name": project_name}. Two processes racing to create the same name is safe: the loser adopts the winner's project. Whether a project is one you may write to — its status, its type — is the server's decision, so the SDK does not second-guess it.

When a name cannot be resolved, whether from a failed lookup, a refused create, or a malformed or ambiguous response, init() returns False and the application runs without telemetry.

What it does

Gives a turn a root. Chat transports like socket.io have no server span, so without a root the model call, each tool call, each MCP handshake and every outbound HTTP request start their own disconnected trace. root_span() opens one span they all nest under, so a user's question is one trace.

Puts the conversation id on every span. Instrumentation libraries tag the spans they own and leave the rest bare. Measured on one application, 2 of 8 instrumentation scopes carried the id, and the untagged spans held over a million tokens — so per-conversation totals were wrong by 15%. This SDK holds the id for the duration of the turn and stamps it on every span started inside, whichever library produced it. An id a library set for itself does not survive that: the open conversation is the one that reaches ingest.

Carries the user's message even when the turn fails. The preview is set when the turn opens, not when it completes, so a request that dies before the first model call still shows what was asked.

What to wrap

root_span() marks a unit of work the application knows the boundaries of and instrumentation cannot infer. A chat turn is one. So is a workflow run:

with aio.root_span(conversation_id=f"{instance_id}:{session_id}", name="workflow_run"):
    ...

Call it once per unit of work, not once per span — it is not a replacement for tracer.start_as_current_span(). name becomes a low-cardinality column, so keep it a fixed label and never interpolate an id into it.

Pass user_id when a turn belongs to a particular person. It rides every span in the unit of work alongside the conversation id, so usage and cost can be attributed per user.

Instrumentation

Instrumentation for models, agents and MCP ships inside the package: init() activates whichever of those libraries is installed in your environment and skips the rest. The FastAPI and httpx layers are the one optional extra (see Installation), and the SDK works with none of them — you still get the root span and identity on whatever your application emits itself.

Call init() as early as possible in your process. Coverage for a client built beforehand depends on how that library's instrumentation attaches: most patch a shared class method and pick up existing instances on their next call, while a few — the FastAPI middleware in the [http] extra among them — attach at construction and only see clients built afterward. Calling init() first is always safe and never the wrong choice.

If your application already configures OpenTelemetry, the SDK adds itself to the existing provider rather than replacing it, and warns if that provider's resource carries no tenant.

Stability

Telemetry never breaks the application: every failure path is swallowed, and init() returns False rather than raising when it cannot start.

service, tenant_id, project_id and endpoint will not be renamed. project_name and aio_collector_endpoint are keyword-only, as are the other optional parameters; always pass them by name.

Upgrading to 1.0.0.dev2. endpoint used to mean the OTLP Collector and now means the AIO server. Where the two differ, move the old value to aio_collector_endpoint; otherwise project resolution is pointed at the Collector.

Troubleshooting

init() returned False and nothing is showing up. It needs a nonblank tenant_id and exactly one of project_id or project_name — passing both, or neither, is refused. The reason is logged at warning level rather than emitting telemetry under the wrong tenant.

Spans are missing tokens, tool calls, or model attributes. The client was possibly constructed before init() ran — see Instrumentation for which integrations that affects. Calling init() before constructing any client sidesteps the question entirely.

Calling init() from more than one place. It is idempotent — the second and later calls are no-ops that return True immediately — so it is safe to call from more than one entry point (a test fixture and the application, for example) without re-registering instrumentation.

License

Apache-2.0. The instrumentation layer is vendored from OpenLIT; UPSTREAM.md, included in the package, records exactly what was changed and why, per the license's attribution requirements.

Release files for acceldata-aio-tracer 1.0.0.dev2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for acceldata-aio-tracer 1.0.0.dev2
File Size Uploaded
acceldata_aio_tracer-1.0.0.dev2.tar.gz 490.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for acceldata-aio-tracer 1.0.0.dev2
File Interpreter ABI Platform
acceldata_aio_tracer-1.0.0.dev2-py3-none-any.whl Python 3 none any Details

Total release size: 1.2 MB

Release files / acceldata_aio_tracer-1.0.0.dev2.tar.gz

Download URL acceldata_aio_tracer-1.0.0.dev2.tar.gz
Size 490.2 kB
Tags Source
SHA-256 checksum
How to use checksums
dac2e399935c26fabee665a387339ca7a8c629b7e20c158d881ab8855669411b
BLAKE2b-256 checksum
How to use checksums
463d0f16765a6de3a1391cd89781d36bfa56fe481f00341a8b34e41e19b980f7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.5 Darwin/25.5.0

Release files / acceldata_aio_tracer-1.0.0.dev2-py3-none-any.whl

Download URL acceldata_aio_tracer-1.0.0.dev2-py3-none-any.whl
Size 671.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
cf8b549428449734eb5eb5854563055dfe74fab7cb37f02012ca8540c1d8ca33
BLAKE2b-256 checksum
How to use checksums
a9e1330f353637f90d451bfe29ad2ea4dd2a7e22005b9b09ab481b988d8b73e0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via poetry/2.4.1 CPython/3.14.5 Darwin/25.5.0
Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page