opentelemetry_sdk/metrics/data/
mod.rs

1//! Types for delivery of pre-aggregated metric time series data.
2
3use std::{any, borrow::Cow, fmt, time::SystemTime};
4
5use opentelemetry::KeyValue;
6
7use crate::{instrumentation::Scope, Resource};
8
9pub use self::temporality::Temporality;
10
11mod temporality;
12
13/// A collection of [ScopeMetrics] and the associated [Resource] that created them.
14#[derive(Debug)]
15pub struct ResourceMetrics {
16    /// The entity that collected the metrics.
17    pub resource: Resource,
18    /// The collection of metrics with unique [Scope]s.
19    pub scope_metrics: Vec<ScopeMetrics>,
20}
21
22/// A collection of metrics produced by a meter.
23#[derive(Default, Debug)]
24pub struct ScopeMetrics {
25    /// The [Scope] that the meter was created with.
26    pub scope: Scope,
27    /// The list of aggregations created by the meter.
28    pub metrics: Vec<Metric>,
29}
30
31/// A collection of one or more aggregated time series from an [Instrument].
32///
33/// [Instrument]: crate::metrics::Instrument
34#[derive(Debug)]
35pub struct Metric {
36    /// The name of the instrument that created this data.
37    pub name: Cow<'static, str>,
38    /// The description of the instrument, which can be used in documentation.
39    pub description: Cow<'static, str>,
40    /// The unit in which the instrument reports.
41    pub unit: Cow<'static, str>,
42    /// The aggregated data from an instrument.
43    pub data: Box<dyn Aggregation>,
44}
45
46/// The store of data reported by an [Instrument].
47///
48/// It will be one of: [Gauge], [Sum], or [Histogram].
49///
50/// [Instrument]: crate::metrics::Instrument
51pub trait Aggregation: fmt::Debug + any::Any + Send + Sync {
52    /// Support downcasting
53    fn as_any(&self) -> &dyn any::Any;
54    /// Support downcasting during aggregation
55    fn as_mut(&mut self) -> &mut dyn any::Any;
56}
57
58/// A measurement of the current value of an instrument.
59#[derive(Debug)]
60pub struct Gauge<T> {
61    /// Represents individual aggregated measurements with unique attributes.
62    pub data_points: Vec<DataPoint<T>>,
63}
64
65impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for Gauge<T> {
66    fn as_any(&self) -> &dyn any::Any {
67        self
68    }
69    fn as_mut(&mut self) -> &mut dyn any::Any {
70        self
71    }
72}
73
74/// Represents the sum of all measurements of values from an instrument.
75#[derive(Debug)]
76pub struct Sum<T> {
77    /// Represents individual aggregated measurements with unique attributes.
78    pub data_points: Vec<DataPoint<T>>,
79    /// Describes if the aggregation is reported as the change from the last report
80    /// time, or the cumulative changes since a fixed start time.
81    pub temporality: Temporality,
82    /// Whether this aggregation only increases or decreases.
83    pub is_monotonic: bool,
84}
85
86impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for Sum<T> {
87    fn as_any(&self) -> &dyn any::Any {
88        self
89    }
90    fn as_mut(&mut self) -> &mut dyn any::Any {
91        self
92    }
93}
94
95/// DataPoint is a single data point in a time series.
96#[derive(Debug)]
97pub struct DataPoint<T> {
98    /// Attributes is the set of key value pairs that uniquely identify the
99    /// time series.
100    pub attributes: Vec<KeyValue>,
101    /// The time when the time series was started.
102    pub start_time: Option<SystemTime>,
103    /// The time when the time series was recorded.
104    pub time: Option<SystemTime>,
105    /// The value of this data point.
106    pub value: T,
107    /// The sampled [Exemplar]s collected during the time series.
108    pub exemplars: Vec<Exemplar<T>>,
109}
110
111impl<T: Copy> Clone for DataPoint<T> {
112    fn clone(&self) -> Self {
113        Self {
114            attributes: self.attributes.clone(),
115            start_time: self.start_time,
116            time: self.time,
117            value: self.value,
118            exemplars: self.exemplars.clone(),
119        }
120    }
121}
122
123/// Represents the histogram of all measurements of values from an instrument.
124#[derive(Debug)]
125pub struct Histogram<T> {
126    /// Individual aggregated measurements with unique attributes.
127    pub data_points: Vec<HistogramDataPoint<T>>,
128    /// Describes if the aggregation is reported as the change from the last report
129    /// time, or the cumulative changes since a fixed start time.
130    pub temporality: Temporality,
131}
132
133impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for Histogram<T> {
134    fn as_any(&self) -> &dyn any::Any {
135        self
136    }
137    fn as_mut(&mut self) -> &mut dyn any::Any {
138        self
139    }
140}
141
142/// A single histogram data point in a time series.
143#[derive(Debug)]
144pub struct HistogramDataPoint<T> {
145    /// The set of key value pairs that uniquely identify the time series.
146    pub attributes: Vec<KeyValue>,
147    /// The time when the time series was started.
148    pub start_time: SystemTime,
149    /// The time when the time series was recorded.
150    pub time: SystemTime,
151
152    /// The number of updates this histogram has been calculated with.
153    pub count: u64,
154    /// The upper bounds of the buckets of the histogram.
155    ///
156    /// Because the last boundary is +infinity this one is implied.
157    pub bounds: Vec<f64>,
158    /// The count of each of the buckets.
159    pub bucket_counts: Vec<u64>,
160
161    /// The minimum value recorded.
162    pub min: Option<T>,
163    /// The maximum value recorded.
164    pub max: Option<T>,
165    /// The sum of the values recorded.
166    pub sum: T,
167
168    /// The sampled [Exemplar]s collected during the time series.
169    pub exemplars: Vec<Exemplar<T>>,
170}
171
172impl<T: Copy> Clone for HistogramDataPoint<T> {
173    fn clone(&self) -> Self {
174        Self {
175            attributes: self.attributes.clone(),
176            start_time: self.start_time,
177            time: self.time,
178            count: self.count,
179            bounds: self.bounds.clone(),
180            bucket_counts: self.bucket_counts.clone(),
181            min: self.min,
182            max: self.max,
183            sum: self.sum,
184            exemplars: self.exemplars.clone(),
185        }
186    }
187}
188
189/// The histogram of all measurements of values from an instrument.
190#[derive(Debug)]
191pub struct ExponentialHistogram<T> {
192    /// The individual aggregated measurements with unique attributes.
193    pub data_points: Vec<ExponentialHistogramDataPoint<T>>,
194
195    /// Describes if the aggregation is reported as the change from the last report
196    /// time, or the cumulative changes since a fixed start time.
197    pub temporality: Temporality,
198}
199
200impl<T: fmt::Debug + Send + Sync + 'static> Aggregation for ExponentialHistogram<T> {
201    fn as_any(&self) -> &dyn any::Any {
202        self
203    }
204    fn as_mut(&mut self) -> &mut dyn any::Any {
205        self
206    }
207}
208
209/// A single exponential histogram data point in a time series.
210#[derive(Debug)]
211pub struct ExponentialHistogramDataPoint<T> {
212    /// The set of key value pairs that uniquely identify the time series.
213    pub attributes: Vec<KeyValue>,
214    /// When the time series was started.
215    pub start_time: SystemTime,
216    /// The time when the time series was recorded.
217    pub time: SystemTime,
218
219    /// The number of updates this histogram has been calculated with.
220    pub count: usize,
221    /// The minimum value recorded.
222    pub min: Option<T>,
223    /// The maximum value recorded.
224    pub max: Option<T>,
225    /// The sum of the values recorded.
226    pub sum: T,
227
228    /// Describes the resolution of the histogram.
229    ///
230    /// Boundaries are located at powers of the base, where:
231    ///
232    ///   base = 2 ^ (2 ^ -scale)
233    pub scale: i8,
234
235    /// The number of values whose absolute value is less than or equal to
236    /// `zero_threshold`.
237    ///
238    /// When `zero_threshold` is `0`, this is the number of values that cannot be
239    /// expressed using the standard exponential formula as well as values that have
240    /// been rounded to zero.
241    pub zero_count: u64,
242
243    /// The range of positive value bucket counts.
244    pub positive_bucket: ExponentialBucket,
245    /// The range of negative value bucket counts.
246    pub negative_bucket: ExponentialBucket,
247
248    /// The width of the zero region.
249    ///
250    /// Where the zero region is defined as the closed interval
251    /// [-zero_threshold, zero_threshold].
252    pub zero_threshold: f64,
253
254    /// The sampled exemplars collected during the time series.
255    pub exemplars: Vec<Exemplar<T>>,
256}
257
258/// A set of bucket counts, encoded in a contiguous array of counts.
259#[derive(Debug, PartialEq)]
260pub struct ExponentialBucket {
261    /// The bucket index of the first entry in the `counts` vec.
262    pub offset: i32,
263
264    /// A vec where `counts[i]` carries the count of the bucket at index `offset + i`.
265    ///
266    /// `counts[i]` is the count of values greater than base^(offset+i) and less than
267    /// or equal to base^(offset+i+1).
268    pub counts: Vec<u64>,
269}
270
271/// A measurement sampled from a time series providing a typical example.
272#[derive(Debug)]
273pub struct Exemplar<T> {
274    /// The attributes recorded with the measurement but filtered out of the
275    /// time series' aggregated data.
276    pub filtered_attributes: Vec<KeyValue>,
277    /// The time when the measurement was recorded.
278    pub time: SystemTime,
279    /// The measured value.
280    pub value: T,
281    /// The ID of the span that was active during the measurement.
282    ///
283    /// If no span was active or the span was not sampled this will be empty.
284    pub span_id: [u8; 8],
285    /// The ID of the trace the active span belonged to during the measurement.
286    ///
287    /// If no span was active or the span was not sampled this will be empty.
288    pub trace_id: [u8; 16],
289}
290
291impl<T: Copy> Clone for Exemplar<T> {
292    fn clone(&self) -> Self {
293        Self {
294            filtered_attributes: self.filtered_attributes.clone(),
295            time: self.time,
296            value: self.value,
297            span_id: self.span_id,
298            trace_id: self.trace_id,
299        }
300    }
301}