Skip to content

Commit 9811782

Browse files
authored
Implement uninstrument for opentelemetry-instrumentation-vertexai (#3328)
* Implement uninstrument for `opentelemetry-insturmentation-vertexai` * Reuse fixture from conftest.py
1 parent 4f9ee01 commit 9811782

File tree

4 files changed

+82
-17
lines changed

4 files changed

+82
-17
lines changed

instrumentation-genai/opentelemetry-instrumentation-vertexai/CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## Unreleased
99

10+
- Implement uninstrument for `opentelemetry-instrumentation-vertexai`
11+
([#3328](https://github.com/open-telemetry/opentelemetry-python-contrib/pull/3328))
12+
1013
## Version 2.0b0 (2025-02-24)
1114

1215
- Added Vertex AI spans for request parameters

instrumentation-genai/opentelemetry-instrumentation-vertexai/src/opentelemetry/instrumentation/vertexai/__init__.py

+28-15
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
from opentelemetry._events import get_event_logger
4949
from opentelemetry.instrumentation.instrumentor import BaseInstrumentor
50+
from opentelemetry.instrumentation.utils import unwrap
5051
from opentelemetry.instrumentation.vertexai.package import _instruments
5152
from opentelemetry.instrumentation.vertexai.patch import (
5253
generate_content_create,
@@ -56,6 +57,23 @@
5657
from opentelemetry.trace import get_tracer
5758

5859

60+
def _client_classes():
61+
# This import is very slow, do it lazily in case instrument() is not called
62+
63+
# pylint: disable=import-outside-toplevel
64+
from google.cloud.aiplatform_v1.services.prediction_service import (
65+
client,
66+
)
67+
from google.cloud.aiplatform_v1beta1.services.prediction_service import (
68+
client as client_v1beta1,
69+
)
70+
71+
return (
72+
client.PredictionServiceClient,
73+
client_v1beta1.PredictionServiceClient,
74+
)
75+
76+
5977
class VertexAIInstrumentor(BaseInstrumentor):
6078
def instrumentation_dependencies(self) -> Collection[str]:
6179
return _instruments
@@ -77,20 +95,15 @@ def _instrument(self, **kwargs: Any):
7795
event_logger_provider=event_logger_provider,
7896
)
7997

80-
wrap_function_wrapper(
81-
module="google.cloud.aiplatform_v1beta1.services.prediction_service.client",
82-
name="PredictionServiceClient.generate_content",
83-
wrapper=generate_content_create(
84-
tracer, event_logger, is_content_enabled()
85-
),
86-
)
87-
wrap_function_wrapper(
88-
module="google.cloud.aiplatform_v1.services.prediction_service.client",
89-
name="PredictionServiceClient.generate_content",
90-
wrapper=generate_content_create(
91-
tracer, event_logger, is_content_enabled()
92-
),
93-
)
98+
for client_class in _client_classes():
99+
wrap_function_wrapper(
100+
client_class,
101+
name="generate_content",
102+
wrapper=generate_content_create(
103+
tracer, event_logger, is_content_enabled()
104+
),
105+
)
94106

95107
def _uninstrument(self, **kwargs: Any) -> None:
96-
"""TODO: implemented in later PR"""
108+
for client_class in _client_classes():
109+
unwrap(client_class, "generate_content")

instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/conftest.py

+4-2
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ def instrument_no_content(
111111

112112
yield instrumentor
113113
os.environ.pop(OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, None)
114-
instrumentor.uninstrument()
114+
if instrumentor.is_instrumented_by_opentelemetry:
115+
instrumentor.uninstrument()
115116

116117

117118
@pytest.fixture
@@ -130,7 +131,8 @@ def instrument_with_content(
130131

131132
yield instrumentor
132133
os.environ.pop(OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT, None)
133-
instrumentor.uninstrument()
134+
if instrumentor.is_instrumented_by_opentelemetry:
135+
instrumentor.uninstrument()
134136

135137

136138
@pytest.fixture(scope="module")
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Copyright The OpenTelemetry Authors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
from __future__ import annotations
16+
17+
import pytest
18+
from google.cloud.aiplatform_v1.services.prediction_service import client
19+
from google.cloud.aiplatform_v1beta1.services.prediction_service import (
20+
client as client_v1beta1,
21+
)
22+
23+
from opentelemetry.instrumentation.vertexai import VertexAIInstrumentor
24+
25+
26+
@pytest.fixture(
27+
name="client_class",
28+
params=[
29+
pytest.param(client.PredictionServiceClient, id="v1"),
30+
pytest.param(client_v1beta1.PredictionServiceClient, id="v1beta1"),
31+
],
32+
)
33+
def fixture_client_class(request: pytest.FixtureRequest):
34+
return request.param
35+
36+
37+
def test_instruments(
38+
instrument_with_content: VertexAIInstrumentor, client_class
39+
):
40+
assert hasattr(client_class.generate_content, "__wrapped__")
41+
42+
43+
def test_uninstruments(
44+
instrument_with_content: VertexAIInstrumentor, client_class
45+
):
46+
instrument_with_content.uninstrument()
47+
assert not hasattr(client_class.generate_content, "__wrapped__")

0 commit comments

Comments
 (0)