telemetry-dev-openai
OpenAI SDK instrumentation for telemetry.dev. It wraps the official openai Python SDK and emits telemetry.dev generation and embedding spans through telemetry-dev.
Install
pip install telemetry-dev-openai
Initialize the core SDK first:
import telemetry_dev
telemetry_dev.init(
api_key="td_live_...",
base_url="http://localhost:4318",
service_name="my-service",
)
Per-client wrapping
from openai import OpenAI
from telemetry_dev_openai import wrap_openai
client = wrap_openai(OpenAI())
client.chat.completions.create(
model="gpt-4o-mini",
messages=[{"role": "user", "content": "Tell me a joke about OpenTelemetry"}],
)
Use this when you want explicit control over which sync or async clients are instrumented.
Global instrumentation
from openai import OpenAI
from telemetry_dev_openai import instrument_openai, uninstrument_openai
instrument_openai()
client = OpenAI()
try:
client.responses.create(model="gpt-4o-mini", input="Tell me a joke about OpenTelemetry")
finally:
uninstrument_openai()
Use this as the app-wide one-liner at startup when all OpenAI clients should be instrumented.
Instrumented surfaces
Sync and async variants are covered:
client.chat.completions.create(...)client.chat.completions.parse(...)client.chat.completions.stream(...)client.responses.create(...)client.responses.parse(...)client.responses.stream(...)when starting a new responseclient.embeddings.create(...)client.images.generate(...),edit(...), andcreate_variation(...)client.audio.speech.create(...),transcriptions.create(...), andtranslations.create(...)client.batches.create(...),retrieve(...), andcancel(...)
The integration maps native OpenAI request/response shapes directly into telemetry.dev fields. It does not normalize messages into another schema.
Streaming
Chat completion streams are traced. Requests are sent unchanged by default, so token usage is only captured when the caller sets stream_options={"include_usage": True} themselves. Pass inject_stream_usage=True to wrap_openai or instrument_openai to inject it automatically; the synthetic usage-only chunk is then hidden from the caller. Injection is opt-in because some providers reject stream_options — for example Azure OpenAI "on your data" (data_sources) returns 400 for it while plain stream=True works.
client = wrap_openai(OpenAI(), inject_stream_usage=True)
Responses API streams are traced through responses.create(stream=True) and responses.stream(response_id=...); terminal response.completed, response.failed, and response.incomplete events close the span.
Embeddings
Embedding calls emit gen_ai.operation.name = "embeddings", request model/input, response model, and token usage. Embedding vectors are intentionally not captured as output.
Provider detection
wrap_openai(AzureOpenAI(...)) and wrap_openai(AsyncAzureOpenAI(...)) record provider azure.ai.openai. Global class instrumentation detects Azure from the resource client when available.
OpenAI clients configured with https://openrouter.ai/api/v1 as their base URL record provider openrouter. The same detection applies to OpenRouter subdomains; unrelated hosts containing openrouter.ai are not matched.
OpenAI-compatible URLs on Groq, xAI, DeepSeek, Together, and Fireworks domains (including their subdomains) record the corresponding provider. Other compatible endpoints retain the openai default.
Limitations
with_raw_responseandwith_streaming_responsesnapshot bound methods on first access in the OpenAI Python SDK. Callwrap_openai()orinstrument_openai()before accessing either helper if those methods need instrumentation.- Unconsumed streams end their spans only when the stream is exhausted, errors, or is closed.
- Binary image and audio bodies are never captured, including binary fields nested in Responses API input and output. Speech download/streaming response spans cover request creation, not later byte consumption. Transcription stream spans remain open through stream consumption and record terminal or bounded partial transcript text and usage.
- Realtime is not wrapped: OpenAI Python 2.x exposes an async WebSocket connection (
realtime.connect), not an event emitter with a stable listener lifecycle, so an explicit event-emitter wrapper would be misleading. - Videos (
client.videos) are not instrumented yet; video create and retrieve calls produce no spans. The TypeScript integration traces them. - Batch list pagination is not instrumented so the SDK's synchronous
AsyncPaginatorremains directly usable withasync for.
Metadata
Release files for telemetry-dev-openai 0.1.4
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| telemetry_dev_openai-0.1.4.tar.gz | 14.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| telemetry_dev_openai-0.1.4-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 30.6 kB
Release files / telemetry_dev_openai-0.1.4.tar.gz
| Download URL | telemetry_dev_openai-0.1.4.tar.gz |
|---|---|
| Size | 14.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
1b886238b0bc1240b6ae3a75a56531d3ecf7124ea0a2cdd3039340050685bc78
|
|
BLAKE2b-256 checksum How to use checksums |
152d8f4f02e91f72eda849c4ef137c8047952e80ef39c9f0617ad00c7b595fb8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|
Release files / telemetry_dev_openai-0.1.4-py3-none-any.whl
| Download URL | telemetry_dev_openai-0.1.4-py3-none-any.whl |
|---|---|
| Size | 15.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
8abca0dbf22a79945a4cea60de3e2d7c9ca013b770a7ab1bcbba22727c2f20ea
|
|
BLAKE2b-256 checksum How to use checksums |
30ab73a4da79a3e3cb68c3dcc16fe2f6f501da2b1ca40112491a1deb7c0db293
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
uv/0.12.5 {"installer":{"name":"uv","version":"0.12.5","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
|