1use chrono::{DateTime, Utc};
4use serde::{Deserialize, Serialize};
5use std::collections::HashMap;
6use std::path::PathBuf;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
10pub struct ExperimentConfig {
11 pub name: String,
13 pub run_name: String,
15 pub base_dir: PathBuf,
17 pub flush_interval_rows: usize,
19 pub flush_interval_ms: u64,
21 pub language: String,
23 pub env_path: Option<String>,
25}
26
27impl ExperimentConfig {
28 pub fn new(name: impl Into<String>, base_dir: impl Into<PathBuf>) -> Self {
29 let now = chrono::Local::now();
30 Self {
31 name: name.into(),
32 run_name: now.format("%Y%m%d_%H%M%S").to_string(),
33 base_dir: base_dir.into(),
34 flush_interval_rows: 50,
35 flush_interval_ms: 500,
36 language: "rust".to_string(),
37 env_path: None,
38 }
39 }
40
41 pub fn with_run_name(mut self, run_name: impl Into<String>) -> Self {
42 self.run_name = run_name.into();
43 self
44 }
45
46 pub fn run_dir(&self) -> PathBuf {
47 self.base_dir.join(&self.name).join(&self.run_name)
48 }
49
50 pub fn experiment_dir(&self) -> PathBuf {
51 self.base_dir.join(&self.name)
52 }
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57#[serde(untagged)]
58pub enum MetricValue {
59 Float(f64),
60 Int(i64),
61 Bool(bool),
62 Text(String),
63}
64
65impl From<f64> for MetricValue {
66 fn from(v: f64) -> Self {
67 MetricValue::Float(v)
68 }
69}
70impl From<f32> for MetricValue {
71 fn from(v: f32) -> Self {
72 MetricValue::Float(v as f64)
73 }
74}
75impl From<i64> for MetricValue {
76 fn from(v: i64) -> Self {
77 MetricValue::Int(v)
78 }
79}
80impl From<i32> for MetricValue {
81 fn from(v: i32) -> Self {
82 MetricValue::Int(v as i64)
83 }
84}
85impl From<usize> for MetricValue {
86 fn from(v: usize) -> Self {
87 MetricValue::Int(v as i64)
88 }
89}
90impl From<bool> for MetricValue {
91 fn from(v: bool) -> Self {
92 MetricValue::Bool(v)
93 }
94}
95impl From<String> for MetricValue {
96 fn from(v: String) -> Self {
97 MetricValue::Text(v)
98 }
99}
100impl From<&str> for MetricValue {
101 fn from(v: &str) -> Self {
102 MetricValue::Text(v.to_string())
103 }
104}
105
106#[derive(Debug, Clone, Serialize, Deserialize)]
108pub struct MetricRow {
109 pub step: Option<u64>,
110 pub timestamp: DateTime<Utc>,
111 pub values: HashMap<String, MetricValue>,
112}
113
114impl MetricRow {
115 pub fn new(values: HashMap<String, MetricValue>, step: Option<u64>) -> Self {
116 Self {
117 step,
118 timestamp: Utc::now(),
119 values,
120 }
121 }
122}
123
124#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
126#[serde(rename_all = "UPPERCASE")]
127pub enum RunStatus {
128 Running,
129 Finished,
130 Failed,
131 Crashed,
132}
133
134impl std::fmt::Display for RunStatus {
135 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
136 match self {
137 RunStatus::Running => write!(f, "RUNNING"),
138 RunStatus::Finished => write!(f, "FINISHED"),
139 RunStatus::Failed => write!(f, "FAILED"),
140 RunStatus::Crashed => write!(f, "CRASHED"),
141 }
142 }
143}
144
145#[derive(Debug, Clone, Serialize, Deserialize)]
147pub struct RunMetadata {
148 pub name: String,
149 pub experiment: String,
150 pub status: RunStatus,
151 pub started_at: DateTime<Utc>,
152 pub finished_at: Option<DateTime<Utc>>,
153 pub duration_secs: Option<f64>,
154 pub description: Option<String>,
155 #[serde(default)]
157 pub metrics: Option<HashMap<String, f64>>,
158 #[serde(default)]
160 pub language: Option<String>,
161 #[serde(default)]
163 pub env_path: Option<String>,
164}
165
166impl Default for RunMetadata {
167 fn default() -> Self {
168 Self {
169 name: String::new(),
170 experiment: String::new(),
171 status: RunStatus::Crashed,
172 started_at: Utc::now(),
173 finished_at: None,
174 duration_secs: None,
175 description: None,
176 metrics: None,
177 language: None,
178 env_path: None,
179 }
180 }
181}
182
183#[derive(Debug, Clone, Serialize, Deserialize, Default)]
185pub struct ExperimentMetadata {
186 pub display_name: Option<String>,
187 pub description: Option<String>,
188 pub tags: Vec<String>,
189}