1use crate::builder::{MetricFormatter, MetricValue};
12use std::error;
13use std::fmt;
14use std::io;
15
16pub trait Metric {
21 fn as_metric_str(&self) -> &str;
22}
23
24#[derive(PartialEq, Eq, Debug, Hash, Clone)]
28pub struct Counter {
29 repr: String,
30}
31
32impl Counter {
33 pub fn new(prefix: &str, key: &str, count: i64) -> Self {
34 Self::from(MetricFormatter::counter(prefix, key, MetricValue::Signed(count)).format())
35 }
36}
37
38impl From<String> for Counter {
39 fn from(s: String) -> Self {
40 Counter { repr: s }
41 }
42}
43
44impl Metric for Counter {
45 fn as_metric_str(&self) -> &str {
46 &self.repr
47 }
48}
49
50#[derive(PartialEq, Eq, Debug, Hash, Clone)]
56pub struct Timer {
57 repr: String,
58}
59
60impl Timer {
61 pub fn new(prefix: &str, key: &str, time: u64) -> Self {
62 Self::from(MetricFormatter::timer(prefix, key, MetricValue::Unsigned(time)).format())
63 }
64}
65
66impl From<String> for Timer {
67 fn from(s: String) -> Self {
68 Timer { repr: s }
69 }
70}
71
72impl Metric for Timer {
73 fn as_metric_str(&self) -> &str {
74 &self.repr
75 }
76}
77
78#[derive(PartialEq, Eq, Debug, Hash, Clone)]
82pub struct Gauge {
83 repr: String,
84}
85
86impl Gauge {
87 pub fn new(prefix: &str, key: &str, value: u64) -> Self {
88 Self::from(MetricFormatter::gauge(prefix, key, MetricValue::Unsigned(value)).format())
89 }
90
91 pub fn new_f64(prefix: &str, key: &str, value: f64) -> Self {
92 Self::from(MetricFormatter::gauge(prefix, key, MetricValue::Float(value)).format())
93 }
94}
95
96impl From<String> for Gauge {
97 fn from(s: String) -> Self {
98 Gauge { repr: s }
99 }
100}
101
102impl Metric for Gauge {
103 fn as_metric_str(&self) -> &str {
104 &self.repr
105 }
106}
107
108#[derive(PartialEq, Eq, Debug, Hash, Clone)]
112pub struct Meter {
113 repr: String,
114}
115
116impl Meter {
117 pub fn new(prefix: &str, key: &str, value: u64) -> Self {
118 Self::from(MetricFormatter::meter(prefix, key, MetricValue::Unsigned(value)).format())
119 }
120}
121
122impl From<String> for Meter {
123 fn from(s: String) -> Self {
124 Meter { repr: s }
125 }
126}
127
128impl Metric for Meter {
129 fn as_metric_str(&self) -> &str {
130 &self.repr
131 }
132}
133
134#[derive(PartialEq, Eq, Debug, Hash, Clone)]
142pub struct Histogram {
143 repr: String,
144}
145
146impl Histogram {
147 pub fn new(prefix: &str, key: &str, value: u64) -> Self {
148 Self::from(MetricFormatter::histogram(prefix, key, MetricValue::Unsigned(value)).format())
149 }
150
151 pub fn new_f64(prefix: &str, key: &str, value: f64) -> Self {
152 Self::from(MetricFormatter::histogram(prefix, key, MetricValue::Float(value)).format())
153 }
154}
155
156impl From<String> for Histogram {
157 fn from(s: String) -> Self {
158 Histogram { repr: s }
159 }
160}
161
162impl Metric for Histogram {
163 fn as_metric_str(&self) -> &str {
164 &self.repr
165 }
166}
167
168#[derive(PartialEq, Eq, Debug, Hash, Clone)]
172pub struct Distribution {
173 repr: String,
174}
175
176impl Distribution {
177 pub fn new(prefix: &str, key: &str, value: u64) -> Self {
178 Self::from(MetricFormatter::distribution(prefix, key, MetricValue::Unsigned(value)).format())
179 }
180
181 pub fn new_f64(prefix: &str, key: &str, value: f64) -> Self {
182 Self::from(MetricFormatter::distribution(prefix, key, MetricValue::Float(value)).format())
183 }
184}
185
186impl From<String> for Distribution {
187 fn from(s: String) -> Self {
188 Distribution { repr: s }
189 }
190}
191
192impl Metric for Distribution {
193 fn as_metric_str(&self) -> &str {
194 &self.repr
195 }
196}
197
198#[derive(PartialEq, Eq, Debug, Hash, Clone)]
202pub struct Set {
203 repr: String,
204}
205
206impl Set {
207 pub fn new(prefix: &str, key: &str, value: i64) -> Self {
208 Self::from(MetricFormatter::set(prefix, key, MetricValue::Signed(value)).format())
209 }
210}
211
212impl From<String> for Set {
213 fn from(s: String) -> Self {
214 Set { repr: s }
215 }
216}
217
218impl Metric for Set {
219 fn as_metric_str(&self) -> &str {
220 &self.repr
221 }
222}
223
224#[derive(PartialEq, Eq, Debug, Hash, Clone, Copy)]
226pub enum ErrorKind {
227 InvalidInput,
228 IoError,
229}
230
231#[derive(Debug)]
234pub struct MetricError {
235 repr: ErrorRepr,
236}
237
238#[derive(Debug)]
239enum ErrorRepr {
240 WithDescription(ErrorKind, &'static str),
241 IoError(io::Error),
242}
243
244impl MetricError {
245 pub fn kind(&self) -> ErrorKind {
247 match self.repr {
248 ErrorRepr::IoError(_) => ErrorKind::IoError,
249 ErrorRepr::WithDescription(kind, _) => kind,
250 }
251 }
252}
253
254impl fmt::Display for MetricError {
255 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
256 match self.repr {
257 ErrorRepr::IoError(ref err) => err.fmt(f),
258 ErrorRepr::WithDescription(_, desc) => desc.fmt(f),
259 }
260 }
261}
262
263impl error::Error for MetricError {
264 fn source(&self) -> Option<&(dyn error::Error + 'static)> {
265 match self.repr {
266 ErrorRepr::IoError(ref err) => Some(err),
267 _ => None,
268 }
269 }
270
271 #[allow(deprecated, deprecated_in_future)]
276 fn description(&self) -> &str {
277 match self.repr {
278 ErrorRepr::IoError(ref err) => err.description(),
279 ErrorRepr::WithDescription(_, desc) => desc,
280 }
281 }
282
283 fn cause(&self) -> Option<&dyn error::Error> {
284 self.source()
285 }
286}
287
288impl From<io::Error> for MetricError {
289 fn from(err: io::Error) -> MetricError {
290 MetricError {
291 repr: ErrorRepr::IoError(err),
292 }
293 }
294}
295
296impl From<(ErrorKind, &'static str)> for MetricError {
297 fn from((kind, desc): (ErrorKind, &'static str)) -> MetricError {
298 MetricError {
299 repr: ErrorRepr::WithDescription(kind, desc),
300 }
301 }
302}
303
304pub type MetricResult<T> = Result<T, MetricError>;
305
306#[cfg(test)]
307mod tests {
308 #![allow(deprecated, deprecated_in_future)]
309
310 use super::{Counter, ErrorKind, Gauge, Histogram, Meter, Metric, MetricError, Set, Timer};
311 use std::error::Error;
312 use std::io;
313
314 #[test]
315 fn test_counter_to_metric_string() {
316 let counter = Counter::new("my.app.", "test.counter", 4);
317 assert_eq!("my.app.test.counter:4|c", counter.as_metric_str());
318 }
319
320 #[test]
321 fn test_counter_no_prefix_to_metric_string() {
322 let counter = Counter::new("", "test.counter", 4);
323 assert_eq!("test.counter:4|c", counter.as_metric_str());
324 }
325
326 #[test]
327 fn test_timer_to_metric_string() {
328 let timer = Timer::new("my.app.", "test.timer", 34);
329 assert_eq!("my.app.test.timer:34|ms", timer.as_metric_str());
330 }
331
332 #[test]
333 fn test_timer_no_prefix_to_metric_string() {
334 let timer = Timer::new("", "test.timer", 34);
335 assert_eq!("test.timer:34|ms", timer.as_metric_str());
336 }
337
338 #[test]
339 fn test_gauge_to_metric_string() {
340 let gauge = Gauge::new("my.app.", "test.gauge", 2);
341 assert_eq!("my.app.test.gauge:2|g", gauge.as_metric_str());
342 }
343
344 #[test]
345 fn test_gauge_no_prefix_to_metric_string() {
346 let gauge = Gauge::new("", "test.gauge", 2);
347 assert_eq!("test.gauge:2|g", gauge.as_metric_str());
348 }
349
350 #[test]
351 fn test_meter_to_metric_string() {
352 let meter = Meter::new("my.app.", "test.meter", 5);
353 assert_eq!("my.app.test.meter:5|m", meter.as_metric_str());
354 }
355
356 #[test]
357 fn test_meter_no_prefix_to_metric_string() {
358 let meter = Meter::new("", "test.meter", 5);
359 assert_eq!("test.meter:5|m", meter.as_metric_str());
360 }
361
362 #[test]
363 fn test_histogram_to_metric_string() {
364 let histogram = Histogram::new("my.app.", "test.histogram", 45);
365 assert_eq!("my.app.test.histogram:45|h", histogram.as_metric_str());
366 }
367
368 #[test]
369 fn test_histogram_no_prefix_to_metric_string() {
370 let histogram = Histogram::new("", "test.histogram", 45);
371 assert_eq!("test.histogram:45|h", histogram.as_metric_str());
372 }
373
374 #[test]
375 fn test_set_to_metric_string() {
376 let set = Set::new("my.app.", "test.set", 4);
377 assert_eq!("my.app.test.set:4|s", set.as_metric_str());
378 }
379
380 #[test]
381 fn test_set_no_prefix_to_metric_string() {
382 let set = Set::new("", "test.set", 4);
383 assert_eq!("test.set:4|s", set.as_metric_str());
384 }
385
386 #[test]
387 fn test_metric_error_kind_io_error() {
388 let io_err = io::Error::new(io::ErrorKind::BrokenPipe, "Broken pipe");
389 let our_err = MetricError::from(io_err);
390 assert_eq!(ErrorKind::IoError, our_err.kind());
391 }
392
393 #[test]
394 fn test_metric_error_kind_invalid_input() {
395 let our_err = MetricError::from((ErrorKind::InvalidInput, "Nope"));
396 assert_eq!(ErrorKind::InvalidInput, our_err.kind());
397 }
398
399 #[test]
400 fn test_metric_error_description_io_error() {
401 let io_err = io::Error::new(io::ErrorKind::PermissionDenied, "Permission!");
402 let our_err = MetricError::from(io_err);
403 assert_eq!("Permission!", our_err.description());
404 }
405
406 #[test]
407 fn test_metric_error_description_other() {
408 let our_err = MetricError::from((ErrorKind::InvalidInput, "Something!"));
409 assert_eq!("Something!", our_err.description());
410 }
411
412 #[test]
413 fn test_metric_error_cause_io_error() {
414 let io_err = io::Error::new(io::ErrorKind::TimedOut, "Timeout!");
415 let our_err = MetricError::from(io_err);
416 assert_eq!("Timeout!", our_err.source().unwrap().description());
417 }
418
419 #[test]
420 fn test_metric_error_cause_other() {
421 let our_err = MetricError::from((ErrorKind::InvalidInput, "Nope!"));
422 assert!(our_err.source().is_none());
423 }
424}