1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
use std::ops::BitOr;
/// Metric kind.
///
/// Defines the kind, or type, of a metric. Follows the supported metric types of `metrics`:
/// - counters
/// - gauges
/// - histograms
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq, PartialOrd, Ord)]
pub enum MetricKind {
/// Counter type.
Counter,
/// Gauge type.
Gauge,
/// Histogram type.
Histogram,
}
/// Metric kind mask.
///
/// Useful for matching against a kind, or kinds, of metrics.
///
/// In order to use for defining multiple metric kinds, can be used in a bitmask fashion, as this
/// type implements bitwise OR support, and checking for inclusion of a specific kind within another
/// kind value can be checked via [`matches`](MetricKindMask::matches):
///
/// ```rust
/// # use metrics_util::{MetricKind, MetricKindMask};
/// # fn main() {
/// // Let's only match counters and histograms:
/// let mask = MetricKindMask::COUNTER | MetricKindMask::HISTOGRAM;
///
/// // And check to see if the kinds we have matches our mask:
/// assert!(!mask.matches(MetricKind::Gauge));
/// assert!(mask.matches(MetricKind::Counter));
///
/// // There's even two handy versions to avoid extra typing:
/// let none_mask = MetricKindMask::NONE;
/// let all_mask = MetricKindMask::ALL;
///
/// assert!(!none_mask.matches(MetricKind::Counter));
/// assert!(!none_mask.matches(MetricKind::Gauge));
/// assert!(!none_mask.matches(MetricKind::Histogram));
/// assert!(all_mask.matches(MetricKind::Counter));
/// assert!(all_mask.matches(MetricKind::Gauge));
/// assert!(all_mask.matches(MetricKind::Histogram));
/// # }
/// ```
#[derive(Debug, Eq, PartialEq, Hash, Clone, Copy, Ord, PartialOrd)]
pub struct MetricKindMask(u8);
impl MetricKindMask {
/// No metric kinds.
pub const NONE: MetricKindMask = MetricKindMask(0);
/// The counter kind.
pub const COUNTER: MetricKindMask = MetricKindMask(1);
/// The gauge kind.
pub const GAUGE: MetricKindMask = MetricKindMask(2);
/// The histogram kind.
pub const HISTOGRAM: MetricKindMask = MetricKindMask(4);
/// All metric kinds.
pub const ALL: MetricKindMask = MetricKindMask(7);
#[inline]
fn value(&self) -> u8 {
self.0
}
/// Whether or not this metric kind contains the specified kind.
pub fn matches(&self, kind: MetricKind) -> bool {
match kind {
MetricKind::Counter => self.0 & MetricKindMask::COUNTER.value() != 0,
MetricKind::Gauge => self.0 & MetricKindMask::GAUGE.value() != 0,
MetricKind::Histogram => self.0 & MetricKindMask::HISTOGRAM.value() != 0,
}
}
}
impl BitOr for MetricKindMask {
type Output = Self;
fn bitor(self, rhs: Self) -> Self::Output {
Self(self.0 | rhs.0)
}
}
#[cfg(test)]
mod tests {
use super::MetricKindMask;
use crate::MetricKind;
#[test]
fn test_matching() {
let cmask = MetricKindMask::COUNTER;
let gmask = MetricKindMask::GAUGE;
let hmask = MetricKindMask::HISTOGRAM;
let nmask = MetricKindMask::NONE;
let amask = MetricKindMask::ALL;
assert!(cmask.matches(MetricKind::Counter));
assert!(!cmask.matches(MetricKind::Gauge));
assert!(!cmask.matches(MetricKind::Histogram));
assert!(!gmask.matches(MetricKind::Counter));
assert!(gmask.matches(MetricKind::Gauge));
assert!(!gmask.matches(MetricKind::Histogram));
assert!(!hmask.matches(MetricKind::Counter));
assert!(!hmask.matches(MetricKind::Gauge));
assert!(hmask.matches(MetricKind::Histogram));
assert!(amask.matches(MetricKind::Counter));
assert!(amask.matches(MetricKind::Gauge));
assert!(amask.matches(MetricKind::Histogram));
assert!(!nmask.matches(MetricKind::Counter));
assert!(!nmask.matches(MetricKind::Gauge));
assert!(!nmask.matches(MetricKind::Histogram));
}
}