opentelemetry_proto/transform/
common.rs

1#[cfg(all(
2    feature = "gen-tonic-messages",
3    any(feature = "trace", feature = "metrics", feature = "logs")
4))]
5use std::time::{Duration, SystemTime, UNIX_EPOCH};
6
7#[cfg(all(
8    feature = "gen-tonic-messages",
9    any(feature = "trace", feature = "metrics", feature = "logs")
10))]
11pub(crate) fn to_nanos(time: SystemTime) -> u64 {
12    time.duration_since(UNIX_EPOCH)
13        .unwrap_or_else(|_| Duration::from_secs(0))
14        .as_nanos() as u64
15}
16
17#[cfg(feature = "gen-tonic-messages")]
18pub mod tonic {
19    use crate::proto::tonic::common::v1::{
20        any_value, AnyValue, ArrayValue, InstrumentationScope, KeyValue,
21    };
22    use opentelemetry::{Array, Value};
23    use std::borrow::Cow;
24
25    #[cfg(any(feature = "trace", feature = "logs"))]
26    #[derive(Debug, Default)]
27    pub struct ResourceAttributesWithSchema {
28        pub attributes: Attributes,
29        pub schema_url: Option<String>,
30    }
31
32    #[cfg(any(feature = "trace", feature = "logs"))]
33    impl From<&opentelemetry_sdk::Resource> for ResourceAttributesWithSchema {
34        fn from(resource: &opentelemetry_sdk::Resource) -> Self {
35            ResourceAttributesWithSchema {
36                attributes: resource_attributes(resource),
37                schema_url: resource.schema_url().map(ToString::to_string),
38            }
39        }
40    }
41
42    #[cfg(any(feature = "trace", feature = "logs"))]
43    use opentelemetry_sdk::Resource;
44
45    impl
46        From<(
47            opentelemetry_sdk::InstrumentationLibrary,
48            Option<Cow<'static, str>>,
49        )> for InstrumentationScope
50    {
51        fn from(
52            data: (
53                opentelemetry_sdk::InstrumentationLibrary,
54                Option<Cow<'static, str>>,
55            ),
56        ) -> Self {
57            let (library, target) = data;
58            if let Some(t) = target {
59                InstrumentationScope {
60                    name: t.to_string(),
61                    version: String::new(),
62                    attributes: vec![],
63                    ..Default::default()
64                }
65            } else {
66                InstrumentationScope {
67                    name: library.name.into_owned(),
68                    version: library.version.map(Cow::into_owned).unwrap_or_default(),
69                    attributes: Attributes::from(library.attributes).0,
70                    ..Default::default()
71                }
72            }
73        }
74    }
75
76    impl
77        From<(
78            &opentelemetry_sdk::InstrumentationLibrary,
79            Option<Cow<'static, str>>,
80        )> for InstrumentationScope
81    {
82        fn from(
83            data: (
84                &opentelemetry_sdk::InstrumentationLibrary,
85                Option<Cow<'static, str>>,
86            ),
87        ) -> Self {
88            let (library, target) = data;
89            if let Some(t) = target {
90                InstrumentationScope {
91                    name: t.to_string(),
92                    version: String::new(),
93                    attributes: vec![],
94                    ..Default::default()
95                }
96            } else {
97                InstrumentationScope {
98                    name: library.name.to_string(),
99                    version: library
100                        .version
101                        .as_ref()
102                        .map(ToString::to_string)
103                        .unwrap_or_default(),
104                    attributes: Attributes::from(library.attributes.clone()).0,
105                    ..Default::default()
106                }
107            }
108        }
109    }
110
111    /// Wrapper type for Vec<`KeyValue`>
112    #[derive(Default, Debug)]
113    pub struct Attributes(pub ::std::vec::Vec<crate::proto::tonic::common::v1::KeyValue>);
114
115    impl From<Vec<opentelemetry::KeyValue>> for Attributes {
116        fn from(kvs: Vec<opentelemetry::KeyValue>) -> Self {
117            Attributes(
118                kvs.into_iter()
119                    .map(|api_kv| KeyValue {
120                        key: api_kv.key.as_str().to_string(),
121                        value: Some(api_kv.value.into()),
122                    })
123                    .collect(),
124            )
125        }
126    }
127
128    #[cfg(feature = "logs")]
129    impl<K: Into<String>, V: Into<AnyValue>> FromIterator<(K, V)> for Attributes {
130        fn from_iter<T: IntoIterator<Item = (K, V)>>(iter: T) -> Self {
131            Attributes(
132                iter.into_iter()
133                    .map(|(k, v)| KeyValue {
134                        key: k.into(),
135                        value: Some(v.into()),
136                    })
137                    .collect(),
138            )
139        }
140    }
141
142    impl From<Value> for AnyValue {
143        fn from(value: Value) -> Self {
144            AnyValue {
145                value: match value {
146                    Value::Bool(val) => Some(any_value::Value::BoolValue(val)),
147                    Value::I64(val) => Some(any_value::Value::IntValue(val)),
148                    Value::F64(val) => Some(any_value::Value::DoubleValue(val)),
149                    Value::String(val) => Some(any_value::Value::StringValue(val.to_string())),
150                    Value::Array(array) => Some(any_value::Value::ArrayValue(match array {
151                        Array::Bool(vals) => array_into_proto(vals),
152                        Array::I64(vals) => array_into_proto(vals),
153                        Array::F64(vals) => array_into_proto(vals),
154                        Array::String(vals) => array_into_proto(vals),
155                    })),
156                },
157            }
158        }
159    }
160
161    fn array_into_proto<T>(vals: Vec<T>) -> ArrayValue
162    where
163        Value: From<T>,
164    {
165        let values = vals
166            .into_iter()
167            .map(|val| AnyValue::from(Value::from(val)))
168            .collect();
169
170        ArrayValue { values }
171    }
172
173    #[cfg(any(feature = "trace", feature = "logs"))]
174    pub(crate) fn resource_attributes(resource: &Resource) -> Attributes {
175        resource
176            .iter()
177            .map(|(k, v)| opentelemetry::KeyValue::new(k.clone(), v.clone()))
178            .collect::<Vec<_>>()
179            .into()
180    }
181}