fix: avoid crashing history graph on empty plot with throttling data

This commit is contained in:
Ilya Zlobintsev 2025-01-12 11:23:35 +02:00
parent 204dcb47fc
commit 4a35ffbde1
2 changed files with 35 additions and 29 deletions

View File

@ -105,7 +105,7 @@ impl PlotData {
self.push_secondary_line_series_with_time(name, point, chrono::Local::now().naive_local()); self.push_secondary_line_series_with_time(name, point, chrono::Local::now().naive_local());
} }
pub fn push_line_series_with_time(&mut self, name: &str, point: f64, time: NaiveDateTime) { fn push_line_series_with_time(&mut self, name: &str, point: f64, time: NaiveDateTime) {
self.line_series self.line_series
.entry(name.to_owned()) .entry(name.to_owned())
.or_default() .or_default()
@ -183,4 +183,8 @@ impl PlotData {
self.throttling self.throttling
.retain(|(time_point, _)| ((maximum_point - *time_point) / 1000) < last_seconds); .retain(|(time_point, _)| ((maximum_point - *time_point) / 1000) < last_seconds);
} }
pub fn is_empty(&self) -> bool {
self.line_series.is_empty() && self.secondary_line_series.is_empty()
}
} }

View File

@ -293,34 +293,36 @@ impl RenderRequest {
.context("Failed to draw mesh")?; .context("Failed to draw mesh")?;
// Draw the throttling histogram as a series of bars. // Draw the throttling histogram as a series of bars.
chart if !data.is_empty() {
.draw_series( chart
data.throttling_iter() .draw_series(
.chunk_by(|(_, _, point)| *point) data.throttling_iter()
.into_iter() .chunk_by(|(_, _, point)| *point)
.filter_map(|(point, group_iter)| point.then_some(group_iter)) .into_iter()
.filter_map(|mut group_iter| { .filter_map(|(point, group_iter)| point.then_some(group_iter))
let first = group_iter.next()?; .filter_map(|mut group_iter| {
Some((first, group_iter.last().unwrap_or(first))) let first = group_iter.next()?;
}) Some((first, group_iter.last().unwrap_or(first)))
.map(|((start, name, _), (end, _, _))| ((start, end), name)) })
.map(|((start_time, end_time), _)| (start_time, end_time)) .map(|((start, name, _), (end, _, _))| ((start, end), name))
.sorted_by_key(|&(start_time, _)| start_time) .map(|((start_time, end_time), _)| (start_time, end_time))
.coalesce(|(start1, end1), (start2, end2)| { .sorted_by_key(|&(start_time, _)| start_time)
if end1 >= start2 { .coalesce(|(start1, end1), (start2, end2)| {
Ok((start1, std::cmp::max(end1, end2))) if end1 >= start2 {
} else { Ok((start1, std::cmp::max(end1, end2)))
Err(((start1, end1), (start2, end2))) } else {
} Err(((start1, end1), (start2, end2)))
}) }
.map(|(start_time, end_time)| { })
Rectangle::new( .map(|(start_time, end_time)| {
[(start_time, 0f64), (end_time, maximum_value)], Rectangle::new(
DEEPORANGE_100.filled(), [(start_time, 0f64), (end_time, maximum_value)],
) DEEPORANGE_100.filled(),
}), )
) }),
.context("Failed to draw throttling histogram")?; )
.context("Failed to draw throttling histogram")?;
}
// Draw the main line series using cubic spline interpolation. // Draw the main line series using cubic spline interpolation.
for (idx, (caption, data)) in (0..).zip(data.line_series_iter()) { for (idx, (caption, data)) in (0..).zip(data.line_series_iter()) {