opentelemetry_proto/
common.rs1use bytes::Bytes;
2use ordered_float::NotNan;
3use vector_core::event::metric::{TagValue, TagValueSet};
4use vrl::value::{ObjectMap, Value};
5
6use super::proto::common::v1::{AnyValue, ArrayValue, KeyValue, any_value::Value as PBValue};
7
8impl From<PBValue> for Value {
9 fn from(av: PBValue) -> Self {
10 match av {
11 PBValue::StringValue(v) => Value::Bytes(Bytes::from(v)),
12 PBValue::BoolValue(v) => Value::Boolean(v),
13 PBValue::IntValue(v) => Value::Integer(v),
14 PBValue::DoubleValue(v) => NotNan::new(v).map(Value::Float).unwrap_or(Value::Null),
15 PBValue::BytesValue(v) => Value::Bytes(Bytes::from(v)),
16 PBValue::ArrayValue(arr) => Value::Array(
17 arr.values
18 .into_iter()
19 .map(|av| av.value.map(Into::into).unwrap_or(Value::Null))
20 .collect::<Vec<Value>>(),
21 ),
22 PBValue::KvlistValue(arr) => kv_list_into_value(arr.values),
23 }
24 }
25}
26
27impl From<PBValue> for TagValue {
28 fn from(pb: PBValue) -> Self {
29 match pb {
30 PBValue::StringValue(s) => TagValue::from(s),
31 PBValue::BoolValue(b) => TagValue::from(b.to_string()),
32 PBValue::IntValue(i) => TagValue::from(i.to_string()),
33 PBValue::DoubleValue(f) => TagValue::from(f.to_string()),
34 PBValue::BytesValue(b) => TagValue::from(String::from_utf8_lossy(&b).to_string()),
35 _ => TagValue::from("null"),
36 }
37 }
38}
39
40impl From<TagValue> for AnyValue {
41 fn from(tag: TagValue) -> Self {
42 match tag {
43 TagValue::Value(s) => Self {
44 value: Some(PBValue::StringValue(s)),
45 },
46 TagValue::Bare => Self { value: None },
47 }
48 }
49}
50
51pub fn str_to_key_value(key: &str, val: TagValue) -> KeyValue {
52 KeyValue {
53 key: key.to_string(),
54 value: Some(val.into()),
55 }
56}
57
58pub fn tag_set_to_any_value(tag_set: TagValueSet) -> Option<AnyValue> {
59 match tag_set {
60 TagValueSet::Empty => None,
61 TagValueSet::Single(tag) => Some(tag.into()),
62 TagValueSet::Set(set) => Some(AnyValue {
63 value: Some(PBValue::ArrayValue(ArrayValue {
64 values: set.into_iter().map(Into::into).collect(),
65 })),
66 }),
67 }
68}
69
70pub fn kv_list_into_value(arr: Vec<KeyValue>) -> Value {
71 Value::Object(
72 arr.into_iter()
73 .filter_map(|kv| {
74 kv.value.map(|av| {
75 (
76 kv.key.into(),
77 av.value.map(Into::into).unwrap_or(Value::Null),
78 )
79 })
80 })
81 .collect::<ObjectMap>(),
82 )
83}
84
85pub fn to_hex(d: &[u8]) -> String {
86 if d.is_empty() {
87 return "".to_string();
88 }
89 hex::encode(d)
90}
91
92#[cfg(test)]
93mod tests {
94 use super::*;
95
96 #[test]
97 fn test_pb_double_value_nan_handling() {
98 let nan_value = PBValue::DoubleValue(f64::NAN);
100 let result = Value::from(nan_value);
101 assert_eq!(result, Value::Null);
102 }
103
104 #[test]
105 fn test_pb_double_value_infinity() {
106 let inf_value = PBValue::DoubleValue(f64::INFINITY);
108 let result = Value::from(inf_value);
109 match result {
110 Value::Float(f) => {
111 assert!(f.into_inner().is_infinite() && f.into_inner().is_sign_positive())
112 }
113 _ => panic!("Expected Float value, got {result:?}"),
114 }
115
116 let neg_inf_value = PBValue::DoubleValue(f64::NEG_INFINITY);
117 let result = Value::from(neg_inf_value);
118 match result {
119 Value::Float(f) => {
120 assert!(f.into_inner().is_infinite() && f.into_inner().is_sign_negative())
121 }
122 _ => panic!("Expected Float value, got {result:?}"),
123 }
124 }
125}