33import time
44from collections .abc import Iterable
55from functools import wraps
6- from typing import TYPE_CHECKING
6+ from typing import TYPE_CHECKING , cast
77
88import sentry_sdk
99from sentry_sdk import consts
4242from sentry_sdk .utils import (
4343 capture_internal_exceptions ,
4444 event_from_exception ,
45+ has_data_collection_enabled ,
4546 reraise ,
4647 safe_serialize ,
4748)
@@ -324,18 +325,12 @@ def _set_responses_api_input_data(
324325 kwargs : "dict[str, Any]" ,
325326 integration : "OpenAIIntegration" ,
326327) -> None :
327- explicit_instructions : "Union[Optional[str], Omit]" = kwargs .get ("instructions" )
328- messages : "Optional[Union[str, ResponseInputParam]]" = kwargs .get ("input" )
329-
330- tools = kwargs .get ("tools" )
331- if tools is not None and _is_given (tools ) and len (tools ) > 0 :
332- set_data_normalized (
333- span , SPANDATA .GEN_AI_REQUEST_AVAILABLE_TOOLS , safe_serialize (tools )
334- )
335-
336328 set_on_span = (
337329 span .set_attribute if isinstance (span , StreamedSpan ) else span .set_data
338330 )
331+
332+ set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "responses" )
333+
339334 model = kwargs .get ("model" )
340335 if model is not None :
341336 set_on_span (SPANDATA .GEN_AI_REQUEST_MODEL , model )
@@ -369,54 +364,73 @@ def _set_responses_api_input_data(
369364 reasoning ["effort" ],
370365 )
371366
372- if not should_send_default_pii () or not integration .include_prompts :
373- set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "responses" )
374- return
375-
376- if (
377- messages is None
378- and explicit_instructions is not None
379- and _is_given (explicit_instructions )
380- ):
381- set_on_span (
382- SPANDATA .GEN_AI_SYSTEM_INSTRUCTIONS ,
383- json .dumps (
384- [
385- {
386- "type" : "text" ,
387- "content" : explicit_instructions ,
388- }
389- ]
390- ),
391- )
367+ client_options = sentry_sdk .get_client ().options
368+ if has_data_collection_enabled (client_options ):
369+ if client_options ["data_collection" ]["gen_ai" ]["inputs" ]:
370+ tools = kwargs .get ("tools" )
371+ if tools is not None and _is_given (tools ) and len (tools ) > 0 :
372+ set_data_normalized (
373+ span , SPANDATA .GEN_AI_REQUEST_AVAILABLE_TOOLS , safe_serialize (tools )
374+ )
375+ else :
376+ # Pre-data collection this was always set, so this needs to be left here for now until
377+ # we deprecate `send_default_pii`. Once we do, this 'else' branch should be removed,
378+ # and the above branch placed below the "if not should_send_default_pii() or not integration.include_prompts"
379+ # line below
380+ tools = kwargs .get ("tools" )
381+ if tools is not None and _is_given (tools ) and len (tools ) > 0 :
382+ set_data_normalized (
383+ span , SPANDATA .GEN_AI_REQUEST_AVAILABLE_TOOLS , safe_serialize (tools )
384+ )
392385
393- set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "responses" )
386+ if has_data_collection_enabled (client_options ):
387+ if not client_options ["data_collection" ]["gen_ai" ]["inputs" ]:
388+ return
389+ elif not should_send_default_pii () or not integration .include_prompts :
394390 return
395391
392+ explicit_instructions : "Union[Optional[str], Omit]" = kwargs .get ("instructions" )
393+ has_explicit_instructions = explicit_instructions is not None and _is_given (
394+ explicit_instructions
395+ )
396+ messages : "Optional[Union[str, ResponseInputParam]]" = kwargs .get ("input" )
397+ instructions_text_parts : "list[TextPart]" = []
398+
396399 if messages is None :
397- set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "responses" )
400+ if has_explicit_instructions :
401+ set_on_span (
402+ SPANDATA .GEN_AI_SYSTEM_INSTRUCTIONS ,
403+ json .dumps (
404+ [
405+ {
406+ "type" : "text" ,
407+ "content" : explicit_instructions ,
408+ }
409+ ]
410+ ),
411+ )
412+ # No messages to record (only instructions at most)
398413 return
399414
400- instructions_text_parts : "list[TextPart]" = []
401- if explicit_instructions is not None and _is_given (explicit_instructions ):
415+ if has_explicit_instructions :
402416 instructions_text_parts .append (
403417 {
404418 "type" : "text" ,
405- "content" : explicit_instructions ,
419+ "content" : cast ( str , explicit_instructions ) ,
406420 }
407421 )
408422
409423 system_instructions = _get_system_instructions_responses (messages )
410424 # Deliberate use of function accepting completions API type because
411425 # of shared structure FOR THIS PURPOSE ONLY.
412426 instructions_text_parts += _transform_system_instructions (system_instructions )
413-
414427 if len (instructions_text_parts ) > 0 :
415428 set_on_span (
416429 SPANDATA .GEN_AI_SYSTEM_INSTRUCTIONS ,
417430 json .dumps (instructions_text_parts ),
418431 )
419432
433+ # Input was provided as a single string
420434 if isinstance (messages , str ):
421435 normalized_messages = normalize_message_roles ([messages ]) # type: ignore
422436 client = sentry_sdk .get_client ()
@@ -430,10 +444,9 @@ def _set_responses_api_input_data(
430444 set_data_normalized (
431445 span , SPANDATA .GEN_AI_REQUEST_MESSAGES , messages_data , unpack = False
432446 )
433-
434- set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "responses" )
435447 return
436448
449+ # Input was provided as a list (potentially a multi-turn conversation)
437450 non_system_messages = [
438451 message for message in messages if not _is_system_instruction_responses (message )
439452 ]
@@ -451,8 +464,6 @@ def _set_responses_api_input_data(
451464 span , SPANDATA .GEN_AI_REQUEST_MESSAGES , messages_data , unpack = False
452465 )
453466
454- set_data_normalized (span , SPANDATA .GEN_AI_OPERATION_NAME , "responses" )
455-
456467
457468def _set_completions_api_input_data (
458469 span : "Union[Span, StreamedSpan]" ,
0 commit comments