llm_browser_testkit/
reporting.rs1use crate::costs::UsageSnapshot;
4
5pub fn print_report(per_test: &[(String, UsageSnapshot)], global: &UsageSnapshot) {
7 if per_test.is_empty() {
8 return;
9 }
10
11 eprintln!();
12 eprintln!("═══════════════════════════════════════════════");
13 eprintln!(" COST REPORT");
14 eprintln!("═══════════════════════════════════════════════");
15
16 for (test_name, snapshot) in per_test {
17 eprintln!(
18 " Test: \"{test_name}\" — ${cost:.4} | {tokens} tokens | {calls} calls",
19 cost = snapshot.total_cost,
20 tokens = snapshot.total_tokens,
21 calls = snapshot.total_calls,
22 );
23 for (ep_name, ep_usage) in &snapshot.endpoints {
24 if ep_usage.calls == 0 {
25 continue;
26 }
27 eprintln!(
28 " endpoint.{ep_name}: {calls:>3} calls, {tokens:>7} tokens, ${cost:.4}",
29 calls = ep_usage.calls,
30 tokens = ep_usage.input_tokens + ep_usage.output_tokens,
31 cost = ep_usage.cost,
32 );
33 }
34 }
35
36 eprintln!("───────────────────────────────────────────────");
37 eprintln!(" GLOBAL SUMMARY");
38 eprintln!(" Total cost: ${cost:.4}", cost = global.total_cost);
39 eprintln!(" Total tokens: {tokens}", tokens = global.total_tokens);
40 eprintln!(" Total calls: {calls}", calls = global.total_calls);
41 eprintln!("═══════════════════════════════════════════════");
42}
43
44pub fn print_budget_warning(message: &str) {
46 eprintln!(" ⚠️ BUDGET WARNING: {message}");
47}
48
49pub fn print_budget_error(message: &str) {
51 eprintln!(" 🛑 BUDGET EXCEEDED: {message}");
52}
53
54#[cfg(test)]
55mod tests {
56 use super::*;
57 use crate::costs::{EndpointUsage, UsageSnapshot};
58 use std::collections::HashMap;
59
60 fn make_snapshot(cost: f64, tokens: u64, calls: u64) -> UsageSnapshot {
61 let mut eps = HashMap::new();
62 eps.insert(
63 "default".to_owned(),
64 EndpointUsage {
65 calls,
66 input_tokens: tokens / 2,
67 output_tokens: tokens / 2,
68 cost,
69 },
70 );
71 UsageSnapshot::from_endpoints(&eps)
72 }
73
74 #[test]
75 fn test_print_report_empty() {
76 print_report(&[], &UsageSnapshot::default());
78 }
79
80 #[test]
81 fn test_print_report_single_test() {
82 let per_test = vec![("test1".to_owned(), make_snapshot(0.05, 500, 3))];
83 print_report(&per_test, &make_snapshot(0.05, 500, 3));
85 }
86
87 #[test]
88 fn test_print_report_zero_cost() {
89 let per_test = vec![("free".to_owned(), make_snapshot(0.0, 0, 0))];
90 print_report(&per_test, &make_snapshot(0.0, 0, 0));
91 }
92
93 #[test]
94 fn test_print_budget_warning_no_panic() {
95 print_budget_warning("cost limit $1.00 exceeded");
96 }
97
98 #[test]
99 fn test_print_budget_error_no_panic() {
100 print_budget_error("cost limit $5.00 exceeded");
101 }
102}