agtrace_engine/analysis/
metrics.rs1use crate::AgentSession;
2
3#[derive(Debug, Clone)]
4pub struct SessionMetrics {
5 pub tool_calls_total: usize,
6 pub tool_failures_total: usize,
7 pub max_e2e_ms: u64,
8 pub max_tool_ms: u64,
9 pub missing_tool_pairs: usize,
10 pub loop_signals: usize,
11 pub longest_chain: usize,
12}
13
14pub fn compute_metrics(session: &AgentSession) -> SessionMetrics {
15 let mut tool_calls_total = 0;
16 let mut tool_failures_total = 0;
17 let mut missing_tool_pairs = 0;
18 let mut max_tool_ms = 0i64;
19 let mut longest_chain = 0;
20 let mut tool_counts_per_turn = Vec::new();
21
22 for turn in &session.turns {
23 let mut turn_tool_count = 0;
24 for step in &turn.steps {
25 turn_tool_count += step.tools.len();
26 tool_calls_total += step.tools.len();
27
28 for tool_exec in &step.tools {
29 if tool_exec.is_error {
30 tool_failures_total += 1;
31 }
32 if tool_exec.result.is_none() {
33 missing_tool_pairs += 1;
34 }
35 if let Some(duration_ms) = tool_exec.duration_ms
36 && duration_ms > max_tool_ms
37 {
38 max_tool_ms = duration_ms;
39 }
40 }
41
42 if step.tools.len() > longest_chain {
43 longest_chain = step.tools.len();
44 }
45 }
46 tool_counts_per_turn.push(turn_tool_count);
47 }
48
49 let max_e2e_ms = session
51 .turns
52 .iter()
53 .map(|turn| turn.stats.duration_ms)
54 .max()
55 .unwrap_or(0);
56
57 let loop_signals = tool_counts_per_turn.iter().filter(|&&c| c > 5).count();
59
60 SessionMetrics {
61 tool_calls_total,
62 tool_failures_total,
63 max_e2e_ms: max_e2e_ms as u64,
64 max_tool_ms: max_tool_ms as u64,
65 missing_tool_pairs,
66 loop_signals,
67 longest_chain,
68 }
69}
70
71