use serde::{Deserialize, Serialize};
use std::time::Duration;
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct ParserMetrics {
pub files_attempted: usize,
pub files_succeeded: usize,
pub files_failed: usize,
#[serde(with = "duration_serde")]
pub total_parse_time: Duration,
pub total_entities: usize,
pub total_relationships: usize,
pub peak_memory_bytes: Option<usize>,
}
mod duration_serde {
use serde::{Deserialize, Deserializer, Serialize, Serializer};
use std::time::Duration;
pub fn serialize<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
duration.as_secs().serialize(serializer)
}
pub fn deserialize<'de, D>(deserializer: D) -> Result<Duration, D::Error>
where
D: Deserializer<'de>,
{
let secs: u64 = u64::deserialize(deserializer)?;
Ok(Duration::from_secs(secs))
}
}
impl Default for ParserMetrics {
fn default() -> Self {
Self {
files_attempted: 0,
files_succeeded: 0,
files_failed: 0,
total_parse_time: Duration::ZERO,
total_entities: 0,
total_relationships: 0,
peak_memory_bytes: None,
}
}
}
impl ParserMetrics {
pub fn success_rate(&self) -> f64 {
if self.files_attempted == 0 {
0.0
} else {
self.files_succeeded as f64 / self.files_attempted as f64
}
}
pub fn avg_parse_time(&self) -> Duration {
if self.files_succeeded == 0 {
Duration::ZERO
} else {
self.total_parse_time / self.files_succeeded as u32
}
}
pub fn avg_entities_per_file(&self) -> f64 {
if self.files_succeeded == 0 {
0.0
} else {
self.total_entities as f64 / self.files_succeeded as f64
}
}
pub fn merge(&mut self, other: &ParserMetrics) {
self.files_attempted += other.files_attempted;
self.files_succeeded += other.files_succeeded;
self.files_failed += other.files_failed;
self.total_parse_time += other.total_parse_time;
self.total_entities += other.total_entities;
self.total_relationships += other.total_relationships;
self.peak_memory_bytes = match (self.peak_memory_bytes, other.peak_memory_bytes) {
(Some(a), Some(b)) => Some(a.max(b)),
(Some(a), None) => Some(a),
(None, Some(b)) => Some(b),
(None, None) => None,
};
}
}