Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
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
Prev Previous commit
Next Next commit
Commit latest changes
  • Loading branch information
DylanRussell committed Sep 18, 2025
commit 375e33cda89421fdeb99b316bc06180cbe7fd4a7
Original file line number Diff line number Diff line change
Expand Up @@ -25,9 +25,9 @@ classifiers = [
]
dependencies = [
"opentelemetry-api ~= 1.28",
"opentelemetry-instrumentation == 0.58b0dev",
"opentelemetry-instrumentation ~= 0.58b0",
"opentelemetry-util-genai == 0.1b0.dev",
"opentelemetry-semantic-conventions == 0.58b0dev",
"opentelemetry-semantic-conventions ~= 0.58b0",
]

[project.optional-dependencies]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@

from typing import Any, Collection

from typing_extensions import assert_never
from wrapt import (
wrap_function_wrapper, # type: ignore[reportUnknownVariableType]
)
Expand Down Expand Up @@ -109,18 +110,26 @@ def instrumentation_dependencies(self) -> Collection[str]:

def _instrument(self, **kwargs: Any):
"""Enable VertexAI instrumentation."""
sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
_OpenTelemetryStabilitySignalType.GEN_AI,
)
tracer_provider = kwargs.get("tracer_provider")
schema = (
Schemas.V1_28_0.value
if sem_conv_opt_in_mode == _StabilityMode.DEFAULT
else Schemas.V1_36_0
)
tracer = get_tracer(
__name__,
"",
tracer_provider,
schema_url=Schemas.V1_28_0.value,
schema_url=schema,
)
event_logger_provider = kwargs.get("event_logger_provider")
event_logger = get_event_logger(
__name__,
"",
schema_url=Schemas.V1_28_0.value,
schema_url=schema,
event_logger_provider=event_logger_provider,
)
sem_conv_opt_in_mode = _OpenTelemetrySemanticConventionStability._get_opentelemetry_stability_opt_in_mode(
Expand All @@ -143,10 +152,7 @@ def _instrument(self, **kwargs: Any):
sem_conv_opt_in_mode,
)
else:
# Impossible to reach here, only 2 opt-in modes exist for GEN_AI.
raise ValueError(
f"Sem Conv opt in mode {sem_conv_opt_in_mode} not supported."
)
assert_never()
for client_class, method_name, wrapper in _methods_to_wrap(
method_wrappers
):
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,12 +134,6 @@ def __init__(
self.capture_content = capture_content
self.sem_conv_opt_in_mode = sem_conv_opt_in_mode

# Deprecations:
# - `gen_ai.system.message` event - use `gen_ai.system_instructions` or
# `gen_ai.input.messages` attributes instead.
# - `gen_ai.user.message`, `gen_ai.assistant.message`, `gen_ai.tool.message` events
# (use `gen_ai.input.messages` attribute instead)
# - `gen_ai.choice` event (use `gen_ai.output.messages` attribute instead)
@contextmanager
def _with_new_instrumentation(
self,
Expand All @@ -166,9 +160,10 @@ def _with_new_instrumentation(

def handle_response(
response: prediction_service.GenerateContentResponse
| prediction_service_v1beta1.GenerateContentResponse,
| prediction_service_v1beta1.GenerateContentResponse
| None,
) -> None:
if span.is_recording():
if span.is_recording() and response:
# When streaming, this is called multiple times so attributes would be
# overwritten. In practice, it looks the API only returns the interesting
# attributes on the last streamed response. However, I couldn't find
Expand Down Expand Up @@ -266,20 +261,11 @@ def generate_content(
with self._with_new_instrumentation(
capture_content, instance, args, kwargs
) as handle_response:
response = None
try:
response = wrapped(*args, **kwargs)
except Exception as e:
api_endpoint: str = instance.api_endpoint # type: ignore[reportUnknownMemberType]
self.event_logger.emit(
create_operation_details_event(
params=_extract_params(*args, **kwargs),
response=None,
capture_content=capture_content,
api_endpoint=api_endpoint,
)
)
raise e
handle_response(response)
finally:
handle_response(response)
return response

async def agenerate_content(
Expand Down Expand Up @@ -312,18 +298,9 @@ async def agenerate_content(
with self._with_new_instrumentation(
capture_content, instance, args, kwargs
) as handle_response:
response = None
try:
response = await wrapped(*args, **kwargs)
except Exception as e:
api_endpoint: str = instance.api_endpoint # type: ignore[reportUnknownMemberType]
self.event_logger.emit(
create_operation_details_event(
params=_extract_params(*args, **kwargs),
response=None,
capture_content=capture_content,
api_endpoint=api_endpoint,
)
)
raise e
handle_response(response)
finally:
handle_response(response)
return response
Original file line number Diff line number Diff line change
Expand Up @@ -329,7 +329,7 @@ def create_operation_details_event(
}:
return event
if params.system_instruction:
attributes["gen_ai.system_instructions"] = [
attributes[GenAIAttributes.GEN_AI_SYSTEM_INSTRUCTIONS] = [
{
"type": "text",
"content": "\n".join(
Expand All @@ -338,12 +338,12 @@ def create_operation_details_event(
}
]
if params.contents:
attributes["gen_ai.input.messages"] = [
attributes[GenAIAttributes.GEN_AI_INPUT_MESSAGES] = [
asdict(_convert_content_to_message(content))
for content in params.contents
]
if response and response.candidates:
attributes["gen_ai.output.messages"] = [
attributes[GenAIAttributes.GEN_AI_OUTPUT_MESSAGES] = [
asdict(x) for x in _convert_response_to_output_messages(response)
]
return event
Expand All @@ -370,7 +370,6 @@ def _convert_content_to_message(
content: content.Content | content_v1beta1.Content,
) -> InputMessage:
parts: MessagePart = []
message = InputMessage(role=content.role, parts=parts)
for idx, part in enumerate(content.parts):
if "function_response" in part:
part = part.function_response
Expand Down Expand Up @@ -399,7 +398,7 @@ def _convert_content_to_message(
)
dict_part["type"] = type(part)
parts.append(dict_part)
return message
return InputMessage(role=content.role, parts=parts)


def response_to_events(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,12 @@ vcrpy==6.0.2
wrapt==1.16.0
yarl==1.15.2
zipp==3.20.2

# when updating, also update in pyproject.toml
-e opentelemetry-instrumentation
opentelemetry-api==1.37
opentelemetry-sdk==1.37
opentelemetry-semantic-conventions==0.58b0
opentelemetry-instrumentation==0.58b0


-e instrumentation-genai/opentelemetry-instrumentation-vertexai[instruments]
-e util/opentelemetry-util-genai
1 change: 0 additions & 1 deletion tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -458,7 +458,6 @@ deps =
openai-latest: -r {toxinidir}/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/requirements.latest.txt
lint-instrumentation-openai-v2: -r {toxinidir}/instrumentation-genai/opentelemetry-instrumentation-openai-v2/tests/requirements.oldest.txt

vertexai-oldest: {[testenv]test_deps}
vertexai-oldest: -r {toxinidir}/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/requirements.oldest.txt
vertexai-latest: {[testenv]test_deps}
vertexai-latest: -r {toxinidir}/instrumentation-genai/opentelemetry-instrumentation-vertexai/tests/requirements.latest.txt
Expand Down
Loading