opentelemetry_spanprocessor_any/attributes/
mod.rs

1//! OpenTelemetry Attributes
2use crate::{Array, Key, KeyValue, Value};
3use std::cmp::Ordering;
4use std::collections::{btree_map, BTreeMap};
5use std::hash::{Hash, Hasher};
6use std::iter::Peekable;
7
8mod encoder;
9pub use encoder::{default_encoder, new_encoder_id, DefaultAttributeEncoder, Encoder, EncoderId};
10
11/// An immutable set of distinct attributes.
12#[derive(Clone, Debug, Default)]
13pub struct AttributeSet {
14    attributes: BTreeMap<Key, Value>,
15}
16
17impl AttributeSet {
18    /// Construct a new attribute set form a distinct set of attributes
19    pub fn from_attributes<T: IntoIterator<Item = KeyValue>>(attributes: T) -> Self {
20        AttributeSet {
21            attributes: attributes
22                .into_iter()
23                .map(|kv| (kv.key, kv.value))
24                .collect(),
25        }
26    }
27
28    /// The attribute set length.
29    pub fn len(&self) -> usize {
30        self.attributes.len()
31    }
32
33    /// Check if the set of attributes are empty.
34    pub fn is_empty(&self) -> bool {
35        self.attributes.is_empty()
36    }
37
38    /// Iterate over the attribute key value pairs.
39    pub fn iter(&self) -> Iter<'_> {
40        self.into_iter()
41    }
42
43    /// Encode the attribute set with the given encoder and cache the result.
44    pub fn encoded(&self, encoder: Option<&dyn Encoder>) -> String {
45        encoder.map_or_else(String::new, |encoder| encoder.encode(&mut self.iter()))
46    }
47}
48
49impl<'a> IntoIterator for &'a AttributeSet {
50    type Item = (&'a Key, &'a Value);
51    type IntoIter = Iter<'a>;
52
53    fn into_iter(self) -> Self::IntoIter {
54        Iter(self.attributes.iter())
55    }
56}
57/// An iterator over the entries of a `Set`.
58#[derive(Debug)]
59pub struct Iter<'a>(btree_map::Iter<'a, Key, Value>);
60impl<'a> Iterator for Iter<'a> {
61    type Item = (&'a Key, &'a Value);
62
63    fn next(&mut self) -> Option<Self::Item> {
64        self.0.next()
65    }
66}
67
68/// Impl of Hash for `KeyValue`
69pub fn hash_attributes<'a, H: Hasher, I: IntoIterator<Item = (&'a Key, &'a Value)>>(
70    state: &mut H,
71    attributes: I,
72) {
73    for (key, value) in attributes.into_iter() {
74        key.hash(state);
75        hash_value(state, value);
76    }
77}
78
79fn hash_value<H: Hasher>(state: &mut H, value: &Value) {
80    match value {
81        Value::Bool(b) => b.hash(state),
82        Value::I64(i) => i.hash(state),
83        Value::F64(f) => {
84            // FIXME: f64 does not impl hash, this impl may have incorrect outcomes.
85            f.to_bits().hash(state)
86        }
87        Value::String(s) => s.hash(state),
88        Value::Array(arr) => match arr {
89            // recursively hash array values
90            Array::Bool(values) => values.iter().for_each(|v| v.hash(state)),
91            Array::I64(values) => values.iter().for_each(|v| v.hash(state)),
92            Array::F64(values) => values.iter().for_each(|v| v.to_bits().hash(state)),
93            Array::String(values) => values.iter().for_each(|v| v.hash(state)),
94        },
95    }
96}
97
98/// Merge two iterators, yielding sorted results
99pub fn merge_iters<
100    'a,
101    'b,
102    A: Iterator<Item = (&'a Key, &'a Value)>,
103    B: Iterator<Item = (&'b Key, &'b Value)>,
104>(
105    a: A,
106    b: B,
107) -> MergeIter<'a, 'b, A, B> {
108    MergeIter {
109        a: a.peekable(),
110        b: b.peekable(),
111    }
112}
113
114/// Merge two iterators, sorting by key
115#[derive(Debug)]
116pub struct MergeIter<'a, 'b, A, B>
117where
118    A: Iterator<Item = (&'a Key, &'a Value)>,
119    B: Iterator<Item = (&'b Key, &'b Value)>,
120{
121    a: Peekable<A>,
122    b: Peekable<B>,
123}
124
125impl<'a, A: Iterator<Item = (&'a Key, &'a Value)>, B: Iterator<Item = (&'a Key, &'a Value)>>
126    Iterator for MergeIter<'a, 'a, A, B>
127{
128    type Item = (&'a Key, &'a Value);
129    fn next(&mut self) -> Option<Self::Item> {
130        let which = match (self.a.peek(), self.b.peek()) {
131            (Some(a), Some(b)) => Some(a.0.cmp(b.0)),
132            (Some(_), None) => Some(Ordering::Less),
133            (None, Some(_)) => Some(Ordering::Greater),
134            (None, None) => None,
135        };
136
137        match which {
138            Some(Ordering::Less) => self.a.next(),
139            Some(Ordering::Equal) => self.a.next(),
140            Some(Ordering::Greater) => self.b.next(),
141            None => None,
142        }
143    }
144}