Skip to content

Commit 1b8eb3a

Browse files
committed
Hack for comparing metrics
1 parent 95ddd95 commit 1b8eb3a

File tree

1 file changed

+105
-23
lines changed

1 file changed

+105
-23
lines changed

lading/src/bin/captool.rs

+105-23
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@ struct Args {
3232
/// path to line-delimited capture file
3333
capture_path: String,
3434

35+
/// path to a second capture file for comparison
36+
#[clap(short, long)]
37+
comparison_capture_path: Option<String>,
38+
3539
/// warmup period in seconds - data points before this time will be ignored
3640
#[clap(long)]
3741
warmup: Option<u64>,
@@ -47,20 +51,15 @@ pub enum Error {
4751
Deserialize(#[from] serde_json::Error),
4852
}
4953

50-
#[tokio::main(flavor = "current_thread")]
51-
async fn main() -> Result<(), Error> {
52-
tracing_subscriber::fmt()
53-
.with_span_events(FmtSpan::FULL)
54-
.with_ansi(false)
55-
.finish()
56-
.init();
57-
58-
info!("Welcome to captool");
59-
let args = Args::parse();
54+
concatenate!(Estimator, [Variance, mean], [Max, max], [Min, min]);
6055

61-
let capture_path = std::path::Path::new(&args.capture_path);
56+
async fn process_capture_path(
57+
args: &Args,
58+
path: &str,
59+
) -> Result<Option<Vec<(String, Estimator)>>, Error> {
60+
let capture_path = std::path::Path::new(&path);
6261
if !capture_path.exists() {
63-
error!("Capture file {} does not exist", &args.capture_path);
62+
error!("Capture file {path} does not exist");
6463
return Err(Error::InvalidArgs);
6564
}
6665

@@ -106,7 +105,7 @@ async fn main() -> Result<(), Error> {
106105
for (name, kind) in names {
107106
println!("{kind}: {name}");
108107
}
109-
return Ok(());
108+
return Ok(None);
110109
}
111110

112111
if let Some(metric) = &args.metric {
@@ -155,26 +154,109 @@ async fn main() -> Result<(), Error> {
155154
entry.1.push(line.value.as_f64());
156155
}
157156

158-
concatenate!(Estimator, [Variance, mean], [Max, max], [Min, min]);
159-
let is_monotonic = |v: &Vec<_>| v.windows(2).all(|w| w[0] <= w[1]);
157+
// let is_monotonic = |v: &Vec<_>| v.windows(2).all(|w| w[0] <= w[1]);
158+
159+
let mut estimators = vec![];
160160

161161
for (_, (labels, values)) in context_map.iter() {
162162
let s: Estimator = values.iter().copied().collect();
163-
info!(
164-
"{metric}[{labels}]: min: {}, mean: {}, max: {}, is_monotonic: {}",
165-
s.min(),
166-
s.mean(),
167-
s.max(),
168-
is_monotonic(values),
169-
labels = labels.iter().cloned().collect::<Vec<String>>().join(",")
170-
);
163+
// println!(
164+
// "{metric}[{labels}]: min: {}, mean: {}, max: {}, is_monotonic: {}",
165+
// s.min(),
166+
// s.mean(),
167+
// s.max(),
168+
// is_monotonic(values),
169+
// labels = labels.iter().cloned().collect::<Vec<String>>().join(",")
170+
// );
171+
172+
let mut context = labels
173+
.iter()
174+
.filter(|v| !v.starts_with("replicate:") && !v.starts_with("pid:"))
175+
.cloned()
176+
.collect::<Vec<_>>();
177+
context.sort();
178+
let context = context.join(",");
179+
180+
estimators.push((context, s));
171181
}
172182

173183
if args.dump_values {
174184
for line in &filtered {
175185
println!("{}: {}", line.fetch_index, line.value);
176186
}
177187
}
188+
189+
return Ok(Some(estimators));
190+
}
191+
192+
Ok(None)
193+
}
194+
195+
#[tokio::main(flavor = "current_thread")]
196+
async fn main() -> Result<(), Error> {
197+
tracing_subscriber::fmt()
198+
.with_env_filter(tracing_subscriber::EnvFilter::from_default_env())
199+
.with_span_events(FmtSpan::FULL)
200+
.with_ansi(false)
201+
.finish()
202+
.init();
203+
204+
info!("Welcome to captool");
205+
let args = Args::parse();
206+
207+
let cap1 = process_capture_path(&args, &args.capture_path).await?;
208+
209+
if let Some(comparison_capture_path) = &args.comparison_capture_path {
210+
let metric = args.metric.clone().unwrap();
211+
212+
let cap1 = cap1.unwrap();
213+
let cap2 = process_capture_path(&args, comparison_capture_path)
214+
.await?
215+
.unwrap();
216+
217+
let all_contexts = cap1
218+
.iter()
219+
.map(|(labels, _)| labels.clone())
220+
.chain(cap2.iter().map(|(labels, _)| labels.clone()))
221+
.collect::<BTreeSet<_>>();
222+
223+
for label in &all_contexts {
224+
let cap1_lookup = &cap1.iter().find(|(labels, _)| labels.contains(label));
225+
let cap2_lookup = &cap2.iter().find(|(labels, _)| labels.contains(label));
226+
227+
if cap1_lookup.is_none() {
228+
println!("{} only present in cap2", label);
229+
continue;
230+
}
231+
if cap2_lookup.is_none() {
232+
println!("{} only present in cap1", label);
233+
continue;
234+
}
235+
236+
let cap1_est = &cap1_lookup.unwrap().1;
237+
let cap2_est = &cap2_lookup.unwrap().1;
238+
239+
let min = cap1_est.min() - cap2_est.min();
240+
let mean = cap1_est.mean() - cap2_est.mean();
241+
let max = cap1_est.max() - cap2_est.max();
242+
243+
if min.abs() > 0.01 || mean.abs() > 0.01 || max.abs() > 0.01 {
244+
println!("{metric}[{label}]");
245+
println!(
246+
"\tA: min: {}, mean: {}, max: {}",
247+
cap1_est.min(),
248+
cap1_est.mean(),
249+
cap1_est.max(),
250+
);
251+
println!(
252+
"\tB: min: {}, mean: {}, max: {}",
253+
cap2_est.min(),
254+
cap2_est.mean(),
255+
cap2_est.max(),
256+
);
257+
println!("\tDiff min: {min}, mean: {mean}, max: {max}");
258+
}
259+
}
178260
}
179261

180262
info!("Bye. :)");

0 commit comments

Comments
 (0)