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
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
use crate::transform::common::to_nanos;
use opentelemetry::sdk::{self, export::trace::SpanData};
use opentelemetry::trace::{Link, SpanId, SpanKind, StatusCode};

#[cfg(feature = "tonic")]
mod tonic {
    use super::*;
    use crate::proto::resource::v1::Resource;
    use crate::proto::trace::v1::{
        span, status, InstrumentationLibrarySpans, ResourceSpans, Span, Status,
    };
    use crate::transform::common::tonic::Attributes;

    impl From<SpanKind> for span::SpanKind {
        fn from(span_kind: SpanKind) -> Self {
            match span_kind {
                SpanKind::Client => span::SpanKind::Client,
                SpanKind::Consumer => span::SpanKind::Consumer,
                SpanKind::Internal => span::SpanKind::Internal,
                SpanKind::Producer => span::SpanKind::Producer,
                SpanKind::Server => span::SpanKind::Server,
            }
        }
    }

    impl From<StatusCode> for status::StatusCode {
        fn from(status_code: StatusCode) -> Self {
            match status_code {
                StatusCode::Ok => status::StatusCode::Ok,
                StatusCode::Unset => status::StatusCode::Unset,
                StatusCode::Error => status::StatusCode::Error,
            }
        }
    }

    impl From<Link> for span::Link {
        fn from(link: Link) -> Self {
            span::Link {
                trace_id: link.span_context().trace_id().to_bytes().to_vec(),
                span_id: link.span_context().span_id().to_bytes().to_vec(),
                trace_state: link.span_context().trace_state().header(),
                attributes: Attributes::from(link.attributes().clone()).0,
                dropped_attributes_count: link.dropped_attributes_count(),
            }
        }
    }

    impl From<SpanData> for ResourceSpans {
        fn from(source_span: SpanData) -> Self {
            let span_kind: span::SpanKind = source_span.span_kind.into();
            ResourceSpans {
                resource: Some(Resource {
                    attributes: resource_attributes(
                        source_span.resource.as_ref().map(AsRef::as_ref),
                    )
                    .0,
                    dropped_attributes_count: 0,
                }),
                instrumentation_library_spans: vec![InstrumentationLibrarySpans {
                    instrumentation_library: Default::default(),
                    spans: vec![Span {
                        trace_id: source_span.span_context.trace_id().to_bytes().to_vec(),
                        span_id: source_span.span_context.span_id().to_bytes().to_vec(),
                        trace_state: source_span.span_context.trace_state().header(),
                        parent_span_id: {
                            if source_span.parent_span_id != SpanId::INVALID {
                                source_span.parent_span_id.to_bytes().to_vec()
                            } else {
                                vec![]
                            }
                        },
                        name: source_span.name.into_owned(),
                        kind: span_kind as i32,
                        start_time_unix_nano: to_nanos(source_span.start_time),
                        end_time_unix_nano: to_nanos(source_span.end_time),
                        dropped_attributes_count: source_span.attributes.dropped_count(),
                        attributes: Attributes::from(source_span.attributes).0,
                        dropped_events_count: source_span.events.dropped_count(),
                        events: source_span
                            .events
                            .into_iter()
                            .map(|event| span::Event {
                                time_unix_nano: to_nanos(event.timestamp),
                                name: event.name.into(),
                                attributes: Attributes::from(event.attributes).0,
                                dropped_attributes_count: event.dropped_attributes_count,
                            })
                            .collect(),
                        dropped_links_count: source_span.links.dropped_count(),
                        links: source_span.links.into_iter().map(Into::into).collect(),
                        status: Some(Status {
                            code: status::StatusCode::from(source_span.status_code).into(),
                            message: source_span.status_message.into_owned(),
                            ..Default::default()
                        }),
                    }],
                }],
            }
        }
    }

    fn resource_attributes(resource: Option<&sdk::Resource>) -> Attributes {
        resource
            .map(|res| {
                res.iter()
                    .map(|(k, v)| opentelemetry::KeyValue::new(k.clone(), v.clone()))
                    .collect::<Vec<_>>()
            })
            .unwrap_or_default()
            .into()
    }
}

