@@ -347,34 +347,68 @@ async def test_async_basic_llm_chain(mock_client, Model, stream):
347347 assert isinstance (props ["$ai_latency" ], float )
348348
349349
350- def test_trace_id_for_multiple_chains (mock_client ):
350+ def test_trace_id_and_inputs_for_multiple_chains (mock_client ):
351351 prompt = ChatPromptTemplate .from_messages (
352352 [
353- ("user" , "Foo" ),
353+ ("user" , "Foo {var} " ),
354354 ]
355355 )
356356 model = FakeMessagesListChatModel (responses = [AIMessage (content = "Bar" )])
357357 callbacks = [CallbackHandler (mock_client )]
358358 chain = prompt | model | RunnableLambda (lambda x : [x ]) | model
359- result = chain .invoke ({}, config = {"callbacks" : callbacks })
359+ result = chain .invoke ({"var" : "bar" }, config = {"callbacks" : callbacks })
360360
361361 assert result .content == "Bar"
362- assert mock_client .capture .call_count == 3
362+ # span, generation, span, generation, trace
363+ assert mock_client .capture .call_count == 5
363364
364- first_call_args = mock_client .capture .call_args_list [0 ][1 ]
365- first_call_props = first_call_args ["properties" ]
366- assert first_call_args ["event" ] == "$ai_generation"
367- assert "distinct_id" in first_call_args
368- assert "$ai_model" in first_call_props
369- assert "$ai_provider" in first_call_props
370- assert first_call_props ["$ai_input" ] == [{"role" : "user" , "content" : "Foo" }]
371- assert first_call_props ["$ai_output_choices" ] == [{"role" : "assistant" , "content" : "Bar" }]
372- assert first_call_props ["$ai_http_status" ] == 200
373- assert first_call_props ["$ai_trace_id" ] is not None
374- assert isinstance (first_call_props ["$ai_latency" ], float )
365+ first_span_args = mock_client .capture .call_args_list [0 ][1 ]
366+ first_span_props = first_span_args ["properties" ]
367+
368+ first_generation_args = mock_client .capture .call_args_list [1 ][1 ]
369+ first_generation_props = first_generation_args ["properties" ]
375370
376- second_generation_args = mock_client .capture .call_args_list [1 ][1 ]
371+ second_span_args = mock_client .capture .call_args_list [2 ][1 ]
372+ second_span_props = second_span_args ["properties" ]
373+
374+ second_generation_args = mock_client .capture .call_args_list [3 ][1 ]
377375 second_generation_props = second_generation_args ["properties" ]
376+
377+ trace_args = mock_client .capture .call_args_list [4 ][1 ]
378+ trace_props = trace_args ["properties" ]
379+
380+ # Prompt span
381+ assert first_span_args ["event" ] == "$ai_span"
382+ assert first_span_props ["$ai_input_state" ] == {"var" : "bar" }
383+ assert first_span_props ["$ai_trace_id" ] == trace_props ["$ai_trace_id" ]
384+ assert first_span_props ["$ai_parent_id" ] == trace_props ["$ai_trace_id" ]
385+ assert "$ai_span_id" in first_span_props
386+ assert first_span_props ["$ai_output_state" ] == ChatPromptTemplate (
387+ messages = [HumanMessage (content = "Foo bar" )]
388+ ).invoke ({})
389+
390+ # first model
391+ assert first_generation_args ["event" ] == "$ai_generation"
392+ assert "distinct_id" in first_generation_args
393+ assert "$ai_model" in first_generation_props
394+ assert "$ai_provider" in first_generation_props
395+ assert first_generation_props ["$ai_input" ] == [{"role" : "user" , "content" : "Foo bar" }]
396+ assert first_generation_props ["$ai_output_choices" ] == [{"role" : "assistant" , "content" : "Bar" }]
397+ assert first_generation_props ["$ai_http_status" ] == 200
398+ assert isinstance (first_generation_props ["$ai_latency" ], float )
399+ assert "$ai_generation_id" in first_generation_props
400+ assert first_generation_props ["$ai_parent_id" ] == trace_props ["$ai_trace_id" ]
401+ assert first_generation_props ["$ai_trace_id" ] == trace_props ["$ai_trace_id" ]
402+
403+ # lambda span
404+ assert second_span_args ["event" ] == "$ai_span"
405+ assert second_span_props ["$ai_input_state" ].content == "Bar"
406+ assert second_span_props ["$ai_trace_id" ] == trace_props ["$ai_trace_id" ]
407+ assert second_span_props ["$ai_parent_id" ] == trace_props ["$ai_trace_id" ]
408+ assert "$ai_span_id" in second_span_props
409+ assert second_span_props ["$ai_output_state" ][0 ].content == "Bar"
410+
411+ # second model
378412 assert second_generation_args ["event" ] == "$ai_generation"
379413 assert "distinct_id" in second_generation_args
380414 assert "$ai_model" in second_generation_props
@@ -385,40 +419,49 @@ def test_trace_id_for_multiple_chains(mock_client):
385419 assert second_generation_props ["$ai_trace_id" ] is not None
386420 assert isinstance (second_generation_props ["$ai_latency" ], float )
387421
388- trace_args = mock_client .capture .call_args_list [2 ][1 ]
389- trace_props = trace_args ["properties" ]
422+ # trace
390423 assert trace_args ["event" ] == "$ai_trace"
391424 assert "distinct_id" in trace_args
392- assert trace_props ["$ai_input_state" ] == {}
425+ assert trace_props ["$ai_input_state" ] == {"var" : "bar" }
393426 assert isinstance (trace_props ["$ai_output_state" ], AIMessage )
394427 assert trace_props ["$ai_output_state" ].content == "Bar"
395428 assert trace_props ["$ai_trace_id" ] is not None
396429 assert trace_props ["$ai_trace_name" ] == "RunnableSequence"
397430
398- # Check that the trace_id is the same as the first call
399- assert first_call_props ["$ai_trace_id" ] == second_generation_props ["$ai_trace_id" ]
400- assert first_call_props ["$ai_trace_id" ] == trace_props ["$ai_trace_id" ]
401-
402431
403432def test_personless_mode (mock_client ):
404433 prompt = ChatPromptTemplate .from_messages ([("user" , "Foo" )])
405434 chain = prompt | FakeMessagesListChatModel (responses = [AIMessage (content = "Bar" )])
406435 chain .invoke ({}, config = {"callbacks" : [CallbackHandler (mock_client )]})
407- assert mock_client .capture .call_count == 2
408- generation_args = mock_client .capture .call_args_list [0 ][1 ]
409- trace_args = mock_client .capture .call_args_list [1 ][1 ]
436+ assert mock_client .capture .call_count == 3
437+ span_args = mock_client .capture .call_args_list [0 ][1 ]
438+ generation_args = mock_client .capture .call_args_list [1 ][1 ]
439+ trace_args = mock_client .capture .call_args_list [2 ][1 ]
440+
441+ # span
442+ assert span_args ["event" ] == "$ai_span"
443+ assert span_args ["properties" ]["$process_person_profile" ] is False
444+ # generation
410445 assert generation_args ["event" ] == "$ai_generation"
411446 assert generation_args ["properties" ]["$process_person_profile" ] is False
447+ # trace
412448 assert trace_args ["event" ] == "$ai_trace"
413449 assert trace_args ["properties" ]["$process_person_profile" ] is False
414450
415451 id = uuid .uuid4 ()
416452 chain .invoke ({}, config = {"callbacks" : [CallbackHandler (mock_client , distinct_id = id )]})
417- assert mock_client .capture .call_count == 4
418- generation_args = mock_client .capture .call_args_list [2 ][1 ]
419- trace_args = mock_client .capture .call_args_list [3 ][1 ]
453+ assert mock_client .capture .call_count == 6
454+ span_args = mock_client .capture .call_args_list [3 ][1 ]
455+ generation_args = mock_client .capture .call_args_list [4 ][1 ]
456+ trace_args = mock_client .capture .call_args_list [5 ][1 ]
457+
458+ # span
459+ assert "$process_person_profile" not in span_args ["properties" ]
460+ assert span_args ["distinct_id" ] == id
461+ # generation
420462 assert "$process_person_profile" not in generation_args ["properties" ]
421463 assert generation_args ["distinct_id" ] == id
464+ # trace
422465 assert "$process_person_profile" not in trace_args ["properties" ]
423466 assert trace_args ["distinct_id" ] == id
424467
@@ -429,22 +472,41 @@ def test_personless_mode_exception(mock_client):
429472 callbacks = CallbackHandler (mock_client )
430473 with pytest .raises (Exception ):
431474 chain .invoke ({}, config = {"callbacks" : [callbacks ]})
432- assert mock_client .capture .call_count == 2
433- generation_args = mock_client .capture .call_args_list [0 ][1 ]
434- trace_args = mock_client .capture .call_args_list [1 ][1 ]
475+ assert mock_client .capture .call_count == 3
476+ span_args = mock_client .capture .call_args_list [0 ][1 ]
477+ generation_args = mock_client .capture .call_args_list [1 ][1 ]
478+ trace_args = mock_client .capture .call_args_list [2 ][1 ]
479+
480+ # span
481+ assert span_args ["event" ] == "$ai_span"
482+ assert span_args ["properties" ]["$process_person_profile" ] is False
483+ # generation
435484 assert generation_args ["event" ] == "$ai_generation"
436485 assert generation_args ["properties" ]["$process_person_profile" ] is False
486+ # trace
437487 assert trace_args ["event" ] == "$ai_trace"
438488 assert trace_args ["properties" ]["$process_person_profile" ] is False
439489
440490 id = uuid .uuid4 ()
441491 with pytest .raises (Exception ):
442492 chain .invoke ({}, config = {"callbacks" : [CallbackHandler (mock_client , distinct_id = id )]})
443- assert mock_client .capture .call_count == 4
444- generation_args = mock_client .capture .call_args_list [2 ][1 ]
445- trace_args = mock_client .capture .call_args_list [3 ][1 ]
493+ assert mock_client .capture .call_count == 6
494+ span_args = mock_client .capture .call_args_list [3 ][1 ]
495+ generation_args = mock_client .capture .call_args_list [4 ][1 ]
496+ trace_args = mock_client .capture .call_args_list [5 ][1 ]
497+
498+ # span
499+ assert span_args ["event" ] == "$ai_span"
500+ assert "$process_person_profile" not in span_args ["properties" ]
501+ assert span_args ["distinct_id" ] == id
502+
503+ # generation
504+ assert generation_args ["event" ] == "$ai_generation"
446505 assert "$process_person_profile" not in generation_args ["properties" ]
447506 assert generation_args ["distinct_id" ] == id
507+
508+ # trace
509+ assert trace_args ["event" ] == "$ai_trace"
448510 assert "$process_person_profile" not in trace_args ["properties" ]
449511 assert trace_args ["distinct_id" ] == id
450512
@@ -468,9 +530,18 @@ def test_metadata(mock_client):
468530 result = chain .invoke ({"plan" : None }, config = {"callbacks" : callbacks })
469531
470532 assert result .content == "Bar"
471- assert mock_client .capture .call_count == 2
533+ assert mock_client .capture .call_count == 3
534+
535+ span_call_args = mock_client .capture .call_args_list [0 ][1 ]
536+ span_call_props = span_call_args ["properties" ]
537+ assert span_call_args ["distinct_id" ] == "test_id"
538+ assert span_call_args ["event" ] == "$ai_span"
539+ assert span_call_props ["$ai_trace_id" ] == "test-trace-id"
540+ assert span_call_props ["foo" ] == "bar"
541+ assert "$ai_parent_id" in span_call_props
542+ assert "$ai_span_id" in span_call_props
472543
473- generation_call_args = mock_client .capture .call_args_list [0 ][1 ]
544+ generation_call_args = mock_client .capture .call_args_list [1 ][1 ]
474545 generation_call_props = generation_call_args ["properties" ]
475546 assert generation_call_args ["distinct_id" ] == "test_id"
476547 assert generation_call_args ["event" ] == "$ai_generation"
@@ -481,7 +552,7 @@ def test_metadata(mock_client):
481552 assert generation_call_props ["$ai_http_status" ] == 200
482553 assert isinstance (generation_call_props ["$ai_latency" ], float )
483554
484- trace_call_args = mock_client .capture .call_args_list [1 ][1 ]
555+ trace_call_args = mock_client .capture .call_args_list [2 ][1 ]
485556 trace_call_props = trace_call_args ["properties" ]
486557 assert trace_call_args ["distinct_id" ] == "test_id"
487558 assert trace_call_args ["event" ] == "$ai_trace"
0 commit comments