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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
//! Types for delivery of pre-aggregated metric time series data.

use std::{any, borrow::Cow, fmt, time::SystemTime};

use opentelemetry::KeyValue;

use crate::{instrumentation::Scope, Resource};

pub use self::temporality::Temporality;

mod temporality;

/// A collection of [ScopeMetrics] and the associated [Resource] that created them.
#[derive(Debug)]
pub struct ResourceMetrics {
    /// The entity that collected the metrics.
    pub resource: Resource,
    /// The collection of metrics with unique [Scope]s.
    pub scope_metrics: Vec<ScopeMetrics>,
}

/// A collection of metrics produced by a meter.
#[derive(Default, Debug)]
pub struct ScopeMetrics {
    /// The [Scope] that the meter was created with.
    pub scope: Scope,
    /// The list of aggregations created by the meter.
    pub metrics: Vec<Metric>,
}

/// A collection of one or more aggregated time series from an [Instrument].
///
/// [Instrument]: crate::metrics::Instrument
#[derive(Debug)]
pub struct Metric {
    /// The name of the instrument that created this data.
    pub name: Cow<'static, str>,
    /// The description of the instrument, which can be used in documentation.
    pub description: Cow<'static, str>,
    /// The unit in which the instrument reports.
    pub unit: Cow<'static, str>,
    /// The aggregated data from an instrument.
    pub data: Box<dyn Aggregation>,
}

/// The store of data reported by an [Instrument].
///
/// It will be one of: [Gauge], [Sum], or [Histogram].
///
/// [Instrument]: crate::metrics::Instrument
pub trait Aggregation: fmt::Debug + any::Any + Send + Sync {
    /// Support downcasting
    fn as_any(&self) -> &dyn any::Any;
    /// Support downcasting during aggregation
    fn as_mut(&mut self) -> &mut dyn any::Any;
}

/// A measurement of the current value of an instrument.
#[derive(Debug)]
pub struct Gauge<T> {
    /// Represents individual aggregated measurements with unique attributes.
    pub data_points: Vec<DataPoint<T>>,
}

impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for Gauge<T> {
    fn as_any(&self) -> &dyn any::Any {
        self
    }
    fn as_mut(&mut self) -> &mut dyn any::Any {
        self
    }
}

/// Represents the sum of all measurements of values from an instrument.
#[derive(Debug)]
pub struct Sum<T> {
    /// Represents individual aggregated measurements with unique attributes.
    pub data_points: Vec<DataPoint<T>>,
    /// Describes if the aggregation is reported as the change from the last report
    /// time, or the cumulative changes since a fixed start time.
    pub temporality: Temporality,
    /// Whether this aggregation only increases or decreases.
    pub is_monotonic: bool,
}

impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for Sum<T> {
    fn as_any(&self) -> &dyn any::Any {
        self
    }
    fn as_mut(&mut self) -> &mut dyn any::Any {
        self
    }
}

/// DataPoint is a single data point in a time series.
#[derive(Debug)]
pub struct DataPoint<T> {
    /// Attributes is the set of key value pairs that uniquely identify the
    /// time series.
    pub attributes: Vec<KeyValue>,
    /// The time when the time series was started.
    pub start_time: Option<SystemTime>,
    /// The time when the time series was recorded.
    pub time: Option<SystemTime>,
    /// The value of this data point.
    pub value: T,
    /// The sampled [Exemplar]s collected during the time series.
    pub exemplars: Vec<Exemplar<T>>,
}

impl<T: Copy> Clone for DataPoint<T> {
    fn clone(&self) -> Self {
        Self {
            attributes: self.attributes.clone(),
            start_time: self.start_time,
            time: self.time,
            value: self.value,
            exemplars: self.exemplars.clone(),
        }
    }
}

/// Represents the histogram of all measurements of values from an instrument.
#[derive(Debug)]
pub struct Histogram<T> {
    /// Individual aggregated measurements with unique attributes.
    pub data_points: Vec<HistogramDataPoint<T>>,
    /// Describes if the aggregation is reported as the change from the last report
    /// time, or the cumulative changes since a fixed start time.
    pub temporality: Temporality,
}

impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for Histogram<T> {
    fn as_any(&self) -> &dyn any::Any {
        self
    }
    fn as_mut(&mut self) -> &mut dyn any::Any {
        self
    }
}

/// A single histogram data point in a time series.
#[derive(Debug)]
pub struct HistogramDataPoint<T> {
    /// The set of key value pairs that uniquely identify the time series.
    pub attributes: Vec<KeyValue>,
    /// The time when the time series was started.
    pub start_time: SystemTime,
    /// The time when the time series was recorded.
    pub time: SystemTime,

