@@ -216,6 +216,10 @@ async def test_first_failed_instrumented_stream(capfire: CaptureLogfire) -> None
216
216
'agent_name' : 'agent' ,
217
217
'logfire.msg' : 'agent run' ,
218
218
'logfire.span_type' : 'span' ,
219
+ 'gen_ai.usage.input_tokens' : 50 ,
220
+ 'gen_ai.usage.output_tokens' : 2 ,
221
+ 'all_messages_events' : '[{"content": "input", "role": "user", "gen_ai.message.index": 0, "event.name": "gen_ai.user.message"}, {"role": "assistant", "content": "hello world", "gen_ai.message.index": 1, "event.name": "gen_ai.assistant.message"}]' ,
222
+ 'logfire.json_schema' : '{"type": "object", "properties": {"all_messages_events": {"type": "array"}, "final_result": {"type": "object"}}}' ,
219
223
},
220
224
},
221
225
]
@@ -236,6 +240,82 @@ def test_all_failed() -> None:
236
240
assert exceptions [0 ].body == {'error' : 'test error' }
237
241
238
242
243
+ @pytest .mark .skipif (not logfire_imports_successful (), reason = 'logfire not installed' )
244
+ def test_all_failed_instrumented (capfire : CaptureLogfire ) -> None :
245
+ fallback_model = FallbackModel (failure_model , failure_model )
246
+ agent = Agent (model = fallback_model , instrument = True )
247
+ with pytest .raises (ExceptionGroup ) as exc_info :
248
+ agent .run_sync ('hello' )
249
+ assert 'All models from FallbackModel failed' in exc_info .value .args [0 ]
250
+ exceptions = exc_info .value .exceptions
251
+ assert len (exceptions ) == 2
252
+ assert isinstance (exceptions [0 ], ModelHTTPError )
253
+ assert exceptions [0 ].status_code == 500
254
+ assert exceptions [0 ].model_name == 'test-function-model'
255
+ assert exceptions [0 ].body == {'error' : 'test error' }
256
+ assert capfire .exporter .exported_spans_as_dict () == snapshot (
257
+ [
258
+ {
259
+ 'name' : 'chat fallback:function:failure_response:,function:failure_response:' ,
260
+ 'context' : {'trace_id' : 1 , 'span_id' : 3 , 'is_remote' : False },
261
+ 'parent' : {'trace_id' : 1 , 'span_id' : 1 , 'is_remote' : False },
262
+ 'start_time' : 2000000000 ,
263
+ 'end_time' : 4000000000 ,
264
+ 'attributes' : {
265
+ 'gen_ai.operation.name' : 'chat' ,
266
+ 'gen_ai.system' : 'fallback:function,function' ,
267
+ 'gen_ai.request.model' : 'fallback:function:failure_response:,function:failure_response:' ,
268
+ 'model_request_parameters' : '{"function_tools": [], "allow_text_output": true, "output_tools": []}' ,
269
+ 'logfire.json_schema' : '{"type": "object", "properties": {"model_request_parameters": {"type": "object"}}}' ,
270
+ 'logfire.span_type' : 'span' ,
271
+ 'logfire.msg' : 'chat fallback:function:failure_response:,function:failure_response:' ,
272
+ 'logfire.level_num' : 17 ,
273
+ },
274
+ 'events' : [
275
+ {
276
+ 'name' : 'exception' ,
277
+ 'timestamp' : 3000000000 ,
278
+ 'attributes' : {
279
+ 'exception.type' : 'pydantic_ai.exceptions.FallbackExceptionGroup' ,
280
+ 'exception.message' : 'All models from FallbackModel failed (2 sub-exceptions)' ,
281
+ 'exception.stacktrace' : '+------------------------------------' ,
282
+ 'exception.escaped' : 'False' ,
283
+ },
284
+ }
285
+ ],
286
+ },
287
+ {
288
+ 'name' : 'agent run' ,
289
+ 'context' : {'trace_id' : 1 , 'span_id' : 1 , 'is_remote' : False },
290
+ 'parent' : None ,
291
+ 'start_time' : 1000000000 ,
292
+ 'end_time' : 6000000000 ,
293
+ 'attributes' : {
294
+ 'model_name' : 'fallback:function:failure_response:,function:failure_response:' ,
295
+ 'agent_name' : 'agent' ,
296
+ 'logfire.msg' : 'agent run' ,
297
+ 'logfire.span_type' : 'span' ,
298
+ 'all_messages_events' : '[{"content": "hello", "role": "user", "gen_ai.message.index": 0, "event.name": "gen_ai.user.message"}]' ,
299
+ 'logfire.json_schema' : '{"type": "object", "properties": {"all_messages_events": {"type": "array"}, "final_result": {"type": "object"}}}' ,
300
+ 'logfire.level_num' : 17 ,
301
+ },
302
+ 'events' : [
303
+ {
304
+ 'name' : 'exception' ,
305
+ 'timestamp' : 5000000000 ,
306
+ 'attributes' : {
307
+ 'exception.type' : 'pydantic_ai.exceptions.FallbackExceptionGroup' ,
308
+ 'exception.message' : 'All models from FallbackModel failed (2 sub-exceptions)' ,
309
+ 'exception.stacktrace' : '+------------------------------------' ,
310
+ 'exception.escaped' : 'False' ,
311
+ },
312
+ }
313
+ ],
314
+ },
315
+ ]
316
+ )
317
+
318
+
239
319
async def success_response_stream (_model_messages : list [ModelMessage ], _agent_info : AgentInfo ) -> AsyncIterator [str ]:
240
320
yield 'hello '
241
321
yield 'world'
0 commit comments