From e1c56f2fc5b7d801c0856bb9332ca19d594fab05 Mon Sep 17 00:00:00 2001 From: Rima-ag <55252887+Rima-ag@users.noreply.github.com> Date: Fri, 27 Feb 2026 06:29:04 +0100 Subject: [PATCH] [google-genai] Test instrumentation on google-genai v1.64.0 (#4253) * [google-genai] Test instrumentation on google-genai v1.63.0 * Add package version upper bound * bump latest version for python 3.9 * fix README * bump google-auth version for python 3.9 * add package upper limit to pyproject.toml * [google-genai] Test instrumentation on google-genai v1.64.0 * fix upper case method in cassette not matching lower case one generated by aiohttp * fix async calls hanging in vcrpy * Remove package upper limit * fix import error in python 3.9 * fix google-genai module lower bound * Add link to vcr issue * Add comment about request method * Fix lint errors * Fix spellcheck --------- Co-authored-by: Aaron Abbott --- instrumentation-genai/README.md | 2 +- .../instrumentation/google_genai/package.py | 2 +- .../tests/generate_content/test_e2e.py | 53 +++++++++++++++++++ .../tests/requirements.latest.txt | 6 ++- 4 files changed, 59 insertions(+), 4 deletions(-) diff --git a/instrumentation-genai/README.md b/instrumentation-genai/README.md index a6498da6a..dbe51b523 100644 --- a/instrumentation-genai/README.md +++ b/instrumentation-genai/README.md @@ -3,7 +3,7 @@ | --------------- | ------------------ | --------------- | -------------- | | [opentelemetry-instrumentation-anthropic](./opentelemetry-instrumentation-anthropic) | anthropic >= 0.16.0 | No | development | [opentelemetry-instrumentation-claude-agent-sdk](./opentelemetry-instrumentation-claude-agent-sdk) | claude-agent-sdk >= 0.1.14 | No | development -| [opentelemetry-instrumentation-google-genai](./opentelemetry-instrumentation-google-genai) | google-genai >= 1.0.0 | No | development +| [opentelemetry-instrumentation-google-genai](./opentelemetry-instrumentation-google-genai) | google-genai >= 1.32.0 | No | development | [opentelemetry-instrumentation-langchain](./opentelemetry-instrumentation-langchain) | langchain >= 0.3.21 | No | development | [opentelemetry-instrumentation-openai-agents-v2](./opentelemetry-instrumentation-openai-agents-v2) | openai-agents >= 0.3.3 | No | development | [opentelemetry-instrumentation-openai-v2](./opentelemetry-instrumentation-openai-v2) | openai >= 1.26.0 | Yes | development diff --git a/instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/package.py b/instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/package.py index 46a0504cc..184b8cd8c 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/package.py +++ b/instrumentation-genai/opentelemetry-instrumentation-google-genai/src/opentelemetry/instrumentation/google_genai/package.py @@ -12,4 +12,4 @@ # See the License for the specific language governing permissions and # limitations under the License. -_instruments = ("google-genai >= 1.0.0",) +_instruments = ("google-genai >= 1.32.0",) diff --git a/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/generate_content/test_e2e.py b/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/generate_content/test_e2e.py index 36802b65d..47abf4b87 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/generate_content/test_e2e.py +++ b/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/generate_content/test_e2e.py @@ -40,6 +40,14 @@ import yaml from google.genai import types from vcr.record_mode import RecordMode +try: + # These modules are only supported in python >= 3.10 + from aiohttp.client_exceptions import ClientConnectionError + from vcr.stubs import aiohttp_stubs +except ImportError: + ClientConnectionError = None + aiohttp_stubs = None + from opentelemetry.instrumentation._semconv import ( OTEL_SEMCONV_STABILITY_OPT_IN, _OpenTelemetrySemanticConventionStability, @@ -135,6 +143,9 @@ def _redact_headers(headers): def _before_record_request(request): + # aiohttp reports the request method in lower case while it is recorded in the cassette in upper case. + if request.method: + request.method = request.method.upper() if request.headers: _redact_headers(request.headers) uri = request.uri @@ -316,6 +327,48 @@ def setup_vcr(vcr): return vcr +@pytest.fixture(name="patch_vcr_aiohttp_stream", scope="module", autouse=True) +def fixture_patch_vcr_aiohttp_stream(): + # Allows the async tests to not be stuck in infinite loop when streaming + # a VCR cassette with aiohttp stubs. + # https://github.com/kevin1024/vcrpy/issues/927 + if ClientConnectionError is None or aiohttp_stubs is None: + return + + class _ReplayMockStream(aiohttp_stubs.MockStream): + # Keep vcrpy's stream behavior, but ignore aiohttp's + # close-time ClientConnectionError("Connection closed") during + # cassette replay, where the full response is already buffered + # and this condition should be treated as normal EOF. + def set_exception(self, exc): + if isinstance(exc, ClientConnectionError) and exc.args == ( + "Connection closed", + ): + return + super().set_exception(exc) + + class _ReplayMockClientResponse(aiohttp_stubs.MockClientResponse): + def __init__(self, *args, **kwargs): + super().__init__(*args, **kwargs) + self._mock_content_stream = None + + @property + def content(self): + # vcrpy's aiohttp MockClientResponse.content creates a fresh stream object + # on every property access. google-genai async streaming repeatedly reads + # response.content.readline() and expects the same stream instance until EOF is + # reached. + if self._mock_content_stream is None: + body = self._body or b"" + stream = _ReplayMockStream() + stream.feed_data(body) + stream.feed_eof() + self._mock_content_stream = stream + return self._mock_content_stream + + aiohttp_stubs.MockClientResponse = _ReplayMockClientResponse + + @pytest.fixture(name="instrumentor") def fixture_instrumentor(): return GoogleGenAiSdkInstrumentor() diff --git a/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/requirements.latest.txt b/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/requirements.latest.txt index 7c7d51164..32e582c83 100644 --- a/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/requirements.latest.txt +++ b/instrumentation-genai/opentelemetry-instrumentation-google-genai/tests/requirements.latest.txt @@ -40,8 +40,10 @@ pytest==7.4.4 pytest-asyncio==0.21.0 pytest-vcr==1.0.2 -google-auth==2.38.0 -google-genai==1.32.0 +google-auth==2.47.0 + +google-genai==1.47.0; python_version < "3.10" +google-genai==1.64.0; python_version >= "3.10" # Install locally from the folder. This path is relative to the # root directory, given invocation from "tox" at root level.