1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161
//! # OpenTelemetry Correlation Context API //! //! A Correlation Context is used to annotate telemetry, adding context and //! information to metrics, traces, and logs. It is an abstract data type //! represented by a set of name/value pairs describing user-defined properties. //! Each name in a [`CorrelationContext`] is associated with exactly one value. //! `CorrelationContext`s are serialized according to the editor's draft of //! the [W3C Correlation Context] specification. //! //! [`CorrelationContext`]: struct.CorrelationContext.html //! [W3C Correlation Context]: https://w3c.github.io/correlation-context/ //! //! # Examples //! //! ``` //! use opentelemetry::api::{ //! CorrelationContextExt, CorrelationContextPropagator, HttpTextFormat, Key //! }; //! use std::collections::HashMap; //! //! // Example correlation value passed in externally via http headers //! let mut headers = HashMap::new(); //! headers.insert("Correlation-Context", "user_id=1".to_string()); //! //! let propagator = CorrelationContextPropagator::new(); //! // can extract from any type that impls `Carrier`, usually an HTTP header map //! let cx = propagator.extract(&headers); //! //! // Iterate over extracted name / value pairs //! for (name, value) in cx.correlation_context() { //! // ... //! } //! //! // Add new correlations //! let cx_with_additions = cx.with_correlations(vec![Key::new("server_id").u64(42)]); //! //! // Inject correlations into http request //! propagator.inject_context(&cx_with_additions, &mut headers); //! //! let header_value = headers.get("Correlation-Context").expect("header is injected"); //! assert!(header_value.contains("user_id=1"), "still contains previous name / value"); //! assert!(header_value.contains("server_id=42"), "contains new name / value pair"); //! ``` use crate::api; use std::collections::{hash_map, HashMap}; use std::iter::FromIterator; mod propagation; pub use propagation::{CorrelationContextExt, CorrelationContextPropagator}; /// A set of name/value pairs describing user-defined properties across systems. #[derive(Debug, Default)] pub struct CorrelationContext { inner: HashMap<api::Key, api::Value>, } impl CorrelationContext { /// Creates an empty `CorrelationContext`. pub fn new() -> Self { CorrelationContext { inner: HashMap::default(), } } /// Returns a reference to the value associated with a given name /// /// # Examples /// /// ``` /// use opentelemetry::api::{CorrelationContext, Value}; /// /// let mut cc = CorrelationContext::new(); /// let _ = cc.insert("my-name", "my-value"); /// /// assert_eq!(cc.get("my-name"), Some(&Value::String("my-value".to_string()))) /// ``` pub fn get<T: Into<api::Key>>(&self, key: T) -> Option<&api::Value> { self.inner.get(&key.into()) } /// Inserts a name-value pair into the correlation context. /// /// If the name was not present, [`None`] is returned. If the name was present, /// the value is updated, and the old value is returned. /// /// # Examples /// /// ``` /// use opentelemetry::api::{CorrelationContext, Value}; /// /// let mut cc = CorrelationContext::new(); /// let _ = cc.insert("my-name", "my-value"); /// /// assert_eq!(cc.get("my-name"), Some(&Value::String("my-value".to_string()))) /// ``` pub fn insert<K, V>(&mut self, key: K, value: V) -> Option<api::Value> where K: Into<api::Key>, V: Into<api::Value>, { self.inner.insert(key.into(), value.into()) } /// Removes a name from the correlation context, returning the value /// corresponding to the name if the pair was previously in the map. pub fn remove<K: Into<api::Key>>(&mut self, key: K) -> Option<api::Value> { self.inner.remove(&key.into()) } /// Returns the number of attributes for this correlation context pub fn len(&self) -> usize { self.inner.len() } /// Returns `true` if the correlation context contains no items. pub fn is_empty(&self) -> bool { self.inner.is_empty() } /// Gets an iterator over the correlation context items, sorted by name. pub fn iter(&self) -> Iter { self.into_iter() } } /// An iterator over the entries of a `CorrelationContext`. #[derive(Debug)] pub struct Iter<'a>(hash_map::Iter<'a, api::Key, api::Value>); impl<'a> Iterator for Iter<'a> { type Item = (&'a api::Key, &'a api::Value); fn next(&mut self) -> Option<Self::Item> { self.0.next() } } impl<'a> IntoIterator for &'a CorrelationContext { type Item = (&'a api::Key, &'a api::Value); type IntoIter = Iter<'a>; fn into_iter(self) -> Self::IntoIter { Iter(self.inner.iter()) } } impl FromIterator<(api::Key, api::Value)> for CorrelationContext { fn from_iter<I: IntoIterator<Item = (api::Key, api::Value)>>(iter: I) -> Self { CorrelationContext { inner: iter.into_iter().collect(), } } } impl FromIterator<api::KeyValue> for CorrelationContext { fn from_iter<I: IntoIterator<Item = api::KeyValue>>(iter: I) -> Self { CorrelationContext { inner: iter.into_iter().map(|kv| (kv.key, kv.value)).collect(), } } }