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
use vector_lib::event::{Metric, MetricValue};

use crate::sinks::util::buffer::metrics::{MetricNormalize, MetricSet};

#[derive(Default)]
pub(crate) struct AppsignalMetricsNormalizer;

impl MetricNormalize for AppsignalMetricsNormalizer {
    fn normalize(&mut self, state: &mut MetricSet, metric: Metric) -> Option<Metric> {
        // We only care about making sure that counters are incremental, and that gauges are
        // always absolute. Other metric types are currently unsupported.
        match &metric.value() {
            // We always send counters as incremental and gauges as absolute. Realistically, any
            // system sending an incremental gauge update is kind of doing it wrong, but alas.
            MetricValue::Counter { .. } => state.make_incremental(metric),
            MetricValue::Gauge { .. } => state.make_absolute(metric),
            // Otherwise, send it through as-is.
            _ => Some(metric),
        }
    }
}

#[cfg(test)]
mod tests {
    use std::collections::BTreeSet;

    use crate::event::{Metric, MetricKind, MetricValue};

    use super::AppsignalMetricsNormalizer;
    use crate::test_util::metrics::{assert_normalize, tests};

    #[test]
    fn absolute_counter() {
        tests::absolute_counter_normalize_to_incremental(AppsignalMetricsNormalizer);
    }

    #[test]
    fn incremental_counter() {
        tests::incremental_counter_normalize_to_incremental(AppsignalMetricsNormalizer);
    }

    #[test]
    fn mixed_counter() {
        tests::mixed_counter_normalize_to_incremental(AppsignalMetricsNormalizer);
    }

    #[test]
    fn absolute_gauge() {
        tests::absolute_gauge_normalize_to_absolute(AppsignalMetricsNormalizer);
    }

    #[test]
    fn incremental_gauge() {
        tests::incremental_gauge_normalize_to_absolute(AppsignalMetricsNormalizer);
    }

    #[test]
    fn mixed_gauge() {
        tests::mixed_gauge_normalize_to_absolute(AppsignalMetricsNormalizer);
    }

    #[test]
    fn other_metrics() {
        let metric = Metric::new(
            "set",
            MetricKind::Incremental,
            MetricValue::Set {
                values: BTreeSet::new(),
            },
        );

        assert_normalize(
            AppsignalMetricsNormalizer,
            vec![metric.clone()],
            vec![Some(metric)],
        );
    }
}