1use crate::bench_session::BenchAgentError;
2use crate::eval_suites::EvalMetricValue;
3use chrono::Local;
4use serde::{Deserialize, Serialize};
5use std::fmt;
6
7#[derive(Default, Deserialize, Serialize)]
9pub struct EvaluationResult {
10 pub name: String,
11 pub metrics: Vec<(String, EvalMetricValue)>,
12 pub errors: Vec<BenchAgentError>,
13}
14
15#[derive(Default, Deserialize, Serialize)]
17pub struct SuiteResult {
18 pub name: String,
19 pub evaluations: Vec<EvaluationResult>,
20}
21
22#[derive(Default, Deserialize, Serialize)]
24pub struct BenchmarkResults {
25 pub provider: String,
26 pub start_time: String,
27 pub suites: Vec<SuiteResult>,
28}
29
30impl EvaluationResult {
31 pub fn new(name: String) -> Self {
32 Self {
33 name,
34 metrics: Vec::new(),
35 errors: Vec::new(),
36 }
37 }
38
39 pub fn add_metric(&mut self, name: String, metric: EvalMetricValue) {
40 self.metrics.push((name, metric));
41 }
42
43 pub fn add_error(&mut self, error: BenchAgentError) {
44 self.errors.push(error);
45 }
46}
47
48impl SuiteResult {
49 pub fn new(name: String) -> Self {
50 Self {
51 name,
52 evaluations: Vec::new(),
53 }
54 }
55
56 pub fn add_evaluation(&mut self, eval: EvaluationResult) {
57 self.evaluations.push(eval);
58 }
59}
60
61impl BenchmarkResults {
62 pub fn new(provider: String) -> Self {
63 Self {
64 provider,
65 start_time: Local::now().format("%Y-%m-%d %H:%M:%S").to_string(),
66 suites: Vec::new(),
67 }
68 }
69
70 pub fn add_suite(&mut self, suite: SuiteResult) {
71 self.suites.push(suite);
72 }
73
74 pub fn summary(&self) -> String {
76 let mut summary = String::new();
77 summary.push_str(&format!("Benchmark Summary - {}\n", self.provider));
78 summary.push_str(&format!("Run at: {}\n\n", self.start_time));
79
80 for suite in &self.suites {
81 summary.push_str(&format!(
82 "Suite: {} ({} evaluations)\n",
83 suite.name,
84 suite.evaluations.len()
85 ));
86
87 let total_metrics: usize = suite.evaluations.iter().map(|e| e.metrics.len()).sum();
89 let total_errors: usize = suite.evaluations.iter().map(|e| e.errors.len()).sum();
90
91 summary.push_str(&format!(" Total metrics: {}\n", total_metrics));
92 if total_errors > 0 {
93 summary.push_str(&format!(" Total errors: {}\n", total_errors));
94 }
95 }
96
97 summary
98 }
99}
100
101impl fmt::Display for BenchmarkResults {
102 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103 writeln!(f, "Benchmark Results")?;
104 writeln!(f, "Provider: {}", self.provider)?;
105 writeln!(f, "Start Time: {}", self.start_time)?;
106 writeln!(f)?;
107
108 for suite in &self.suites {
109 writeln!(f, "Suite: {}", suite.name)?;
110
111 for eval in &suite.evaluations {
112 writeln!(f, " Evaluation: {}", eval.name)?;
113 for (metric_name, metric_value) in &eval.metrics {
114 writeln!(f, " {}: {}", metric_name, metric_value)?;
115 }
116 if !eval.errors.is_empty() {
117 writeln!(f, " Errors:")?;
118 for error in &eval.errors {
119 writeln!(
120 f,
121 " [{}] {}: {}",
122 error.timestamp.format("%H:%M:%S"),
123 error.level,
124 error.message
125 )?;
126 }
127 }
128 writeln!(f)?;
129 }
130 }
131 Ok(())
132 }
133}