aws_smithy_http_client/client/pool/
stats.rs1use std::sync::atomic::{AtomicUsize, Ordering};
19
20#[derive(Clone, Copy, Debug, Eq, PartialEq)]
26#[non_exhaustive]
27pub struct ConnectionCapacityStats {
28 limit: usize,
29 in_use: usize,
30}
31
32impl ConnectionCapacityStats {
33 pub(super) fn new(limit: usize, in_use: usize) -> Self {
34 Self { limit, in_use }
35 }
36
37 pub fn limit(&self) -> usize {
39 self.limit
40 }
41
42 pub fn in_use(&self) -> usize {
44 self.in_use
45 }
46}
47
48#[derive(Clone, Copy, Debug, Eq, PartialEq)]
52#[non_exhaustive]
53pub struct OriginConnectionStats {
54 capacity: Option<ConnectionCapacityStats>,
55}
56
57impl OriginConnectionStats {
58 pub(super) fn new(capacity: Option<ConnectionCapacityStats>) -> Self {
59 Self { capacity }
60 }
61
62 pub fn capacity(&self) -> Option<&ConnectionCapacityStats> {
64 self.capacity.as_ref()
65 }
66}
67
68#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
74#[non_exhaustive]
75pub struct Http1ConnectionStats {
76 idle: usize,
77 active: usize,
78 draining: usize,
79 upgraded: usize,
80}
81
82impl Http1ConnectionStats {
83 pub fn idle(&self) -> usize {
85 self.idle
86 }
87
88 pub fn active(&self) -> usize {
93 self.active
94 }
95
96 pub fn draining(&self) -> usize {
98 self.draining
99 }
100
101 pub fn upgraded(&self) -> usize {
103 self.upgraded
104 }
105}
106
107#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
113#[non_exhaustive]
114pub struct Http2ConnectionStats {
115 accepting: usize,
116 draining: usize,
117 active_requests: usize,
118}
119
120impl Http2ConnectionStats {
121 pub fn accepting(&self) -> usize {
123 self.accepting
124 }
125
126 pub fn draining(&self) -> usize {
128 self.draining
129 }
130
131 pub fn active_requests(&self) -> usize {
133 self.active_requests
134 }
135}
136
137#[derive(Clone, Copy, Debug, Default, Eq, PartialEq)]
143#[non_exhaustive]
144pub struct PartitionConnectionStats {
145 pending_acquisitions: usize,
146 establishing_connections: usize,
147 h1: Http1ConnectionStats,
148 h2: Http2ConnectionStats,
149 physically_live_connections: usize,
150}
151
152impl PartitionConnectionStats {
153 pub fn pending_acquisitions(&self) -> usize {
155 self.pending_acquisitions
156 }
157
158 pub fn establishing_connections(&self) -> usize {
163 self.establishing_connections
164 }
165
166 pub fn h1(&self) -> &Http1ConnectionStats {
168 &self.h1
169 }
170
171 pub fn h2(&self) -> &Http2ConnectionStats {
173 &self.h2
174 }
175
176 pub fn physically_live_connections(&self) -> usize {
181 self.physically_live_connections
182 }
183}
184
185#[derive(Debug, Default)]
191pub(super) struct CellConnectionStats {
192 establishing: AtomicUsize,
193 h1_draining: AtomicUsize,
194 h1_upgraded: AtomicUsize,
195 h2_draining: AtomicUsize,
196 physically_live: AtomicUsize,
197}
198
199impl CellConnectionStats {
200 pub(super) fn establishment_started(&self) {
201 increment(
202 &self.establishing,
203 "connection establishment count exhausted",
204 );
205 }
206
207 pub(super) fn establishment_finished(&self) {
208 decrement(
209 &self.establishing,
210 "connection establishment completed without a matching start",
211 );
212 }
213
214 pub(super) fn physical_connection_started(&self) {
215 increment(&self.physically_live, "physical connection count exhausted");
216 }
217
218 pub(super) fn physical_connection_finished(&self) {
219 decrement(
220 &self.physically_live,
221 "physical connection completed without a matching start",
222 );
223 }
224
225 pub(super) fn h1_drain_started(&self) {
226 increment(&self.h1_draining, "HTTP/1 draining count exhausted");
227 }
228
229 pub(super) fn h1_drain_finished(&self) {
230 decrement(
231 &self.h1_draining,
232 "HTTP/1 drain completed without a matching start",
233 );
234 }
235
236 pub(super) fn h1_drain_upgraded(&self) {
237 self.h1_drain_finished();
238 increment(&self.h1_upgraded, "HTTP/1 upgraded count exhausted");
239 }
240
241 pub(super) fn h1_upgrade_started(&self) {
242 increment(&self.h1_upgraded, "HTTP/1 upgraded count exhausted");
243 }
244
245 pub(super) fn h1_upgrade_finished(&self) {
246 decrement(
247 &self.h1_upgraded,
248 "HTTP/1 upgrade completed without a matching start",
249 );
250 }
251
252 pub(super) fn h2_drain_started(&self) {
253 increment(&self.h2_draining, "HTTP/2 draining count exhausted");
254 }
255
256 pub(super) fn h2_drain_finished(&self) {
257 decrement(
258 &self.h2_draining,
259 "HTTP/2 drain completed without a matching start",
260 );
261 }
262
263 pub(super) fn snapshot(
264 &self,
265 pending_acquisitions: usize,
266 h1_idle: usize,
267 h1_active: usize,
268 h2_accepting: usize,
269 h2_active_requests: usize,
270 ) -> PartitionConnectionStats {
271 PartitionConnectionStats {
272 pending_acquisitions,
273 establishing_connections: self.establishing.load(Ordering::Relaxed),
274 h1: Http1ConnectionStats {
275 idle: h1_idle,
276 active: h1_active,
277 draining: self.h1_draining.load(Ordering::Relaxed),
278 upgraded: self.h1_upgraded.load(Ordering::Relaxed),
279 },
280 h2: Http2ConnectionStats {
281 accepting: h2_accepting,
282 draining: self.h2_draining.load(Ordering::Relaxed),
283 active_requests: h2_active_requests,
284 },
285 physically_live_connections: self.physically_live.load(Ordering::Relaxed),
286 }
287 }
288}
289
290fn increment(counter: &AtomicUsize, message: &'static str) {
291 counter
292 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |value| {
293 value.checked_add(1)
294 })
295 .expect(message);
296}
297
298fn decrement(counter: &AtomicUsize, message: &'static str) {
299 counter
300 .fetch_update(Ordering::Relaxed, Ordering::Relaxed, |value| {
301 value.checked_sub(1)
302 })
303 .expect(message);
304}
305
306#[cfg(test)]
307mod tests {
308 use super::*;
309
310 #[test]
311 fn snapshot_combines_exact_and_lifetime_state() {
312 let stats = CellConnectionStats::default();
313 stats.establishment_started();
314 stats.physical_connection_started();
315 stats.h1_drain_started();
316 stats.h1_drain_upgraded();
317 stats.h2_drain_started();
318
319 let snapshot = stats.snapshot(2, 3, 4, 5, 6);
320
321 assert_eq!(2, snapshot.pending_acquisitions());
322 assert_eq!(1, snapshot.establishing_connections());
323 assert_eq!(3, snapshot.h1().idle());
324 assert_eq!(4, snapshot.h1().active());
325 assert_eq!(0, snapshot.h1().draining());
326 assert_eq!(1, snapshot.h1().upgraded());
327 assert_eq!(5, snapshot.h2().accepting());
328 assert_eq!(1, snapshot.h2().draining());
329 assert_eq!(6, snapshot.h2().active_requests());
330 assert_eq!(1, snapshot.physically_live_connections());
331 }
332}