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;
16use std::sync::Arc;
17
18use opentelemetry_proto::tonic::common::v1::any_value::Value::{
19    ArrayValue, BoolValue, BytesValue, DoubleValue, IntValue, KvlistValue, StringValue,
20    StringValueStrindex,
21};
22use opentelemetry_proto::tonic::common::v1::{AnyValue, KeyValue};
23use serde::Serialize;
24use serde::ser::{SerializeMap, SerializeSeq};
25
26use crate::otlp::utils::key_value_to_jsonb;
27
28#[derive(Clone, Debug)]
29pub struct OtlpAnyValue<'a>(&'a AnyValue);
30
31impl<'a> From<&'a AnyValue> for OtlpAnyValue<'a> {
32    fn from(any_val: &'a AnyValue) -> Self {
33        Self(any_val)
34    }
35}
36
37impl OtlpAnyValue<'_> {
38    pub fn none() -> Self {
39        Self(&AnyValue { value: None })
40    }
41}
42
43/// specialize Display when it's only a String
44impl Display for OtlpAnyValue<'_> {
45    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
46        if let Some(StringValue(v)) = &self.0.value {
47            write!(f, "{v}")
48        } else {
49            write!(f, "{}", serde_json::to_string(self).unwrap_or_default())
50        }
51    }
52}
53
54impl Serialize for OtlpAnyValue<'_> {
55    fn serialize<S>(&self, zer: S) -> Result<S::Ok, S::Error>
56    where
57        S: serde::Serializer,
58    {
59        match &self.0.value {
60            Some(val) => match &val {
61                StringValue(v) => zer.serialize_str(v),
62                BoolValue(v) => zer.serialize_bool(*v),
63                IntValue(v) => zer.serialize_i64(*v),
64                DoubleValue(v) => zer.serialize_f64(*v),
65                ArrayValue(v) => {
66                    let mut seq = zer.serialize_seq(Some(v.values.len()))?;
67                    for val in &v.values {
68                        seq.serialize_element(&OtlpAnyValue::from(val))?;
69                    }
70                    seq.end()
71                }
72                KvlistValue(v) => {
73                    let mut map = zer.serialize_map(Some(v.values.len()))?;
74                    for kv in &v.values {
75                        match &kv.value {
76                            Some(val) => map.serialize_entry(&kv.key, &OtlpAnyValue::from(val))?,
77                            None => map.serialize_entry(&kv.key, &OtlpAnyValue::none())?,
78                        }
79                    }
80                    map.end()
81                }
82                BytesValue(v) => zer.serialize_bytes(v),
83                // `StringValueStrindex` is profiling-signal-only and references the
84                // Profiling `ProfilesDictionary.string_table`, which is unavailable
85                // here. Per the OTLP spec, non-Profiling receivers must treat it as
86                // a non-fatal issue and process the value as if it were absent.
87                StringValueStrindex(_) => zer.serialize_none(),
88            },
89            None => zer.serialize_none(),
90        }
91    }
92}
93
94#[derive(Debug, Clone)]
95pub struct Attributes(Vec<KeyValue>);
96
97impl Display for Attributes {
98    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
99        write!(f, "{}", serde_json::to_string(self).unwrap_or_default())
100    }
101}
102
103impl Serialize for Attributes {
104    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
105    where
106        S: serde::Serializer,
107    {
108        let mut map = serializer.serialize_map(Some(self.0.len()))?;
109        for attr in &self.0 {
110            match &attr.value {
111                Some(val) => map.serialize_entry(&attr.key, &OtlpAnyValue::from(val))?,
112                None => map.serialize_entry(&attr.key, &OtlpAnyValue::none())?,
113            }
114        }
115        map.end()
116    }
117}
118
119impl From<Vec<KeyValue>> for Attributes {
120    fn from(attrs: Vec<KeyValue>) -> Self {
121        Self(attrs)
122    }
123}
124
125impl From<&[KeyValue]> for Attributes {
126    fn from(attrs: &[KeyValue]) -> Self {
127        Self(attrs.to_vec())
128    }
129}
130
131impl From<Attributes> for jsonb::Value<'static> {
132    fn from(attrs: Attributes) -> jsonb::Value<'static> {
133        key_value_to_jsonb(attrs.0)
134    }
135}
136
137impl Attributes {
138    pub fn take(self) -> Vec<KeyValue> {
139        self.0
140    }
141
142    pub fn get_ref(&self) -> &Vec<KeyValue> {
143        &self.0
144    }
145
146    pub fn get_mut(&mut self) -> &mut Vec<KeyValue> {
147        &mut self.0
148    }
149}
150
151/// Attributes shared by every span of one resource or scope.
152///
153/// Empty attributes are kept as `None` so that the common case of a resource or
154/// scope without attributes costs no allocation and no atomic refcounting.
155#[derive(Debug, Clone)]
156pub struct SharedAttributes(Option<Arc<Attributes>>);
157
158impl From<Attributes> for SharedAttributes {
159    fn from(attributes: Attributes) -> Self {
160        Self((!attributes.0.is_empty()).then(|| Arc::new(attributes)))
161    }
162}
163
164impl AsRef<Attributes> for SharedAttributes {
165    fn as_ref(&self) -> &Attributes {
166        static EMPTY: Attributes = Attributes(Vec::new());
167        self.0.as_deref().unwrap_or(&EMPTY)
168    }
169}
170
171impl SharedAttributes {
172    /// Returns owned attributes, copying them unless this is the last holder.
173    pub fn into_owned(self) -> Attributes {
174        match self.0 {
175            // Spans usually still share with their group, so skip the
176            // compare-exchange that would fail inside `unwrap_or_clone`.
177            Some(attributes) if Arc::strong_count(&attributes) > 1 => attributes.as_ref().clone(),
178            Some(attributes) => Arc::unwrap_or_clone(attributes),
179            None => Attributes(Vec::new()),
180        }
181    }
182}
183
184#[cfg(test)]
185mod tests {
186    use opentelemetry_proto::tonic::common::v1::any_value::Value;
187    use opentelemetry_proto::tonic::common::v1::{AnyValue, ArrayValue, KeyValue, KeyValueList};
188
189    use crate::otlp::trace::attributes::{Attributes, OtlpAnyValue};
190
191    #[test]
192    fn test_null_value() {
193        let otlp_value = OtlpAnyValue::from(&AnyValue { value: None });
194        assert_eq!("null", serde_json::to_string(&otlp_value).unwrap())
195    }
196
197    #[test]
198    fn test_otlp_any_value_display() {
199        let values = vec![
200            (
201                "string value",
202                Value::StringValue(String::from("string value")),
203            ),
204            ("true", Value::BoolValue(true)),
205            ("1", Value::IntValue(1)),
206            ("1.1", Value::DoubleValue(1.1)),
207            ("[1,2,3]", Value::BytesValue(vec![1, 2, 3])),
208        ];
209
210        for (expect, val) in values {
211            let any_value = AnyValue { value: Some(val) };
212            let otlp_value = OtlpAnyValue::from(&any_value);
213            assert_eq!(expect, otlp_value.to_string());
214        }
215    }
216
217    #[test]
218    fn test_any_value_primitive_type_serialize() {
219        let values = vec![
220            (
221                r#""string value""#,
222                Value::StringValue(String::from("string value")),
223            ),
224            ("true", Value::BoolValue(true)),
225            ("1", Value::IntValue(1)),
226            ("1.1", Value::DoubleValue(1.1)),
227            ("[1,2,3]", Value::BytesValue(vec![1, 2, 3])),
228        ];
229
230        for (expect, val) in values {
231            let any_val = AnyValue { value: Some(val) };
232            let otlp_value = OtlpAnyValue::from(&any_val);
233            assert_eq!(expect, serde_json::to_string(&otlp_value).unwrap());
234        }
235    }
236
237    #[test]
238    fn test_any_value_array_type_serialize() {
239        let values = vec![
240            ("[]", vec![]),
241            ("[null]", vec![AnyValue { value: None }]),
242            (
243                r#"["string1","string2","string3"]"#,
244                vec![
245                    AnyValue {
246                        value: Some(Value::StringValue(String::from("string1"))),
247                    },
248                    AnyValue {
249                        value: Some(Value::StringValue(String::from("string2"))),
250                    },
251                    AnyValue {
252                        value: Some(Value::StringValue(String::from("string3"))),
253                    },
254                ],
255            ),
256            (
257                "[1,2,3]",
258                vec![
259                    AnyValue {
260                        value: Some(Value::IntValue(1)),
261                    },
262                    AnyValue {
263                        value: Some(Value::IntValue(2)),
264                    },
265                    AnyValue {
266                        value: Some(Value::IntValue(3)),
267                    },
268                ],
269            ),
270            (
271                "[1.1,2.2,3.3]",
272                vec![
273                    AnyValue {
274                        value: Some(Value::DoubleValue(1.1)),
275                    },
276                    AnyValue {
277                        value: Some(Value::DoubleValue(2.2)),
278                    },
279                    AnyValue {
280                        value: Some(Value::DoubleValue(3.3)),
281                    },
282                ],
283            ),
284            (
285                "[true,false,true]",
286                vec![
287                    AnyValue {
288                        value: Some(Value::BoolValue(true)),
289                    },
290                    AnyValue {
291                        value: Some(Value::BoolValue(false)),
292                    },
293                    AnyValue {
294                        value: Some(Value::BoolValue(true)),
295                    },
296                ],
297            ),
298            (
299                r#"[1,1.1,"str_value",true,null]"#,
300                vec![
301                    AnyValue {
302                        value: Some(Value::IntValue(1)),
303                    },
304                    AnyValue {
305                        value: Some(Value::DoubleValue(1.1)),
306                    },
307                    AnyValue {
308                        value: Some(Value::StringValue("str_value".into())),
309                    },
310                    AnyValue {
311                        value: Some(Value::BoolValue(true)),
312                    },
313                    AnyValue { value: None },
314                ],
315            ),
316        ];
317
318        for (expect, values) in values {
319            let any_val = AnyValue {
320                value: Some(Value::ArrayValue(ArrayValue { values })),
321            };
322            let otlp_value = OtlpAnyValue::from(&any_val);
323            assert_eq!(expect, serde_json::to_string(&otlp_value).unwrap());
324        }
325    }
326
327    #[test]
328    fn test_any_value_map_type_serialize() {
329        let cases = vec![
330            ("{}", vec![]),
331            (
332                r#"{"key1":null}"#,
333                vec![KeyValue {
334                    key: "key1".into(),
335                    value: None,
336                    ..Default::default()
337                }],
338            ),
339            (
340                r#"{"key1":null}"#,
341                vec![KeyValue {
342                    key: "key1".into(),
343                    value: Some(AnyValue { value: None }),
344                    ..Default::default()
345                }],
346            ),
347            (
348                r#"{"key1":"val1"}"#,
349                vec![KeyValue {
350                    key: "key1".into(),
351                    value: Some(AnyValue {
352                        value: Some(Value::StringValue(String::from("val1"))),
353                    }),
354                    ..Default::default()
355                }],
356            ),
357        ];
358
359        for (expect, values) in cases {
360            let any_val = AnyValue {
361                value: Some(Value::KvlistValue(KeyValueList { values })),
362            };
363            let otlp_value = OtlpAnyValue::from(&any_val);
364            assert_eq!(expect, serde_json::to_string(&otlp_value).unwrap());
365        }
366    }
367
368    #[test]
369    fn test_attributes_serialize() {
370        let cases = vec![
371            ("{}", vec![]),
372            (
373                r#"{"key1":null}"#,
374                vec![KeyValue {
375                    key: "key1".into(),
376                    value: None,
377                    ..Default::default()
378                }],
379            ),
380            (
381                r#"{"key1":null}"#,
382                vec![KeyValue {
383                    key: "key1".into(),
384                    value: Some(AnyValue { value: None }),
385                    ..Default::default()
386                }],
387            ),
388            (
389                r#"{"key1":"val1"}"#,
390                vec![KeyValue {
391                    key: "key1".into(),
392                    value: Some(AnyValue {
393                        value: Some(Value::StringValue(String::from("val1"))),
394                    }),
395                    ..Default::default()
396                }],
397            ),
398        ];
399
400        for (expect, values) in cases {
401            assert_eq!(expect, serde_json::to_string(&Attributes(values)).unwrap());
402        }
403    }
404}