opentelemetry_spanprocessor_any/attributes/
encoder.rs

1use crate::{Key, Value};
2use std::fmt::{self, Write};
3use std::sync::atomic::{AtomicUsize, Ordering};
4
5static ENCODER_ID_COUNTER: AtomicUsize = AtomicUsize::new(0);
6
7/// Encoder is a mechanism for serializing an attribute set into a specific string
8/// representation that supports caching, to avoid repeated serialization. An
9/// example could be an exporter encoding the attribute set into a wire
10/// representation.
11pub trait Encoder: fmt::Debug {
12    /// Encode returns the serialized encoding of the attribute
13    /// set using its Iterator. This result may be cached.
14    fn encode(&self, attributes: &mut dyn Iterator<Item = (&Key, &Value)>) -> String;
15
16    /// A value that is unique for each class of attribute encoder. Attribute encoders
17    /// allocate these using `new_encoder_id`.
18    fn id(&self) -> EncoderId;
19}
20
21/// EncoderID is used to identify distinct Encoder
22/// implementations, for caching encoded results.
23#[derive(Debug)]
24pub struct EncoderId(usize);
25
26impl EncoderId {
27    /// Check if the id is valid
28    pub fn is_valid(&self) -> bool {
29        self.0 != 0
30    }
31}
32
33/// Default attribute encoding strategy
34#[derive(Debug)]
35pub struct DefaultAttributeEncoder;
36
37impl Encoder for DefaultAttributeEncoder {
38    fn encode(&self, attributes: &mut dyn Iterator<Item = (&Key, &Value)>) -> String {
39        attributes
40            .enumerate()
41            .fold(String::new(), |mut acc, (idx, (key, value))| {
42                let offset = acc.len();
43                if idx > 0 {
44                    acc.push(',')
45                }
46
47                if write!(acc, "{}", key).is_err() {
48                    acc.truncate(offset);
49                    return acc;
50                }
51
52                acc.push('=');
53                if write!(acc, "{}", value).is_err() {
54                    acc.truncate(offset);
55                    return acc;
56                }
57
58                acc
59            })
60    }
61
62    fn id(&self) -> EncoderId {
63        new_encoder_id()
64    }
65}
66
67/// Build a new default encoder
68pub fn default_encoder() -> Box<dyn Encoder + Send + Sync> {
69    Box::new(DefaultAttributeEncoder)
70}
71
72/// Build a new encoder id
73pub fn new_encoder_id() -> EncoderId {
74    let old_encoder_id = ENCODER_ID_COUNTER.fetch_add(1, Ordering::AcqRel);
75    EncoderId(old_encoder_id + 1)
76}