#[cfg(feature = "http-proto")]
mod prost {
    use super::*;
    use crate::proto::prost::resource::v1::Resource;
    use crate::proto::prost::trace::v1::{
        span, status, InstrumentationLibrarySpans, ResourceSpans, Span, Status,
    };
    use crate::transform::common::prost::Attributes;

    impl From<SpanKind> for span::SpanKind {
        fn from(span_kind: SpanKind) -> Self {
            match span_kind {
                SpanKind::Client => span::SpanKind::Client,
                SpanKind::Consumer => span::SpanKind::Consumer,
                SpanKind::Internal => span::SpanKind::Internal,
                SpanKind::Producer => span::SpanKind::Producer,
                SpanKind::Server => span::SpanKind::Server,
            }
        }
    }

    impl From<StatusCode> for status::StatusCode {
        fn from(status_code: StatusCode) -> Self {
            match status_code {
                StatusCode::Ok => status::StatusCode::Ok,
                StatusCode::Unset => status::StatusCode::Unset,
                StatusCode::Error => status::StatusCode::Error,
            }
        }
    }

    impl From<Link> for span::Link {
        fn from(link: Link) -> Self {
            span::Link {
                trace_id: link.span_context().trace_id().to_bytes().to_vec(),
                span_id: link.span_context().span_id().to_bytes().to_vec(),
                trace_state: link.span_context().trace_state().header(),
                attributes: Attributes::from(link.attributes().clone()).0,
                dropped_attributes_count: link.dropped_attributes_count(),
            }
        }
    }

    impl From<SpanData> for ResourceSpans {
        fn from(source_span: SpanData) -> Self {
            let span_kind: span::SpanKind = source_span.span_kind.into();
            ResourceSpans {
                resource: Some(Resource {
                    attributes: resource_attributes(
                        source_span.resource.as_ref().map(AsRef::as_ref),
                    )
                    .0,
                    dropped_attributes_count: 0,
                }),
                instrumentation_library_spans: vec![InstrumentationLibrarySpans {
                    instrumentation_library: Default::default(),
                    spans: vec![Span {
                        trace_id: source_span.span_context.trace_id().to_bytes().to_vec(),
                        span_id: source_span.span_context.span_id().to_bytes().to_vec(),
                        trace_state: source_span.span_context.trace_state().header(),
                        parent_span_id: {
                            if source_span.parent_span_id != SpanId::INVALID {
                                source_span.parent_span_id.to_bytes().to_vec()
                            } else {
                                vec![]
                            }
                        },
                        name: source_span.name.into_owned(),
                        kind: span_kind as i32,
                        start_time_unix_nano: to_nanos(source_span.start_time),
                        end_time_unix_nano: to_nanos(source_span.end_time),
                        dropped_attributes_count: source_span.attributes.dropped_count(),
                        attributes: Attributes::from(source_span.attributes).0,
                        dropped_events_count: source_span.events.dropped_count(),
                        events: source_span
                            .events
                            .into_iter()
                            .map(|event| span::Event {
                                time_unix_nano: to_nanos(event.timestamp),
                                name: event.name.into(),
                                attributes: Attributes::from(event.attributes).0,
                                dropped_attributes_count: event.dropped_attributes_count,
                            })
                            .collect(),
                        dropped_links_count: source_span.links.dropped_count(),
                        links: source_span.links.into_iter().map(Into::into).collect(),
                        status: Some(Status {
                            code: status::StatusCode::from(source_span.status_code).into(),
                            message: source_span.status_message.into_owned(),
                            ..Default::default()
                        }),
                    }],
                }],
            }
        }
    }

    fn resource_attributes(resource: Option<&sdk::Resource>) -> Attributes {
        resource
            .map(|res| {
                res.iter()
                    .map(|(k, v)| opentelemetry::KeyValue::new(k.clone(), v.clone()))
                    .collect::<Vec<_>>()
            })
            .unwrap_or_default()
            .into()
    }
}

#[cfg(feature = "grpc-sys")]
mod grpcio {
    use super::*;
    use crate::proto::grpcio::resource::Resource;
    use crate::proto::grpcio::trace::{
        InstrumentationLibrarySpans, ResourceSpans, Span, Span_Event, Span_Link, Span_SpanKind,
        Status, Status_StatusCode,
    };
    use crate::transform::common::grpcio::Attributes;
    use protobuf::{RepeatedField, SingularPtrField};

