Skip to main content

metrique_aggregation/
value.rs

1//! Strategies for aggregating values
2
3use metrique_writer::MetricValue;
4
5use crate::{
6    histogram::{Histogram, SortAndMerge},
7    traits::AggregateValue,
8};
9use std::{marker::PhantomData, ops::AddAssign};
10
11/// Sums values when aggregating
12///
13/// Use for request counts, error counts, bytes transferred, or any metric
14/// where you want to sum values together.
15pub struct Sum;
16
17impl<T> AggregateValue<T> for Sum
18where
19    T: Default + AddAssign,
20{
21    type Aggregated = T;
22
23    fn insert(accum: &mut T, value: T) {
24        *accum += value;
25    }
26}
27
28/// Aggregation strategy that preserves the most recently set value
29pub struct KeepLast;
30
31impl<T: Clone> AggregateValue<T> for KeepLast {
32    type Aggregated = Option<T>;
33
34    fn insert(accum: &mut Self::Aggregated, value: T) {
35        *accum = Some(value)
36    }
37}
38
39/// Wrap a given strategy to support optional values by ignoring `None`
40pub struct MergeOptions<Inner> {
41    _data: PhantomData<Inner>,
42}
43
44impl<T, S> AggregateValue<Option<T>> for MergeOptions<S>
45where
46    S: AggregateValue<T>,
47{
48    type Aggregated = S::Aggregated;
49
50    fn insert(accum: &mut Self::Aggregated, value: Option<T>) {
51        if let Some(v) = value {
52            <S as AggregateValue<T>>::insert(accum, v);
53        }
54    }
55}
56
57/// Helper wrapper used by the aggregate macro to automatically copy Copy types in MergeRef
58pub struct CopyWrapper<Inner> {
59    data: PhantomData<Inner>,
60}
61
62impl<'a, T, S> AggregateValue<&'a T> for CopyWrapper<S>
63where
64    T: Copy,
65    S: AggregateValue<T>,
66{
67    type Aggregated = S::Aggregated;
68
69    fn insert(accum: &mut Self::Aggregated, value: &'a T) {
70        <S as AggregateValue<T>>::insert(accum, *value);
71    }
72}
73
74/// Flatten strategy for fields that already implement Merge
75///
76/// Use this when you want to aggregate a field that is itself an aggregatable type.
77pub struct Flatten;
78
79impl<T> AggregateValue<T> for Flatten
80where
81    T: crate::traits::Merge,
82{
83    type Aggregated = T::Merged;
84
85    fn insert(accum: &mut Self::Aggregated, value: T) {
86        T::merge(accum, value);
87    }
88}
89
90/// Distribution preserves all values while compressing duplicates
91///
92/// This is effectively a type alias for `Histogram<T, SortAndMerge>`, however,
93/// when used as an aggregate strategy, it avoids the needs to name `T`.
94pub struct Distribution;
95impl<T: MetricValue> AggregateValue<T> for Distribution {
96    type Aggregated = Histogram<T, SortAndMerge>;
97
98    fn insert(accum: &mut Self::Aggregated, value: T) {
99        accum.add_value(value);
100    }
101}
102
103/// Key type for aggregations with no key fields
104#[derive(Clone, Hash, PartialEq, Eq)]
105pub struct NoKey;
106
107impl<T> crate::traits::Key<T> for NoKey {
108    type Key<'a> = NoKey;
109
110    fn from_source(_source: &T) -> Self::Key<'_> {
111        NoKey
112    }
113
114    fn static_key<'a>(_key: &Self::Key<'a>) -> Self::Key<'static> {
115        NoKey
116    }
117
118    fn static_key_matches<'a>(_owned: &Self::Key<'static>, _borrowed: &Self::Key<'a>) -> bool {
119        true
120    }
121}
122
123impl metrique_core::CloseValue for NoKey {
124    type Closed = Self;
125
126    fn close(self) -> Self::Closed {
127        self
128    }
129}
130
131impl<NS: metrique_core::NameStyle> metrique_core::InflectableEntry<NS> for NoKey {
132    fn write<'a>(&'a self, _w: &mut impl metrique_writer::EntryWriter<'a>) {}
133}
134
135impl metrique_writer::Entry for NoKey {
136    fn write<'a>(&'a self, _w: &mut impl metrique_writer::EntryWriter<'a>) {}
137
138    fn sample_group(
139        &self,
140    ) -> impl Iterator<Item = metrique_writer_core::entry::SampleGroupElement> {
141        std::iter::empty()
142    }
143}