Skip to content

feat: add Python Azure OpenAI instrumentation package - #156

Open
louayboukhris wants to merge 1 commit into
future-agi:devfrom
louayboukhris:feat/python-azure-openai-integration
Open

feat: add Python Azure OpenAI instrumentation package#156
louayboukhris wants to merge 1 commit into
future-agi:devfrom
louayboukhris:feat/python-azure-openai-integration

Conversation

@louayboukhris

@louayboukhris louayboukhris commented Apr 17, 2026

Copy link
Copy Markdown

Add traceai-azure-openai package for tracing Azure OpenAI API calls. This brings Python parity with the existing Java Azure OpenAI integration.

  • AzureOpenAIInstrumentor for auto-instrumenting AzureOpenAI/AsyncAzureOpenAI clients
  • Azure-specific attributes: deployment name, API version, endpoint
  • Chat completions, embeddings, and completions tracing
  • Streaming and async support
  • Unit tests (7 tests) and usage examples

Pull Request

Description

tracing Azure OpenAI API calls

Add traceai-azure-openai package for tracing Azure OpenAI API calls.
This brings Python parity with the existing Java Azure OpenAI integration.

- AzureOpenAIInstrumentor for auto-instrumenting AzureOpenAI/AsyncAzureOpenAI clients
- Azure-specific attributes: deployment name, API version, endpoint
- Chat completions, embeddings, and completions tracing
- Streaming and async support
- Unit tests (7 tests) and usage examples
@louayboukhris
louayboukhris marked this pull request as draft April 20, 2026 15:52
@louayboukhris
louayboukhris marked this pull request as ready for review April 20, 2026 15:54
@nik13 nik13 added the enhancement New feature or request label Apr 21, 2026
@abhijaisrivastava15
abhijaisrivastava15 requested review from JayaSurya-27 and removed request for atharva-bhange June 24, 2026 13:55
@Phoenix1454

Copy link
Copy Markdown

Nice work on this the streaming and async coverage is solid. One thing I noticed in init.py: _instrument patches openai.OpenAI.request rather than openai.AzureOpenAI.request directly. Since AzureOpenAI inherits from OpenAI this works in isolation, but if someone has both OpenAIInstrumentor and AzureOpenAIInstrumentor active in the same process they'd both be patching the same method on the same base class which could cause double instrumentation or one silently overwriting the other's wrapper. Would wrapping AzureOpenAI.request directly be cleaner so each instrumentor owns its own target?

Also logger = logging.getLogger(name) appears twice in init.py (before and after the try/except block) second one's redundant.

@NVJKKartik
NVJKKartik changed the base branch from main to dev August 10, 2026 10:22
@NVJKKartik

Copy link
Copy Markdown
Contributor

Hey thanks for putting this together, but I want to stop this one before it goes further, because I think the premise doesn't hold.

traceai-openai already traces Azure OpenAI today. In the Python SDK, AzureOpenAI subclasses OpenAI and doesn't override request():

AzureOpenAI.request is OpenAI.request → True

AzureOpenAIInstrumentor._instrument() wraps openai.OpenAI.request and openai.AsyncOpenAI.request — the exact same two targets OpenAIInstrumentor already wraps, and it never references AzureOpenAI anywhere. I ran
the existing instrumentor against an Azure client with an in-memory exporter and it emits a complete span already. The only thing actually wrong is the provider label saying openai instead of azure.

Two things in your PR are genuinely better than what's on dev and I'd like to keep them:

  • _is_azure_openai_instance() — the isinstance check beats host.endswith("openai.azure.com"), which misses sovereign clouds (.azure.us, .azure.cn) and APIM-fronted endpoints
  • gen_ai.azure.deployment and gen_ai.azure.api_version

That's ~20 lines into _get_attributes_from_instance in traceai_openai. Could you redo it as that instead?

The reasons I don't want to ship the separate package:

Duplicate spans. Any app using both OpenAI and Azure installs both instrumentors, both wrap the same function, and every Azure call produces two spans. That's double ingest cost for customers and broken trace
trees. I verified it — 2 spans.

Uninstrument leak. The Azure instrumentor captures _original_request after the OpenAI one has already wrapped it, so uninstrumenting in the wrong order leaves OpenAI.request permanently wrapped.

On the Java parity point: that doesn't transfer. Java needs two packages because it wraps two genuinely different SDKs com.openai:openai-java vs com.azure:azure-ai-openai. Python has one SDK and one class
hierarchy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants