1use crate::wasi;
2use std::borrow::Cow;
3
4impl From<wasi::otel::metrics::ResourceMetrics>
5 for opentelemetry_sdk::metrics::data::ResourceMetrics
6{
7 fn from(value: wasi::otel::metrics::ResourceMetrics) -> Self {
8 Self {
9 resource: value.resource.into(),
10 scope_metrics: value.scope_metrics.into_iter().map(Into::into).collect(),
11 }
12 }
13}
14
15impl From<wasi::otel::metrics::Resource> for opentelemetry_sdk::Resource {
16 fn from(value: wasi::otel::metrics::Resource) -> Self {
17 let attributes: Vec<opentelemetry::KeyValue> =
18 value.attributes.into_iter().map(Into::into).collect();
19 let schema_url: Option<String> = value.schema_url;
20 match schema_url {
21 Some(url) => opentelemetry_sdk::resource::Resource::builder()
22 .with_schema_url(attributes, url)
23 .build(),
24 None => opentelemetry_sdk::resource::Resource::builder()
25 .with_attributes(attributes)
26 .build(),
27 }
28 }
29}
30
31impl From<wasi::otel::metrics::ScopeMetrics> for opentelemetry_sdk::metrics::data::ScopeMetrics {
32 fn from(value: wasi::otel::metrics::ScopeMetrics) -> Self {
33 Self {
34 scope: value.scope.into(),
35 metrics: value.metrics.into_iter().map(Into::into).collect(),
36 }
37 }
38}
39
40impl From<wasi::otel::metrics::Metric> for opentelemetry_sdk::metrics::data::Metric {
41 fn from(value: wasi::otel::metrics::Metric) -> Self {
42 Self {
43 name: Cow::Owned(value.name),
44 description: Cow::Owned(value.description),
45 unit: Cow::Owned(value.unit),
46 data: value.data.into(),
47 }
48 }
49}
50
51macro_rules! exemplars_to_otel {
53 (
54 $wasi_exemplar_list:expr,
55 $exemplar_type:ty
56 ) => {
57 $wasi_exemplar_list
58 .iter()
59 .map(|e| {
60 let span_id: [u8; 8] = e
61 .span_id
62 .as_bytes()
63 .try_into()
64 .expect("failed to parse span ID");
65 let trace_id: [u8; 16] = e
66 .trace_id
67 .as_bytes()
68 .try_into()
69 .expect("failed to parse trace ID");
70 opentelemetry_sdk::metrics::data::Exemplar::<$exemplar_type> {
71 filtered_attributes: e
72 .filtered_attributes
73 .to_owned()
74 .into_iter()
75 .map(Into::into)
76 .collect(),
77 time: e.time.into(),
78 value: e.value.into(),
79 span_id,
80 trace_id,
81 }
82 })
83 .collect()
84 };
85}
86
87macro_rules! wasi_gauge_to_otel {
89 ($gauge:expr, $number_type:ty) => {
90 Box::new(opentelemetry_sdk::metrics::data::Gauge {
91 data_points: $gauge
92 .data_points
93 .iter()
94 .map(|dp| opentelemetry_sdk::metrics::data::GaugeDataPoint {
95 attributes: dp.attributes.iter().map(Into::into).collect(),
96 value: dp.value.into(),
97 exemplars: exemplars_to_otel!(dp.exemplars, $number_type),
98 })
99 .collect(),
100 start_time: match $gauge.start_time {
101 Some(t) => Some(t.into()),
102 None => None,
103 },
104 time: $gauge.time.into(),
105 })
106 };
107}
108
109macro_rules! wasi_sum_to_otel {
111 ($sum:expr, $number_type:ty) => {
112 Box::new(opentelemetry_sdk::metrics::data::Sum {
113 data_points: $sum
114 .data_points
115 .iter()
116 .map(|dp| opentelemetry_sdk::metrics::data::SumDataPoint {
117 attributes: dp.attributes.iter().map(Into::into).collect(),
118 exemplars: exemplars_to_otel!(dp.exemplars, $number_type),
119 value: dp.value.into(),
120 })
121 .collect(),
122 start_time: $sum.start_time.into(),
123 time: $sum.time.into(),
124 temporality: $sum.temporality.into(),
125 is_monotonic: $sum.is_monotonic,
126 })
127 };
128}
129
130macro_rules! wasi_histogram_to_otel {
132 ($histogram:expr, $number_type:ty) => {
133 Box::new(opentelemetry_sdk::metrics::data::Histogram {
134 data_points: $histogram
135 .data_points
136 .iter()
137 .map(|dp| opentelemetry_sdk::metrics::data::HistogramDataPoint {
138 attributes: dp.attributes.iter().map(Into::into).collect(),
139 bounds: dp.bounds.to_owned(),
140 bucket_counts: dp.bucket_counts.to_owned(),
141 exemplars: exemplars_to_otel!(dp.exemplars, $number_type),
142 count: dp.count,
143 max: match dp.max {
144 Some(m) => Some(m.into()),
145 None => None,
146 },
147 min: match dp.min {
148 Some(m) => Some(m.into()),
149 None => None,
150 },
151 sum: dp.sum.into(),
152 })
153 .collect(),
154 start_time: $histogram.start_time.into(),
155 time: $histogram.time.into(),
156 temporality: $histogram.temporality.into(),
157 })
158 };
159}
160
161macro_rules! wasi_exponential_histogram_to_otel {
163 ($histogram:expr, $number_type:ty) => {
164 Box::new(opentelemetry_sdk::metrics::data::ExponentialHistogram {
165 data_points: $histogram
166 .data_points
167 .iter()
168 .map(
169 |dp| opentelemetry_sdk::metrics::data::ExponentialHistogramDataPoint {
170 attributes: dp.attributes.iter().map(Into::into).collect(),
171 exemplars: exemplars_to_otel!(dp.exemplars, $number_type),
172 count: dp.count as usize,
173 max: match dp.max {
174 Some(m) => Some(m.into()),
175 None => None,
176 },
177 min: match dp.min {
178 Some(m) => Some(m.into()),
179 None => None,
180 },
181 sum: dp.sum.into(),
182 scale: dp.scale,
183 zero_count: dp.zero_count,
184 positive_bucket: dp.positive_bucket.to_owned().into(),
185 negative_bucket: dp.negative_bucket.to_owned().into(),
186 zero_threshold: dp.zero_threshold,
187 },
188 )
189 .collect(),
190 start_time: $histogram.start_time.into(),
191 time: $histogram.time.into(),
192 temporality: $histogram.temporality.into(),
193 })
194 };
195}
196
197impl From<wasi::otel::metrics::MetricData>
198 for Box<dyn opentelemetry_sdk::metrics::data::Aggregation>
199{
200 fn from(value: wasi::otel::metrics::MetricData) -> Self {
201 match value {
202 wasi::otel::metrics::MetricData::F64Sum(s) => wasi_sum_to_otel!(s, f64),
203 wasi::otel::metrics::MetricData::S64Sum(s) => wasi_sum_to_otel!(s, i64),
204 wasi::otel::metrics::MetricData::U64Sum(s) => wasi_sum_to_otel!(s, u64),
205 wasi::otel::metrics::MetricData::F64Gauge(g) => wasi_gauge_to_otel!(g, f64),
206 wasi::otel::metrics::MetricData::S64Gauge(g) => wasi_gauge_to_otel!(g, i64),
207 wasi::otel::metrics::MetricData::U64Gauge(g) => wasi_gauge_to_otel!(g, u64),
208 wasi::otel::metrics::MetricData::F64Histogram(h) => wasi_histogram_to_otel!(h, f64),
209 wasi::otel::metrics::MetricData::S64Histogram(h) => wasi_histogram_to_otel!(h, i64),
210 wasi::otel::metrics::MetricData::U64Histogram(h) => wasi_histogram_to_otel!(h, u64),
211 wasi::otel::metrics::MetricData::F64ExponentialHistogram(h) => {
212 wasi_exponential_histogram_to_otel!(h, f64)
213 }
214 wasi::otel::metrics::MetricData::S64ExponentialHistogram(h) => {
215 wasi_exponential_histogram_to_otel!(h, i64)
216 }
217 wasi::otel::metrics::MetricData::U64ExponentialHistogram(h) => {
218 wasi_exponential_histogram_to_otel!(h, u64)
219 }
220 }
221 }
222}
223
224impl From<wasi::otel::metrics::MetricNumber> for f64 {
225 fn from(value: wasi::otel::metrics::MetricNumber) -> Self {
226 match value {
227 wasi::otel::metrics::MetricNumber::F64(n) => n,
228 _ => panic!("error converting WASI MetricNumber to f64"),
229 }
230 }
231}
232
233impl From<wasi::otel::metrics::MetricNumber> for u64 {
234 fn from(value: wasi::otel::metrics::MetricNumber) -> Self {
235 match value {
236 wasi::otel::metrics::MetricNumber::U64(n) => n,
237 _ => panic!("error converting WASI MetricNumber to u64"),
238 }
239 }
240}
241
242impl From<wasi::otel::metrics::MetricNumber> for i64 {
243 fn from(value: wasi::otel::metrics::MetricNumber) -> Self {
244 match value {
245 wasi::otel::metrics::MetricNumber::S64(n) => n,
246 _ => panic!("error converting WASI MetricNumber to i64"),
247 }
248 }
249}
250
251impl From<wasi::otel::metrics::ExponentialBucket>
252 for opentelemetry_sdk::metrics::data::ExponentialBucket
253{
254 fn from(value: wasi::otel::metrics::ExponentialBucket) -> Self {
255 Self {
256 offset: value.offset,
257 counts: value.counts,
258 }
259 }
260}
261
262impl From<wasi::otel::metrics::Temporality> for opentelemetry_sdk::metrics::Temporality {
263 fn from(value: wasi::otel::metrics::Temporality) -> Self {
264 use opentelemetry_sdk::metrics::Temporality;
265 match value {
266 wasi::otel::metrics::Temporality::Cumulative => Temporality::Cumulative,
267 wasi::otel::metrics::Temporality::Delta => Temporality::Delta,
268 wasi::otel::metrics::Temporality::LowMemory => Temporality::LowMemory,
269 }
270 }
271}