opentelemetry_proto/
proto.rs

1/// provide serde support for proto traceIds and spanIds.
2/// Those are hex encoded strings in the jsons but they are byte arrays in the proto.
3/// See https://opentelemetry.io/docs/specs/otlp/#json-protobuf-encoding for more details
4#[cfg(all(feature = "with-serde", feature = "gen-tonic-messages"))]
5pub(crate) mod serializers {
6    use crate::tonic::common::v1::any_value::{self, Value};
7    use crate::tonic::common::v1::AnyValue;
8    use serde::de::{self, MapAccess, Visitor};
9    use serde::ser::{SerializeMap, SerializeSeq, SerializeStruct};
10    use serde::{Deserialize, Deserializer, Serialize, Serializer};
11    use std::fmt;
12
13    // hex string <-> bytes conversion
14
15    pub fn serialize_to_hex_string<S>(bytes: &[u8], serializer: S) -> Result<S::Ok, S::Error>
16    where
17        S: Serializer,
18    {
19        let hex_string = const_hex::encode(bytes);
20        serializer.serialize_str(&hex_string)
21    }
22
23    pub fn deserialize_from_hex_string<'de, D>(deserializer: D) -> Result<Vec<u8>, D::Error>
24    where
25        D: Deserializer<'de>,
26    {
27        struct BytesVisitor;
28
29        impl<'de> Visitor<'de> for BytesVisitor {
30            type Value = Vec<u8>;
31
32            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
33                formatter.write_str("a string representing hex-encoded bytes")
34            }
35
36            fn visit_str<E>(self, value: &str) -> Result<Vec<u8>, E>
37            where
38                E: de::Error,
39            {
40                const_hex::decode(value).map_err(E::custom)
41            }
42        }
43
44        deserializer.deserialize_str(BytesVisitor)
45    }
46
47    // AnyValue <-> KeyValue conversion
48    pub fn serialize_to_value<S>(value: &Option<Value>, serializer: S) -> Result<S::Ok, S::Error>
49    where
50        S: Serializer,
51    {
52        match &value {
53            Some(Value::IntValue(i)) => {
54                // Attempt to serialize the intValue field
55                let mut map = serializer.serialize_map(Some(1))?;
56                map.serialize_entry("intValue", &i.to_string());
57                map.end()
58            }
59            Some(Value::BytesValue(b)) => {
60                let mut map = serializer.serialize_map(Some(1))?;
61                map.serialize_entry("bytesValue", &base64::encode(b));
62                map.end()
63            }
64            Some(value) => value.serialize(serializer),
65            None => serializer.serialize_none(),
66        }
67    }
68
69    pub fn deserialize_from_value<'de, D>(deserializer: D) -> Result<Option<Value>, D::Error>
70    where
71        D: Deserializer<'de>,
72    {
73        struct ValueVisitor;
74
75        #[derive(Deserialize)]
76        #[serde(untagged)]
77        enum StringOrInt {
78            Int(i64),
79            String(String),
80        }
81
82        impl StringOrInt {
83            fn get_int<'de, V>(&self) -> Result<i64, V::Error>
84            where
85                V: de::MapAccess<'de>,
86            {
87                match self {
88                    Self::Int(val) => Ok(*val),
89                    Self::String(val) => Ok(val.parse::<i64>().map_err(de::Error::custom)?),
90                }
91            }
92        }
93
94        impl<'de> de::Visitor<'de> for ValueVisitor {
95            type Value = Option<Value>;
96
97            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
98                formatter.write_str("a JSON object for AnyValue")
99            }
100
101            fn visit_map<V>(self, mut map: V) -> Result<Option<Value>, V::Error>
102            where
103                V: de::MapAccess<'de>,
104            {
105                let mut value: Option<any_value::Value> = None;
106
107                while let Some(key) = map.next_key::<String>()? {
108                    let key_str = key.as_str();
109                    match key_str {
110                        "stringValue" => {
111                            let s = map.next_value()?;
112                            value = Some(any_value::Value::StringValue(s));
113                        }
114                        "boolValue" => {
115                            let b = map.next_value()?;
116                            value = Some(any_value::Value::BoolValue(b));
117                        }
118                        "intValue" => {
119                            let int_value = map.next_value::<StringOrInt>()?.get_int::<V>()?;
120                            value = Some(any_value::Value::IntValue(int_value));
121                        }
122                        "doubleValue" => {
123                            let d = map.next_value()?;
124                            value = Some(any_value::Value::DoubleValue(d));
125                        }
126                        "arrayValue" => {
127                            let a = map.next_value()?;
128                            value = Some(any_value::Value::ArrayValue(a));
129                        }
130                        "kvlistValue" => {
131                            let kv = map.next_value()?;
132                            value = Some(any_value::Value::KvlistValue(kv));
133                        }
134                        "bytesValue" => {
135                            let base64: String = map.next_value()?;
136                            let decoded = base64::decode(base64.as_bytes())
137                                .map_err(|e| de::Error::custom(e))?;
138                            value = Some(any_value::Value::BytesValue(decoded));
139                        }
140                        _ => {
141                            //skip unknown keys, and handle error later.
142                            continue;
143                        }
144                    }
145                }
146
147                if let Some(v) = value {
148                    Ok(Some(v))
149                } else {
150                    Err(de::Error::custom(
151                        "Invalid data for Value, no known keys found",
152                    ))
153                }
154            }
155        }
156
157        let value = deserializer.deserialize_map(ValueVisitor)?;
158        Ok(value)
159    }
160
161    pub fn serialize_u64_to_string<S>(value: &u64, serializer: S) -> Result<S::Ok, S::Error>
162    where
163        S: Serializer,
164    {
165        let s = value.to_string();
166        serializer.serialize_str(&s)
167    }
168
169    pub fn deserialize_string_to_u64<'de, D>(deserializer: D) -> Result<u64, D::Error>
170    where
171        D: Deserializer<'de>,
172    {
173        let s: String = Deserialize::deserialize(deserializer)?;
174        s.parse::<u64>().map_err(de::Error::custom)
175    }
176
177    pub fn serialize_vec_u64_to_string<S>(value: &[u64], serializer: S) -> Result<S::Ok, S::Error>
178    where
179        S: Serializer,
180    {
181        let s = value.iter()
182            .map(|v| v.to_string())
183            .collect::<Vec<_>>();
184        let mut sq = serializer.serialize_seq(Some(s.len()))?;
185        for v in value {
186            sq.serialize_element(&v.to_string())?;
187        }
188        sq.end()
189    }
190
191    pub fn deserialize_vec_string_to_vec_u64<'de, D>(deserializer: D) -> Result<Vec<u64>, D::Error>
192    where
193        D: Deserializer<'de>,
194    {
195        let s: Vec<String> = Deserialize::deserialize(deserializer)?;
196        s.into_iter()
197            .map(|v| v.parse::<u64>().map_err(de::Error::custom))
198            .collect()
199    }
200
201    pub fn serialize_i64_to_string<S>(value: &i64, serializer: S) -> Result<S::Ok, S::Error>
202    where
203        S: Serializer,
204    {
205        let s = value.to_string();
206        serializer.serialize_str(&s)
207    }
208
209    pub fn deserialize_string_to_i64<'de, D>(deserializer: D) -> Result<i64, D::Error>
210    where
211        D: Deserializer<'de>,
212    {
213        let s: String = Deserialize::deserialize(deserializer)?;
214        s.parse::<i64>().map_err(de::Error::custom)
215    }
216}
217
218#[cfg(feature = "gen-tonic-messages")]
219#[path = "proto/tonic"]
220/// Generated files using [`tonic`](https://docs.rs/crate/tonic) and [`prost`](https://docs.rs/crate/prost)
221pub mod tonic {
222    /// Service stub and clients
223    #[path = ""]
224    pub mod collector {
225        #[cfg(feature = "logs")]
226        #[path = ""]
227        pub mod logs {
228            #[path = "opentelemetry.proto.collector.logs.v1.rs"]
229            pub mod v1;
230        }
231
232        #[cfg(feature = "metrics")]
233        #[path = ""]
234        pub mod metrics {
235            #[path = "opentelemetry.proto.collector.metrics.v1.rs"]
236            pub mod v1;
237        }
238
239        #[cfg(feature = "trace")]
240        #[path = ""]
241        pub mod trace {
242            #[path = "opentelemetry.proto.collector.trace.v1.rs"]
243            pub mod v1;
244        }
245
246        #[cfg(feature = "profiles")]
247        #[path = ""]
248        pub mod profiles {
249            #[path = "opentelemetry.proto.collector.profiles.v1development.rs"]
250            pub mod v1development;
251        }
252    }
253
254    /// Common types used across all signals
255    #[path = ""]
256    pub mod common {
257        #[path = "opentelemetry.proto.common.v1.rs"]
258        pub mod v1;
259    }
260
261    /// Generated types used in logging.
262    #[cfg(feature = "logs")]
263    #[path = ""]
264    pub mod logs {
265        #[path = "opentelemetry.proto.logs.v1.rs"]
266        pub mod v1;
267    }
268
269    /// Generated types used in metrics.
270    #[cfg(feature = "metrics")]
271    #[path = ""]
272    pub mod metrics {
273        #[path = "opentelemetry.proto.metrics.v1.rs"]
274        pub mod v1;
275    }
276
277    /// Generated types used in resources.
278    #[path = ""]
279    pub mod resource {
280        #[path = "opentelemetry.proto.resource.v1.rs"]
281        pub mod v1;
282    }
283
284    /// Generated types used in traces.
285    #[cfg(feature = "trace")]
286    #[path = ""]
287    pub mod trace {
288        #[path = "opentelemetry.proto.trace.v1.rs"]
289        pub mod v1;
290    }
291
292    /// Generated types used in zpages.
293    #[cfg(feature = "zpages")]
294    #[path = ""]
295    pub mod tracez {
296        #[path = "opentelemetry.proto.tracez.v1.rs"]
297        pub mod v1;
298    }
299
300    /// Generated types used in zpages.
301    #[cfg(feature = "profiles")]
302    #[path = ""]
303    pub mod profiles {
304        #[path = "opentelemetry.proto.profiles.v1development.rs"]
305        pub mod v1development;
306    }
307
308    pub use crate::transform::common::tonic::Attributes;
309}