metrix/instruments/
counter.rs1use crate::instruments::{
2 AcceptAllLabels, Instrument, InstrumentAdapter, LabelFilter, LabelPredicate, Update, Updates,
3};
4use crate::snapshot::Snapshot;
5use crate::util;
6use crate::{Descriptive, PutsSnapshot};
7
8pub struct Counter {
29 name: String,
30 title: Option<String>,
31 description: Option<String>,
32 count: u64,
33}
34
35impl Counter {
36 pub fn new<T: Into<String>>(name: T) -> Counter {
37 Counter {
38 name: name.into(),
39 title: None,
40 description: None,
41 count: 0,
42 }
43 }
44 pub fn new_with_defaults<T: Into<String>>(name: T) -> Counter {
45 Self::new(name)
46 }
47
48 pub fn get_name(&self) -> &str {
49 &self.name
50 }
51
52 pub fn set_name<T: Into<String>>(&mut self, name: T) {
53 self.name = name.into();
54 }
55
56 pub fn name<T: Into<String>>(mut self, name: T) -> Self {
57 self.set_name(name);
58 self
59 }
60
61 pub fn set_title<T: Into<String>>(&mut self, title: T) {
62 self.title = Some(title.into())
63 }
64
65 pub fn title<T: Into<String>>(mut self, title: T) -> Self {
66 self.set_title(title);
67 self
68 }
69
70 pub fn set_description<T: Into<String>>(&mut self, description: T) {
71 self.description = Some(description.into())
72 }
73
74 pub fn description<T: Into<String>>(mut self, description: T) -> Self {
75 self.set_description(description);
76 self
77 }
78
79 pub fn inc(&mut self) {
81 self.count += 1;
82 }
83
84 pub fn inc_by(&mut self, n: u64) {
86 self.count += n;
87 }
88
89 pub fn get(&self) -> u64 {
91 self.count
92 }
93
94 pub fn accept<L: Eq + Send + 'static, F: Into<LabelFilter<L>>>(
95 self,
96 accept: F,
97 ) -> InstrumentAdapter<L, Self> {
98 InstrumentAdapter::accept(accept, self)
99 }
100
101 pub fn for_label<L: Eq + Send + 'static>(self, label: L) -> InstrumentAdapter<L, Self> {
104 self.accept(label)
105 }
106
107 pub fn for_labels<L: Eq + Send + 'static>(self, labels: Vec<L>) -> InstrumentAdapter<L, Self> {
112 self.accept(labels)
113 }
114
115 pub fn for_all_labels<L: Eq + Send + 'static>(self) -> InstrumentAdapter<L, Self> {
118 self.accept(AcceptAllLabels)
119 }
120
121 pub fn for_labels_by_predicate<L, P>(self, label_predicate: P) -> InstrumentAdapter<L, Self>
124 where
125 L: Eq + Send + 'static,
126 P: Fn(&L) -> bool + Send + 'static,
127 {
128 self.accept(LabelPredicate(label_predicate))
129 }
130
131 pub fn adapter<L: Eq + Send + 'static>(self) -> InstrumentAdapter<L, Self> {
134 InstrumentAdapter::deaf(self)
135 }
136}
137
138impl Instrument for Counter {}
139
140impl PutsSnapshot for Counter {
141 fn put_snapshot(&self, into: &mut Snapshot, descriptive: bool) {
142 util::put_postfixed_descriptives(self, &self.name, into, descriptive);
143 into.items.push((self.name.clone(), self.count.into()));
144 }
145}
146
147impl Updates for Counter {
148 fn update(&mut self, with: &Update) -> usize {
149 match *with {
150 Update::Observation(_) => {
151 self.inc();
152 1
153 }
154 Update::Observations(n, _) => {
155 self.inc_by(n);
156 1
157 }
158 Update::ObservationWithValue(_, _) => {
159 self.inc();
160 1
161 }
162 }
163 }
164}
165
166impl Descriptive for Counter {
167 fn title(&self) -> Option<&str> {
168 self.title.as_deref()
169 }
170
171 fn description(&self) -> Option<&str> {
172 self.description.as_deref()
173 }
174}
175
176#[cfg(test)]
177mod test {
178 use std::time::Instant;
179
180 use super::*;
181
182 #[test]
183 fn updates() {
184 let mut counter = Counter::new("");
185
186 assert_eq!(counter.get(), 0);
187
188 counter.update(&Update::Observation(Instant::now()));
189 assert_eq!(counter.get(), 1);
190
191 counter.update(&Update::Observations(1, Instant::now()));
192 assert_eq!(counter.get(), 2);
193
194 counter.update(&Update::Observations(3, Instant::now()));
195 assert_eq!(counter.get(), 5);
196
197 counter.update(&Update::ObservationWithValue(33.into(), Instant::now()));
198 assert_eq!(counter.get(), 6);
199 }
200}