diff --git a/instrumentation/opentelemetry-instrumentation-genai-openai/src/opentelemetry/instrumentation/genai/openai/response_wrappers.py b/instrumentation/opentelemetry-instrumentation-genai-openai/src/opentelemetry/instrumentation/genai/openai/response_wrappers.py index 019e8223..dc4f9e22 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-openai/src/opentelemetry/instrumentation/genai/openai/response_wrappers.py +++ b/instrumentation/opentelemetry-instrumentation-genai-openai/src/opentelemetry/instrumentation/genai/openai/response_wrappers.py @@ -161,10 +161,10 @@ def process_event(self, event: "ResponseStreamEvent[TextFormatT]") -> None: event, "response", None ) - if response and not self._self_invocation.request_model: + if response and not self._self_invocation.response_model_name: model = response.model if model: - self._self_invocation.request_model = model + self._self_invocation.response_model_name = model if event_type == "response.completed": self._stop(response) diff --git a/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_embedding_invocation_unit.py b/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_embedding_invocation_unit.py index 1594001f..6afba67f 100644 --- a/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_embedding_invocation_unit.py +++ b/instrumentation/opentelemetry-instrumentation-genai-openai/tests/test_embedding_invocation_unit.py @@ -60,8 +60,6 @@ def test_model_omitted_when_missing(handler, span_exporter): invocation = create_embedding_invocation(handler, {}, _make_client()) invocation.stop() - assert invocation.request_model is None - spans = span_exporter.get_finished_spans() assert len(spans) == 1 span = spans[0] @@ -77,8 +75,6 @@ def test_model_preserved_when_provided(handler, span_exporter): ) invocation.stop() - assert invocation.request_model == "text-embedding-3-small" - spans = span_exporter.get_finished_spans() assert len(spans) == 1 span = spans[0] diff --git a/util/opentelemetry-util-genai/.changelog/150.changed b/util/opentelemetry-util-genai/.changelog/150.changed new file mode 100644 index 00000000..c3934916 --- /dev/null +++ b/util/opentelemetry-util-genai/.changelog/150.changed @@ -0,0 +1,2 @@ +Restricted start-time sampling attributes to invocation construction time; +they should not be settable after start. diff --git a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py index 70fad50d..82dcc987 100644 --- a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py +++ b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_agent_invocation.py @@ -64,12 +64,12 @@ def __init__( else _operation_name, span_kind=span_kind, ) - self.request_model = request_model - self.server_address = server_address - self.server_port = server_port - self.provider = provider + self._provider: str | None = provider + self._request_model: str | None = request_model + self._server_address: str | None = server_address + self._server_port: int | None = server_port - self.agent_name: str | None = agent_name + self._agent_name: str | None = agent_name self.agent_id: str | None = None self.agent_description: str | None = None self.agent_version: str | None = None @@ -99,37 +99,35 @@ def __init__( self.system_instruction: list[MessagePart] = [] self.tool_definitions: list[ToolDefinition] | None = None - self._start(self._get_base_attributes()) + self._start(self._get_start_attributes()) - def _get_base_attributes(self) -> dict[str, Any]: + @property + def agent_name(self) -> str | None: + """The agent name provided at construction time.""" + return self._agent_name + + def _get_start_attributes(self) -> dict[str, Any]: """Return sampling-relevant attributes available at span creation time.""" optional_attrs = ( - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (GenAI.GEN_AI_AGENT_NAME, self.agent_name), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), + (GenAI.GEN_AI_AGENT_NAME, self._agent_name), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) return { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, + GenAI.GEN_AI_PROVIDER_NAME: self._provider, **{k: v for k, v in optional_attrs if v is not None}, } - def _get_common_attributes(self) -> dict[str, Any]: + def _get_agent_attributes(self) -> dict[str, Any]: + """Return agent attributes not known at span creation time.""" optional_attrs = ( - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), - (GenAI.GEN_AI_AGENT_NAME, self.agent_name), (GenAI.GEN_AI_AGENT_ID, self.agent_id), (GenAI.GEN_AI_AGENT_DESCRIPTION, self.agent_description), (GenAI.GEN_AI_AGENT_VERSION, self.agent_version), ) - return { - GenAI.GEN_AI_OPERATION_NAME: self._operation_name, - **{k: v for k, v in optional_attrs if v is not None}, - } + return {k: v for k, v in optional_attrs if v is not None} def _get_request_attributes(self) -> dict[str, Any]: optional_attrs = ( @@ -178,10 +176,10 @@ def _get_content_attributes_for_span(self) -> dict[str, Any]: def _get_metric_attributes(self) -> dict[str, Any]: optional_attrs = ( - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (GenAI.GEN_AI_PROVIDER_NAME, self._provider), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) attrs: dict[str, Any] = { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -205,7 +203,7 @@ def _apply_finish(self, error: Error | None = None) -> None: self._apply_error_attributes(error) attributes: dict[str, Any] = {} - attributes.update(self._get_common_attributes()) + attributes.update(self._get_agent_attributes()) attributes.update(self._get_request_attributes()) attributes.update(self._get_response_attributes()) attributes.update(self._get_usage_attributes()) diff --git a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_embedding_invocation.py b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_embedding_invocation.py index eedd2fcd..dc1e52f3 100644 --- a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_embedding_invocation.py +++ b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_embedding_invocation.py @@ -48,25 +48,26 @@ def __init__( else _operation_name, span_kind=SpanKind.CLIENT, ) - self.provider = provider # e.g., azure.ai.openai, openai, aws.bedrock - self.request_model = request_model - self.server_address = server_address - self.server_port = server_port + # e.g., azure.ai.openai, openai, aws.bedrock + self._provider: str = provider + self._request_model: str | None = request_model + self._server_address: str | None = server_address + self._server_port: int | None = server_port # encoding_formats can be multi-value -> combinational cardinality risk. # Keep on spans/events only. self.encoding_formats: list[str] | None = None self.input_tokens: int | None = None self.dimension_count: int | None = None self.response_model_name: str | None = None - self._start(self._get_base_attributes()) + self._start(self._get_start_attributes()) - def _get_base_attributes(self) -> dict[str, Any]: + def _get_start_attributes(self) -> dict[str, Any]: """Return sampling-relevant attributes available at span creation time.""" optional_attrs = ( - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), + (GenAI.GEN_AI_PROVIDER_NAME, self._provider), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) return { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -75,11 +76,11 @@ def _get_base_attributes(self) -> dict[str, Any]: def _get_metric_attributes(self) -> dict[str, Any]: optional_attrs = ( - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), + (GenAI.GEN_AI_PROVIDER_NAME, self._provider), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), (GenAI.GEN_AI_RESPONSE_MODEL, self.response_model_name), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) attrs: dict[str, AttributeValue] = { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -95,22 +96,13 @@ def _get_metric_token_counts(self) -> dict[str, int]: def _apply_finish(self, error: Error | None = None) -> None: optional_attrs = ( - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), (GenAI.GEN_AI_EMBEDDINGS_DIMENSION_COUNT, self.dimension_count), (GenAI.GEN_AI_REQUEST_ENCODING_FORMATS, self.encoding_formats), (GenAI.GEN_AI_RESPONSE_MODEL, self.response_model_name), (GenAI.GEN_AI_USAGE_INPUT_TOKENS, self.input_tokens), ) attributes: dict[str, Any] = { - GenAI.GEN_AI_OPERATION_NAME: self._operation_name, - **{ - key: value - for key, value in optional_attrs - if value is not None - }, + key: value for key, value in optional_attrs if value is not None } if error is not None: self._apply_error_attributes(error) diff --git a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py index 751403e7..361220e5 100644 --- a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py +++ b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_inference_invocation.py @@ -67,10 +67,10 @@ def __init__( else operation_name, span_kind=SpanKind.CLIENT, ) - self.provider = provider - self.request_model = request_model - self.server_address = server_address - self.server_port = server_port + self._provider: str = provider + self._request_model: str | None = request_model + self._server_address: str | None = server_address + self._server_port: int | None = server_port self.input_messages: list[InputMessage] = [] self.output_messages: list[OutputMessage] = [] @@ -95,7 +95,7 @@ def __init__( self.top_k: float | None = None self.request_choice_count: int | None = None self.output_type: str | None = None - self._start(self._get_base_attributes()) + self._start(self._get_start_attributes()) def _get_message_attributes(self, *, for_span: bool) -> dict[str, Any]: return get_content_attributes( @@ -118,12 +118,12 @@ def _get_finish_reasons(self) -> list[str] | None: return reasons or None return None - def _get_base_attributes(self) -> dict[str, Any]: + def _get_start_attributes(self) -> dict[str, Any]: optional_attrs = ( - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), + (GenAI.GEN_AI_PROVIDER_NAME, self._provider), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) return { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -131,7 +131,7 @@ def _get_base_attributes(self) -> dict[str, Any]: } def _get_attributes(self) -> dict[str, Any]: - attrs = self._get_base_attributes() + attrs = self._get_start_attributes() if self.output_tokens is None and self.thinking_tokens is None: output_tokens = None else: @@ -171,7 +171,7 @@ def _get_attributes(self) -> dict[str, Any]: return attrs def _get_metric_attributes(self) -> dict[str, Any]: - attrs = self._get_base_attributes() + attrs = self._get_start_attributes() if self.response_model_name is not None: attrs[GenAI.GEN_AI_RESPONSE_MODEL] = self.response_model_name attrs.update(self.metric_attributes) @@ -302,8 +302,8 @@ def _sync_to_invocation(self) -> None: inv = self._inference_invocation if inv is None: return - inv.provider = self.provider or "" - inv.request_model = self.request_model + # Start attributes (provider, request_model, server_address, server_port) + # are fixed at construction in _start_with_handler and cannot be reassigned. inv.input_messages = self.input_messages inv.output_messages = self.output_messages inv.system_instruction = self.system_instruction @@ -319,8 +319,6 @@ def _sync_to_invocation(self) -> None: inv.max_tokens = self.max_tokens inv.stop_sequences = self.stop_sequences inv.seed = self.seed - inv.server_address = self.server_address - inv.server_port = self.server_port inv.attributes = self.attributes inv.metric_attributes = self.metric_attributes diff --git a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_retrieval_invocation.py b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_retrieval_invocation.py index 071b20fa..4c15e623 100644 --- a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_retrieval_invocation.py +++ b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_retrieval_invocation.py @@ -68,24 +68,24 @@ def __init__( else _operation_name, span_kind=SpanKind.CLIENT, ) - self.data_source_id = data_source_id - self.provider = provider - self.request_model = request_model - self.server_address = server_address - self.server_port = server_port + self._data_source_id: str | None = data_source_id + self._provider: str | None = provider + self._request_model: str | None = request_model + self._server_address: str | None = server_address + self._server_port: int | None = server_port self.top_k: float | None = None self.query_text: str | None = None self.documents: Sequence[Mapping[str, Any]] | None = None - self._start(self._get_base_attributes()) + self._start(self._get_start_attributes()) - def _get_base_attributes(self) -> dict[str, AttributeValue]: + def _get_start_attributes(self) -> dict[str, AttributeValue]: """Return sampling-relevant attributes available at span creation time.""" optional_attrs: tuple[tuple[str, AttributeValue | None], ...] = ( - (GenAI.GEN_AI_DATA_SOURCE_ID, self.data_source_id), - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (GenAI.GEN_AI_DATA_SOURCE_ID, self._data_source_id), + (GenAI.GEN_AI_PROVIDER_NAME, self._provider), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) return { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -95,10 +95,10 @@ def _get_base_attributes(self) -> dict[str, AttributeValue]: def _get_metric_attributes(self) -> dict[str, AttributeValue]: # data_source_id intentionally excluded — high cardinality optional_attrs: tuple[tuple[str, AttributeValue | None], ...] = ( - (GenAI.GEN_AI_PROVIDER_NAME, self.provider), - (GenAI.GEN_AI_REQUEST_MODEL, self.request_model), - (server_attributes.SERVER_ADDRESS, self.server_address), - (server_attributes.SERVER_PORT, self.server_port), + (GenAI.GEN_AI_PROVIDER_NAME, self._provider), + (GenAI.GEN_AI_REQUEST_MODEL, self._request_model), + (server_attributes.SERVER_ADDRESS, self._server_address), + (server_attributes.SERVER_PORT, self._server_port), ) attrs: dict[str, AttributeValue] = { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, diff --git a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_tool_invocation.py b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_tool_invocation.py index 8563685f..a23085ec 100644 --- a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_tool_invocation.py +++ b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_tool_invocation.py @@ -62,25 +62,25 @@ def __init__( span_name=f"{_operation_name} {name}" if name else _operation_name, ) self.should_capture_content_on_span = should_capture_content_on_spans() - self.name = name + self._name: str = name self.tool_result: AttributeValue | None = None # Since arguments and tool_result can be expensive to serialize, # it's recommended to check the content capture flag in the # instrumentation library before assigning these attributes # to the invocation. self.arguments: AttributeValue | None = None - self.tool_call_id = tool_call_id - self.tool_type = tool_type - self.tool_description = tool_description - self._start(self._get_base_attributes()) + self._tool_call_id: str | None = tool_call_id + self._tool_type: str | None = tool_type + self._tool_description: str | None = tool_description + self._start(self._get_start_attributes()) - def _get_base_attributes(self) -> dict[str, Any]: + def _get_start_attributes(self) -> dict[str, Any]: """Return sampling-relevant attributes available at span creation time.""" optional_attrs = ( - (GenAI.GEN_AI_TOOL_NAME, self.name), - (GenAI.GEN_AI_TOOL_CALL_ID, self.tool_call_id), - (GenAI.GEN_AI_TOOL_TYPE, self.tool_type), - (GenAI.GEN_AI_TOOL_DESCRIPTION, self.tool_description), + (GenAI.GEN_AI_TOOL_NAME, self._name), + (GenAI.GEN_AI_TOOL_CALL_ID, self._tool_call_id), + (GenAI.GEN_AI_TOOL_TYPE, self._tool_type), + (GenAI.GEN_AI_TOOL_DESCRIPTION, self._tool_description), ) return { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -98,10 +98,6 @@ def _apply_finish(self, error: Error | None = None) -> None: if error is not None: self._apply_error_attributes(error) optional_attrs = ( - (GenAI.GEN_AI_TOOL_NAME, self.name), - (GenAI.GEN_AI_TOOL_CALL_ID, self.tool_call_id), - (GenAI.GEN_AI_TOOL_TYPE, self.tool_type), - (GenAI.GEN_AI_TOOL_DESCRIPTION, self.tool_description), ( GenAI.GEN_AI_TOOL_CALL_ARGUMENTS, self.arguments @@ -116,8 +112,7 @@ def _apply_finish(self, error: Error | None = None) -> None: ), ) attributes: dict[str, Any] = { - GenAI.GEN_AI_OPERATION_NAME: self._operation_name, - **{k: v for k, v in optional_attrs if v is not None}, + k: v for k, v in optional_attrs if v is not None } attributes.update(self.attributes) self.span.set_attributes(attributes) diff --git a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py index e7d6ff7e..cab707e2 100644 --- a/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py +++ b/util/opentelemetry-util-genai/src/opentelemetry/util/genai/_workflow_invocation.py @@ -52,12 +52,12 @@ def __init__( span_name=f"{_operation_name} {name}" if name else _operation_name, span_kind=SpanKind.INTERNAL, ) - self.name = name + self._name: str | None = name self.input_messages: list[InputMessage] = [] self.output_messages: list[OutputMessage] = [] - self._start(self._get_base_attributes()) + self._start(self._get_start_attributes()) - def _get_base_attributes(self) -> dict[str, Any]: + def _get_start_attributes(self) -> dict[str, Any]: """Return sampling-relevant attributes available at span creation time.""" attrs: dict[str, Any] = { GenAI.GEN_AI_OPERATION_NAME: self._operation_name, @@ -86,10 +86,7 @@ def _get_messages_for_span(self) -> dict[str, Any]: } def _apply_finish(self, error: Error | None = None) -> None: - attributes: dict[str, Any] = { - GenAI.GEN_AI_OPERATION_NAME: self._operation_name - } - attributes.update(self._get_messages_for_span()) + attributes: dict[str, Any] = self._get_messages_for_span() if error is not None: self._apply_error_attributes(error) attributes.update(self.attributes) diff --git a/util/opentelemetry-util-genai/tests/test_handler_agent.py b/util/opentelemetry-util-genai/tests/test_handler_agent.py index 338786d1..aa732a37 100644 --- a/util/opentelemetry-util-genai/tests/test_handler_agent.py +++ b/util/opentelemetry-util-genai/tests/test_handler_agent.py @@ -71,8 +71,8 @@ def test_no_server_attributes(self): def test_all_attributes(self): invocation = self.handler.invoke_local_agent( request_model="gpt-4", + agent_name="Full Agent", ) - invocation.agent_name = "Full Agent" invocation.agent_id = "agent-123" invocation.agent_description = "A test agent" invocation.agent_version = "1.0.0" @@ -175,8 +175,8 @@ def test_context_manager_error(self): ) def test_context_manager_default_invocation(self): - with self.handler.invoke_local_agent() as inv: - inv.agent_name = "Dynamic Agent" + with self.handler.invoke_local_agent(agent_name="Dynamic Agent"): + pass assert len(self.span_exporter.get_finished_spans()) == 1 def test_default_values(self): @@ -184,7 +184,7 @@ def test_default_values(self): invocation.stop() assert invocation._operation_name == "invoke_agent" assert invocation.agent_name is None - assert invocation.request_model is None + assert invocation._request_model is None assert not invocation.input_messages assert not invocation.output_messages assert invocation.tool_definitions is None @@ -245,16 +245,6 @@ def test_default_attributes_are_independent(self): inv2.stop() inv1.stop() - def test_agent_name_set_after_construction(self): - invocation = self.handler.invoke_local_agent() - invocation.agent_name = "Named Agent" - invocation.stop() - span = self.span_exporter.get_finished_spans()[0] - # Span name is not updated after construction — agent_name should be - # passed at construction time for correct span naming and sampling. - assert span.name == "invoke_agent" - assert span.attributes[GenAI.GEN_AI_AGENT_NAME] == "Named Agent" - def test_agent_name_passed_at_construction(self): invocation = self.handler.invoke_local_agent( agent_name="Constructor Agent" @@ -435,8 +425,8 @@ def test_all_attributes(self): request_model="gpt-4", server_address="api.openai.com", server_port=443, + agent_name="Remote Agent", ) - invocation.agent_name = "Remote Agent" invocation.agent_id = "agent-123" invocation.agent_description = "A remote test agent" invocation.agent_version = "1.0.0" diff --git a/util/opentelemetry-util-genai/tests/test_handler_completion_hook.py b/util/opentelemetry-util-genai/tests/test_handler_completion_hook.py index 300597b4..bc4766c0 100644 --- a/util/opentelemetry-util-genai/tests/test_handler_completion_hook.py +++ b/util/opentelemetry-util-genai/tests/test_handler_completion_hook.py @@ -231,8 +231,9 @@ def test_local_agent_hook_called_on_stop_with_messages(self): ) ] - invocation = handler.invoke_local_agent(request_model="gpt-4") - invocation.agent_name = "Math Tutor" + invocation = handler.invoke_local_agent( + request_model="gpt-4", agent_name="Math Tutor" + ) invocation.input_messages = input_messages invocation.output_messages = output_messages invocation.system_instruction = system_instruction diff --git a/util/opentelemetry-util-genai/tests/test_handler_retrieval.py b/util/opentelemetry-util-genai/tests/test_handler_retrieval.py index 06835b35..b274827d 100644 --- a/util/opentelemetry-util-genai/tests/test_handler_retrieval.py +++ b/util/opentelemetry-util-genai/tests/test_handler_retrieval.py @@ -279,7 +279,7 @@ def test_context_manager_creates_and_ends_span(self) -> None: def test_context_manager_default_invocation(self) -> None: with self.handler.retrieval() as inv: self.assertIsInstance(inv, RetrievalInvocation) - self.assertIsNone(inv.data_source_id) + self.assertIsNone(inv._data_source_id) self.assertEqual(inv._operation_name, "retrieval") def test_context_manager_success_has_unset_status(self) -> None: diff --git a/util/opentelemetry-util-genai/tests/test_handler_workflow.py b/util/opentelemetry-util-genai/tests/test_handler_workflow.py index a304f5b8..5e75507e 100644 --- a/util/opentelemetry-util-genai/tests/test_handler_workflow.py +++ b/util/opentelemetry-util-genai/tests/test_handler_workflow.py @@ -178,7 +178,7 @@ def test_workflow_context_manager_creates_and_ends_span(self) -> None: def test_workflow_context_manager_default_invocation(self) -> None: with self.handler.workflow() as inv: self.assertIsInstance(inv, WorkflowInvocation) - self.assertIsNone(inv.name) + self.assertIsNone(inv._name) self.assertEqual(inv._operation_name, "invoke_workflow") diff --git a/util/opentelemetry-util-genai/tests/test_workflow_invocation.py b/util/opentelemetry-util-genai/tests/test_workflow_invocation.py index 5a8a559d..6ddfd30a 100644 --- a/util/opentelemetry-util-genai/tests/test_workflow_invocation.py +++ b/util/opentelemetry-util-genai/tests/test_workflow_invocation.py @@ -29,7 +29,7 @@ def setUp(self): def test_default_values(self): invocation = self.handler.workflow(name=None) invocation.stop() - assert invocation.name is None + assert invocation._name is None assert invocation._operation_name == "invoke_workflow" assert not invocation.input_messages assert not invocation.output_messages @@ -39,7 +39,7 @@ def test_default_values(self): def test_custom_name(self): invocation = self.handler.workflow(name="customer_support_pipeline") invocation.stop() - assert invocation.name == "customer_support_pipeline" + assert invocation._name == "customer_support_pipeline" def test_with_input_messages(self): msg = InputMessage(role="user", parts=[Text(content="hello")]) @@ -95,7 +95,7 @@ def test_full_construction(self): invocation.input_messages = [inp] invocation.output_messages = [out] invocation.stop() - assert invocation.name == "my_workflow" + assert invocation._name == "my_workflow" assert len(invocation.input_messages) == 1 assert len(invocation.output_messages) == 1 assert invocation.output_messages[0].parts[0].content == "answer"