opentelemetry_proto/transform/
metrics.rs1#[allow(deprecated)]
6#[cfg(feature = "gen-tonic-messages")]
7pub mod tonic {
8 use std::fmt::Debug;
9
10 use opentelemetry::{otel_debug, Key, Value};
11 use opentelemetry_sdk::metrics::data::{
12 AggregatedMetrics, Exemplar as SdkExemplar,
13 ExponentialHistogram as SdkExponentialHistogram, Gauge as SdkGauge,
14 Histogram as SdkHistogram, Metric as SdkMetric, MetricData, ResourceMetrics,
15 ScopeMetrics as SdkScopeMetrics, Sum as SdkSum,
16 };
17 use opentelemetry_sdk::metrics::Temporality;
18 use opentelemetry_sdk::Resource as SdkResource;
19
20 use crate::proto::tonic::{
21 collector::metrics::v1::ExportMetricsServiceRequest,
22 common::v1::KeyValue,
23 metrics::v1::{
24 exemplar, exemplar::Value as TonicExemplarValue,
25 exponential_histogram_data_point::Buckets as TonicBuckets,
26 metric::Data as TonicMetricData, number_data_point,
27 number_data_point::Value as TonicDataPointValue,
28 AggregationTemporality as TonicTemporality, AggregationTemporality,
29 DataPointFlags as TonicDataPointFlags, Exemplar as TonicExemplar,
30 ExponentialHistogram as TonicExponentialHistogram,
31 ExponentialHistogramDataPoint as TonicExponentialHistogramDataPoint,
32 Gauge as TonicGauge, Histogram as TonicHistogram,
33 HistogramDataPoint as TonicHistogramDataPoint, Metric as TonicMetric,
34 NumberDataPoint as TonicNumberDataPoint, ResourceMetrics as TonicResourceMetrics,
35 ScopeMetrics as TonicScopeMetrics, Sum as TonicSum,
36 },
37 resource::v1::Resource as TonicResource,
38 };
39 use crate::transform::common::to_nanos;
40
41 impl From<u64> for exemplar::Value {
42 fn from(value: u64) -> Self {
43 exemplar::Value::AsInt(i64::try_from(value).unwrap_or_default())
44 }
45 }
46
47 impl From<i64> for exemplar::Value {
48 fn from(value: i64) -> Self {
49 exemplar::Value::AsInt(value)
50 }
51 }
52
53 impl From<f64> for exemplar::Value {
54 fn from(value: f64) -> Self {
55 exemplar::Value::AsDouble(value)
56 }
57 }
58
59 impl From<u64> for number_data_point::Value {
60 fn from(value: u64) -> Self {
61 number_data_point::Value::AsInt(i64::try_from(value).unwrap_or_default())
62 }
63 }
64
65 impl From<i64> for number_data_point::Value {
66 fn from(value: i64) -> Self {
67 number_data_point::Value::AsInt(value)
68 }
69 }
70
71 impl From<f64> for number_data_point::Value {
72 fn from(value: f64) -> Self {
73 number_data_point::Value::AsDouble(value)
74 }
75 }
76
77 impl From<(&Key, &Value)> for KeyValue {
78 fn from(kv: (&Key, &Value)) -> Self {
79 KeyValue {
80 key: kv.0.to_string(),
81 value: Some(kv.1.clone().into()),
82 }
83 }
84 }
85
86 impl From<&opentelemetry::KeyValue> for KeyValue {
87 fn from(kv: &opentelemetry::KeyValue) -> Self {
88 KeyValue {
89 key: kv.key.to_string(),
90 value: Some(kv.value.clone().into()),
91 }
92 }
93 }
94
95 impl From<Temporality> for AggregationTemporality {
96 fn from(temporality: Temporality) -> Self {
97 match temporality {
98 Temporality::Cumulative => AggregationTemporality::Cumulative,
99 Temporality::Delta => AggregationTemporality::Delta,
100 other => {
101 otel_debug!(
102 name: "AggregationTemporality::Unknown",
103 message = "Unknown temporality,using default instead.",
104 unknown_temporality = format!("{:?}", other),
105 default_temporality = format!("{:?}", Temporality::Cumulative)
106 );
107 AggregationTemporality::Cumulative
108 }
109 }
110 }
111 }
112
113 impl From<&ResourceMetrics> for ExportMetricsServiceRequest {
114 fn from(rm: &ResourceMetrics) -> Self {
115 ExportMetricsServiceRequest {
116 resource_metrics: vec![TonicResourceMetrics {
117 resource: Some((rm.resource()).into()),
118 scope_metrics: rm.scope_metrics().map(Into::into).collect(),
119 schema_url: rm
120 .resource()
121 .schema_url()
122 .map(Into::into)
123 .unwrap_or_default(),
124 }],
125 }
126 }
127 }
128
129 impl From<&SdkResource> for TonicResource {
130 fn from(resource: &SdkResource) -> Self {
131 TonicResource {
132 attributes: resource.iter().map(Into::into).collect(),
133 dropped_attributes_count: 0,
134 entity_refs: vec![], }
136 }
137 }
138
139 impl From<&SdkScopeMetrics> for TonicScopeMetrics {
140 fn from(sm: &SdkScopeMetrics) -> Self {
141 TonicScopeMetrics {
142 scope: Some((sm.scope(), None).into()),
143 metrics: sm.metrics().map(Into::into).collect(),
144 schema_url: sm
145 .scope()
146 .schema_url()
147 .map(ToOwned::to_owned)
148 .unwrap_or_default(),
149 }
150 }
151 }
152
153 impl From<&SdkMetric> for TonicMetric {
154 fn from(metric: &SdkMetric) -> Self {
155 TonicMetric {
156 name: metric.name().to_string(),
157 description: metric.description().to_string(),
158 unit: metric.unit().to_string(),
159 metadata: vec![], data: Some(match metric.data() {
161 AggregatedMetrics::F64(data) => data.into(),
162 AggregatedMetrics::U64(data) => data.into(),
163 AggregatedMetrics::I64(data) => data.into(),
164 }),
165 }
166 }
167 }
168
169 impl<T> From<&MetricData<T>> for TonicMetricData
170 where
171 T: Numeric + Debug,
172 {
173 fn from(data: &MetricData<T>) -> Self {
174 match data {
175 MetricData::Gauge(gauge) => TonicMetricData::Gauge(gauge.into()),
176 MetricData::Sum(sum) => TonicMetricData::Sum(sum.into()),
177 MetricData::Histogram(hist) => TonicMetricData::Histogram(hist.into()),
178 MetricData::ExponentialHistogram(hist) => {
179 TonicMetricData::ExponentialHistogram(hist.into())
180 }
181 }
182 }
183 }
184
185 trait Numeric: Into<TonicExemplarValue> + Into<TonicDataPointValue> + Copy {
186 fn into_f64(self) -> f64;
188 }
189
190 impl Numeric for u64 {
191 fn into_f64(self) -> f64 {
192 self as f64
193 }
194 }
195
196 impl Numeric for i64 {
197 fn into_f64(self) -> f64 {
198 self as f64
199 }
200 }
201
202 impl Numeric for f64 {
203 fn into_f64(self) -> f64 {
204 self
205 }
206 }
207
208 impl<T> From<&SdkHistogram<T>> for TonicHistogram
209 where
210 T: Numeric,
211 {
212 fn from(hist: &SdkHistogram<T>) -> Self {
213 TonicHistogram {
214 data_points: hist
215 .data_points()
216 .map(|dp| TonicHistogramDataPoint {
217 attributes: dp.attributes().map(Into::into).collect(),
218 start_time_unix_nano: to_nanos(hist.start_time()),
219 time_unix_nano: to_nanos(hist.time()),
220 count: dp.count(),
221 sum: Some(dp.sum().into_f64()),
222 bucket_counts: dp.bucket_counts().collect(),
223 explicit_bounds: dp.bounds().collect(),
224 exemplars: dp.exemplars().map(Into::into).collect(),
225 flags: TonicDataPointFlags::default() as u32,
226 min: dp.min().map(Numeric::into_f64),
227 max: dp.max().map(Numeric::into_f64),
228 })
229 .collect(),
230 aggregation_temporality: TonicTemporality::from(hist.temporality()).into(),
231 }
232 }
233 }
234
235 impl<T> From<&SdkExponentialHistogram<T>> for TonicExponentialHistogram
236 where
237 T: Numeric,
238 {
239 fn from(hist: &SdkExponentialHistogram<T>) -> Self {
240 TonicExponentialHistogram {
241 data_points: hist
242 .data_points()
243 .map(|dp| TonicExponentialHistogramDataPoint {
244 attributes: dp.attributes().map(Into::into).collect(),
245 start_time_unix_nano: to_nanos(hist.start_time()),
246 time_unix_nano: to_nanos(hist.time()),
247 count: dp.count() as u64,
248 sum: Some(dp.sum().into_f64()),
249 scale: dp.scale().into(),
250 zero_count: dp.zero_count(),
251 positive: Some(TonicBuckets {
252 offset: dp.positive_bucket().offset(),
253 bucket_counts: dp.positive_bucket().counts().collect(),
254 }),
255 negative: Some(TonicBuckets {
256 offset: dp.negative_bucket().offset(),
257 bucket_counts: dp.negative_bucket().counts().collect(),
258 }),
259 flags: TonicDataPointFlags::default() as u32,
260 exemplars: dp.exemplars().map(Into::into).collect(),
261 min: dp.min().map(Numeric::into_f64),
262 max: dp.max().map(Numeric::into_f64),
263 zero_threshold: dp.zero_threshold(),
264 })
265 .collect(),
266 aggregation_temporality: TonicTemporality::from(hist.temporality()).into(),
267 }
268 }
269 }
270
271 impl<T> From<&SdkSum<T>> for TonicSum
272 where
273 T: Debug + Into<TonicExemplarValue> + Into<TonicDataPointValue> + Copy,
274 {
275 fn from(sum: &SdkSum<T>) -> Self {
276 TonicSum {
277 data_points: sum
278 .data_points()
279 .map(|dp| TonicNumberDataPoint {
280 attributes: dp.attributes().map(Into::into).collect(),
281 start_time_unix_nano: to_nanos(sum.start_time()),
282 time_unix_nano: to_nanos(sum.time()),
283 exemplars: dp.exemplars().map(Into::into).collect(),
284 flags: TonicDataPointFlags::default() as u32,
285 value: Some(dp.value().into()),
286 })
287 .collect(),
288 aggregation_temporality: TonicTemporality::from(sum.temporality()).into(),
289 is_monotonic: sum.is_monotonic(),
290 }
291 }
292 }
293
294 impl<T> From<&SdkGauge<T>> for TonicGauge
295 where
296 T: Debug + Into<TonicExemplarValue> + Into<TonicDataPointValue> + Copy,
297 {
298 fn from(gauge: &SdkGauge<T>) -> Self {
299 TonicGauge {
300 data_points: gauge
301 .data_points()
302 .map(|dp| TonicNumberDataPoint {
303 attributes: dp.attributes().map(Into::into).collect(),
304 start_time_unix_nano: gauge.start_time().map(to_nanos).unwrap_or_default(),
305 time_unix_nano: to_nanos(gauge.time()),
306 exemplars: dp.exemplars().map(Into::into).collect(),
307 flags: TonicDataPointFlags::default() as u32,
308 value: Some(dp.value().into()),
309 })
310 .collect(),
311 }
312 }
313 }
314
315 impl<T> From<&SdkExemplar<T>> for TonicExemplar
316 where
317 T: Into<TonicExemplarValue> + Copy,
318 {
319 fn from(ex: &SdkExemplar<T>) -> Self {
320 TonicExemplar {
321 filtered_attributes: ex
322 .filtered_attributes()
323 .map(|kv| (&kv.key, &kv.value).into())
324 .collect(),
325 time_unix_nano: to_nanos(ex.time()),
326 span_id: ex.span_id().into(),
327 trace_id: ex.trace_id().into(),
328 value: Some(ex.value.into()),
329 }
330 }
331 }
332}