use std::collections::HashMap;
use std::sync::{Arc, Mutex};
use super::{MetricSnapshot, ResourceSnapshot};
use crate::run::Run;
use crate::storage::{ExperimentStorage, RunStatus};
pub type SubscriptionCallback = Box<dyn Fn(&str, f64) + Send>;
pub trait DashboardSource {
fn status(&self) -> RunStatus;
fn recent_metrics(&self, limit: usize) -> HashMap<String, MetricSnapshot>;
fn subscribe(&self, callback: SubscriptionCallback);
fn resource_usage(&self) -> ResourceSnapshot;
}
impl<S: ExperimentStorage> DashboardSource for Run<S> {
fn status(&self) -> RunStatus {
if self.is_finished() {
let storage = self.storage_ref();
storage
.lock()
.ok()
.and_then(|s| s.get_run_status(&self.id).ok())
.unwrap_or(RunStatus::Success)
} else {
RunStatus::Running
}
}
fn recent_metrics(&self, limit: usize) -> HashMap<String, MetricSnapshot> {
let mut result = HashMap::new();
let storage = self.storage_ref();
if let Ok(guard) = storage.lock() {
for key in self.metric_keys() {
if let Ok(points) = guard.get_metrics(&self.id, &key) {
let recent: Vec<_> = if points.len() > limit {
points[points.len() - limit..].to_vec()
} else {
points
};
let snapshot = MetricSnapshot::from_points(&key, &recent);
result.insert(key, snapshot);
}
}
}
result
}
fn subscribe(&self, _callback: SubscriptionCallback) {
}
fn resource_usage(&self) -> ResourceSnapshot {
ResourceSnapshot::new().with_cpu_util(0.0).with_gpu_util(0.0).with_memory(0, 0)
}
}
impl<S: ExperimentStorage> Run<S> {
pub(crate) fn storage_ref(&self) -> &Arc<Mutex<S>> {
&self.storage
}
pub fn metric_keys(&self) -> Vec<String> {
self.step_counters.keys().cloned().collect()
}
}