1#![forbid(unsafe_code)]
7
8use inspect::Inspect;
9use std::sync::atomic::AtomicU64;
10use std::sync::atomic::Ordering;
11
12#[derive(Debug, Default, Clone)]
14pub struct Counter(u64);
15
16impl Counter {
17 pub fn new() -> Self {
19 Self::default()
20 }
21
22 pub fn increment(&mut self) {
24 self.add(1);
25 }
26
27 pub fn add(&mut self, n: u64) {
29 self.0 = self.0.wrapping_add(n);
30 }
31
32 pub fn get(&self) -> u64 {
34 self.0
35 }
36}
37
38impl Inspect for Counter {
39 fn inspect(&self, req: inspect::Request<'_>) {
40 req.with_counter_format().value(self.0)
41 }
42}
43
44#[derive(Debug, Default)]
48pub struct SharedCounter(AtomicU64);
49
50impl SharedCounter {
51 pub fn new() -> Self {
53 Self::default()
54 }
55
56 pub fn increment(&self) {
58 self.add(1);
59 }
60
61 pub fn add(&self, n: u64) {
63 self.0.fetch_add(n, Ordering::Relaxed);
64 }
65
66 pub fn get(&self) -> u64 {
68 self.0.load(Ordering::Relaxed)
69 }
70}
71
72impl Inspect for SharedCounter {
73 fn inspect(&self, req: inspect::Request<'_>) {
74 req.with_counter_format()
75 .value(self.0.load(Ordering::Relaxed))
76 }
77}
78
79#[derive(Clone, Debug)]
81pub struct Histogram<const N: usize>([u64; N]);
82
83impl<const N: usize> Default for Histogram<N> {
84 fn default() -> Self {
85 Self::new()
86 }
87}
88
89impl<const N: usize> Histogram<N> {
90 pub fn new() -> Self {
92 assert!(N > 2);
93 assert!(N < BUCKETS.len());
94 Self([0; N])
95 }
96
97 pub fn add_sample(&mut self, n: impl Into<u64>) {
99 self.0[(64 - n.into().leading_zeros() as usize).min(N - 1)] += 1;
100 }
101}
102
103static BUCKETS: &[&str] = &[
104 "0",
105 "1",
106 "2-3",
107 "4-7",
108 "8-15",
109 "16-31",
110 "32-63",
111 "64-127",
112 "128-255",
113 "256-511",
114 "512-1023",
115 "1024-2047",
116 "2048-4195",
117 "4196-8191",
118 "8192-16383",
119 "16384-32767",
120 "32768-65535",
121];
122
123static WIDTH: &[usize] = &[1, 1, 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5];
124
125impl<const N: usize> Inspect for Histogram<N> {
126 fn inspect(&self, req: inspect::Request<'_>) {
127 let mut resp = req.respond();
128 for (i, &n) in self.0[..N - 1].iter().enumerate() {
129 resp.counter(BUCKETS[i], n);
130 }
131 resp.counter(&BUCKETS[N - 1][..WIDTH[N - 1] + 1], self.0[N - 1]);
132 }
133}