1
- from __future__ import absolute_import
2
-
1
+ from sentry_sdk import consts
3
2
from sentry_sdk ._types import TYPE_CHECKING
4
3
5
4
if TYPE_CHECKING :
6
5
from typing import Any , Iterable , List , Optional , Callable , Iterator
7
6
from sentry_sdk .tracing import Span
8
7
8
+ import sentry_sdk
9
9
from sentry_sdk ._functools import wraps
10
10
from sentry_sdk .hub import Hub
11
11
from sentry_sdk .integrations import DidNotEnable , Integration
12
- from sentry_sdk .utils import logger , capture_internal_exceptions
12
+ from sentry_sdk .utils import logger , capture_internal_exceptions , event_from_exception
13
13
14
14
try :
15
15
from openai .resources .chat .completions import Completions
@@ -42,9 +42,9 @@ def count_tokens(s):
42
42
return 0
43
43
44
44
45
- COMPLETION_TOKENS = "completion_tоkens"
46
- PROMPT_TOKENS = "prompt_tоkens"
47
- TOTAL_TOKENS = "total_tоkens"
45
+ COMPLETION_TOKENS_USED = "ai. completion_tоkens.used "
46
+ PROMPT_TOKENS_USED = "ai. prompt_tоkens.used "
47
+ TOTAL_TOKENS_USED = "ai. total_tоkens.used "
48
48
49
49
50
50
class OpenAIIntegration (Integration ):
@@ -54,7 +54,19 @@ class OpenAIIntegration(Integration):
54
54
def setup_once ():
55
55
# type: () -> None
56
56
Completions .create = _wrap_chat_completion_create (Completions .create )
57
- Embeddings .create = _wrap_enbeddings_create (Embeddings .create )
57
+ Embeddings .create = _wrap_embeddings_create (Embeddings .create )
58
+
59
+
60
+ def _capture_exception (hub , exc ):
61
+ # type: (Hub, Any) -> None
62
+
63
+ if hub .client is not None :
64
+ event , hint = event_from_exception (
65
+ exc ,
66
+ client_options = hub .client .options ,
67
+ mechanism = {"type" : "openai" , "handled" : False },
68
+ )
69
+ hub .capture_event (event , hint = hint )
58
70
59
71
60
72
def _calculate_chat_completion_usage (
@@ -98,23 +110,18 @@ def _calculate_chat_completion_usage(
98
110
total_tokens = prompt_tokens + completion_tokens
99
111
100
112
if completion_tokens != 0 :
101
- span .set_data (COMPLETION_TOKENS , completion_tokens )
113
+ span .set_data (COMPLETION_TOKENS_USED , completion_tokens )
102
114
if prompt_tokens != 0 :
103
- span .set_data (PROMPT_TOKENS , prompt_tokens )
115
+ span .set_data (PROMPT_TOKENS_USED , prompt_tokens )
104
116
if total_tokens != 0 :
105
- span .set_data (TOTAL_TOKENS , total_tokens )
117
+ span .set_data (TOTAL_TOKENS_USED , total_tokens )
106
118
107
119
108
120
def _wrap_chat_completion_create (f ):
109
121
# type: (Callable[..., Any]) -> Callable[..., Any]
110
122
@wraps (f )
111
123
def new_chat_completion (* args , ** kwargs ):
112
124
# type: (*Any, **Any) -> Any
113
- hub = Hub .current
114
- integration = hub .get_integration (OpenAIIntegration )
115
- if integration is None :
116
- return f (* args , ** kwargs )
117
-
118
125
if "messages" not in kwargs :
119
126
# invalid call (in all versions of openai), let it return error
120
127
return f (* args , ** kwargs )
@@ -130,13 +137,21 @@ def new_chat_completion(*args, **kwargs):
130
137
model = kwargs .get ("model" )
131
138
streaming = kwargs .get ("stream" )
132
139
133
- span = hub .start_span (op = "openai" , description = "Chat Completion" )
140
+ span = sentry_sdk .start_span (
141
+ op = consts .OP .OPENAI_CHAT_COMPLETIONS_CREATE , description = "Chat Completion"
142
+ )
134
143
span .__enter__ ()
135
- res = f (* args , ** kwargs )
144
+ try :
145
+ res = f (* args , ** kwargs )
146
+ except Exception as e :
147
+ _capture_exception (Hub .current , e )
148
+ span .__exit__ (None , None , None )
149
+ raise e from None
150
+
136
151
with capture_internal_exceptions ():
137
152
span .set_data ("messages" , messages )
138
- span .set_tag ("model" , model )
139
- span .set_tag ("streaming" , streaming )
153
+ span .set_data ("model" , model )
154
+ span .set_data ("streaming" , streaming )
140
155
141
156
if hasattr (res , "choices" ):
142
157
span .set_data ("response" , res .choices [0 ].message )
@@ -175,32 +190,34 @@ def new_iterator():
175
190
176
191
res ._iterator = new_iterator ()
177
192
else :
178
- span .set_tag ("unknown_response" , True )
193
+ span .set_data ("unknown_response" , True )
179
194
span .__exit__ (None , None , None )
180
195
return res
181
196
182
197
return new_chat_completion
183
198
184
199
185
- def _wrap_enbeddings_create (f ):
200
+ def _wrap_embeddings_create (f ):
186
201
# type: (Callable[..., Any]) -> Callable[..., Any]
187
202
188
203
@wraps (f )
189
204
def new_embeddings_create (* args , ** kwargs ):
190
205
# type: (*Any, **Any) -> Any
191
- hub = Hub .current
192
- integration = hub .get_integration (OpenAIIntegration )
193
- if integration is None :
194
- return f (* args , ** kwargs )
195
-
196
- with hub .start_span (op = "openai" , description = "Embeddings Creation" ) as span :
206
+ with sentry_sdk .start_span (
207
+ op = consts .OP .OPENAI_EMBEDDINGS_CREATE ,
208
+ description = "OpenAI Embedding Creation" ,
209
+ ) as span :
197
210
if "input" in kwargs and isinstance (kwargs ["input" ], str ):
198
211
span .set_data ("input" , kwargs ["input" ])
199
212
if "model" in kwargs :
200
- span .set_tag ("model" , kwargs ["model" ])
213
+ span .set_data ("model" , kwargs ["model" ])
201
214
if "dimensions" in kwargs :
202
- span .set_tag ("dimensions" , kwargs ["dimensions" ])
203
- response = f (* args , ** kwargs )
215
+ span .set_data ("dimensions" , kwargs ["dimensions" ])
216
+ try :
217
+ response = f (* args , ** kwargs )
218
+ except Exception as e :
219
+ _capture_exception (Hub .current , e )
220
+ raise e from None
204
221
205
222
prompt_tokens = 0
206
223
total_tokens = 0
@@ -220,8 +237,8 @@ def new_embeddings_create(*args, **kwargs):
220
237
if total_tokens == 0 :
221
238
total_tokens = prompt_tokens
222
239
223
- span .set_data (PROMPT_TOKENS , prompt_tokens )
224
- span .set_data (TOTAL_TOKENS , total_tokens )
240
+ span .set_data (PROMPT_TOKENS_USED , prompt_tokens )
241
+ span .set_data (TOTAL_TOKENS_USED , total_tokens )
225
242
226
243
return response
227
244
0 commit comments