Skip to content

Commit 9370642

Browse files
committed
feat(graph): show how many checks are in the store for each minute
1 parent 03b2251 commit 9370642

File tree

4 files changed

+79
-18
lines changed

4 files changed

+79
-18
lines changed

.zed/tasks.json

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Static tasks configuration.
2+
//
3+
// Example:
4+
[
5+
{
6+
"label": "make graph",
7+
"command": "cargo run --release -- --graph",
8+
"env": {
9+
"NETPULSE_LOG_LEVEL": "TRACE"
10+
},
11+
"use_new_terminal": false,
12+
"allow_concurrent_runs": false,
13+
"reveal": "no_focus",
14+
"reveal_target": "dock",
15+
"hide": "never"
16+
}
17+
]

src/analyze.rs

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@
2929
//! - Outage analysis
3030
//! - Store metadata (hashes, versions)
3131
32-
use chrono::{DateTime, Local};
32+
use chrono::{DateTime, Local, TimeDelta};
3333
use deepsize::DeepSizeOf;
34+
use plotters::prelude::IntoMonthly;
3435
use tracing::{error, trace};
3536

3637
use crate::errors::AnalysisError;
@@ -39,6 +40,7 @@ use crate::store::Store;
3940

4041
use std::collections::HashMap;
4142
use std::fmt::{Display, Write};
43+
use std::ops::RangeBounds;
4244
use std::os::unix::fs::MetadataExt;
4345

4446
use self::outage::Outage;
@@ -226,6 +228,27 @@ pub fn outages_detailed(all: &[&Check], f: &mut String, dump: bool) -> Result<()
226228
Ok(())
227229
}
228230

231+
pub fn checks_per_time_group<'check>(
232+
checks: impl IntoIterator<Item = &'check Check>,
233+
) -> HashMap<i64, usize> {
234+
let cbt = group_by_time(checks);
235+
assert!(!cbt.is_empty());
236+
let mut times: Vec<_> = cbt.values().collect();
237+
times.sort();
238+
let time_start = times.first().unwrap()[0].timestamp();
239+
let time_end = times.last().unwrap()[0].timestamp();
240+
241+
let mut buf: HashMap<i64, usize> = HashMap::new();
242+
243+
let mut current = time_start;
244+
while current < time_end {
245+
buf.insert(current, cbt.get(&current).map(|a| a.len()).unwrap_or(0));
246+
current += 60;
247+
}
248+
249+
buf
250+
}
251+
229252
pub fn group_by_time<'check>(
230253
checks: impl IntoIterator<Item = &'check Check>,
231254
) -> HashMap<i64, CheckGroup<'check>> {

src/analyze/graph.rs

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::fmt::Write;
22
use std::path::Path;
33

4-
use chrono::{DateTime, Local};
4+
use chrono::{DateTime, Local, TimeZone};
55
use plotters::prelude::*;
66
use tracing::trace;
77

@@ -23,10 +23,6 @@ pub fn draw_checks(checks: &[Check], file: impl AsRef<Path>) -> Result<(), Analy
2323
times.sort();
2424
let timespan =
2525
times.first().unwrap()[0].timestamp_parsed()..times.last().unwrap()[0].timestamp_parsed();
26-
let mut x_axis: Vec<_> = Vec::new();
27-
for t in 0..time_grouped.len() {
28-
x_axis.push(t);
29-
}
3026

3127
for group in time_grouped.values() {
3228
data.push((
@@ -36,6 +32,13 @@ pub fn draw_checks(checks: &[Check], file: impl AsRef<Path>) -> Result<(), Analy
3632
}
3733
data.sort_by_key(|a| a.0);
3834

35+
let cpt = super::checks_per_time_group(checks.iter());
36+
let mut checks_per_time: Vec<(DateTime<Local>, usize)> = cpt
37+
.iter()
38+
.map(|(k, v)| (Local.timestamp_opt(*k, 0).unwrap(), *v))
39+
.collect();
40+
checks_per_time.sort_by_key(|a| a.0);
41+
3942
let root = BitMapBackend::new(outfile, (1920, 1080)).into_drawing_area();
4043
root.fill(&WHITE).map_err(|e| AnalysisError::GraphDraw {
4144
reason: e.to_string(),
@@ -45,11 +48,16 @@ pub fn draw_checks(checks: &[Check], file: impl AsRef<Path>) -> Result<(), Analy
4548
.margin(10)
4649
.caption("Outage Severity over all time", ("sans-serif", 60))
4750
.set_label_area_size(LabelAreaPosition::Left, 60)
48-
.set_label_area_size(LabelAreaPosition::Bottom, 30)
49-
.build_cartesian_2d(timespan, 0.0..1.0)
51+
.set_label_area_size(LabelAreaPosition::Right, 60)
52+
.set_label_area_size(LabelAreaPosition::Bottom, 60)
53+
.build_cartesian_2d(timespan.clone(), 0.0..1.0)
5054
.map_err(|e| AnalysisError::GraphDraw {
5155
reason: e.to_string(),
52-
})?;
56+
})?
57+
.set_secondary_coord(
58+
timespan,
59+
0f64..checks_per_time.last().map(|a| a.1 as f64).unwrap(),
60+
);
5361

5462
chart
5563
.configure_mesh()
@@ -61,17 +69,24 @@ pub fn draw_checks(checks: &[Check], file: impl AsRef<Path>) -> Result<(), Analy
6169
.map_err(|e| AnalysisError::GraphDraw {
6270
reason: e.to_string(),
6371
})?;
72+
chart
73+
.configure_secondary_axes()
74+
.y_desc("Amount of Checks")
75+
.draw()
76+
.map_err(|e| AnalysisError::GraphDraw {
77+
reason: e.to_string(),
78+
})?;
79+
80+
let processed_serevity_data = data.iter().map(|(a, b)| (*a, f64::from(*b)));
81+
chart
82+
.draw_series(AreaSeries::new(processed_serevity_data, 0.0, RED.mix(0.2)).border_style(RED))
83+
.map_err(|e| AnalysisError::GraphDraw {
84+
reason: e.to_string(),
85+
})?;
6486

65-
let processed_data = data.iter().map(|(a, b)| (*a, f64::from(*b)));
66-
trace!("dumping whole processed data: \n{}", {
67-
let mut buf = String::new();
68-
for (idx, row) in processed_data.clone().enumerate() {
69-
writeln!(buf, "{:08},{},{:.06}", idx, row.0, row.1).unwrap();
70-
}
71-
buf
72-
});
87+
let checks_per_time_f64 = checks_per_time.into_iter().map(|(t, v)| (t, v as f64));
7388
chart
74-
.draw_series(AreaSeries::new(processed_data, 0.0, RED.mix(0.2)).border_style(RED))
89+
.draw_series(AreaSeries::new(checks_per_time_f64, 0.0, BLUE.mix(0.2)))
7590
.map_err(|e| AnalysisError::GraphDraw {
7691
reason: e.to_string(),
7792
})?;

src/analyze/outage.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,12 @@ pub enum Severity {
8181
None,
8282
}
8383

84+
impl Severity {
85+
pub fn raw(self) -> f64 {
86+
f64::from(self)
87+
}
88+
}
89+
8490
impl From<&[&Check]> for Severity {
8591
fn from(value: &[&Check]) -> Self {
8692
let percentage: f64 =

0 commit comments

Comments
 (0)