-
Notifications
You must be signed in to change notification settings - Fork 512
chore: refactor use_span to be close automatically #1293
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -319,14 +319,20 @@ def end_model_invoke_span( | |
| ) -> None: | ||
| """End a model invocation span with results and metrics. | ||
|
|
||
| Note: When using with trace_api.use_span(end_on_exit=True), the span will be automatically | ||
| closed and exceptions recorded. This method just sets the necessary attributes. | ||
|
|
||
| Args: | ||
| span: The span to end. | ||
| span: The span to set attributes on. | ||
| message: The message response from the model. | ||
| usage: Token usage information from the model call. | ||
| metrics: Metrics from the model call. | ||
| stop_reason (StopReason): The reason the model stopped generating. | ||
| error: Optional exception if the model call failed. | ||
| stop_reason: The reason the model stopped generating. | ||
| error: Optional exception if the model call failed (not used when end_on_exit=True). | ||
| """ | ||
| # Set end time attribute | ||
| span.set_attribute("gen_ai.event.end_time", datetime.now(timezone.utc).isoformat()) | ||
|
|
||
| attributes: Dict[str, AttributeValue] = { | ||
| "gen_ai.usage.prompt_tokens": usage["inputTokens"], | ||
| "gen_ai.usage.input_tokens": usage["inputTokens"], | ||
|
|
@@ -361,7 +367,12 @@ def end_model_invoke_span( | |
| event_attributes={"finish_reason": str(stop_reason), "message": serialize(message["content"])}, | ||
| ) | ||
|
|
||
| self._end_span(span, attributes, error) | ||
| self._set_attributes(span, attributes) | ||
|
|
||
| # Note: self._end_span() is commented out because when using trace_api.use_span(end_on_exit=True), | ||
| # the span is automatically closed and exceptions are automatically recorded by OpenTelemetry. | ||
| # Status is also automatically set to UNSET (OK) on success or ERROR on exception. | ||
| # self._end_span(span, attributes, error) | ||
|
|
||
| def start_tool_call_span( | ||
| self, | ||
|
|
@@ -493,7 +504,7 @@ def start_event_loop_cycle_span( | |
| parent_span: Optional[Span] = None, | ||
| custom_trace_attributes: Optional[Mapping[str, AttributeValue]] = None, | ||
| **kwargs: Any, | ||
| ) -> Optional[Span]: | ||
| ) -> Span: | ||
| """Start a new span for an event loop cycle. | ||
|
|
||
| Args: | ||
|
|
@@ -537,13 +548,21 @@ def end_event_loop_cycle_span( | |
| ) -> None: | ||
| """End an event loop cycle span with results. | ||
|
|
||
| Note: When using with trace_api.use_span(end_on_exit=True), the span will be automatically | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We're forcing callers to close this now, right? If so, document that instead of
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. OTEL will end the span automatically when exiting the function (regardless of success or exception being thrown). Previously we ended the span and recorded the exception by ourselves in our tracer setup in the |
||
| closed and exceptions recorded. This method just sets the necessary attributes. | ||
|
|
||
| Args: | ||
| span: The span to end. | ||
| span: The span to set attributes on. | ||
| message: The message response from this cycle. | ||
| tool_result_message: Optional tool result message if a tool was called. | ||
| error: Optional exception if the cycle failed. | ||
| error: Optional exception if the cycle failed (not used when end_on_exit=True). | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. When is
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll remove this! It should be always True. |
||
| """ | ||
| attributes: Dict[str, AttributeValue] = {} | ||
| if not span: | ||
| return | ||
|
|
||
| # Set end time attribute | ||
| span.set_attribute("gen_ai.event.end_time", datetime.now(timezone.utc).isoformat()) | ||
|
|
||
| event_attributes: Dict[str, AttributeValue] = {"message": serialize(message["content"])} | ||
|
|
||
| if tool_result_message: | ||
|
|
@@ -566,7 +585,11 @@ def end_event_loop_cycle_span( | |
| ) | ||
| else: | ||
| self._add_event(span, "gen_ai.choice", event_attributes=event_attributes) | ||
| self._end_span(span, attributes, error) | ||
|
|
||
| # Note: self._end_span() is commented out because when using trace_api.use_span(end_on_exit=True), | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Callers have no control over this; we can leave an explaining comment saying "We don't use self._end_span() because callers are responsible via closing" But don't leave this commented out, just remove it |
||
| # the span is automatically closed and exceptions are automatically recorded by OpenTelemetry. | ||
| # Status is also automatically set to UNSET (OK) on success or ERROR on exception. | ||
| # self._end_span(span, attributes, error) | ||
|
|
||
| def start_agent_span( | ||
| self, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -246,8 +246,6 @@ def test_end_model_invoke_span(mock_span): | |
| "gen_ai.choice", | ||
| attributes={"message": json.dumps(message["content"]), "finish_reason": "end_turn"}, | ||
| ) | ||
| mock_span.set_status.assert_called_once_with(StatusCode.OK) | ||
| mock_span.end.assert_called_once() | ||
|
|
||
|
|
||
| def test_end_model_invoke_span_latest_conventions(mock_span, monkeypatch): | ||
|
|
@@ -284,9 +282,6 @@ def test_end_model_invoke_span_latest_conventions(mock_span, monkeypatch): | |
| }, | ||
| ) | ||
|
|
||
| mock_span.set_status.assert_called_once_with(StatusCode.OK) | ||
| mock_span.end.assert_called_once() | ||
|
|
||
|
|
||
| def test_start_tool_call_span(mock_tracer): | ||
| """Test starting a tool call span.""" | ||
|
|
@@ -650,8 +645,6 @@ def test_end_event_loop_cycle_span(mock_span): | |
| "tool.result": json.dumps(tool_result_message["content"]), | ||
| }, | ||
| ) | ||
| mock_span.set_status.assert_called_once_with(StatusCode.OK) | ||
| mock_span.end.assert_called_once() | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we be asserting that it was closed correctly?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. it is not closed in our tracer anymore, but I can add validation in other places. |
||
|
|
||
|
|
||
| def test_end_event_loop_cycle_span_latest_conventions(mock_span, monkeypatch): | ||
|
|
@@ -687,8 +680,6 @@ def test_end_event_loop_cycle_span_latest_conventions(mock_span, monkeypatch): | |
| ) | ||
| }, | ||
| ) | ||
| mock_span.set_status.assert_called_once_with(StatusCode.OK) | ||
| mock_span.end.assert_called_once() | ||
|
|
||
|
|
||
| def test_start_agent_span(mock_tracer): | ||
|
|
@@ -860,8 +851,6 @@ def test_end_model_invoke_span_with_cache_metrics(mock_span): | |
| mock_span.set_attribute.assert_any_call("gen_ai.usage.cache_write_input_tokens", 3) | ||
| mock_span.set_attribute.assert_any_call("gen_ai.server.request.duration", 10) | ||
| mock_span.set_attribute.assert_any_call("gen_ai.server.time_to_first_token", 5) | ||
| mock_span.set_status.assert_called_once_with(StatusCode.OK) | ||
| mock_span.end.assert_called_once() | ||
|
|
||
|
|
||
| def test_end_agent_span_with_cache_metrics(mock_span): | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.