Skip to main content

servers/otlp/trace/
attributes.rs

1// Copyright 2023 Greptime Team
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::fmt::Display;
16
17use opentelemetry_proto::tonic::common::v1::any_value::Value::{
18    ArrayValue, BoolValue, BytesValue, DoubleValue, IntValue, KvlistValue, StringValue,
19    StringValueStrindex,
20};
21use opentelemetry_proto::tonic::common::v1::{AnyValue, KeyValue};
22use serde::Serialize;
23use serde::ser::{SerializeMap, SerializeSeq};
24
25use crate::otlp::utils::key_value_to_jsonb;
26
27#[derive(Clone, Debug)]
28pub struct OtlpAnyValue<'a>(&'a AnyValue);
29
30impl<'a> From<&'a AnyValue> for OtlpAnyValue<'a> {
31    fn from(any_val: &'a AnyValue) -> Self {
32        Self(any_val)
33    }
34}
35
36impl OtlpAnyValue<'_> {
37    pub fn none() -> Self {
38        Self(&AnyValue { value: None })
39    }
40}
41
42/// specialize Display when it's only a String
43impl Display for OtlpAnyValue<'_> {
44    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
45        if let Some(StringValue(v)) = &self.0.value {
46            write!(f, "{v}")
47        } else {
48            write!(f, "{}", serde_json::to_string(self).unwrap_or_default())
49        }
50    }
51}
52
53impl Serialize for OtlpAnyValue<'_> {
54    fn serialize<S>(&self, zer: S) -> Result<S::Ok, S::Error>
55    where
56        S: serde::Serializer,
57    {
58        match &self.0.value {
59            Some(val) => match &val {
60                StringValue(v) => zer.serialize_str(v),
61                BoolValue(v) => zer.serialize_bool(*v),
62                IntValue(v) => zer.serialize_i64(*v),
63                DoubleValue(v) => zer.serialize_f64(*v),
64                ArrayValue(v) => {
65                    let mut seq = zer.serialize_seq(Some(v.values.len()))?;
66                    for val in &v.values {
67                        seq.serialize_element(&OtlpAnyValue::from(val))?;
68                    }
69                    seq.end()
70                }
71                KvlistValue(v) => {
72                    let mut map = zer.serialize_map(Some(v.values.len()))?;
73                    for kv in &v.values {
74                        match &kv.value {
75                            Some(val) => map.serialize_entry(&kv.key, &OtlpAnyValue::from(val))?,
76                            None => map.serialize_entry(&kv.key, &OtlpAnyValue::none())?,
77                        }
78                    }
79                    map.end()
80                }
81                BytesValue(v) => zer.serialize_bytes(v),
82                // `StringValueStrindex` is profiling-signal-only and references the
83                // Profiling `ProfilesDictionary.string_table`, which is unavailable
84                // here. Per the OTLP spec, non-Profiling receivers must treat it as
85                // a non-fatal issue and process the value as if it were absent.
86                StringValueStrindex(_) => zer.serialize_none(),
87            },
88            None => zer.serialize_none(),
89        }
90    }
91}
92
93#[derive(Debug, Clone)]
94pub struct Attributes(Vec<KeyValue>);
95
96impl Display for Attributes {
97    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
98        write!(f, "{}", serde_json::to_string(self).unwrap_or_default())
99    }
100}
101
102impl Serialize for Attributes {
103    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
104    where
105        S: serde::Serializer,
106    {
107        let mut map = serializer.serialize_map(Some(self.0.len()))?;
108        for attr in &self.0 {
109            match &attr.value {
110                Some(val) => map.serialize_entry(&attr.key, &OtlpAnyValue::from(val))?,
111                None => map.serialize_entry(&attr.key, &OtlpAnyValue::none())?,
112            }
113        }
114        map.end()
115    }
116}
117
118impl From<Vec<KeyValue>> for Attributes {
119    fn from(attrs: Vec<KeyValue>) -> Self {
120        Self(attrs)
121    }
122}
123
124impl From<&[KeyValue]> for Attributes {
125    fn from(attrs: &[KeyValue]) -> Self {
126        Self(attrs.to_vec())
127    }
128}
129
130impl From<Attributes> for jsonb::Value<'static> {
131    fn from(attrs: Attributes) -> jsonb::Value<'static> {
132        key_value_to_jsonb(attrs.0)
133    }
134}
135
136impl Attributes {
137    pub fn take(self) -> Vec<KeyValue> {
138        self.0
139    }
140
141    pub fn get_ref(&self) -> &Vec<KeyValue> {
142        &self.0
143    }
144
145    pub fn get_mut(&mut self) -> &mut Vec<KeyValue> {
146        &mut self.0
147    }
148}
149
150#[cfg(test)]
151mod tests {
152    use opentelemetry_proto::tonic::common::v1::any_value::Value;
153    use opentelemetry_proto::tonic::common::v1::{AnyValue, ArrayValue, KeyValue, KeyValueList};
154
155    use crate::otlp::trace::attributes::{Attributes, OtlpAnyValue};
156
157    #[test]
158    fn test_null_value() {
159        let otlp_value = OtlpAnyValue::from(&AnyValue { value: None });
160        assert_eq!("null", serde_json::to_string(&otlp_value).unwrap())
161    }
162
163    #[test]
164    fn test_otlp_any_value_display() {
165        let values = vec![
166            (
167                "string value",
168                Value::StringValue(String::from("string value")),
169            ),
170            ("true", Value::BoolValue(true)),
171            ("1", Value::IntValue(1)),
172            ("1.1", Value::DoubleValue(1.1)),
173            ("[1,2,3]", Value::BytesValue(vec![1, 2, 3])),
174        ];
175
176        for (expect, val) in values {
177            let any_value = AnyValue { value: Some(val) };
178            let otlp_value = OtlpAnyValue::from(&any_value);
179            assert_eq!(expect, otlp_value.to_string());
180        }
181    }
182
183    #[test]
184    fn test_any_value_primitive_type_serialize() {
185        let values = vec![
186            (
187                r#""string value""#,
188                Value::StringValue(String::from("string value")),
189            ),
190            ("true", Value::BoolValue(true)),
191            ("1", Value::IntValue(1)),
192            ("1.1", Value::DoubleValue(1.1)),
193            ("[1,2,3]", Value::BytesValue(vec![1, 2, 3])),
194        ];
195
196        for (expect, val) in values {
197            let any_val = AnyValue { value: Some(val) };
198            let otlp_value = OtlpAnyValue::from(&any_val);
199            assert_eq!(expect, serde_json::to_string(&otlp_value).unwrap());
200        }
201    }
202
203    #[test]
204    fn test_any_value_array_type_serialize() {
205        let values = vec![
206            ("[]", vec![]),
207            ("[null]", vec![AnyValue { value: None }]),
208            (
209                r#"["string1","string2","string3"]"#,
210                vec![
211                    AnyValue {
212                        value: Some(Value::StringValue(String::from("string1"))),
213                    },
214                    AnyValue {
215                        value: Some(Value::StringValue(String::from("string2"))),
216                    },
217                    AnyValue {
218                        value: Some(Value::StringValue(String::from("string3"))),
219                    },
220                ],
221            ),
222            (
223                "[1,2,3]",
224                vec![
225                    AnyValue {
226                        value: Some(Value::IntValue(1)),
227                    },
228                    AnyValue {
229                        value: Some(Value::IntValue(2)),
230                    },
231                    AnyValue {
232                        value: Some(Value::IntValue(3)),
233                    },
234                ],
235            ),
236            (
237                "[1.1,2.2,3.3]",
238                vec![
239                    AnyValue {
240                        value: Some(Value::DoubleValue(1.1)),
241                    },
242                    AnyValue {
243                        value: Some(Value::DoubleValue(2.2)),
244                    },
245                    AnyValue {
246                        value: Some(Value::DoubleValue(3.3)),
247                    },
248                ],
249            ),
250            (
251                "[true,false,true]",
252                vec![
253                    AnyValue {
254                        value: Some(Value::BoolValue(true)),
255                    },
256                    AnyValue {
257                        value: Some(Value::BoolValue(false)),
258                    },
259                    AnyValue {
260                        value: Some(Value::BoolValue(true)),
261                    },
262                ],
263            ),
264            (
265                r#"[1,1.1,"str_value",true,null]"#,
266                vec![
267                    AnyValue {
268                        value: Some(Value::IntValue(1)),
269                    },
270                    AnyValue {
271                        value: Some(Value::DoubleValue(1.1)),
272                    },
273                    AnyValue {
274                        value: Some(Value::StringValue("str_value".into())),
275                    },
276                    AnyValue {
277                        value: Some(Value::BoolValue(true)),
278                    },
279                    AnyValue { value: None },
280                ],
281            ),
282        ];
283
284        for (expect, values) in values {
285            let any_val = AnyValue {
286                value: Some(Value::ArrayValue(ArrayValue { values })),
287            };
288            let otlp_value = OtlpAnyValue::from(&any_val);
289            assert_eq!(expect, serde_json::to_string(&otlp_value).unwrap());
290        }
291    }
292
293    #[test]
294    fn test_any_value_map_type_serialize() {
295        let cases = vec![
296            ("{}", vec![]),
297            (
298                r#"{"key1":null}"#,
299                vec![KeyValue {
300                    key: "key1".into(),
301                    value: None,
302                    ..Default::default()
303                }],
304            ),
305            (
306                r#"{"key1":null}"#,
307                vec![KeyValue {
308                    key: "key1".into(),
309                    value: Some(AnyValue { value: None }),
310                    ..Default::default()
311                }],
312            ),
313            (
314                r#"{"key1":"val1"}"#,
315                vec![KeyValue {
316                    key: "key1".into(),
317                    value: Some(AnyValue {
318                        value: Some(Value::StringValue(String::from("val1"))),
319                    }),
320                    ..Default::default()
321                }],
322            ),
323        ];
324
325        for (expect, values) in cases {
326            let any_val = AnyValue {
327                value: Some(Value::KvlistValue(KeyValueList { values })),
328            };
329            let otlp_value = OtlpAnyValue::from(&any_val);
330            assert_eq!(expect, serde_json::to_string(&otlp_value).unwrap());
331        }
332    }
333
334    #[test]
335    fn test_attributes_serialize() {
336        let cases = vec![
337            ("{}", vec![]),
338            (
339                r#"{"key1":null}"#,
340                vec![KeyValue {
341                    key: "key1".into(),
342                    value: None,
343                    ..Default::default()
344                }],
345            ),
346            (
347                r#"{"key1":null}"#,
348                vec![KeyValue {
349                    key: "key1".into(),
350                    value: Some(AnyValue { value: None }),
351                    ..Default::default()
352                }],
353            ),
354            (
355                r#"{"key1":"val1"}"#,
356                vec![KeyValue {
357                    key: "key1".into(),
358                    value: Some(AnyValue {
359                        value: Some(Value::StringValue(String::from("val1"))),
360                    }),
361                    ..Default::default()
362                }],
363            ),
364        ];
365
366        for (expect, values) in cases {
367            assert_eq!(expect, serde_json::to_string(&Attributes(values)).unwrap());
368        }
369    }
370}