aws_smithy_observability_otel/
attributes.rs1use std::ops::Deref;
10
11use aws_smithy_observability::{AttributeValue, Attributes};
12use opentelemetry::{KeyValue, Value};
13
14pub(crate) struct AttributesWrap(Attributes);
15impl AttributesWrap {
16 pub(crate) fn new(inner: Attributes) -> Self {
17 Self(inner)
18 }
19}
20impl Deref for AttributesWrap {
21 type Target = Attributes;
22
23 fn deref(&self) -> &Self::Target {
24 &self.0
25 }
26}
27
28pub(crate) fn kv_from_option_attr(input: Option<&Attributes>) -> Vec<KeyValue> {
29 input
30 .map(|attr| AttributesWrap::new(attr.clone()))
31 .unwrap_or(AttributesWrap::new(Attributes::new()))
32 .into()
33}
34
35#[allow(dead_code)]
36pub(crate) fn option_attr_from_kv(input: &[KeyValue]) -> Option<Attributes> {
37 if input.is_empty() {
38 return None;
39 }
40
41 Some(AttributesWrap::from(input).0)
42}
43
44impl From<AttributesWrap> for Vec<KeyValue> {
45 fn from(value: AttributesWrap) -> Self {
46 value
47 .0
48 .into_attributes()
49 .map(|(k, v)| {
50 KeyValue::new(
51 k,
52 match v {
53 AttributeValue::I64(val) => Value::I64(val),
54 AttributeValue::F64(val) => Value::F64(val),
55 AttributeValue::String(val) => Value::String(val.into()),
56 AttributeValue::Bool(val) => Value::Bool(val),
57 _ => Value::String("UNSUPPORTED ATTRIBUTE VALUE TYPE".into()),
58 },
59 )
60 })
61 .collect::<Vec<KeyValue>>()
62 }
63}
64
65impl From<&[KeyValue]> for AttributesWrap {
66 fn from(value: &[KeyValue]) -> Self {
67 let mut attrs = Attributes::new();
68
69 value.iter().for_each(|kv| {
70 attrs.set(
71 kv.key.clone(),
72 match &kv.value {
73 Value::Bool(val) => AttributeValue::Bool(*val),
74 Value::I64(val) => AttributeValue::I64(*val),
75 Value::F64(val) => AttributeValue::F64(*val),
76 Value::String(val) => AttributeValue::String(val.clone().into()),
77 Value::Array(_) => {
78 AttributeValue::String("UNSUPPORTED ATTRIBUTE VALUE TYPE".into())
79 }
80 },
81 )
82 });
83
84 AttributesWrap(attrs)
85 }
86}
87
88#[cfg(test)]
89mod tests {
90 use std::collections::HashMap;
91
92 use super::*;
93 use aws_smithy_observability::{AttributeValue, Attributes};
94 use opentelemetry::Value;
95
96 #[test]
97 fn attr_to_kv() {
98 let mut attrs = Attributes::new();
99 attrs.set("I64", AttributeValue::I64(64));
100 attrs.set("F64", AttributeValue::F64(64.0));
101 attrs.set("String", AttributeValue::String("I AM A STRING".into()));
102 attrs.set("Bool", AttributeValue::Bool(true));
103
104 let kv = kv_from_option_attr(Some(&attrs));
105
106 let kv_map: HashMap<String, Value> = kv
107 .into_iter()
108 .map(|kv| (kv.key.to_string(), kv.value))
109 .collect();
110
111 assert_eq!(kv_map.get("I64").unwrap(), &Value::I64(64));
112 assert_eq!(kv_map.get("F64").unwrap(), &Value::F64(64.0));
113 assert_eq!(
114 kv_map.get("String").unwrap(),
115 &Value::String("I AM A STRING".into())
116 );
117 assert_eq!(kv_map.get("Bool").unwrap(), &Value::Bool(true));
118 }
119
120 #[test]
121 fn kv_to_attr() {
122 let kvs: Vec<KeyValue> = vec![
123 KeyValue::new("Bool", Value::Bool(true)),
124 KeyValue::new("String", Value::String("I AM A STRING".into())),
125 KeyValue::new("I64", Value::I64(64)),
126 KeyValue::new("F64", Value::F64(64.0)),
127 ];
128
129 let attrs = option_attr_from_kv(&kvs).unwrap();
130 assert_eq!(attrs.get("Bool").unwrap(), &AttributeValue::Bool(true));
131 assert_eq!(
132 attrs.get("String").unwrap(),
133 &AttributeValue::String("I AM A STRING".into())
134 );
135 assert_eq!(attrs.get("I64").unwrap(), &AttributeValue::I64(64));
136 assert_eq!(attrs.get("F64").unwrap(), &AttributeValue::F64(64.0));
137 }
138}