Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions .github/renovate.json5
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
"pip_requirements": {
// Default pip_requirements fileMatch only allows [\w-]* between
// "requirements" and ".txt", so per-instrumentation
// requirements.latest.txt files are skipped without this.
"managerFilePatterns": ["/(^|/)requirements\\.txt$/", "/(^|/)requirements\\.latest\\.txt$/"]
// requirements.latest.txt and requirements.<lib>-v<N>.txt files are
// skipped without this.
"managerFilePatterns": [
"/(^|/)requirements\\.txt$/",
"/(^|/)requirements\\.latest\\.txt$/",
"/(^|/)requirements\\.[\\w-]+-v\\d+\\.txt$/"
]
},
// Manage WEAVER_VERSION and SEMCONV_GENAI_REF in versions.env via their
// `# renovate:` annotations.
Expand Down Expand Up @@ -65,6 +70,14 @@
"matchPackageNames": ["pydantic"],
"allowedVersions": "<2.13"
},
{
// requirements.<lib>-v<N>.txt tests the newest release of an older
// major of <lib>, so <lib> itself must stay on that major while the
// rest of the file keeps updating. Add one rule per such file.
"matchFileNames": ["**/requirements.openai-v2.txt"],
"matchPackageNames": ["openai"],
"allowedVersions": "<3"
},
{
"matchUpdateTypes": ["minor", "major"],
"schedule": ["before 8am on Monday"]
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ All instrumentations use [opentelemetry-util-genai](./util/opentelemetry-util-ge
| --------------- | ----------------- | ------- |
| [opentelemetry-instrumentation-genai-anthropic](./instrumentation/opentelemetry-instrumentation-genai-anthropic) | anthropic >= 0.16.0 | [1.0b0](https://pypi.org/project/opentelemetry-instrumentation-genai-anthropic/) |
| [opentelemetry-instrumentation-genai-langchain](./instrumentation/opentelemetry-instrumentation-genai-langchain) | langchain >= 0.3.21 | [1.0b0](https://pypi.org/project/opentelemetry-instrumentation-genai-langchain/) |
| [opentelemetry-instrumentation-genai-openai](./instrumentation/opentelemetry-instrumentation-genai-openai) | openai >= 1.26.0 | [1.0b0](https://pypi.org/project/opentelemetry-instrumentation-genai-openai/) |
| [opentelemetry-instrumentation-genai-openai](./instrumentation/opentelemetry-instrumentation-genai-openai) | openai >= 1.26.0, < 4 | [1.0b0](https://pypi.org/project/opentelemetry-instrumentation-genai-openai/) |
| [opentelemetry-instrumentation-genai-openai-agents](./instrumentation/opentelemetry-instrumentation-genai-openai-agents) | openai-agents >= 0.3.3 | [1.0b0](https://pypi.org/project/opentelemetry-instrumentation-genai-openai-agents/) |
| [opentelemetry-instrumentation-google-genai](./instrumentation/opentelemetry-instrumentation-google-genai) | google-genai >= 1.32.0, <3 | [1.0b1](https://pypi.org/project/opentelemetry-instrumentation-google-genai/) |

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Extend supported version range for the openai library to include v3.
Comment thread
lmolkova marked this conversation as resolved.
Resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix ``server.address`` and ``server.port`` not recorded when using openai v3 (httpx2 URL type).
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ dependencies = [
]

[project.optional-dependencies]
instruments = ["openai >= 1.26.0"]
instruments = ["openai >= 1.26.0, < 4"]

[project.entry-points.opentelemetry_instrumentor]
openai = "opentelemetry.instrumentation.genai.openai:OpenAIInstrumentor"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@
runtime_checkable,
)

import httpx
try:
import httpx as _http_lib
except ImportError:
import httpx2 as _http_lib
from openai import AsyncStream, Stream
from wrapt import ObjectProxy

Expand Down Expand Up @@ -51,7 +54,7 @@ class RawResponseLike(ParsableResponse, Protocol):
finalize the span when the caller never calls ``parse()``.
"""

http_response: httpx.Response
http_response: _http_lib.Response


class RawResponseStreamProxy(ObjectProxy):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,6 @@
# SPDX-License-Identifier: Apache-2.0


_instruments = ("openai >= 1.26.0",)
_instruments = ("openai >= 1.26.0, < 4",)

_supports_metrics = True
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
from urllib.parse import urlparse

import openai
from httpx import URL
from openai import NotGiven

from opentelemetry.semconv._incubating.attributes import (
Expand Down Expand Up @@ -68,13 +67,13 @@ def get_server_address_and_port(
base_url = getattr(base_client, "base_url", None)
if not base_url:
return None, None
address = None
port = None
if isinstance(base_url, URL):
address = base_url.host
port = base_url.port
elif isinstance(base_url, str):
url = urlparse(base_url)

# Use getattr rather than isinstance(base_url, httpx.URL): openai v1/v2
# uses httpx.URL while v3 uses httpx2.URL; both expose .host and .port.
address = getattr(base_url, "host", None)
Comment thread
lmolkova marked this conversation as resolved.
Resolved
port = getattr(base_url, "port", None)
if not address:
url = urlparse(str(base_url))
address = url.hostname
port = url.port

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,17 +37,16 @@
# This variant of the requirements aims to test the system using
# the newest supported version of external dependencies.

openai==2.52.0
openai==3.1.0
# older pydantic is required for PyPy < 3.11
pydantic==2.12.5
httpx==0.28.1
httpx2==2.7.0
# older jiter is required for PyPy < 3.11
Comment thread
lmolkova marked this conversation as resolved.
Resolved
jiter==0.11.1
Deprecated==1.3.1
importlib-metadata==9.0.0
packaging==26.2
wrapt==2.2.2
opentelemetry-instrumentation-httpx==0.64b0
# test with the latest version of opentelemetry-api, sdk, semantic conventions, and instrumentation

-e instrumentation/opentelemetry-instrumentation-genai-openai
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Copyright The OpenTelemetry Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


# ********************************
# WARNING: NOT HERMETIC !!!!!!!!!!
# ********************************
#
# This "requirements.txt" is installed in conjunction
# with multiple other dependencies in the top-level "tox.ini"
# file. In particular, please see:
#
# openai-v2: {[testenv]test_deps}
# openai-v2: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/requirements.openai-v2.txt
#
# This provides additional dependencies, namely:
#
# opentelemetry-api
# opentelemetry-sdk
# opentelemetry-semantic-conventions
# opentelemetry-instrumentation
#
# ... with a "dev" version based on the latest distribution.


# This variant of the requirements aims to test the system using
# the latest openai v2.x release (httpx-based, as opposed to the httpx2-based v3.x).
# It also includes opentelemetry-instrumentation-httpx to exercise the httpx interop tests.

openai==2.54.0
# older pydantic is required for PyPy < 3.11
pydantic==2.12.5
httpx==0.28.1
opentelemetry-instrumentation-httpx==0.64b0
# older jiter is required for PyPy < 3.11
jiter==0.11.1
Deprecated==1.3.1
importlib-metadata==9.0.0
packaging==26.2
wrapt==2.2.2
# test with the latest version of opentelemetry-api, sdk, semantic conventions, and instrumentation

-e instrumentation/opentelemetry-instrumentation-genai-openai
-e util/opentelemetry-util-genai
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@
from typing import Any

import pytest
from httpx import URL

try:
from httpx import URL
except ImportError:
from httpx2 import URL

from opentelemetry.instrumentation.genai.openai.patch import (
_create_embedding_invocation as create_embedding_invocation,
Expand Down Expand Up @@ -98,6 +102,18 @@ def test_server_address_and_port_from_client(handler, span_exporter):
assert span.attributes[ServerAttributes.SERVER_PORT] == 8080


def test_server_address_and_port_from_non_httpx_url(handler, span_exporter):
"""Works with any URL object exposing .host/.port (e.g. httpx2.URL)."""
fake_url = SimpleNamespace(host="openrouter.ai", port=None)
client = _make_client(fake_url)
invocation = create_embedding_invocation(handler, {"model": "m"}, client)
invocation.stop()

span = span_exporter.get_finished_spans()[0]
assert span.attributes[ServerAttributes.SERVER_ADDRESS] == "openrouter.ai"
assert ServerAttributes.SERVER_PORT not in span.attributes


# ─── create_embedding_invocation: dimensions / encoding_format ──────────────


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,12 @@

import json

import httpx
import pytest
from openai import AsyncOpenAI, OpenAI

# Only pinned in requirements.latest.txt; oldest envs skip this module.
# Only pinned in requirements.openai-v2.txt; other envs (openai v3+ uses
# httpx2, oldest has no httpx instrumentation) skip this module.
httpx = pytest.importorskip("httpx")
HTTPXClientInstrumentor = pytest.importorskip(
"opentelemetry.instrumentation.httpx"
).HTTPXClientInstrumentor
Expand Down
6 changes: 5 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ envlist =
; oldest deps run only on the minimum supported Python: the lowest declared dependency versions
; predate newer interpreters and ship no wheels for them. latest covers the full interpreter range.
py3{10,11,12,13,14}-test-instrumentation-genai-openai-latest
py3{10,11,12,13,14}-test-instrumentation-genai-openai-v2
py310-test-instrumentation-genai-openai-oldest
pypy3-test-instrumentation-genai-openai-latest
py314-test-instrumentation-genai-openai-conformance
Expand Down Expand Up @@ -123,6 +124,9 @@ deps =
openai-latest: {[testenv]test_deps}
openai-latest: {[testenv]pytest_deps}
openai-latest: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/requirements.latest.txt
openai-v2: {[testenv]test_deps}
openai-v2: {[testenv]pytest_deps}
openai-v2: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/requirements.openai-v2.txt
openai-conformance: {[testenv]pytest_deps}
openai-conformance: -r {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/requirements.latest.txt

Expand Down Expand Up @@ -245,7 +249,7 @@ commands_pre =
coverage: python {toxinidir}/scripts/eachdist.py install --editable

commands =
test-instrumentation-genai-openai-{oldest,latest}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests {posargs}
test-instrumentation-genai-openai-{oldest,latest,v2}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests {posargs}
test-instrumentation-genai-openai-conformance: pytest {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_conformance.py --vcr-record=none {posargs}
lint-instrumentation-genai-openai: sh -c "cd instrumentation && ruff check opentelemetry-instrumentation-genai-openai"
test-instrumentation-genai-openai_agents-{oldest,latest}: pytest --ignore={toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai-agents/tests/test_conformance.py {toxinidir}/instrumentation/opentelemetry-instrumentation-genai-openai-agents/tests {posargs}
Expand Down
34 changes: 17 additions & 17 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading