8181 "method" : "stream" ,
8282 "span_name" : "anthropic.chat" ,
8383 },
84- # # Beta API methods (regular Anthropic SDK)
85- # {
86- # "package": "anthropic.resources.beta.messages.messages",
87- # "object": "Messages",
88- # "method": "create",
89- # "span_name": "anthropic.chat",
90- # },
91- # {
92- # "package": "anthropic.resources.beta.messages.messages",
93- # "object": "Messages",
94- # "method": "stream",
95- # "span_name": "anthropic.chat",
96- # },
97- # # Beta API methods (Bedrock SDK)
98- # {
99- # "package": "anthropic.lib.bedrock._beta_messages",
100- # "object": "Messages",
101- # "method": "create",
102- # "span_name": "anthropic.chat",
103- # },
104- # {
105- # "package": "anthropic.lib.bedrock._beta_messages",
106- # "object": "Messages",
107- # "method": "stream",
108- # "span_name": "anthropic.chat",
109- # },
84+ # Beta API methods (regular Anthropic SDK)
85+ {
86+ "package" : "anthropic.resources.beta.messages.messages" ,
87+ "object" : "Messages" ,
88+ "method" : "create" ,
89+ "span_name" : "anthropic.chat" ,
90+ },
91+ {
92+ "package" : "anthropic.resources.beta.messages.messages" ,
93+ "object" : "Messages" ,
94+ "method" : "stream" ,
95+ "span_name" : "anthropic.chat" ,
96+ },
97+ # Beta API methods (Bedrock SDK)
98+ {
99+ "package" : "anthropic.lib.bedrock._beta_messages" ,
100+ "object" : "Messages" ,
101+ "method" : "create" ,
102+ "span_name" : "anthropic.chat" ,
103+ },
104+ {
105+ "package" : "anthropic.lib.bedrock._beta_messages" ,
106+ "object" : "Messages" ,
107+ "method" : "stream" ,
108+ "span_name" : "anthropic.chat" ,
109+ },
110110]
111111
112112WRAPPED_AMETHODS = [
122122 "method" : "create" ,
123123 "span_name" : "anthropic.chat" ,
124124 },
125- # # Beta API async methods (regular Anthropic SDK)
126- # {
127- # "package": "anthropic.resources.beta.messages.messages",
128- # "object": "AsyncMessages",
129- # "method": "create",
130- # "span_name": "anthropic.chat",
131- # },
132- # {
133- # "package": "anthropic.resources.beta.messages.messages",
134- # "object": "AsyncMessages",
135- # "method": "stream",
136- # "span_name": "anthropic.chat",
137- # },
138- # # Beta API async methods (Bedrock SDK)
139- # {
140- # "package": "anthropic.lib.bedrock._beta_messages",
141- # "object": "AsyncMessages",
142- # "method": "create",
143- # "span_name": "anthropic.chat",
144- # },
145- # {
146- # "package": "anthropic.lib.bedrock._beta_messages",
147- # "object": "AsyncMessages",
148- # "method": "stream",
149- # "span_name": "anthropic.chat",
150- # },
125+ # Beta API async methods (regular Anthropic SDK)
126+ {
127+ "package" : "anthropic.resources.beta.messages.messages" ,
128+ "object" : "AsyncMessages" ,
129+ "method" : "create" ,
130+ "span_name" : "anthropic.chat" ,
131+ },
132+ {
133+ "package" : "anthropic.resources.beta.messages.messages" ,
134+ "object" : "AsyncMessages" ,
135+ "method" : "stream" ,
136+ "span_name" : "anthropic.chat" ,
137+ },
138+ # Beta API async methods (Bedrock SDK)
139+ {
140+ "package" : "anthropic.lib.bedrock._beta_messages" ,
141+ "object" : "AsyncMessages" ,
142+ "method" : "create" ,
143+ "span_name" : "anthropic.chat" ,
144+ },
145+ {
146+ "package" : "anthropic.lib.bedrock._beta_messages" ,
147+ "object" : "AsyncMessages" ,
148+ "method" : "stream" ,
149+ "span_name" : "anthropic.chat" ,
150+ },
151151]
152152
153153
@@ -182,14 +182,35 @@ async def _aset_token_usage(
182182 token_histogram : Histogram = None ,
183183 choice_counter : Counter = None ,
184184):
185- from opentelemetry .instrumentation .anthropic .utils import _aextract_response_data
185+ import inspect
186+
187+ # If we get a coroutine, await it
188+ if inspect .iscoroutine (response ):
189+ try :
190+ response = await response
191+ except Exception as e :
192+ import logging
193+ logger = logging .getLogger (__name__ )
194+ logger .debug (f"Failed to await coroutine response: { e } " )
195+ return
196+
197+ # Handle with_raw_response wrapped responses first
198+ if response and hasattr (response , "parse" ) and callable (response .parse ):
199+ try :
200+ response = response .parse ()
201+ except Exception as e :
202+ import logging
203+ logger = logging .getLogger (__name__ )
204+ logger .debug (f"Failed to parse with_raw_response: { e } " )
205+ return
186206
187- response = await _aextract_response_data (response )
207+ # Safely get usage attribute without extracting the whole object
208+ usage = getattr (response , "usage" , None ) if response else None
188209
189- if usage := response . get ( "usage" ) :
190- prompt_tokens = usage . input_tokens
191- cache_read_tokens = dict (usage ). get ( "cache_read_input_tokens" , 0 ) or 0
192- cache_creation_tokens = dict (usage ). get ( "cache_creation_input_tokens" , 0 ) or 0
210+ if usage :
211+ prompt_tokens = getattr ( usage , " input_tokens" , 0 )
212+ cache_read_tokens = getattr (usage , "cache_read_input_tokens" , 0 ) or 0
213+ cache_creation_tokens = getattr (usage , "cache_creation_input_tokens" , 0 ) or 0
193214 else :
194215 prompt_tokens = await acount_prompt_tokens_from_request (anthropic , request )
195216 cache_read_tokens = 0
@@ -206,18 +227,18 @@ async def _aset_token_usage(
206227 },
207228 )
208229
209- if usage := response . get ( "usage" ) :
210- completion_tokens = usage . output_tokens
230+ if usage :
231+ completion_tokens = getattr ( usage , " output_tokens" , 0 )
211232 else :
212233 completion_tokens = 0
213234 if hasattr (anthropic , "count_tokens" ):
214- if response .get ("completion" ):
235+ completion_attr = getattr (response , "completion" , None )
236+ content_attr = getattr (response , "content" , None )
237+ if completion_attr :
238+ completion_tokens = await anthropic .count_tokens (completion_attr )
239+ elif content_attr and len (content_attr ) > 0 :
215240 completion_tokens = await anthropic .count_tokens (
216- response .get ("completion" )
217- )
218- elif response .get ("content" ):
219- completion_tokens = await anthropic .count_tokens (
220- response .get ("content" )[0 ].text
241+ content_attr [0 ].text
221242 )
222243
223244 if (
@@ -236,17 +257,19 @@ async def _aset_token_usage(
236257 total_tokens = input_tokens + completion_tokens
237258
238259 choices = 0
239- if isinstance (response .get ("content" ), list ):
240- choices = len (response .get ("content" ))
241- elif response .get ("completion" ):
260+ content_attr = getattr (response , "content" , None )
261+ completion_attr = getattr (response , "completion" , None )
262+ if isinstance (content_attr , list ):
263+ choices = len (content_attr )
264+ elif completion_attr :
242265 choices = 1
243266
244267 if choices > 0 and choice_counter :
245268 choice_counter .add (
246269 choices ,
247270 attributes = {
248271 ** metric_attributes ,
249- SpanAttributes .LLM_RESPONSE_STOP_REASON : response . get ( "stop_reason" ),
272+ SpanAttributes .LLM_RESPONSE_STOP_REASON : getattr ( response , "stop_reason" , None ),
250273 },
251274 )
252275
@@ -276,14 +299,32 @@ def _set_token_usage(
276299 token_histogram : Histogram = None ,
277300 choice_counter : Counter = None ,
278301):
279- from opentelemetry .instrumentation .anthropic .utils import _extract_response_data
302+ import inspect
303+
304+ # If we get a coroutine, we cannot process it in sync context
305+ if inspect .iscoroutine (response ):
306+ import logging
307+ logger = logging .getLogger (__name__ )
308+ logger .warning (f"_set_token_usage received coroutine { response } - token usage processing skipped" )
309+ return
310+
311+ # Handle with_raw_response wrapped responses first
312+ if response and hasattr (response , "parse" ) and callable (response .parse ):
313+ try :
314+ response = response .parse ()
315+ except Exception as e :
316+ import logging
317+ logger = logging .getLogger (__name__ )
318+ logger .debug (f"Failed to parse with_raw_response: { e } " )
319+ return
280320
281- response = _extract_response_data (response )
321+ # Safely get usage attribute without extracting the whole object
322+ usage = getattr (response , "usage" , None ) if response else None
282323
283- if usage := response . get ( "usage" ) :
284- prompt_tokens = usage . input_tokens
285- cache_read_tokens = dict (usage ). get ( "cache_read_input_tokens" , 0 ) or 0
286- cache_creation_tokens = dict (usage ). get ( "cache_creation_input_tokens" , 0 ) or 0
324+ if usage :
325+ prompt_tokens = getattr ( usage , " input_tokens" , 0 )
326+ cache_read_tokens = getattr (usage , "cache_read_input_tokens" , 0 ) or 0
327+ cache_creation_tokens = getattr (usage , "cache_creation_input_tokens" , 0 ) or 0
287328 else :
288329 prompt_tokens = count_prompt_tokens_from_request (anthropic , request )
289330 cache_read_tokens = 0
@@ -300,16 +341,18 @@ def _set_token_usage(
300341 },
301342 )
302343
303- if usage := response . get ( "usage" ) :
304- completion_tokens = usage . output_tokens
344+ if usage :
345+ completion_tokens = getattr ( usage , " output_tokens" , 0 )
305346 else :
306347 completion_tokens = 0
307348 if hasattr (anthropic , "count_tokens" ):
308- if response .get ("completion" ):
309- completion_tokens = anthropic .count_tokens (response .get ("completion" ))
310- elif response .get ("content" ):
349+ completion_attr = getattr (response , "completion" , None )
350+ content_attr = getattr (response , "content" , None )
351+ if completion_attr :
352+ completion_tokens = anthropic .count_tokens (completion_attr )
353+ elif content_attr and len (content_attr ) > 0 :
311354 completion_tokens = anthropic .count_tokens (
312- response . get ( "content" ) [0 ].text
355+ content_attr [0 ].text
313356 )
314357
315358 if (
@@ -328,17 +371,19 @@ def _set_token_usage(
328371 total_tokens = input_tokens + completion_tokens
329372
330373 choices = 0
331- if isinstance (response .get ("content" ), list ):
332- choices = len (response .get ("content" ))
333- elif response .get ("completion" ):
374+ content_attr = getattr (response , "content" , None )
375+ completion_attr = getattr (response , "completion" , None )
376+ if isinstance (content_attr , list ):
377+ choices = len (content_attr )
378+ elif completion_attr :
334379 choices = 1
335380
336381 if choices > 0 and choice_counter :
337382 choice_counter .add (
338383 choices ,
339384 attributes = {
340385 ** metric_attributes ,
341- SpanAttributes .LLM_RESPONSE_STOP_REASON : response . get ( "stop_reason" ),
386+ SpanAttributes .LLM_RESPONSE_STOP_REASON : getattr ( response , "stop_reason" , None ),
342387 },
343388 )
344389
0 commit comments