From 4917b6a6570908837461344f27348a86b955bfb3 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 18 Mar 2026 10:19:58 +0100 Subject: [PATCH 1/5] ref(openai): Move input handling code into API-specific functions --- sentry_sdk/integrations/openai.py | 135 ++++++++++++++++------- tests/integrations/openai/test_openai.py | 14 +++ 2 files changed, 110 insertions(+), 39 deletions(-) diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index a5556b8776..dfa3225d74 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -219,28 +219,13 @@ def _calculate_token_usage( ) -def _commmon_set_input_data( +def _set_responses_api_input_data( span: "Span", kwargs: "dict[str, Any]", + integration: "OpenAIIntegration", ) -> None: - # Input attributes: Common - set_data_normalized(span, SPANDATA.GEN_AI_SYSTEM, "openai") - - # Input attributes: Optional - kwargs_keys_to_attributes = { - "model": SPANDATA.GEN_AI_REQUEST_MODEL, - "stream": SPANDATA.GEN_AI_RESPONSE_STREAMING, - "max_tokens": SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, - "presence_penalty": SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, - "frequency_penalty": SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, - "temperature": SPANDATA.GEN_AI_REQUEST_TEMPERATURE, - "top_p": SPANDATA.GEN_AI_REQUEST_TOP_P, - } - for key, attribute in kwargs_keys_to_attributes.items(): - value = kwargs.get(key) - - if value is not None and _is_given(value): - set_data_normalized(span, attribute, value) + explicit_instructions: "Union[Optional[str], Omit]" = kwargs.get("instructions") + messages: "Optional[Union[str, ResponseInputParam]]" = kwargs.get("input") # Input attributes: Tools tools = kwargs.get("tools") @@ -249,18 +234,36 @@ def _commmon_set_input_data( span, SPANDATA.GEN_AI_REQUEST_AVAILABLE_TOOLS, safe_serialize(tools) ) + model = kwargs.get("model") + if model is not None and _is_given(model): + span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model) -def _set_responses_api_input_data( - span: "Span", - kwargs: "dict[str, Any]", - integration: "OpenAIIntegration", -) -> None: - explicit_instructions: "Union[Optional[str], Omit]" = kwargs.get("instructions") - messages: "Optional[Union[str, ResponseInputParam]]" = kwargs.get("input") + stream = kwargs.get("stream") + if stream is not None and _is_given(stream): + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + + max_tokens = kwargs.get("max_tokens") + if max_tokens is not None and _is_given(max_tokens): + span.set_data(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + + presence_penalty = kwargs.get("presence_penalty") + if presence_penalty is not None and _is_given(presence_penalty): + span.set_data(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + + frequency_penalty = kwargs.get("frequency_penalty") + if frequency_penalty is not None and _is_given(frequency_penalty): + span.set_data(SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty) + + temperature = kwargs.get("temperature") + if temperature is not None and _is_given(temperature): + span.set_data(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + + top_p = kwargs.get("top_p") + if top_p is not None and _is_given(top_p): + span.set_data(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) if not should_send_default_pii() or not integration.include_prompts: set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - _commmon_set_input_data(span, kwargs) return if ( @@ -281,12 +284,10 @@ def _set_responses_api_input_data( ) set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - _commmon_set_input_data(span, kwargs) return if messages is None: set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - _commmon_set_input_data(span, kwargs) return instructions_text_parts: "list[TextPart]" = [] @@ -319,7 +320,6 @@ def _set_responses_api_input_data( ) set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - _commmon_set_input_data(span, kwargs) return non_system_messages = [ @@ -335,7 +335,6 @@ def _set_responses_api_input_data( ) set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - _commmon_set_input_data(span, kwargs) def _set_completions_api_input_data( @@ -347,13 +346,47 @@ def _set_completions_api_input_data( "messages" ) + # Input attributes: Tools + tools = kwargs.get("tools") + if tools is not None and _is_given(tools) and len(tools) > 0: + set_data_normalized( + span, SPANDATA.GEN_AI_REQUEST_AVAILABLE_TOOLS, safe_serialize(tools) + ) + + model = kwargs.get("model") + if model is not None and _is_given(model): + span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model) + + stream = kwargs.get("stream") + if stream is not None and _is_given(stream): + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + + max_tokens = kwargs.get("max_tokens") + if max_tokens is not None and _is_given(max_tokens): + span.set_data(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + + presence_penalty = kwargs.get("presence_penalty") + if presence_penalty is not None and _is_given(presence_penalty): + span.set_data(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + + frequency_penalty = kwargs.get("frequency_penalty") + if frequency_penalty is not None and _is_given(frequency_penalty): + span.set_data(SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty) + + temperature = kwargs.get("temperature") + if temperature is not None and _is_given(temperature): + span.set_data(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + + top_p = kwargs.get("top_p") + if top_p is not None and _is_given(top_p): + span.set_data(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + if ( not should_send_default_pii() or not integration.include_prompts or messages is None ): set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "chat") - _commmon_set_input_data(span, kwargs) return if isinstance(messages, str): @@ -365,13 +398,11 @@ def _set_completions_api_input_data( span, SPANDATA.GEN_AI_REQUEST_MESSAGES, messages_data, unpack=False ) set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "chat") - _commmon_set_input_data(span, kwargs) return # dict special case following https://github.com/openai/openai-python/blob/3e0c05b84a2056870abf3bd6a5e7849020209cc3/src/openai/_utils/_transform.py#L194-L197 if not isinstance(messages, Iterable) or isinstance(messages, dict): set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "chat") - _commmon_set_input_data(span, kwargs) return messages = list(messages) @@ -399,7 +430,6 @@ def _set_completions_api_input_data( ) set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "chat") - _commmon_set_input_data(span, kwargs) def _set_embeddings_input_data( @@ -411,19 +441,45 @@ def _set_embeddings_input_data( "input" ) + model = kwargs.get("model") + if model is not None and _is_given(model): + span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model) + + stream = kwargs.get("stream") + if stream is not None and _is_given(stream): + span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + + max_tokens = kwargs.get("max_tokens") + if max_tokens is not None and _is_given(max_tokens): + span.set_data(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + + presence_penalty = kwargs.get("presence_penalty") + if presence_penalty is not None and _is_given(presence_penalty): + span.set_data(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + + frequency_penalty = kwargs.get("frequency_penalty") + if frequency_penalty is not None and _is_given(frequency_penalty): + span.set_data(SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty) + + temperature = kwargs.get("temperature") + if temperature is not None and _is_given(temperature): + span.set_data(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + + top_p = kwargs.get("top_p") + if top_p is not None and _is_given(top_p): + span.set_data(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + if ( not should_send_default_pii() or not integration.include_prompts or messages is None ): set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - _commmon_set_input_data(span, kwargs) return if isinstance(messages, str): set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - _commmon_set_input_data(span, kwargs) normalized_messages = normalize_message_roles([messages]) # type: ignore scope = sentry_sdk.get_current_scope() @@ -440,7 +496,6 @@ def _set_embeddings_input_data( # dict special case following https://github.com/openai/openai-python/blob/3e0c05b84a2056870abf3bd6a5e7849020209cc3/src/openai/_utils/_transform.py#L194-L197 if not isinstance(messages, Iterable) or isinstance(messages, dict): set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - _commmon_set_input_data(span, kwargs) return messages = list(messages) @@ -458,7 +513,6 @@ def _set_embeddings_input_data( ) set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "embeddings") - _commmon_set_input_data(span, kwargs) def _set_common_output_data( @@ -551,6 +605,7 @@ def _new_chat_completion_common(f: "Any", *args: "Any", **kwargs: "Any") -> "Any ) span.__enter__() + span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") _set_completions_api_input_data(span, kwargs, integration) start_time = time.perf_counter() @@ -945,6 +1000,7 @@ def _new_embeddings_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "A name=f"embeddings {model}", origin=OpenAIIntegration.origin, ) as span: + span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") _set_embeddings_input_data(span, kwargs, integration) response = yield f, args, kwargs @@ -1036,6 +1092,7 @@ def _new_responses_create_common(f: "Any", *args: "Any", **kwargs: "Any") -> "An ) span.__enter__() + span.set_data(SPANDATA.GEN_AI_SYSTEM, "openai") _set_responses_api_input_data(span, kwargs, integration) start_time = time.perf_counter() diff --git a/tests/integrations/openai/test_openai.py b/tests/integrations/openai/test_openai.py index 23fb0d9ad7..249a32b768 100644 --- a/tests/integrations/openai/test_openai.py +++ b/tests/integrations/openai/test_openai.py @@ -161,6 +161,7 @@ def test_nonstreaming_chat_completion_no_prompts( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS not in span["data"] assert SPANDATA.GEN_AI_REQUEST_MESSAGES not in span["data"] @@ -240,6 +241,7 @@ def test_nonstreaming_chat_completion(sentry_init, capture_events, messages, req assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" param_id = request.node.callspec.id if "blocks" in param_id: @@ -306,6 +308,7 @@ async def test_nonstreaming_chat_completion_async_no_prompts( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert SPANDATA.GEN_AI_SYSTEM_INSTRUCTIONS not in span["data"] assert SPANDATA.GEN_AI_REQUEST_MESSAGES not in span["data"] @@ -385,6 +388,7 @@ async def test_nonstreaming_chat_completion_async( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" param_id = request.node.callspec.id if "blocks" in param_id: @@ -503,6 +507,7 @@ def test_streaming_chat_completion_no_prompts( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert span["data"][SPANDATA.GEN_AI_RESPONSE_MODEL] == "model-id" @@ -630,6 +635,7 @@ def test_streaming_chat_completion(sentry_init, capture_events, messages, reques assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" param_id = request.node.callspec.id if "blocks" in param_id: @@ -758,6 +764,7 @@ async def test_streaming_chat_completion_async_no_prompts( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert span["data"][SPANDATA.GEN_AI_RESPONSE_MODEL] == "model-id" @@ -895,6 +902,7 @@ async def test_streaming_chat_completion_async( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.chat" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert span["data"][SPANDATA.GEN_AI_RESPONSE_MODEL] == "model-id" @@ -1036,6 +1044,7 @@ def test_embeddings_create_no_pii( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.embeddings" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert SPANDATA.GEN_AI_EMBEDDINGS_INPUT not in span["data"] @@ -1116,6 +1125,7 @@ def test_embeddings_create(sentry_init, capture_events, input, request): assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.embeddings" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" param_id = request.node.callspec.id if param_id == "string": @@ -1187,6 +1197,7 @@ async def test_embeddings_create_async_no_pii( assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.embeddings" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert SPANDATA.GEN_AI_EMBEDDINGS_INPUT not in span["data"] @@ -1270,6 +1281,7 @@ async def test_embeddings_create_async(sentry_init, capture_events, input, reque assert tx["type"] == "transaction" span = tx["spans"][0] assert span["op"] == "gen_ai.embeddings" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" param_id = request.node.callspec.id if param_id == "string": @@ -2772,6 +2784,7 @@ def test_streaming_responses_api( (transaction,) = events (span,) = transaction["spans"] assert span["op"] == "gen_ai.responses" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert span["data"][SPANDATA.GEN_AI_RESPONSE_MODEL] == "response-model-id" @@ -2829,6 +2842,7 @@ async def test_streaming_responses_api_async( (transaction,) = events (span,) = transaction["spans"] assert span["op"] == "gen_ai.responses" + assert span["data"][SPANDATA.GEN_AI_SYSTEM] == "openai" assert span["data"][SPANDATA.GEN_AI_RESPONSE_MODEL] == "response-model-id" From 426154603849122896f939a82a90d3c6022a7dca Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 18 Mar 2026 10:38:23 +0100 Subject: [PATCH 2/5] keep set_data_normalized --- sentry_sdk/integrations/openai.py | 48 +++++++++++++++++-------------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index dfa3225d74..c79d5d5a43 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -236,31 +236,33 @@ def _set_responses_api_input_data( model = kwargs.get("model") if model is not None and _is_given(model): - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_MODEL, model) stream = kwargs.get("stream") if stream is not None and _is_given(stream): - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + set_data_normalized(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) max_tokens = kwargs.get("max_tokens") if max_tokens is not None and _is_given(max_tokens): - span.set_data(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) presence_penalty = kwargs.get("presence_penalty") if presence_penalty is not None and _is_given(presence_penalty): - span.set_data(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) frequency_penalty = kwargs.get("frequency_penalty") if frequency_penalty is not None and _is_given(frequency_penalty): - span.set_data(SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty) + set_data_normalized( + SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty + ) temperature = kwargs.get("temperature") if temperature is not None and _is_given(temperature): - span.set_data(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) top_p = kwargs.get("top_p") if top_p is not None and _is_given(top_p): - span.set_data(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) if not should_send_default_pii() or not integration.include_prompts: set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") @@ -355,31 +357,33 @@ def _set_completions_api_input_data( model = kwargs.get("model") if model is not None and _is_given(model): - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_MODEL, model) stream = kwargs.get("stream") if stream is not None and _is_given(stream): - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + set_data_normalized(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) max_tokens = kwargs.get("max_tokens") if max_tokens is not None and _is_given(max_tokens): - span.set_data(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) presence_penalty = kwargs.get("presence_penalty") if presence_penalty is not None and _is_given(presence_penalty): - span.set_data(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) frequency_penalty = kwargs.get("frequency_penalty") if frequency_penalty is not None and _is_given(frequency_penalty): - span.set_data(SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty) + set_data_normalized( + SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty + ) temperature = kwargs.get("temperature") if temperature is not None and _is_given(temperature): - span.set_data(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) top_p = kwargs.get("top_p") if top_p is not None and _is_given(top_p): - span.set_data(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) if ( not should_send_default_pii() @@ -443,31 +447,33 @@ def _set_embeddings_input_data( model = kwargs.get("model") if model is not None and _is_given(model): - span.set_data(SPANDATA.GEN_AI_REQUEST_MODEL, model) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_MODEL, model) stream = kwargs.get("stream") if stream is not None and _is_given(stream): - span.set_data(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + set_data_normalized(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) max_tokens = kwargs.get("max_tokens") if max_tokens is not None and _is_given(max_tokens): - span.set_data(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) presence_penalty = kwargs.get("presence_penalty") if presence_penalty is not None and _is_given(presence_penalty): - span.set_data(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) frequency_penalty = kwargs.get("frequency_penalty") if frequency_penalty is not None and _is_given(frequency_penalty): - span.set_data(SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty) + set_data_normalized( + SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty + ) temperature = kwargs.get("temperature") if temperature is not None and _is_given(temperature): - span.set_data(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) top_p = kwargs.get("top_p") if top_p is not None and _is_given(top_p): - span.set_data(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + set_data_normalized(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) if ( not should_send_default_pii() From 1f6149e0fa2e878fac06c2edb23305c022557935 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 18 Mar 2026 10:59:09 +0100 Subject: [PATCH 3/5] . --- sentry_sdk/integrations/openai.py | 56 +++++++++++++++++++------------ 1 file changed, 35 insertions(+), 21 deletions(-) diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index c79d5d5a43..59590abcce 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -236,33 +236,35 @@ def _set_responses_api_input_data( model = kwargs.get("model") if model is not None and _is_given(model): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_MODEL, model) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MODEL, model) stream = kwargs.get("stream") if stream is not None and _is_given(stream): - set_data_normalized(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) max_tokens = kwargs.get("max_tokens") if max_tokens is not None and _is_given(max_tokens): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) presence_penalty = kwargs.get("presence_penalty") if presence_penalty is not None and _is_given(presence_penalty): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + set_data_normalized( + span, SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty + ) frequency_penalty = kwargs.get("frequency_penalty") if frequency_penalty is not None and _is_given(frequency_penalty): set_data_normalized( - SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty + span, SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty ) temperature = kwargs.get("temperature") if temperature is not None and _is_given(temperature): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) top_p = kwargs.get("top_p") if top_p is not None and _is_given(top_p): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) if not should_send_default_pii() or not integration.include_prompts: set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") @@ -357,33 +359,39 @@ def _set_completions_api_input_data( model = kwargs.get("model") if model is not None and _is_given(model): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_MODEL, model) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MODEL, model) stream = kwargs.get("stream") if stream is not None and _is_given(stream): - set_data_normalized(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) max_tokens = kwargs.get("max_tokens") if max_tokens is not None and _is_given(max_tokens): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) presence_penalty = kwargs.get("presence_penalty") if presence_penalty is not None and _is_given(presence_penalty): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + set_data_normalized( + span, SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty + ) frequency_penalty = kwargs.get("frequency_penalty") if frequency_penalty is not None and _is_given(frequency_penalty): set_data_normalized( - SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty + span, SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty ) temperature = kwargs.get("temperature") if temperature is not None and _is_given(temperature): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) top_p = kwargs.get("top_p") if top_p is not None and _is_given(top_p): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + + if not should_send_default_pii() or not integration.include_prompts: + set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") + return if ( not should_send_default_pii() @@ -447,33 +455,39 @@ def _set_embeddings_input_data( model = kwargs.get("model") if model is not None and _is_given(model): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_MODEL, model) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MODEL, model) stream = kwargs.get("stream") if stream is not None and _is_given(stream): - set_data_normalized(SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) + set_data_normalized(span, SPANDATA.GEN_AI_RESPONSE_STREAMING, stream) max_tokens = kwargs.get("max_tokens") if max_tokens is not None and _is_given(max_tokens): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MAX_TOKENS, max_tokens) presence_penalty = kwargs.get("presence_penalty") if presence_penalty is not None and _is_given(presence_penalty): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty) + set_data_normalized( + span, SPANDATA.GEN_AI_REQUEST_PRESENCE_PENALTY, presence_penalty + ) frequency_penalty = kwargs.get("frequency_penalty") if frequency_penalty is not None and _is_given(frequency_penalty): set_data_normalized( - SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty + span, SPANDATA.GEN_AI_REQUEST_FREQUENCY_PENALTY, frequency_penalty ) temperature = kwargs.get("temperature") if temperature is not None and _is_given(temperature): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TEMPERATURE, temperature) top_p = kwargs.get("top_p") if top_p is not None and _is_given(top_p): - set_data_normalized(SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) + + if not should_send_default_pii() or not integration.include_prompts: + set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") + return if ( not should_send_default_pii() From 36842e05c818b0ae526b66a6c3e2d63f5eaf344f Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 18 Mar 2026 11:03:57 +0100 Subject: [PATCH 4/5] . --- sentry_sdk/integrations/openai.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index 59590abcce..a82c406ad7 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -389,10 +389,6 @@ def _set_completions_api_input_data( if top_p is not None and _is_given(top_p): set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) - if not should_send_default_pii() or not integration.include_prompts: - set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - return - if ( not should_send_default_pii() or not integration.include_prompts @@ -485,10 +481,6 @@ def _set_embeddings_input_data( if top_p is not None and _is_given(top_p): set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_TOP_P, top_p) - if not should_send_default_pii() or not integration.include_prompts: - set_data_normalized(span, SPANDATA.GEN_AI_OPERATION_NAME, "responses") - return - if ( not should_send_default_pii() or not integration.include_prompts From 532fa654306efe6272a454e73b8aa4c7b29a6350 Mon Sep 17 00:00:00 2001 From: Alexander Alderman Webb Date: Wed, 18 Mar 2026 11:25:30 +0100 Subject: [PATCH 5/5] . --- sentry_sdk/integrations/openai.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sentry_sdk/integrations/openai.py b/sentry_sdk/integrations/openai.py index a82c406ad7..f47cd46384 100644 --- a/sentry_sdk/integrations/openai.py +++ b/sentry_sdk/integrations/openai.py @@ -227,7 +227,6 @@ def _set_responses_api_input_data( explicit_instructions: "Union[Optional[str], Omit]" = kwargs.get("instructions") messages: "Optional[Union[str, ResponseInputParam]]" = kwargs.get("input") - # Input attributes: Tools tools = kwargs.get("tools") if tools is not None and _is_given(tools) and len(tools) > 0: set_data_normalized( @@ -350,7 +349,6 @@ def _set_completions_api_input_data( "messages" ) - # Input attributes: Tools tools = kwargs.get("tools") if tools is not None and _is_given(tools) and len(tools) > 0: set_data_normalized( @@ -449,6 +447,12 @@ def _set_embeddings_input_data( "input" ) + tools = kwargs.get("tools") + if tools is not None and _is_given(tools) and len(tools) > 0: + set_data_normalized( + span, SPANDATA.GEN_AI_REQUEST_AVAILABLE_TOOLS, safe_serialize(tools) + ) + model = kwargs.get("model") if model is not None and _is_given(model): set_data_normalized(span, SPANDATA.GEN_AI_REQUEST_MODEL, model)