qlog_dancer/plots/
pending.rs1use crate::datastore::{
31 self,
32};
33
34use crate::plots::*;
35
36use crate::datastore::Datastore;
37use crate::seriesstore::SeriesStore;
38
39#[derive(Debug, Default)]
40pub struct PendingPlotParams {
41 pub clamp: ClampParams,
42 pub chart_size: ChartSize,
43 pub colors: PlotColors,
44 pub display_chart_title: bool,
45}
46
47struct PendingStack {
48 pub time: f64,
49 pub pending: i32,
50 pub in_flight: i32,
51}
52
53pub fn plot_pending(
54 params: &PendingPlotParams, filename: &str, ss: &SeriesStore, ds: &Datastore,
55 ty: &ChartOutputType,
56) {
57 let x_max = match ds.vantage_point {
59 datastore::VantagePoint::Client => ss.received_x_max,
60 datastore::VantagePoint::Server => ss.sent_x_max,
61 };
62
63 let mut y_max = 0;
64
65 let chart_config = ChartConfig {
66 title: "pending".into(),
67 input_filename: filename.into(),
68 clamp: params.clamp.clone(),
69 app_proto: ds.application_proto,
70 host: ds.host.clone(),
71 session_id: ds.session_id,
72 ty: ty.clone(),
73 };
74
75 chart_config.init_chart_dir();
76
77 let mut x = 0f64;
78 let step_size = 1f64;
79
80 let mut series = vec![];
81
82 while x < x_max {
83 let mut pending = 0;
84 let mut in_flight = 0;
85
86 for req in ds.http_requests.values() {
87 match (
88 req.time_discovery,
89 req.time_first_headers_tx,
90 req.time_fin_rx,
91 ) {
92 (Some(dt), Some(hdrs_tx), Some(fin)) => {
93 if x >= dt && x < hdrs_tx && x < fin {
94 pending += 1;
95 } else if x >= hdrs_tx && x < fin {
96 in_flight += 1;
97 }
98 },
99
100 (Some(dt), None, None) =>
101 if x >= dt {
102 pending += 1;
103 },
104
105 (Some(dt), Some(hdrs_tx), None) =>
106 if x >= dt {
107 pending += 1;
108 } else if x >= hdrs_tx {
109 in_flight += 1;
110 },
111
112 _ => (),
113 }
114 }
115 series.push(PendingStack {
116 time: x,
117 pending,
118 in_flight,
119 });
120 x += step_size;
121
122 y_max = y_max.max(pending + in_flight);
123 }
124
125 #[cfg(not(target_arch = "wasm32"))]
128 let chart_path = chart_config.chart_filepath();
129
130 #[cfg(not(target_arch = "wasm32"))]
131 let root = make_chart_bitmap_area(
132 &chart_path,
133 params.chart_size,
134 params.colors,
135 ChartMargin::default(),
136 );
137
138 #[cfg(target_arch = "wasm32")]
139 let canvas_id: String = chart_config.canvas_id().unwrap_or_default();
140
141 #[cfg(target_arch = "wasm32")]
142 let root =
143 make_chart_canvas_area(&canvas_id, params.colors, ChartMargin::default());
144
145 let mut builder = ChartBuilder::on(&root);
146 builder
147 .set_label_area_size(LabelAreaPosition::Left, 40)
148 .set_label_area_size(LabelAreaPosition::Bottom, 40);
149
150 if params.display_chart_title {
151 let caption =
152 format!("{} Pending vs. In-flight requests (stacked)", filename);
153 builder.caption(caption, chart_title_style(¶ms.colors.caption));
154 }
155
156 let mut ctx = builder.build_cartesian_2d(0f64..x_max, 0..y_max).unwrap();
157
158 ctx.configure_mesh()
159 .axis_style(params.colors.axis)
160 .bold_line_style(params.colors.bold_line.mix(0.5))
161 .light_line_style(params.colors.light_line.mix(0.2))
162 .label_style(chart_label_style(¶ms.colors.caption))
163 .draw()
164 .unwrap();
165
166 ctx.draw_series(series.iter().map(|stack| {
167 let shrink = step_size / 4f64;
171 let x0 = stack.time + shrink;
172 let x1 = x0 + (step_size - shrink);
173
174 #[allow(clippy::let_and_return)]
177 let in_flight_bar = Rectangle::new(
178 [(x0, 0), (x1, stack.in_flight)],
179 colors::FOREST_GREEN.filled(),
180 );
181 in_flight_bar
182 }))
183 .unwrap()
184 .label("In-flight requests")
185 .legend(|(x, y)| {
186 PathElement::new(vec![(x, y), (x + 20, y)], colors::FOREST_GREEN)
187 });
188
189 ctx.draw_series(series.iter().map(|stack| {
190 let shrink = step_size / 3f64;
194 let x0 = stack.time + shrink;
195 let x1 = x0 + (step_size - shrink);
196
197 #[allow(clippy::let_and_return)]
201 let pending_bar = Rectangle::new(
202 [(x0, stack.in_flight), (x1, stack.in_flight + stack.pending)],
203 colors::ORANGE.filled(),
204 );
205 pending_bar
206 }))
207 .unwrap()
208 .label("Pending requests")
209 .legend(|(x, y)| PathElement::new(vec![(x, y), (x + 20, y)], colors::ORANGE));
210
211 ctx.configure_series_labels()
212 .label_font(chart_label_style(¶ms.colors.caption))
213 .background_style(params.colors.fill.mix(0.8))
214 .border_style(params.colors.axis)
215 .position(SeriesLabelPosition::UpperRight)
216 .draw()
217 .unwrap();
218}