agtrace_engine/analysis/
metrics.rs

1use 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    // Calculate max e2e time (turn duration)
50    let max_e2e_ms = session
51        .turns
52        .iter()
53        .map(|turn| turn.stats.duration_ms)
54        .max()
55        .unwrap_or(0);
56
57    // Heuristic: Loop detection (same turn has > 5 tool calls)
58    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// Tests will be added after integration is complete and we can use real session data