    /// The number of updates this histogram has been calculated with.
    pub count: u64,
    /// The upper bounds of the buckets of the histogram.
    ///
    /// Because the last boundary is +infinity this one is implied.
    pub bounds: Vec<f64>,
    /// The count of each of the buckets.
    pub bucket_counts: Vec<u64>,

    /// The minimum value recorded.
    pub min: Option<T>,
    /// The maximum value recorded.
    pub max: Option<T>,
    /// The sum of the values recorded.
    pub sum: T,

    /// The sampled [Exemplar]s collected during the time series.
    pub exemplars: Vec<Exemplar<T>>,
}

impl<T: Copy> Clone for HistogramDataPoint<T> {
    fn clone(&self) -> Self {
        Self {
            attributes: self.attributes.clone(),
            start_time: self.start_time,
            time: self.time,
            count: self.count,
            bounds: self.bounds.clone(),
            bucket_counts: self.bucket_counts.clone(),
            min: self.min,
            max: self.max,
            sum: self.sum,
            exemplars: self.exemplars.clone(),
        }
    }
}

/// The histogram of all measurements of values from an instrument.
#[derive(Debug)]
pub struct ExponentialHistogram<T> {
    /// The individual aggregated measurements with unique attributes.
    pub data_points: Vec<ExponentialHistogramDataPoint<T>>,

    /// Describes if the aggregation is reported as the change from the last report
    /// time, or the cumulative changes since a fixed start time.
    pub temporality: Temporality,
}

impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for ExponentialHistogram<T> {
    fn as_any(&self) -> &dyn any::Any {
        self
    }
    fn as_mut(&mut self) -> &mut dyn any::Any {
        self
    }
}

/// A single exponential histogram data point in a time series.
#[derive(Debug)]
pub struct ExponentialHistogramDataPoint<T> {
    /// The set of key value pairs that uniquely identify the time series.
    pub attributes: Vec<KeyValue>,
    /// When the time series was started.
    pub start_time: SystemTime,
    /// The time when the time series was recorded.
    pub time: SystemTime,

    /// The number of updates this histogram has been calculated with.
    pub count: usize,
    /// The minimum value recorded.
    pub min: Option<T>,
    /// The maximum value recorded.
    pub max: Option<T>,
    /// The sum of the values recorded.
    pub sum: T,

    /// Describes the resolution of the histogram.
    ///
    /// Boundaries are located at powers of the base, where:
    ///
    ///   base = 2 ^ (2 ^ -scale)
    pub scale: i8,

    /// The number of values whose absolute value is less than or equal to
    /// `zero_threshold`.
    ///
    /// When `zero_threshold` is `0`, this is the number of values that cannot be
    /// expressed using the standard exponential formula as well as values that have
    /// been rounded to zero.
    pub zero_count: u64,

    /// The range of positive value bucket counts.
    pub positive_bucket: ExponentialBucket,
    /// The range of negative value bucket counts.
    pub negative_bucket: ExponentialBucket,

    /// The width of the zero region.
    ///
    /// Where the zero region is defined as the closed interval
    /// [-zero_threshold, zero_threshold].
    pub zero_threshold: f64,

    /// The sampled exemplars collected during the time series.
    pub exemplars: Vec<Exemplar<T>>,
}

/// A set of bucket counts, encoded in a contiguous array of counts.
#[derive(Debug, PartialEq)]
pub struct ExponentialBucket {
    /// The bucket index of the first entry in the `counts` vec.
    pub offset: i32,

    /// A vec where `counts[i]` carries the count of the bucket at index `offset + i`.
    ///
    /// `counts[i]` is the count of values greater than base^(offset+i) and less than
    /// or equal to base^(offset+i+1).
    pub counts: Vec<u64>,
}

/// A measurement sampled from a time series providing a typical example.
#[derive(Debug)]
pub struct Exemplar<T> {
    /// The attributes recorded with the measurement but filtered out of the
    /// time series' aggregated data.
    pub filtered_attributes: Vec<KeyValue>,
    /// The time when the measurement was recorded.
    pub time: SystemTime,
    /// The measured value.
    pub value: T,
    /// The ID of the span that was active during the measurement.
    ///
    /// If no span was active or the span was not sampled this will be empty.
    pub span_id: [u8; 8],
    /// The ID of the trace the active span belonged to during the measurement.
    ///
    /// If no span was active or the span was not sampled this will be empty.
    pub trace_id: [u8; 16],
}

impl<T: Copy> Clone for Exemplar<T> {
    fn clone(&self) -> Self {
        Self {
            filtered_attributes: self.filtered_attributes.clone(),
            time: self.time,
            value: self.value,
            span_id: self.span_id,
            trace_id: self.trace_id,
        }
    }
}