opentelemetry/propagation/
mod.rs

1//! # OpenTelemetry Propagator interface
2//! Cross-cutting concerns send their state to the next process using Propagators, which are defined
3//! as objects used to read and write context data to and from messages exchanged by the applications.
4//!
5//! `Propagator`s leverage the [`Context`] to inject and extract data for each cross-cutting concern,
6//! such as `TraceContext` and [`Baggage`].
7//!
8//! The Propagators API is expected to be leveraged by users writing instrumentation libraries.
9//!
10//! Currently, the following `Propagator` types are supported:
11//! -  [`TextMapPropagator`], inject values into and extracts values from carriers as string key/value pairs
12//!
13//! A binary Propagator type will be added in
14//! the future, See [tracking issues](https://github.com/open-telemetry/opentelemetry-specification/issues/437)).
15//!
16//! `Propagator`s uses [`Injector`] and [`Extractor`] to read and write context data to and from messages.
17//! Each specific Propagator type defines its expected carrier type, such as a string map or a byte array.
18//!
19//! [`Baggage`]: crate::baggage::Baggage
20//! [`Context`]: crate::Context
21
22use std::collections::HashMap;
23
24pub mod composite;
25pub mod text_map_propagator;
26
27pub use composite::TextMapCompositePropagator;
28pub use text_map_propagator::TextMapPropagator;
29
30/// Injector provides an interface for adding fields from an underlying struct like `HashMap`
31pub trait Injector {
32    /// Add a key and value to the underlying data.
33    fn set(&mut self, key: &str, value: String);
34}
35
36/// Extractor provides an interface for removing fields from an underlying struct like `HashMap`
37pub trait Extractor {
38    /// Get a value from a key from the underlying data.
39    fn get(&self, key: &str) -> Option<&str>;
40
41    /// Collect all the keys from the underlying data.
42    fn keys(&self) -> Vec<&str>;
43}
44
45impl<S: std::hash::BuildHasher> Injector for HashMap<String, String, S> {
46    /// Set a key and value in the HashMap.
47    fn set(&mut self, key: &str, value: String) {
48        self.insert(key.to_lowercase(), value);
49    }
50}
51
52impl<S: std::hash::BuildHasher> Extractor for HashMap<String, String, S> {
53    /// Get a value for a key from the HashMap.
54    fn get(&self, key: &str) -> Option<&str> {
55        self.get(&key.to_lowercase()).map(|v| v.as_str())
56    }
57
58    /// Collect all the keys from the HashMap.
59    fn keys(&self) -> Vec<&str> {
60        self.keys().map(|k| k.as_str()).collect::<Vec<_>>()
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use super::*;
67
68    #[test]
69    fn hash_map_get() {
70        let mut carrier = HashMap::new();
71        carrier.set("headerName", "value".to_string());
72
73        assert_eq!(
74            Extractor::get(&carrier, "HEADERNAME"),
75            Some("value"),
76            "case insensitive extraction"
77        );
78    }
79
80    #[test]
81    fn hash_map_keys() {
82        let mut carrier = HashMap::new();
83        carrier.set("headerName1", "value1".to_string());
84        carrier.set("headerName2", "value2".to_string());
85
86        let got = Extractor::keys(&carrier);
87        assert_eq!(got.len(), 2);
88        assert!(got.contains(&"headername1"));
89        assert!(got.contains(&"headername2"));
90    }
91}