    impl From<SpanKind> for Span_SpanKind {
        fn from(span_kind: SpanKind) -> Self {
            match span_kind {
                SpanKind::Client => Span_SpanKind::SPAN_KIND_CLIENT,
                SpanKind::Consumer => Span_SpanKind::SPAN_KIND_CONSUMER,
                SpanKind::Internal => Span_SpanKind::SPAN_KIND_INTERNAL,
                SpanKind::Producer => Span_SpanKind::SPAN_KIND_PRODUCER,
                SpanKind::Server => Span_SpanKind::SPAN_KIND_SERVER,
            }
        }
    }

    impl From<StatusCode> for Status_StatusCode {
        fn from(status_code: StatusCode) -> Self {
            match status_code {
                StatusCode::Ok => Status_StatusCode::STATUS_CODE_OK,
                StatusCode::Unset => Status_StatusCode::STATUS_CODE_UNSET,
                StatusCode::Error => Status_StatusCode::STATUS_CODE_ERROR,
            }
        }
    }

    impl From<Link> for Span_Link {
        fn from(link: Link) -> Self {
            Span_Link {
                trace_id: link.span_context().trace_id().to_bytes().to_vec(),
                span_id: link.span_context().span_id().to_bytes().to_vec(),
                trace_state: link.span_context().trace_state().header(),
                attributes: Attributes::from(link.attributes().clone()).0,
                dropped_attributes_count: link.dropped_attributes_count(),
                ..Default::default()
            }
        }
    }

    impl From<SpanData> for ResourceSpans {
        fn from(source_span: SpanData) -> Self {
            ResourceSpans {
                resource: SingularPtrField::from(Some(Resource {
                    attributes: resource_attributes(
                        source_span.resource.as_ref().map(AsRef::as_ref),
                    )
                    .0,
                    dropped_attributes_count: 0,
                    ..Default::default()
                })),
                instrumentation_library_spans: RepeatedField::from_vec(vec![
                    InstrumentationLibrarySpans {
                        instrumentation_library: Default::default(),
                        spans: RepeatedField::from_vec(vec![Span {
                            trace_id: source_span.span_context.trace_id().to_bytes().to_vec(),
                            span_id: source_span.span_context.span_id().to_bytes().to_vec(),
                            trace_state: source_span.span_context.trace_state().header(),
                            parent_span_id: {
                                if source_span.parent_span_id != SpanId::INVALID {
                                    source_span.parent_span_id.to_bytes().to_vec()
                                } else {
                                    vec![]
                                }
                            },
                            name: source_span.name.into_owned(),
                            kind: source_span.span_kind.into(),
                            start_time_unix_nano: to_nanos(source_span.start_time),
                            end_time_unix_nano: to_nanos(source_span.end_time),
                            dropped_attributes_count: source_span.attributes.dropped_count(),
                            attributes: Attributes::from(source_span.attributes).0,
                            dropped_events_count: source_span.events.dropped_count(),
                            events: RepeatedField::from_vec(
                                source_span
                                    .events
                                    .into_iter()
                                    .map(|event| Span_Event {
                                        time_unix_nano: to_nanos(event.timestamp),
                                        name: event.name.into(),
                                        attributes: Attributes::from(event.attributes).0,
                                        dropped_attributes_count: event.dropped_attributes_count,
                                        ..Default::default()
                                    })
                                    .collect(),
                            ),
                            dropped_links_count: source_span.links.dropped_count(),
                            links: RepeatedField::from_vec(
                                source_span.links.into_iter().map(Into::into).collect(),
                            ),
                            status: SingularPtrField::some(Status {
                                code: Status_StatusCode::from(source_span.status_code),
                                message: source_span.status_message.into_owned(),
                                ..Default::default()
                            }),
                            ..Default::default()
                        }]),
                        ..Default::default()
                    },
                ]),
                ..Default::default()
            }
        }
    }

    fn resource_attributes(resource: Option<&sdk::Resource>) -> Attributes {
        resource
            .map(|resource| {
                resource
                    .iter()
                    .map(|(k, v)| opentelemetry::KeyValue::new(k.clone(), v.clone()))
                    .collect::<Vec<_>>()
            })
            .unwrap_or_default()
            .into()
    }
}