scirs2_metrics/serialization/
mod.rs1use chrono::{DateTime, Utc};
7use serde::{Deserialize, Serialize};
8use std::collections::HashMap;
9use std::fs::File;
10use std::io::{Read, Write};
11use std::path::Path;
12
13use crate::error::{MetricsError, Result};
14
15pub mod comparison;
17pub mod format;
18
19#[derive(Debug, Clone, Serialize, Deserialize)]
23pub struct MetricResult {
24 pub name: String,
26 pub value: f64,
28 pub additional_values: Option<HashMap<String, f64>>,
30 pub timestamp: DateTime<Utc>,
32 pub metadata: Option<MetricMetadata>,
34}
35
36#[derive(Debug, Clone, Serialize, Deserialize, Default)]
40pub struct MetricMetadata {
41 pub dataset_id: Option<String>,
43 pub model_id: Option<String>,
45 pub parameters: Option<HashMap<String, String>>,
47 pub additional_metadata: Option<HashMap<String, String>>,
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
55pub struct MetricCollection {
56 pub name: String,
58 pub description: Option<String>,
60 pub metrics: Vec<MetricResult>,
62 pub created_at: DateTime<Utc>,
64 pub updated_at: DateTime<Utc>,
66 pub version: String,
68}
69
70impl MetricCollection {
71 pub fn new(name: &str, description: Option<&str>) -> Self {
82 let now = Utc::now();
83
84 MetricCollection {
85 name: name.to_string(),
86 description: description.map(|s| s.to_string()),
87 metrics: Vec::new(),
88 created_at: now,
89 updated_at: now,
90 version: "1.0.0".to_string(),
91 }
92 }
93
94 pub fn add_metric(&mut self, metric: MetricResult) -> &mut Self {
104 self.metrics.push(metric);
105 self.updated_at = Utc::now();
106 self
107 }
108
109 pub fn with_version(&mut self, version: &str) -> &mut Self {
119 self.version = version.to_string();
120 self
121 }
122
123 pub fn save<P: AsRef<Path>>(&self, path: P, format: SerializationFormat) -> Result<()> {
134 let serialized = match format {
135 SerializationFormat::Json => serde_json::to_string_pretty(self)
136 .map_err(|e| MetricsError::SerializationError(e.to_string()))?,
137 SerializationFormat::Yaml => serde_yaml::to_string(self)
138 .map_err(|e| MetricsError::SerializationError(e.to_string()))?,
139 SerializationFormat::Toml => toml::to_string_pretty(self)
140 .map_err(|e| MetricsError::SerializationError(e.to_string()))?,
141 SerializationFormat::Cbor => {
142 let mut bytes = Vec::new();
143 ciborium::ser::into_writer(self, &mut bytes)
144 .map_err(|e| MetricsError::SerializationError(e.to_string()))?;
145 return save_binary(path, &bytes);
146 }
147 };
148
149 savetext(path, &serialized)
150 }
151
152 pub fn load<P: AsRef<Path>>(path: P, format: SerializationFormat) -> Result<Self> {
163 match format {
164 SerializationFormat::Json => {
165 let text = loadtext(path)?;
166 serde_json::from_str(&text)
167 .map_err(|e| MetricsError::SerializationError(e.to_string()))
168 }
169 SerializationFormat::Yaml => {
170 let text = loadtext(path)?;
171 serde_yaml::from_str(&text)
172 .map_err(|e| MetricsError::SerializationError(e.to_string()))
173 }
174 SerializationFormat::Toml => {
175 let text = loadtext(path)?;
176 toml::from_str(&text).map_err(|e| MetricsError::SerializationError(e.to_string()))
177 }
178 SerializationFormat::Cbor => {
179 let bytes = load_binary(path)?;
180 ciborium::de::from_reader(&bytes[..])
181 .map_err(|e| MetricsError::SerializationError(e.to_string()))
182 }
183 }
184 }
185}
186
187#[allow(dead_code)]
200pub fn create_metric_result(
201 name: &str,
202 value: f64,
203 additional_values: Option<HashMap<String, f64>>,
204 metadata: Option<MetricMetadata>,
205) -> MetricResult {
206 MetricResult {
207 name: name.to_string(),
208 value,
209 additional_values,
210 timestamp: Utc::now(),
211 metadata,
212 }
213}
214
215#[derive(Debug, Clone, Copy, PartialEq, Eq)]
217pub enum SerializationFormat {
218 Json,
220 Yaml,
222 Toml,
224 Cbor,
226}
227
228#[allow(dead_code)]
239fn savetext<P: AsRef<Path>>(path: P, text: &str) -> Result<()> {
240 let mut file = File::create(path).map_err(|e| MetricsError::IOError(e.to_string()))?;
241
242 file.write_all(text.as_bytes())
243 .map_err(|e| MetricsError::IOError(e.to_string()))?;
244
245 Ok(())
246}
247
248#[allow(dead_code)]
258fn loadtext<P: AsRef<Path>>(path: P) -> Result<String> {
259 let mut file = File::open(path).map_err(|e| MetricsError::IOError(e.to_string()))?;
260
261 let mut contents = String::new();
262 file.read_to_string(&mut contents)
263 .map_err(|e| MetricsError::IOError(e.to_string()))?;
264
265 Ok(contents)
266}
267
268#[allow(dead_code)]
279fn save_binary<P: AsRef<Path>>(path: P, data: &[u8]) -> Result<()> {
280 let mut file = File::create(path).map_err(|e| MetricsError::IOError(e.to_string()))?;
281
282 file.write_all(data)
283 .map_err(|e| MetricsError::IOError(e.to_string()))?;
284
285 Ok(())
286}
287
288#[allow(dead_code)]
298fn load_binary<P: AsRef<Path>>(path: P) -> Result<Vec<u8>> {
299 let mut file = File::open(path).map_err(|e| MetricsError::IOError(e.to_string()))?;
300
301 let mut contents = Vec::new();
302 file.read_to_end(&mut contents)
303 .map_err(|e| MetricsError::IOError(e.to_string()))?;
304
305 Ok(contents)
306}