@@ -660,7 +660,7 @@ def _set_common_output_data(
660660 span .__exit__ (None , None , None )
661661
662662
663- def _new_chat_completion_common (f : "Any" , * args : "Any" , ** kwargs : "Any" ) -> "Any" :
663+ def _new_sync_chat_completion (f : "Any" , * args : "Any" , ** kwargs : "Any" ) -> "Any" :
664664 integration = sentry_sdk .get_client ().get_integration (OpenAIIntegration )
665665 if integration is None :
666666 return f (* args , ** kwargs )
@@ -693,7 +693,97 @@ def _new_chat_completion_common(f: "Any", *args: "Any", **kwargs: "Any") -> "Any
693693 _set_completions_api_input_data (span , kwargs , integration )
694694
695695 start_time = time .perf_counter ()
696- response = yield f , args , kwargs
696+
697+ try :
698+ response = f (* args , ** kwargs )
699+ except Exception as exc :
700+ exc_info = sys .exc_info ()
701+ with capture_internal_exceptions ():
702+ _capture_exception (exc )
703+ reraise (* exc_info )
704+
705+ # Attribute check to fail gracefully if the attribute is not present in future `openai` versions.
706+ if isinstance (response , Stream ) and hasattr (response , "_iterator" ):
707+ messages = kwargs .get ("messages" )
708+
709+ if messages is not None and isinstance (messages , str ):
710+ messages = [messages ]
711+
712+ response ._iterator = _wrap_synchronous_completions_chunk_iterator (
713+ span = span ,
714+ integration = integration ,
715+ start_time = start_time ,
716+ messages = messages ,
717+ response = response ,
718+ old_iterator = response ._iterator ,
719+ finish_span = True ,
720+ )
721+
722+ # Attribute check to fail gracefully if the attribute is not present in future `openai` versions.
723+ elif isinstance (response , AsyncStream ) and hasattr (response , "_iterator" ):
724+ messages = kwargs .get ("messages" )
725+
726+ if messages is not None and isinstance (messages , str ):
727+ messages = [messages ]
728+
729+ response ._iterator = _wrap_asynchronous_completions_chunk_iterator (
730+ span = span ,
731+ integration = integration ,
732+ start_time = start_time ,
733+ messages = messages ,
734+ response = response ,
735+ old_iterator = response ._iterator ,
736+ finish_span = True ,
737+ )
738+ else :
739+ _set_completions_api_output_data (
740+ span , response , kwargs , integration , finish_span = True
741+ )
742+
743+ return response
744+
745+
746+ async def _new_async_chat_completion (f : "Any" , * args : "Any" , ** kwargs : "Any" ) -> "Any" :
747+ integration = sentry_sdk .get_client ().get_integration (OpenAIIntegration )
748+ if integration is None :
749+ return await f (* args , ** kwargs )
750+
751+ if "messages" not in kwargs :
752+ # invalid call (in all versions of openai), let it return error
753+ return await f (* args , ** kwargs )
754+
755+ try :
756+ iter (kwargs ["messages" ])
757+ except TypeError :
758+ # invalid call (in all versions), messages must be iterable
759+ return await f (* args , ** kwargs )
760+
761+ model = kwargs .get ("model" )
762+
763+ span = sentry_sdk .start_span (
764+ op = consts .OP .GEN_AI_CHAT ,
765+ name = f"chat { model } " ,
766+ origin = OpenAIIntegration .origin ,
767+ )
768+ span .__enter__ ()
769+
770+ span .set_data (SPANDATA .GEN_AI_SYSTEM , "openai" )
771+
772+ # Same bool handling as in https://github.com/openai/openai-python/blob/acd0c54d8a68efeedde0e5b4e6c310eef1ce7867/src/openai/resources/completions.py#L585
773+ is_streaming_response = kwargs .get ("stream" , False ) or False
774+ span .set_data (SPANDATA .GEN_AI_RESPONSE_STREAMING , is_streaming_response )
775+
776+ _set_completions_api_input_data (span , kwargs , integration )
777+
778+ start_time = time .perf_counter ()
779+
780+ try :
781+ response = await f (* args , ** kwargs )
782+ except Exception as exc :
783+ exc_info = sys .exc_info ()
784+ with capture_internal_exceptions ():
785+ _capture_exception (exc )
786+ reraise (* exc_info )
697787
698788 # Attribute check to fail gracefully if the attribute is not present in future `openai` versions.
699789 if isinstance (response , Stream ) and hasattr (response , "_iterator" ):
@@ -1050,69 +1140,27 @@ def _set_embeddings_output_data(
10501140
10511141
10521142def _wrap_chat_completion_create (f : "Callable[..., Any]" ) -> "Callable[..., Any]" :
1053- def _execute_sync (f : "Any" , * args : "Any" , ** kwargs : "Any" ) -> "Any" :
1054- gen = _new_chat_completion_common (f , * args , ** kwargs )
1055-
1056- try :
1057- f , args , kwargs = next (gen )
1058- except StopIteration as e :
1059- return e .value
1060-
1061- try :
1062- try :
1063- result = f (* args , ** kwargs )
1064- except Exception as e :
1065- exc_info = sys .exc_info ()
1066- with capture_internal_exceptions ():
1067- _capture_exception (e )
1068- reraise (* exc_info )
1069-
1070- return gen .send (result )
1071- except StopIteration as e :
1072- return e .value
1073-
10741143 @wraps (f )
10751144 def _sentry_patched_create_sync (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
10761145 integration = sentry_sdk .get_client ().get_integration (OpenAIIntegration )
10771146 if integration is None or "messages" not in kwargs :
10781147 # no "messages" means invalid call (in all versions of openai), let it return error
10791148 return f (* args , ** kwargs )
10801149
1081- return _execute_sync (f , * args , ** kwargs )
1150+ return _new_sync_chat_completion (f , * args , ** kwargs )
10821151
10831152 return _sentry_patched_create_sync
10841153
10851154
10861155def _wrap_async_chat_completion_create (f : "Callable[..., Any]" ) -> "Callable[..., Any]" :
1087- async def _execute_async (f : "Any" , * args : "Any" , ** kwargs : "Any" ) -> "Any" :
1088- gen = _new_chat_completion_common (f , * args , ** kwargs )
1089-
1090- try :
1091- f , args , kwargs = next (gen )
1092- except StopIteration as e :
1093- return await e .value
1094-
1095- try :
1096- try :
1097- result = await f (* args , ** kwargs )
1098- except Exception as e :
1099- exc_info = sys .exc_info ()
1100- with capture_internal_exceptions ():
1101- _capture_exception (e )
1102- reraise (* exc_info )
1103-
1104- return gen .send (result )
1105- except StopIteration as e :
1106- return e .value
1107-
11081156 @wraps (f )
11091157 async def _sentry_patched_create_async (* args : "Any" , ** kwargs : "Any" ) -> "Any" :
11101158 integration = sentry_sdk .get_client ().get_integration (OpenAIIntegration )
11111159 if integration is None or "messages" not in kwargs :
11121160 # no "messages" means invalid call (in all versions of openai), let it return error
11131161 return await f (* args , ** kwargs )
11141162
1115- return await _execute_async (f , * args , ** kwargs )
1163+ return await _new_async_chat_completion (f , * args , ** kwargs )
11161164
11171165 return _sentry_patched_create_async
11181166
0 commit comments