zlayer_observability/
propagation.rs1use opentelemetry::propagation::{Extractor, Injector};
7use std::collections::HashMap;
8
9pub struct HeaderExtractor<'a, T>(pub &'a T);
11
12impl Extractor for HeaderExtractor<'_, http::HeaderMap> {
13 fn get(&self, key: &str) -> Option<&str> {
14 self.0.get(key).and_then(|v| v.to_str().ok())
15 }
16
17 fn keys(&self) -> Vec<&str> {
18 self.0.keys().map(|k| k.as_str()).collect()
19 }
20}
21
22impl Extractor for HeaderExtractor<'_, HashMap<String, String>> {
23 fn get(&self, key: &str) -> Option<&str> {
24 self.0.get(key).map(|s| s.as_str())
25 }
26
27 fn keys(&self) -> Vec<&str> {
28 self.0.keys().map(|s| s.as_str()).collect()
29 }
30}
31
32pub struct HeaderInjector<'a, T>(pub &'a mut T);
34
35impl Injector for HeaderInjector<'_, http::HeaderMap> {
36 fn set(&mut self, key: &str, value: String) {
37 if let Ok(name) = http::header::HeaderName::from_bytes(key.as_bytes()) {
38 if let Ok(val) = http::header::HeaderValue::from_str(&value) {
39 self.0.insert(name, val);
40 }
41 }
42 }
43}
44
45impl Injector for HeaderInjector<'_, HashMap<String, String>> {
46 fn set(&mut self, key: &str, value: String) {
47 self.0.insert(key.to_string(), value);
48 }
49}
50
51#[cfg(feature = "propagation")]
56pub fn extract_context_from_headers(headers: &http::HeaderMap) -> opentelemetry::Context {
57 use opentelemetry::global;
58 global::get_text_map_propagator(|propagator| propagator.extract(&HeaderExtractor(headers)))
59}
60
61#[cfg(feature = "propagation")]
65pub fn inject_context_to_headers(headers: &mut http::HeaderMap) {
66 use opentelemetry::global;
67 global::get_text_map_propagator(|propagator| {
68 propagator.inject(&mut HeaderInjector(headers));
69 });
70}
71
72#[cfg(feature = "propagation")]
74pub fn extract_context_from_map(map: &HashMap<String, String>) -> opentelemetry::Context {
75 use opentelemetry::global;
76 global::get_text_map_propagator(|propagator| propagator.extract(&HeaderExtractor(map)))
77}
78
79#[cfg(feature = "propagation")]
81pub fn inject_context_to_map(map: &mut HashMap<String, String>) {
82 use opentelemetry::global;
83 global::get_text_map_propagator(|propagator| {
84 propagator.inject(&mut HeaderInjector(map));
85 });
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_hashmap_extractor() {
94 let mut map = HashMap::new();
95 map.insert("traceparent".to_string(), "00-abc123-def456-01".to_string());
96
97 let extractor = HeaderExtractor(&map);
98 assert_eq!(extractor.get("traceparent"), Some("00-abc123-def456-01"));
99 assert_eq!(extractor.get("nonexistent"), None);
100 }
101
102 #[test]
103 fn test_hashmap_injector() {
104 let mut map = HashMap::new();
105 {
106 let mut injector = HeaderInjector(&mut map);
107 injector.set("traceparent", "00-abc123-def456-01".to_string());
108 }
109 assert_eq!(
110 map.get("traceparent"),
111 Some(&"00-abc123-def456-01".to_string())
112 );
113 }
114
115 #[test]
116 fn test_header_map_extractor() {
117 let mut headers = http::HeaderMap::new();
118 headers.insert("traceparent", "00-abc123-def456-01".parse().unwrap());
119
120 let extractor = HeaderExtractor(&headers);
121 assert_eq!(extractor.get("traceparent"), Some("00-abc123-def456-01"));
122 }
123
124 #[test]
125 fn test_header_map_injector() {
126 let mut headers = http::HeaderMap::new();
127 {
128 let mut injector = HeaderInjector(&mut headers);
129 injector.set("traceparent", "00-abc123-def456-01".to_string());
130 }
131 assert_eq!(
132 headers.get("traceparent").and_then(|v| v.to_str().ok()),
133 Some("00-abc123-def456-01")
134 );
135 }
136}