1use std::sync::atomic::{AtomicU64, Ordering};
10
11#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
13pub struct RequestCounts {
14 pub get: u64,
15 pub head: u64,
16 pub put: u64,
17 pub copy: u64,
18 pub delete: u64,
19 pub list: u64,
20 pub multipart: u64,
23}
24
25impl RequestCounts {
26 pub fn total(&self) -> u64 {
27 self.get + self.head + self.put + self.copy + self.delete + self.list + self.multipart
28 }
29}
30
31#[derive(Debug, Clone, Copy, PartialEq, Eq)]
32pub enum RequestKind {
33 Get,
34 Head,
35 Put,
36 Copy,
37 Delete,
38 List,
39 Multipart,
40}
41
42#[derive(Debug, Default)]
44pub struct RequestCounter {
45 get: AtomicU64,
46 head: AtomicU64,
47 put: AtomicU64,
48 copy: AtomicU64,
49 delete: AtomicU64,
50 list: AtomicU64,
51 multipart: AtomicU64,
52}
53
54impl RequestCounter {
55 pub fn bump(&self, kind: RequestKind) {
56 let c = match kind {
57 RequestKind::Get => &self.get,
58 RequestKind::Head => &self.head,
59 RequestKind::Put => &self.put,
60 RequestKind::Copy => &self.copy,
61 RequestKind::Delete => &self.delete,
62 RequestKind::List => &self.list,
63 RequestKind::Multipart => &self.multipart,
64 };
65 c.fetch_add(1, Ordering::Relaxed);
66 }
67
68 pub fn snapshot(&self) -> RequestCounts {
69 RequestCounts {
70 get: self.get.load(Ordering::Relaxed),
71 head: self.head.load(Ordering::Relaxed),
72 put: self.put.load(Ordering::Relaxed),
73 copy: self.copy.load(Ordering::Relaxed),
74 delete: self.delete.load(Ordering::Relaxed),
75 list: self.list.load(Ordering::Relaxed),
76 multipart: self.multipart.load(Ordering::Relaxed),
77 }
78 }
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::memory::MemoryStore;
84 use crate::{crc64_nvme, GenerationStamps, ObjectStore, PutCondition};
85 use bytes::Bytes;
86
87 #[tokio::test]
91 async fn requests_are_counted_by_kind() {
92 let s = MemoryStore::new();
93 let st = GenerationStamps { generation: 1, epoch: 0, flush_uuid: "t".into(), boundary_source: None, posix: None };
94 let m = s.put_whole("k", Bytes::from_static(b"x"), &PutCondition::IfNoneMatchAny, &st, crc64_nvme(b"x")).await.unwrap();
95 s.head("k").await.unwrap();
96 s.get_whole("k", None).await.unwrap();
97 s.get_whole("k", None).await.unwrap();
98 s.list("").await.unwrap();
99 s.delete_if_match("k", &m.etag).await.unwrap();
100 let c = s.request_counts().expect("the double counts");
101 assert_eq!((c.put, c.head, c.get, c.list, c.delete, c.copy, c.multipart), (1, 1, 2, 1, 1, 0, 0), "{c:?}");
102 assert_eq!(c.total(), 6);
103 }
104}