open-telemetry / open-telemetry/opentelemetry-python-contrib
`openai` 3.x: `server.address` / `server.port` are never recorded (`isinstance` check misses `httpx2.URL`)
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 1.1k
- Forks
- 1.1k
- Avg merge
- 4d 15h
- Merged PRs (30d)
- 16
Description
Describe your environment
- OS: macOS 15 (arm64)
- Python: 3.13.13
- Package version:
opentelemetry-instrumentation-openai-v22.4b0 - Related:
openai3.0.0,httpx0.28.1,httpx22.10.0
What happened?
Spans produced for OpenAI SDK calls no longer carry the server.address (or server.port) attribute
when the installed openai is 3.x. The same code against openai 2.54.0 records them normally.
The cause is in instrumentation/openai_v2/utils.py:
from httpx import URL # line 23
...
def get_server_address_and_port(client_instance): # line 98
base_client = getattr(client_instance, "_client", None)
base_url = getattr(base_client, "base_url", None)
if not base_url:
return None, None
address = None
port = None
if isinstance(base_url, URL): # httpx.URL
address = base_url.host
port = base_url.port
elif isinstance(base_url, str):
url = urlparse(base_url)
address = url.hostname
port = url.port
...
openai 3.x builds on httpx2, so client._client.base_url is an httpx2.URL. It is neither an
httpx.URL nor a str, so both branches are skipped and the function returns (None, None). Because the
values are only set when truthy, the attributes are dropped silently, with no warning and no error.
Steps to reproduce
from openai import OpenAI
from opentelemetry.instrumentation.openai_v2.utils import get_server_address_and_port
client = OpenAI(base_url="https://openrouter.ai/api/v1", api_key="x")
print(type(client._client.base_url)) # <class 'httpx2.URL'>
print(get_server_address_and_port(client.chat.completions))
# openai 2.54.0 -> ('openrouter.ai', None)
# openai 3.0.0 -> (None, None)
End to end, with a real request through the instrumentor, the emitted span attributes are:
openai 2.54.0: gen_ai.operation.name, gen_ai.provider.name, gen_ai.request.model,
gen_ai.response.finish_reasons, gen_ai.response.id, gen_ai.response.model,
gen_ai.usage.input_tokens, gen_ai.usage.output_tokens, server.address
openai 3.0.0 : (identical, minus server.address)
Expected result
server.address and server.port are recorded regardless of which URL type the SDK uses internally, as
required by the semantic conventions for client spans.
Actual result
Both attributes are absent on openai 3.x.
Why it matters beyond a missing attribute
gen_ai.provider.name names the SDK, not the operator of the endpoint. For anything reached through
the OpenAI-compatible protocol, such as a router or gateway, an Azure OpenAI deployment, or a self-hosted
vLLM or Ollama server, server.address is the only attribute distinguishing them. Without it, all of these are
indistinguishable from a direct api.openai.com call, so consumers that attribute traffic per provider or
per region will silently misattribute it. It fails quietly, which makes it easy to miss in a version bump.
Suggested fix
Avoid the type check and read the URL structurally, which also covers any future URL implementation:
def get_server_address_and_port(client_instance):
base_client = getattr(client_instance, "_client", None)
base_url = getattr(base_client, "base_url", None)
if not base_url:
return None, None
address = getattr(base_url, "host", None)
port = getattr(base_url, "port", None)
if not address: # plain string base_url
parsed = urlparse(str(base_url))
address, port = parsed.hostname, parsed.port
if port == 443:
port = None
return address, port
Both httpx.URL and httpx2.URL expose .host / .port, so this keeps existing behaviour and fixes
3.x. A regression test asserting server.address is present for a non-default base_url would catch the
next recurrence. The current tests pass with the attribute missing.
I'm happy to open a PR with the fix and the test if that's useful.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in instrumentation/openai_v2/utils.py at get_server_address_and_port and reproduce the difference with openai 2.54.0 and 3.0.0 using the base_url shown in the issue. Verify that server.address and server.port are retained for both URL implementations, then add a regression test covering the non-default base URL and run the existing OpenAI instrumentation tests.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- observability-sre
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100