From afad9c045a5c1021fb331597330fe4ef7180d3ac Mon Sep 17 00:00:00 2001 From: moe-berri Date: Tue, 6 Oct 2026 14:14:09 -0700 Subject: [PATCH] fix(tracing): classify tool attempts without optional span tags --- .../crates/traces-clickhouse/query/span_detail.sql | 2 +- litellm-rust/crates/traces-clickhouse/tests/reads.rs | 11 +++++++---- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/litellm-rust/crates/traces-clickhouse/query/span_detail.sql b/litellm-rust/crates/traces-clickhouse/query/span_detail.sql index af26edeb17c..8d8b1b401ea 100644 --- a/litellm-rust/crates/traces-clickhouse/query/span_detail.sql +++ b/litellm-rust/crates/traces-clickhouse/query/span_detail.sql @@ -66,7 +66,7 @@ SELECT o.SpanId AS span_id, concat('[', arrayStringConcat(arrayFilter(result -> JSONExtractString(result, 'id') != '' AND NOT has(e.call_ids, JSONExtractString(result, 'id')), JSONExtractArrayRaw(o.Output, 'tool_results')), ','), ']'), '[]'), 'lens.content.input_source', multiIf(o.native_tool AND length(i.values) = 1, i.source_span, o.Input != '', o.SpanId, ''), - 'lens.content.execution_status', if(o.native_tool AND o.SpanAttributes['span.type'] = 'tool', + 'lens.content.execution_status', if(o.native_tool, if(x.execution_span_id != '', 'recorded', 'not_recorded'), ''), 'lens.content.output_source', multiIf(o.Output != '', o.SpanId, o.native_tool AND length(r.values) = 1, r.source_span, o.ObservationType = 'agent' AND a.output != '', a.source_span, ''), 'lens.content.input_status', multiIf(o.native_tool AND length(i.values) > 1, 'conflicting', input != '', 'recorded', 'not_recorded'), diff --git a/litellm-rust/crates/traces-clickhouse/tests/reads.rs b/litellm-rust/crates/traces-clickhouse/tests/reads.rs index c4474a52eb1..0dabf9d8727 100644 --- a/litellm-rust/crates/traces-clickhouse/tests/reads.rs +++ b/litellm-rust/crates/traces-clickhouse/tests/reads.rs @@ -844,14 +844,17 @@ async fn native_cost_correlation_survives_session_grouping_and_excludes_other_ow } #[rstest] -#[case::recorded(false, true)] -#[case::conflicting(true, true)] -#[case::invocation_without_execution(false, false)] +#[case::recorded(false, true, true)] +#[case::conflicting(true, true, true)] +#[case::invocation_without_execution(false, false, true)] +#[case::untyped_invocation_without_execution(false, false, false)] +#[case::untyped_invocation_with_execution(false, true, false)] #[tokio::test] async fn native_tool_content_agrees_between_single_and_bulk_reads( #[future(awt)] migrated_database: TestResult, #[case] conflict: bool, #[case] executed: bool, + #[case] span_type: bool, ) -> TestResult { use litellm_storage_clickhouse::fetch; use litellm_traces::query::named::{SpanDetailParams, SpanDetailsParams}; @@ -977,7 +980,7 @@ async fn native_tool_content_agrees_between_single_and_bulk_reads( ("Output".into(), json!(output)), ( "SpanAttributes".into(), - json!({"session.id":session,"tool_use_id":"call", "span.type": if kind == "tool" { "tool" } else { "" }}), + json!({"session.id":session,"tool_use_id":"call", "span.type": if span_type && kind == "tool" { "tool" } else { "" }}), ), ("TeamId".into(), json!(team)), ("ApiKeyHash".into(), json!(key)),