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, 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 = 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                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_i64_to_string<S>(value: &i64, serializer: S) -> Result<S::Ok, S::Error>
178    where
179        S: Serializer,
180    {
181        let s = value.to_string();
182        serializer.serialize_str(&s)
183    }
184
185    pub fn deserialize_string_to_i64<'de, D>(deserializer: D) -> Result<i64, D::Error>
186    where
187        D: Deserializer<'de>,
188    {
189        let s: String = Deserialize::deserialize(deserializer)?;
190        s.parse::<i64>().map_err(de::Error::custom)
191    }
192}
193
194#[cfg(feature = "gen-tonic-messages")]
195#[path = "proto/tonic"]
196/// Generated files using [`tonic`](https://docs.rs/crate/tonic) and [`prost`](https://docs.rs/crate/prost)
197pub mod tonic {
198    /// Service stub and clients
199    #[path = ""]
200    pub mod collector {
201        #[cfg(feature = "logs")]
202        #[path = ""]
203        pub mod logs {
204            #[path = "opentelemetry.proto.collector.logs.v1.rs"]
205            pub mod v1;
206        }
207
208        #[cfg(feature = "metrics")]
209        #[path = ""]
210        pub mod metrics {
211            #[path = "opentelemetry.proto.collector.metrics.v1.rs"]
212            pub mod v1;
213        }
214
215        #[cfg(feature = "trace")]
216        #[path = ""]
217        pub mod trace {
218            #[path = "opentelemetry.proto.collector.trace.v1.rs"]
219            pub mod v1;
220        }
221    }
222
223    /// Common types used across all signals
224    #[path = ""]
225    pub mod common {
226        #[path = "opentelemetry.proto.common.v1.rs"]
227        pub mod v1;
228    }
229
230    /// Generated types used in logging.
231    #[cfg(feature = "logs")]
232    #[path = ""]
233    pub mod logs {
234        #[path = "opentelemetry.proto.logs.v1.rs"]
235        pub mod v1;
236    }
237
238    /// Generated types used in metrics.
239    #[cfg(feature = "metrics")]
240    #[path = ""]
241    pub mod metrics {
242        #[path = "opentelemetry.proto.metrics.v1.rs"]
243        pub mod v1;
244    }
245
246    /// Generated types used in resources.
247    #[path = ""]
248    pub mod resource {
249        #[path = "opentelemetry.proto.resource.v1.rs"]
250        pub mod v1;
251    }
252
253    /// Generated types used in traces.
254    #[cfg(feature = "trace")]
255    #[path = ""]
256    pub mod trace {
257        #[path = "opentelemetry.proto.trace.v1.rs"]
258        pub mod v1;
259    }
260
261    /// Generated types used in zpages.
262    #[cfg(feature = "zpages")]
263    #[path = ""]
264    pub mod tracez {
265        #[path = "opentelemetry.proto.tracez.v1.rs"]
266        pub mod v1;
267    }
268
269    pub use crate::transform::common::tonic::Attributes;
270}