diff --git a/opentelemetry-http/CHANGELOG.md b/opentelemetry-http/CHANGELOG.md index e1dd980535..a8a6d03430 100644 --- a/opentelemetry-http/CHANGELOG.md +++ b/opentelemetry-http/CHANGELOG.md @@ -2,6 +2,8 @@ ## vNext +- Implementation of `Extractor::get_all` for `HeaderExtractor` + ## 0.30.0 Released 2025-May-23 diff --git a/opentelemetry-http/src/lib.rs b/opentelemetry-http/src/lib.rs index 301979f85f..ad1c86cb64 100644 --- a/opentelemetry-http/src/lib.rs +++ b/opentelemetry-http/src/lib.rs @@ -43,6 +43,16 @@ impl Extractor for HeaderExtractor<'_> { .map(|value| value.as_str()) .collect::>() } + + /// Get all the values for a key from the HeaderMap + fn get_all(&self, key: &str) -> Option> { + let all_iter = self.0.get_all(key).iter(); + if let (0, Some(0)) = all_iter.size_hint() { + return None; + } + + Some(all_iter.filter_map(|value| value.to_str().ok()).collect()) + } } pub type HttpError = Box; @@ -236,6 +246,8 @@ impl ResponseExt for Response { #[cfg(test)] mod tests { + use http::HeaderValue; + use super::*; #[test] @@ -250,6 +262,32 @@ mod tests { ) } + #[test] + fn http_headers_get_all() { + let mut carrier = http::HeaderMap::new(); + carrier.append("headerName", HeaderValue::from_static("value")); + carrier.append("headerName", HeaderValue::from_static("value2")); + carrier.append("headerName", HeaderValue::from_static("value3")); + + assert_eq!( + HeaderExtractor(&carrier).get_all("HEADERNAME"), + Some(vec!["value", "value2", "value3"]), + "all values from a key extraction" + ) + } + + #[test] + fn http_headers_get_all_missing_key() { + let mut carrier = http::HeaderMap::new(); + carrier.append("headerName", HeaderValue::from_static("value")); + + assert_eq!( + HeaderExtractor(&carrier).get_all("not_existing"), + None, + "all values from a missing key extraction" + ) + } + #[test] fn http_headers_keys() { let mut carrier = http::HeaderMap::new(); diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 8cefac6661..e5aca778da 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -2,6 +2,8 @@ ## vNext +- Add `get_all` method to `opentelemetry::propagation::Extractor` to return all values of the given propagation key and provide a default implementation. + ## 0.30.0 Released 2025-May-23 diff --git a/opentelemetry/src/propagation/mod.rs b/opentelemetry/src/propagation/mod.rs index 863517980b..4bc0e78887 100644 --- a/opentelemetry/src/propagation/mod.rs +++ b/opentelemetry/src/propagation/mod.rs @@ -40,6 +40,11 @@ pub trait Extractor { /// Collect all the keys from the underlying data. fn keys(&self) -> Vec<&str>; + + /// Get all values from a key from the underlying data. + fn get_all(&self, key: &str) -> Option> { + self.get(key).map(|value| vec![value]) + } } impl Injector for HashMap { @@ -77,6 +82,30 @@ mod tests { ); } + #[test] + fn hash_map_get_all() { + let mut carrier = HashMap::new(); + carrier.set("headerName", "value".to_string()); + + assert_eq!( + Extractor::get_all(&carrier, "HEADERNAME"), + Some(vec!["value"]), + "case insensitive get_all extraction" + ); + } + + #[test] + fn hash_map_get_all_missing_key() { + let mut carrier = HashMap::new(); + carrier.set("headerName", "value".to_string()); + + assert_eq!( + Extractor::get_all(&carrier, "missing_key"), + None, + "case insensitive get_all extraction" + ); + } + #[test] fn hash_map_keys() { let mut carrier = HashMap::new();