From 0e7b0061a0956336e3e704936d357fb0b60b7dd4 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 9 May 2023 16:05:09 -0700 Subject: [PATCH 1/6] more OrderMap to root of the otel-api crate --- opentelemetry-api/src/lib.rs | 4 + opentelemetry-api/src/trace/mod.rs | 2 - opentelemetry-api/src/trace/order_map.rs | 670 ------------------ opentelemetry-api/src/trace/tracer.rs | 2 +- opentelemetry-sdk/src/trace/sampler.rs | 3 +- .../trace/sampler/jaeger_remote/sampler.rs | 4 +- opentelemetry-sdk/src/trace/tracer.rs | 4 +- 7 files changed, 10 insertions(+), 679 deletions(-) delete mode 100644 opentelemetry-api/src/trace/order_map.rs diff --git a/opentelemetry-api/src/lib.rs b/opentelemetry-api/src/lib.rs index e19182726f..6f9190d351 100644 --- a/opentelemetry-api/src/lib.rs +++ b/opentelemetry-api/src/lib.rs @@ -51,6 +51,10 @@ pub use context::{Context, ContextGuard}; mod common; +mod order_map; + +pub use order_map::OrderMap; + #[cfg(any(feature = "testing", test))] #[doc(hidden)] pub mod testing; diff --git a/opentelemetry-api/src/trace/mod.rs b/opentelemetry-api/src/trace/mod.rs index e3886b0e3b..f496d67ecf 100644 --- a/opentelemetry-api/src/trace/mod.rs +++ b/opentelemetry-api/src/trace/mod.rs @@ -169,7 +169,6 @@ use thiserror::Error; mod context; pub mod noop; -mod order_map; mod span; mod span_context; mod tracer; @@ -179,7 +178,6 @@ pub use self::{ context::{ get_active_span, mark_span_as_active, FutureExt, SpanRef, TraceContextExt, WithContext, }, - order_map::OrderMap, span::{Span, SpanKind, Status}, span_context::{SpanContext, SpanId, TraceFlags, TraceId, TraceState}, tracer::{SamplingDecision, SamplingResult, SpanBuilder, Tracer}, diff --git a/opentelemetry-api/src/trace/order_map.rs b/opentelemetry-api/src/trace/order_map.rs deleted file mode 100644 index b69cc7090d..0000000000 --- a/opentelemetry-api/src/trace/order_map.rs +++ /dev/null @@ -1,670 +0,0 @@ -use crate::{Key, KeyValue, Value}; -use indexmap::map::{ - Drain, Entry, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut, -}; -use indexmap::{Equivalent, IndexMap}; -use std::collections::hash_map::RandomState; -use std::hash::{BuildHasher, Hash}; -use std::iter::FromIterator; -use std::ops::{Index, IndexMut, RangeBounds}; - -/// A hash table implementation that preserves insertion order across all operations. -/// -/// Entries will be returned according to their insertion order when iterating over the collection. -#[derive(Clone, Debug)] -pub struct OrderMap(IndexMap); - -impl OrderMap { - /// Create a new map. (Does not allocate) - #[inline] - pub fn new() -> Self { - Self(IndexMap::new()) - } - - /// Create a new map with capacity for `n` key-value pairs. (Does not - /// allocate if `n` is zero.) - /// - /// Computes in **O(n)** time. - #[inline] - pub fn with_capacity(n: usize) -> Self { - Self(IndexMap::with_capacity(n)) - } -} - -impl OrderMap { - /// Create a new map with capacity for `n` key-value pairs. (Does not - /// allocate if `n` is zero.) - /// - /// Computes in **O(n)** time. - #[inline] - pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self { - Self(IndexMap::with_capacity_and_hasher(n, hash_builder)) - } - - /// Create a new map with `hash_builder`. - /// - /// This function is `const`, so it - /// can be called in `static` contexts. - pub const fn with_hasher(hash_builder: S) -> Self { - Self(IndexMap::with_hasher(hash_builder)) - } - - /// Computes in **O(1)** time. - pub fn capacity(&self) -> usize { - self.0.capacity() - } - - /// Return a reference to the map's `BuildHasher`. - pub fn hasher(&self) -> &S { - self.0.hasher() - } - - /// Return the number of key-value pairs in the map. - /// - /// Computes in **O(1)** time. - #[inline] - pub fn len(&self) -> usize { - self.0.len() - } - - /// Returns true if the map contains no elements. - /// - /// Computes in **O(1)** time. - #[inline] - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Return an iterator over the key-value pairs of the map, in their order - pub fn iter(&self) -> Iter<'_, K, V> { - self.0.iter() - } - - /// Return an iterator over the key-value pairs of the map, in their order - pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { - self.0.iter_mut() - } - - /// Return an iterator over the keys of the map, in their order - pub fn keys(&self) -> Keys<'_, K, V> { - self.0.keys() - } - - /// Return an owning iterator over the keys of the map, in their order - pub fn into_keys(self) -> IntoKeys { - self.0.into_keys() - } - - /// Return an iterator over the values of the map, in their order - pub fn values(&self) -> Values<'_, K, V> { - self.0.values() - } - - /// Return an iterator over mutable references to the values of the map, - /// in their order - pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { - self.0.values_mut() - } - - /// Return an owning iterator over the values of the map, in their order - pub fn into_values(self) -> IntoValues { - self.0.into_values() - } - - /// Remove all key-value pairs in the map, while preserving its capacity. - /// - /// Computes in **O(n)** time. - pub fn clear(&mut self) { - self.0.clear(); - } - - /// Shortens the map, keeping the first `len` elements and dropping the rest. - /// - /// If `len` is greater than the map's current length, this has no effect. - pub fn truncate(&mut self, len: usize) { - self.0.truncate(len); - } - - /// Clears the `IndexMap` in the given index range, returning those - /// key-value pairs as a drain iterator. - /// - /// The range may be any type that implements `RangeBounds`, - /// including all of the `std::ops::Range*` types, or even a tuple pair of - /// `Bound` start and end values. To drain the map entirely, use `RangeFull` - /// like `map.drain(..)`. - /// - /// This shifts down all entries following the drained range to fill the - /// gap, and keeps the allocated memory for reuse. - /// - /// ***Panics*** if the starting point is greater than the end point or if - /// the end point is greater than the length of the map. - pub fn drain(&mut self, range: R) -> Drain<'_, K, V> - where - R: RangeBounds, - { - self.0.drain(range) - } - - /// Splits the collection into two at the given index. - /// - /// Returns a newly allocated map containing the elements in the range - /// `[at, len)`. After the call, the original map will be left containing - /// the elements `[0, at)` with its previous capacity unchanged. - /// - /// ***Panics*** if `at > len`. - pub fn split_off(&mut self, at: usize) -> Self - where - S: Clone, - { - Self(self.0.split_off(at)) - } -} - -impl OrderMap -where - K: Hash + Eq, - S: BuildHasher, -{ - /// Reserve capacity for `additional` more key-value pairs. - /// - /// Computes in **O(n)** time. - pub fn reserve(&mut self, additional: usize) { - self.0.reserve(additional) - } - - /// Shrink the capacity of the map as much as possible. - /// - /// Computes in **O(n)** time. - pub fn shrink_to_fit(&mut self) { - self.0.shrink_to_fit() - } - - /// Insert a key-value pair in the map. - /// - /// If an equivalent key already exists in the map: the key remains and - /// retains in its place in the order, its corresponding value is updated - /// with `value` and the older value is returned inside `Some(_)`. - /// - /// If no equivalent key existed in the map: the new key-value pair is - /// inserted, last in order, and `None` is returned. - /// - /// Computes in **O(1)** time (amortized average). - /// - /// See also [`entry`](#method.entry) if you you want to insert *or* modify - /// or if you need to get the index of the corresponding key-value pair. - pub fn insert(&mut self, key: K, value: V) -> Option { - self.0.insert(key, value) - } - - /// Insert a key-value pair in the map, and get their index. - /// - /// If an equivalent key already exists in the map: the key remains and - /// retains in its place in the order, its corresponding value is updated - /// with `value` and the older value is returned inside `(index, Some(_))`. - /// - /// If no equivalent key existed in the map: the new key-value pair is - /// inserted, last in order, and `(index, None)` is returned. - /// - /// Computes in **O(1)** time (amortized average). - /// - /// See also [`entry`](#method.entry) if you you want to insert *or* modify - /// or if you need to get the index of the corresponding key-value pair. - pub fn insert_full(&mut self, key: K, value: V) -> (usize, Option) { - self.0.insert_full(key, value) - } - - /// Get the given key’s corresponding entry in the map for insertion and/or - /// in-place manipulation. - /// - /// Computes in **O(1)** time (amortized average). - pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { - self.0.entry(key) - } - - /// Return `true` if an equivalent to `key` exists in the map. - /// - /// Computes in **O(1)** time (average). - pub fn contains_key(&self, key: &Q) -> bool - where - Q: Hash + Equivalent, - { - self.0.contains_key(key) - } - - /// Return a reference to the value stored for `key`, if it is present, - /// else `None`. - /// - /// Computes in **O(1)** time (average). - pub fn get(&self, key: &Q) -> Option<&V> - where - Q: Hash + Equivalent, - { - self.0.get(key) - } - - /// Return references to the key-value pair stored for `key`, - /// if it is present, else `None`. - /// - /// Computes in **O(1)** time (average). - pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> - where - Q: Hash + Equivalent, - { - self.0.get_key_value(key) - } - - /// Return item index, key and value - pub fn get_full(&self, key: &Q) -> Option<(usize, &K, &V)> - where - Q: Hash + Equivalent, - { - self.0.get_full(key) - } - - /// Return item index, if it exists in the map - /// - /// Computes in **O(1)** time (average). - pub fn get_index_of(&self, key: &Q) -> Option - where - Q: Hash + Equivalent, - { - self.0.get_index_of(key) - } - - /// Return a mutable reference to the element pointed at by `key`, if it exists. - pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> - where - Q: Hash + Equivalent, - { - self.0.get_mut(key) - } - - /// Return a mutable reference to the element pointed at by `key`, if it exists. - /// It also returns the element's index and its key. - pub fn get_full_mut(&mut self, key: &Q) -> Option<(usize, &K, &mut V)> - where - Q: Hash + Equivalent, - { - self.0.get_full_mut(key) - } - - /// Remove the key-value pair equivalent to `key` and return - /// its value. - /// - /// Like `Vec::remove`, the pair is removed by shifting all of the - /// elements that follow it, preserving their relative order. - /// **This perturbs the index of all of those elements!** - /// - /// Return `None` if `key` is not in map. - /// - /// Computes in **O(n)** time (average). - pub fn shift_remove(&mut self, key: &Q) -> Option - where - Q: Hash + Equivalent, - { - self.0.shift_remove(key) - } - - /// Remove and return the key-value pair equivalent to `key`. - /// - /// Like `Vec::remove`, the pair is removed by shifting all of the - /// elements that follow it, preserving their relative order. - /// **This perturbs the index of all of those elements!** - /// - /// Return `None` if `key` is not in map. - /// - /// Computes in **O(n)** time (average). - pub fn shift_remove_entry(&mut self, key: &Q) -> Option<(K, V)> - where - Q: Hash + Equivalent, - { - self.0.shift_remove_entry(key) - } - - /// Remove the key-value pair equivalent to `key` and return it and - /// the index it had. - /// - /// Like `Vec::remove`, the pair is removed by shifting all of the - /// elements that follow it, preserving their relative order. - /// **This perturbs the index of all of those elements!** - /// - /// Return `None` if `key` is not in map. - /// - /// Computes in **O(n)** time (average). - pub fn shift_remove_full(&mut self, key: &Q) -> Option<(usize, K, V)> - where - Q: Hash + Equivalent, - { - self.0.shift_remove_full(key) - } - - /// Remove the last key-value pair - /// - /// This preserves the order of the remaining elements. - /// - /// Computes in **O(1)** time (average). - pub fn pop(&mut self) -> Option<(K, V)> { - self.0.pop() - } - - /// Scan through each key-value pair in the map and keep those where the - /// closure `keep` returns `true`. - /// - /// The elements are visited in order, and remaining elements keep their - /// order. - /// - /// Computes in **O(n)** time (average). - pub fn retain(&mut self, keep: F) - where - F: FnMut(&K, &mut V) -> bool, - { - self.0.retain(keep); - } -} - -impl OrderMap { - /// Get a key-value pair by index - /// - /// Valid indices are *0 <= index < self.len()* - /// - /// Computes in **O(1)** time. - pub fn get_index(&self, index: usize) -> Option<(&K, &V)> { - self.0.get_index(index) - } - - /// Get a key-value pair by index - /// - /// Valid indices are *0 <= index < self.len()* - /// - /// Computes in **O(1)** time. - pub fn get_index_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> { - self.0.get_index_mut(index) - } - - /// Get the first key-value pair - /// - /// Computes in **O(1)** time. - pub fn first(&self) -> Option<(&K, &V)> { - self.0.first() - } - - /// Get the first key-value pair, with mutable access to the value - /// - /// Computes in **O(1)** time. - pub fn first_mut(&mut self) -> Option<(&K, &mut V)> { - self.0.first_mut() - } - - /// Get the last key-value pair - /// - /// Computes in **O(1)** time. - pub fn last(&self) -> Option<(&K, &V)> { - self.0.last() - } - - /// Get the last key-value pair, with mutable access to the value - /// - /// Computes in **O(1)** time. - pub fn last_mut(&mut self) -> Option<(&K, &mut V)> { - self.0.last_mut() - } - - /// Remove the key-value pair by index - /// - /// Valid indices are *0 <= index < self.len()* - /// - /// Like `Vec::remove`, the pair is removed by shifting all of the - /// elements that follow it, preserving their relative order. - /// **This perturbs the index of all of those elements!** - /// - /// Computes in **O(n)** time (average). - pub fn shift_remove_index(&mut self, index: usize) -> Option<(K, V)> { - self.0.shift_remove_index(index) - } -} - -impl<'a, K, V, S> IntoIterator for &'a OrderMap { - type Item = (&'a K, &'a V); - type IntoIter = Iter<'a, K, V>; - fn into_iter(self) -> Self::IntoIter { - self.0.iter() - } -} - -impl<'a, K, V, S> IntoIterator for &'a mut OrderMap { - type Item = (&'a K, &'a mut V); - type IntoIter = IterMut<'a, K, V>; - fn into_iter(self) -> Self::IntoIter { - self.0.iter_mut() - } -} - -impl IntoIterator for OrderMap { - type Item = (K, V); - type IntoIter = IntoIter; - fn into_iter(self) -> Self::IntoIter { - self.0.into_iter() - } -} - -/// Access `OrderMap` values corresponding to a key. -/// -/// Panics if the value is missing. -impl Index<&Q> for OrderMap -where - Q: Hash + Equivalent, - K: Hash + Eq, - S: BuildHasher, -{ - type Output = V; - - /// Returns a reference to the value corresponding to the supplied `key`. - /// - /// ***Panics*** if `key` is not present in the map. - fn index(&self, key: &Q) -> &V { - self.0.index(key) - } -} - -/// Access `Ordermap` values corresponding to a key. -/// -/// Mutable indexing allows changing / updating values of key-value -/// pairs that are already present. -/// -/// You can **not** insert new pairs with index syntax, use `.insert()`. -impl IndexMut<&Q> for OrderMap -where - Q: Hash + Equivalent, - K: Hash + Eq, - S: BuildHasher, -{ - /// Returns a mutable reference to the value corresponding to the supplied `key`. - /// - /// ***Panics*** if `key` is not present in the map. - fn index_mut(&mut self, key: &Q) -> &mut V { - self.0.index_mut(key) - } -} - -/// Access `IndexMap` values at indexed positions. -/// -/// It panics if the index is out of bounds. -impl Index for OrderMap { - type Output = V; - - /// Returns a reference to the value at the supplied `index`. - /// - /// ***Panics*** if `index` is out of bounds. - fn index(&self, index: usize) -> &V { - self.0.index(index) - } -} - -/// Access `IndexMap` values at indexed positions. -/// -/// Mutable indexing allows changing / updating indexed values -/// that are already present. -/// -/// You can **not** insert new values with index syntax, use `.insert()`. -/// -/// # Examples -/// -/// ``` -/// use indexmap::IndexMap; -/// -/// let mut map = IndexMap::new(); -/// for word in "Lorem ipsum dolor sit amet".split_whitespace() { -/// map.insert(word.to_lowercase(), word.to_string()); -/// } -/// let lorem = &mut map[0]; -/// assert_eq!(lorem, "Lorem"); -/// lorem.retain(char::is_lowercase); -/// assert_eq!(map["lorem"], "orem"); -/// ``` -/// -/// ```should_panic -/// use indexmap::IndexMap; -/// -/// let mut map = IndexMap::new(); -/// map.insert("foo", 1); -/// map[10] = 1; // panics! -/// ``` -impl IndexMut for OrderMap { - /// Returns a mutable reference to the value at the supplied `index`. - /// - /// ***Panics*** if `index` is out of bounds. - fn index_mut(&mut self, index: usize) -> &mut V { - self.0.index_mut(index) - } -} - -impl FromIterator<(K, V)> for OrderMap -where - K: Hash + Eq, - S: BuildHasher + Default, -{ - /// Create an `OrderMap` from the sequence of key-value pairs in the - /// iterable. - /// - /// `from_iter` uses the same logic as `extend`. See - /// [`extend`](#method.extend) for more details. - fn from_iter>(iterable: I) -> Self { - Self(IndexMap::from_iter(iterable)) - } -} - -// todo: uncomment when the MSRV bumps -// impl From<[(K, V); N]> for OrderMap -// where -// K: Hash + Eq, -// { -// fn from(arr: [(K, V); N]) -> Self { -// Self(IndexMap::from(arr)) -// } -// } - -impl Extend<(K, V)> for OrderMap -where - K: Hash + Eq, - S: BuildHasher, -{ - /// Extend the map with all key-value pairs in the iterable. - /// - /// This is equivalent to calling [`insert`](#method.insert) for each of - /// them in order, which means that for keys that already existed - /// in the map, their value is updated but it keeps the existing order. - /// - /// New keys are inserted in the order they appear in the sequence. If - /// equivalents of a key occur more than once, the last corresponding value - /// prevails. - fn extend>(&mut self, iterable: I) { - self.0.extend(iterable) - } -} - -impl<'a, K, V, S> Extend<(&'a K, &'a V)> for OrderMap -where - K: 'a + Hash + Eq + Copy, - V: 'a + Copy, - S: BuildHasher, -{ - /// Extend the map with all key-value pairs in the iterable. - /// - /// See the first extend method for more details. - fn extend>(&mut self, iterable: I) { - self.0.extend(iterable) - } -} - -impl Default for OrderMap -where - S: Default, -{ - /// Return an empty `OrderMap` - fn default() -> Self { - Self(IndexMap::default()) - } -} - -impl PartialEq> for OrderMap -where - K: Hash + Eq, - V1: PartialEq, - S1: BuildHasher, - S2: BuildHasher, -{ - fn eq(&self, other: &OrderMap) -> bool { - self.0.eq(&other.0) - } -} - -impl Eq for OrderMap -where - K: Eq + Hash, - V: Eq, - S: BuildHasher, -{ -} - -impl FromIterator for OrderMap -where - S: BuildHasher + Default, -{ - /// Create an `OrderMap` from the sequence of key-value pairs in the - /// iterable. - /// - /// `from_iter` uses the same logic as `extend`. See - /// [`extend`](#method.extend) for more details. - fn from_iter>(iterable: I) -> Self { - Self(IndexMap::from_iter( - iterable.into_iter().map(|kv| (kv.key, kv.value)), - )) - } -} - -// todo: uncomment below when bumping MSRV -// impl From<[KeyValue; N]> for OrderMap { -// fn from(arr: [KeyValue; N]) -> Self { -// let arr = arr.map(|kv| (kv.key, kv.value)); -// Self(IndexMap::from(arr)) -// } -// } - -impl Extend for OrderMap -where - S: BuildHasher, -{ - /// Extend the map with all key-value pairs in the iterable. - /// - /// This is equivalent to calling [`insert`](#method.insert) for each of - /// them in order, which means that for keys that already existed - /// in the map, their value is updated but it keeps the existing order. - /// - /// New keys are inserted in the order they appear in the sequence. If - /// equivalents of a key occur more than once, the last corresponding value - /// prevails. - fn extend>(&mut self, iterable: I) { - self.0 - .extend(iterable.into_iter().map(|kv| (kv.key, kv.value))) - } -} diff --git a/opentelemetry-api/src/trace/tracer.rs b/opentelemetry-api/src/trace/tracer.rs index dde5cbe7b3..e16329ce3d 100644 --- a/opentelemetry-api/src/trace/tracer.rs +++ b/opentelemetry-api/src/trace/tracer.rs @@ -1,4 +1,4 @@ -use crate::trace::OrderMap; +use crate::OrderMap; use crate::{ trace::{Event, Link, Span, SpanId, SpanKind, Status, TraceContextExt, TraceId, TraceState}, Context, Key, KeyValue, Value, diff --git a/opentelemetry-sdk/src/trace/sampler.rs b/opentelemetry-sdk/src/trace/sampler.rs index bfd0aaf157..a67c25ec63 100644 --- a/opentelemetry-sdk/src/trace/sampler.rs +++ b/opentelemetry-sdk/src/trace/sampler.rs @@ -1,9 +1,8 @@ -use opentelemetry_api::trace::OrderMap; use opentelemetry_api::{ trace::{ Link, SamplingDecision, SamplingResult, SpanKind, TraceContextExt, TraceId, TraceState, }, - Context, Key, Value, + Context, Key, OrderMap, Value, }; use std::convert::TryInto; diff --git a/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs b/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs index 8975f5867a..5e438a81d5 100644 --- a/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs +++ b/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs @@ -3,8 +3,8 @@ use crate::trace::sampler::jaeger_remote::sampling_strategy::Inner; use crate::trace::{Sampler, ShouldSample, TraceRuntime}; use futures_util::{stream, StreamExt as _}; use http::Uri; -use opentelemetry_api::trace::{Link, OrderMap, SamplingResult, SpanKind, TraceError, TraceId}; -use opentelemetry_api::{global, Context, Key, Value}; +use opentelemetry_api::trace::{Link, SamplingResult, SpanKind, TraceError, TraceId}; +use opentelemetry_api::{global, Context, Key, Value, OrderMap}; use opentelemetry_http::HttpClient; use std::str::FromStr; use std::sync::Arc; diff --git a/opentelemetry-sdk/src/trace/tracer.rs b/opentelemetry-sdk/src/trace/tracer.rs index f30fb94c70..7d8d854704 100644 --- a/opentelemetry-sdk/src/trace/tracer.rs +++ b/opentelemetry-sdk/src/trace/tracer.rs @@ -17,10 +17,10 @@ use crate::{ InstrumentationLibrary, }; use opentelemetry_api::trace::{ - Link, OrderMap, SamplingDecision, SamplingResult, SpanBuilder, SpanContext, SpanId, SpanKind, + Link, SamplingDecision, SamplingResult, SpanBuilder, SpanContext, SpanId, SpanKind, TraceContextExt, TraceFlags, TraceId, TraceState, }; -use opentelemetry_api::{Context, Key, KeyValue, Value}; +use opentelemetry_api::{Context, Key, KeyValue, OrderMap, Value}; use std::fmt; use std::sync::Weak; From 4aa5fe32e34a6753859088a94fa8284003e7e055 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 9 May 2023 16:06:51 -0700 Subject: [PATCH 2/6] missed file.. --- opentelemetry-api/src/order_map.rs | 670 +++++++++++++++++++++++++++++ 1 file changed, 670 insertions(+) create mode 100644 opentelemetry-api/src/order_map.rs diff --git a/opentelemetry-api/src/order_map.rs b/opentelemetry-api/src/order_map.rs new file mode 100644 index 0000000000..b69cc7090d --- /dev/null +++ b/opentelemetry-api/src/order_map.rs @@ -0,0 +1,670 @@ +use crate::{Key, KeyValue, Value}; +use indexmap::map::{ + Drain, Entry, IntoIter, IntoKeys, IntoValues, Iter, IterMut, Keys, Values, ValuesMut, +}; +use indexmap::{Equivalent, IndexMap}; +use std::collections::hash_map::RandomState; +use std::hash::{BuildHasher, Hash}; +use std::iter::FromIterator; +use std::ops::{Index, IndexMut, RangeBounds}; + +/// A hash table implementation that preserves insertion order across all operations. +/// +/// Entries will be returned according to their insertion order when iterating over the collection. +#[derive(Clone, Debug)] +pub struct OrderMap(IndexMap); + +impl OrderMap { + /// Create a new map. (Does not allocate) + #[inline] + pub fn new() -> Self { + Self(IndexMap::new()) + } + + /// Create a new map with capacity for `n` key-value pairs. (Does not + /// allocate if `n` is zero.) + /// + /// Computes in **O(n)** time. + #[inline] + pub fn with_capacity(n: usize) -> Self { + Self(IndexMap::with_capacity(n)) + } +} + +impl OrderMap { + /// Create a new map with capacity for `n` key-value pairs. (Does not + /// allocate if `n` is zero.) + /// + /// Computes in **O(n)** time. + #[inline] + pub fn with_capacity_and_hasher(n: usize, hash_builder: S) -> Self { + Self(IndexMap::with_capacity_and_hasher(n, hash_builder)) + } + + /// Create a new map with `hash_builder`. + /// + /// This function is `const`, so it + /// can be called in `static` contexts. + pub const fn with_hasher(hash_builder: S) -> Self { + Self(IndexMap::with_hasher(hash_builder)) + } + + /// Computes in **O(1)** time. + pub fn capacity(&self) -> usize { + self.0.capacity() + } + + /// Return a reference to the map's `BuildHasher`. + pub fn hasher(&self) -> &S { + self.0.hasher() + } + + /// Return the number of key-value pairs in the map. + /// + /// Computes in **O(1)** time. + #[inline] + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns true if the map contains no elements. + /// + /// Computes in **O(1)** time. + #[inline] + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Return an iterator over the key-value pairs of the map, in their order + pub fn iter(&self) -> Iter<'_, K, V> { + self.0.iter() + } + + /// Return an iterator over the key-value pairs of the map, in their order + pub fn iter_mut(&mut self) -> IterMut<'_, K, V> { + self.0.iter_mut() + } + + /// Return an iterator over the keys of the map, in their order + pub fn keys(&self) -> Keys<'_, K, V> { + self.0.keys() + } + + /// Return an owning iterator over the keys of the map, in their order + pub fn into_keys(self) -> IntoKeys { + self.0.into_keys() + } + + /// Return an iterator over the values of the map, in their order + pub fn values(&self) -> Values<'_, K, V> { + self.0.values() + } + + /// Return an iterator over mutable references to the values of the map, + /// in their order + pub fn values_mut(&mut self) -> ValuesMut<'_, K, V> { + self.0.values_mut() + } + + /// Return an owning iterator over the values of the map, in their order + pub fn into_values(self) -> IntoValues { + self.0.into_values() + } + + /// Remove all key-value pairs in the map, while preserving its capacity. + /// + /// Computes in **O(n)** time. + pub fn clear(&mut self) { + self.0.clear(); + } + + /// Shortens the map, keeping the first `len` elements and dropping the rest. + /// + /// If `len` is greater than the map's current length, this has no effect. + pub fn truncate(&mut self, len: usize) { + self.0.truncate(len); + } + + /// Clears the `IndexMap` in the given index range, returning those + /// key-value pairs as a drain iterator. + /// + /// The range may be any type that implements `RangeBounds`, + /// including all of the `std::ops::Range*` types, or even a tuple pair of + /// `Bound` start and end values. To drain the map entirely, use `RangeFull` + /// like `map.drain(..)`. + /// + /// This shifts down all entries following the drained range to fill the + /// gap, and keeps the allocated memory for reuse. + /// + /// ***Panics*** if the starting point is greater than the end point or if + /// the end point is greater than the length of the map. + pub fn drain(&mut self, range: R) -> Drain<'_, K, V> + where + R: RangeBounds, + { + self.0.drain(range) + } + + /// Splits the collection into two at the given index. + /// + /// Returns a newly allocated map containing the elements in the range + /// `[at, len)`. After the call, the original map will be left containing + /// the elements `[0, at)` with its previous capacity unchanged. + /// + /// ***Panics*** if `at > len`. + pub fn split_off(&mut self, at: usize) -> Self + where + S: Clone, + { + Self(self.0.split_off(at)) + } +} + +impl OrderMap +where + K: Hash + Eq, + S: BuildHasher, +{ + /// Reserve capacity for `additional` more key-value pairs. + /// + /// Computes in **O(n)** time. + pub fn reserve(&mut self, additional: usize) { + self.0.reserve(additional) + } + + /// Shrink the capacity of the map as much as possible. + /// + /// Computes in **O(n)** time. + pub fn shrink_to_fit(&mut self) { + self.0.shrink_to_fit() + } + + /// Insert a key-value pair in the map. + /// + /// If an equivalent key already exists in the map: the key remains and + /// retains in its place in the order, its corresponding value is updated + /// with `value` and the older value is returned inside `Some(_)`. + /// + /// If no equivalent key existed in the map: the new key-value pair is + /// inserted, last in order, and `None` is returned. + /// + /// Computes in **O(1)** time (amortized average). + /// + /// See also [`entry`](#method.entry) if you you want to insert *or* modify + /// or if you need to get the index of the corresponding key-value pair. + pub fn insert(&mut self, key: K, value: V) -> Option { + self.0.insert(key, value) + } + + /// Insert a key-value pair in the map, and get their index. + /// + /// If an equivalent key already exists in the map: the key remains and + /// retains in its place in the order, its corresponding value is updated + /// with `value` and the older value is returned inside `(index, Some(_))`. + /// + /// If no equivalent key existed in the map: the new key-value pair is + /// inserted, last in order, and `(index, None)` is returned. + /// + /// Computes in **O(1)** time (amortized average). + /// + /// See also [`entry`](#method.entry) if you you want to insert *or* modify + /// or if you need to get the index of the corresponding key-value pair. + pub fn insert_full(&mut self, key: K, value: V) -> (usize, Option) { + self.0.insert_full(key, value) + } + + /// Get the given key’s corresponding entry in the map for insertion and/or + /// in-place manipulation. + /// + /// Computes in **O(1)** time (amortized average). + pub fn entry(&mut self, key: K) -> Entry<'_, K, V> { + self.0.entry(key) + } + + /// Return `true` if an equivalent to `key` exists in the map. + /// + /// Computes in **O(1)** time (average). + pub fn contains_key(&self, key: &Q) -> bool + where + Q: Hash + Equivalent, + { + self.0.contains_key(key) + } + + /// Return a reference to the value stored for `key`, if it is present, + /// else `None`. + /// + /// Computes in **O(1)** time (average). + pub fn get(&self, key: &Q) -> Option<&V> + where + Q: Hash + Equivalent, + { + self.0.get(key) + } + + /// Return references to the key-value pair stored for `key`, + /// if it is present, else `None`. + /// + /// Computes in **O(1)** time (average). + pub fn get_key_value(&self, key: &Q) -> Option<(&K, &V)> + where + Q: Hash + Equivalent, + { + self.0.get_key_value(key) + } + + /// Return item index, key and value + pub fn get_full(&self, key: &Q) -> Option<(usize, &K, &V)> + where + Q: Hash + Equivalent, + { + self.0.get_full(key) + } + + /// Return item index, if it exists in the map + /// + /// Computes in **O(1)** time (average). + pub fn get_index_of(&self, key: &Q) -> Option + where + Q: Hash + Equivalent, + { + self.0.get_index_of(key) + } + + /// Return a mutable reference to the element pointed at by `key`, if it exists. + pub fn get_mut(&mut self, key: &Q) -> Option<&mut V> + where + Q: Hash + Equivalent, + { + self.0.get_mut(key) + } + + /// Return a mutable reference to the element pointed at by `key`, if it exists. + /// It also returns the element's index and its key. + pub fn get_full_mut(&mut self, key: &Q) -> Option<(usize, &K, &mut V)> + where + Q: Hash + Equivalent, + { + self.0.get_full_mut(key) + } + + /// Remove the key-value pair equivalent to `key` and return + /// its value. + /// + /// Like `Vec::remove`, the pair is removed by shifting all of the + /// elements that follow it, preserving their relative order. + /// **This perturbs the index of all of those elements!** + /// + /// Return `None` if `key` is not in map. + /// + /// Computes in **O(n)** time (average). + pub fn shift_remove(&mut self, key: &Q) -> Option + where + Q: Hash + Equivalent, + { + self.0.shift_remove(key) + } + + /// Remove and return the key-value pair equivalent to `key`. + /// + /// Like `Vec::remove`, the pair is removed by shifting all of the + /// elements that follow it, preserving their relative order. + /// **This perturbs the index of all of those elements!** + /// + /// Return `None` if `key` is not in map. + /// + /// Computes in **O(n)** time (average). + pub fn shift_remove_entry(&mut self, key: &Q) -> Option<(K, V)> + where + Q: Hash + Equivalent, + { + self.0.shift_remove_entry(key) + } + + /// Remove the key-value pair equivalent to `key` and return it and + /// the index it had. + /// + /// Like `Vec::remove`, the pair is removed by shifting all of the + /// elements that follow it, preserving their relative order. + /// **This perturbs the index of all of those elements!** + /// + /// Return `None` if `key` is not in map. + /// + /// Computes in **O(n)** time (average). + pub fn shift_remove_full(&mut self, key: &Q) -> Option<(usize, K, V)> + where + Q: Hash + Equivalent, + { + self.0.shift_remove_full(key) + } + + /// Remove the last key-value pair + /// + /// This preserves the order of the remaining elements. + /// + /// Computes in **O(1)** time (average). + pub fn pop(&mut self) -> Option<(K, V)> { + self.0.pop() + } + + /// Scan through each key-value pair in the map and keep those where the + /// closure `keep` returns `true`. + /// + /// The elements are visited in order, and remaining elements keep their + /// order. + /// + /// Computes in **O(n)** time (average). + pub fn retain(&mut self, keep: F) + where + F: FnMut(&K, &mut V) -> bool, + { + self.0.retain(keep); + } +} + +impl OrderMap { + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index(&self, index: usize) -> Option<(&K, &V)> { + self.0.get_index(index) + } + + /// Get a key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Computes in **O(1)** time. + pub fn get_index_mut(&mut self, index: usize) -> Option<(&mut K, &mut V)> { + self.0.get_index_mut(index) + } + + /// Get the first key-value pair + /// + /// Computes in **O(1)** time. + pub fn first(&self) -> Option<(&K, &V)> { + self.0.first() + } + + /// Get the first key-value pair, with mutable access to the value + /// + /// Computes in **O(1)** time. + pub fn first_mut(&mut self) -> Option<(&K, &mut V)> { + self.0.first_mut() + } + + /// Get the last key-value pair + /// + /// Computes in **O(1)** time. + pub fn last(&self) -> Option<(&K, &V)> { + self.0.last() + } + + /// Get the last key-value pair, with mutable access to the value + /// + /// Computes in **O(1)** time. + pub fn last_mut(&mut self) -> Option<(&K, &mut V)> { + self.0.last_mut() + } + + /// Remove the key-value pair by index + /// + /// Valid indices are *0 <= index < self.len()* + /// + /// Like `Vec::remove`, the pair is removed by shifting all of the + /// elements that follow it, preserving their relative order. + /// **This perturbs the index of all of those elements!** + /// + /// Computes in **O(n)** time (average). + pub fn shift_remove_index(&mut self, index: usize) -> Option<(K, V)> { + self.0.shift_remove_index(index) + } +} + +impl<'a, K, V, S> IntoIterator for &'a OrderMap { + type Item = (&'a K, &'a V); + type IntoIter = Iter<'a, K, V>; + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + +impl<'a, K, V, S> IntoIterator for &'a mut OrderMap { + type Item = (&'a K, &'a mut V); + type IntoIter = IterMut<'a, K, V>; + fn into_iter(self) -> Self::IntoIter { + self.0.iter_mut() + } +} + +impl IntoIterator for OrderMap { + type Item = (K, V); + type IntoIter = IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +/// Access `OrderMap` values corresponding to a key. +/// +/// Panics if the value is missing. +impl Index<&Q> for OrderMap +where + Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + type Output = V; + + /// Returns a reference to the value corresponding to the supplied `key`. + /// + /// ***Panics*** if `key` is not present in the map. + fn index(&self, key: &Q) -> &V { + self.0.index(key) + } +} + +/// Access `Ordermap` values corresponding to a key. +/// +/// Mutable indexing allows changing / updating values of key-value +/// pairs that are already present. +/// +/// You can **not** insert new pairs with index syntax, use `.insert()`. +impl IndexMut<&Q> for OrderMap +where + Q: Hash + Equivalent, + K: Hash + Eq, + S: BuildHasher, +{ + /// Returns a mutable reference to the value corresponding to the supplied `key`. + /// + /// ***Panics*** if `key` is not present in the map. + fn index_mut(&mut self, key: &Q) -> &mut V { + self.0.index_mut(key) + } +} + +/// Access `IndexMap` values at indexed positions. +/// +/// It panics if the index is out of bounds. +impl Index for OrderMap { + type Output = V; + + /// Returns a reference to the value at the supplied `index`. + /// + /// ***Panics*** if `index` is out of bounds. + fn index(&self, index: usize) -> &V { + self.0.index(index) + } +} + +/// Access `IndexMap` values at indexed positions. +/// +/// Mutable indexing allows changing / updating indexed values +/// that are already present. +/// +/// You can **not** insert new values with index syntax, use `.insert()`. +/// +/// # Examples +/// +/// ``` +/// use indexmap::IndexMap; +/// +/// let mut map = IndexMap::new(); +/// for word in "Lorem ipsum dolor sit amet".split_whitespace() { +/// map.insert(word.to_lowercase(), word.to_string()); +/// } +/// let lorem = &mut map[0]; +/// assert_eq!(lorem, "Lorem"); +/// lorem.retain(char::is_lowercase); +/// assert_eq!(map["lorem"], "orem"); +/// ``` +/// +/// ```should_panic +/// use indexmap::IndexMap; +/// +/// let mut map = IndexMap::new(); +/// map.insert("foo", 1); +/// map[10] = 1; // panics! +/// ``` +impl IndexMut for OrderMap { + /// Returns a mutable reference to the value at the supplied `index`. + /// + /// ***Panics*** if `index` is out of bounds. + fn index_mut(&mut self, index: usize) -> &mut V { + self.0.index_mut(index) + } +} + +impl FromIterator<(K, V)> for OrderMap +where + K: Hash + Eq, + S: BuildHasher + Default, +{ + /// Create an `OrderMap` from the sequence of key-value pairs in the + /// iterable. + /// + /// `from_iter` uses the same logic as `extend`. See + /// [`extend`](#method.extend) for more details. + fn from_iter>(iterable: I) -> Self { + Self(IndexMap::from_iter(iterable)) + } +} + +// todo: uncomment when the MSRV bumps +// impl From<[(K, V); N]> for OrderMap +// where +// K: Hash + Eq, +// { +// fn from(arr: [(K, V); N]) -> Self { +// Self(IndexMap::from(arr)) +// } +// } + +impl Extend<(K, V)> for OrderMap +where + K: Hash + Eq, + S: BuildHasher, +{ + /// Extend the map with all key-value pairs in the iterable. + /// + /// This is equivalent to calling [`insert`](#method.insert) for each of + /// them in order, which means that for keys that already existed + /// in the map, their value is updated but it keeps the existing order. + /// + /// New keys are inserted in the order they appear in the sequence. If + /// equivalents of a key occur more than once, the last corresponding value + /// prevails. + fn extend>(&mut self, iterable: I) { + self.0.extend(iterable) + } +} + +impl<'a, K, V, S> Extend<(&'a K, &'a V)> for OrderMap +where + K: 'a + Hash + Eq + Copy, + V: 'a + Copy, + S: BuildHasher, +{ + /// Extend the map with all key-value pairs in the iterable. + /// + /// See the first extend method for more details. + fn extend>(&mut self, iterable: I) { + self.0.extend(iterable) + } +} + +impl Default for OrderMap +where + S: Default, +{ + /// Return an empty `OrderMap` + fn default() -> Self { + Self(IndexMap::default()) + } +} + +impl PartialEq> for OrderMap +where + K: Hash + Eq, + V1: PartialEq, + S1: BuildHasher, + S2: BuildHasher, +{ + fn eq(&self, other: &OrderMap) -> bool { + self.0.eq(&other.0) + } +} + +impl Eq for OrderMap +where + K: Eq + Hash, + V: Eq, + S: BuildHasher, +{ +} + +impl FromIterator for OrderMap +where + S: BuildHasher + Default, +{ + /// Create an `OrderMap` from the sequence of key-value pairs in the + /// iterable. + /// + /// `from_iter` uses the same logic as `extend`. See + /// [`extend`](#method.extend) for more details. + fn from_iter>(iterable: I) -> Self { + Self(IndexMap::from_iter( + iterable.into_iter().map(|kv| (kv.key, kv.value)), + )) + } +} + +// todo: uncomment below when bumping MSRV +// impl From<[KeyValue; N]> for OrderMap { +// fn from(arr: [KeyValue; N]) -> Self { +// let arr = arr.map(|kv| (kv.key, kv.value)); +// Self(IndexMap::from(arr)) +// } +// } + +impl Extend for OrderMap +where + S: BuildHasher, +{ + /// Extend the map with all key-value pairs in the iterable. + /// + /// This is equivalent to calling [`insert`](#method.insert) for each of + /// them in order, which means that for keys that already existed + /// in the map, their value is updated but it keeps the existing order. + /// + /// New keys are inserted in the order they appear in the sequence. If + /// equivalents of a key occur more than once, the last corresponding value + /// prevails. + fn extend>(&mut self, iterable: I) { + self.0 + .extend(iterable.into_iter().map(|kv| (kv.key, kv.value))) + } +} From 41888bee63a482a8d11c688f10df066a6404722c Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 9 May 2023 16:42:53 -0700 Subject: [PATCH 3/6] fix lint --- opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs | 2 +- opentelemetry-sdk/src/trace/tracer.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs b/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs index 5e438a81d5..8be1070e53 100644 --- a/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs +++ b/opentelemetry-sdk/src/trace/sampler/jaeger_remote/sampler.rs @@ -4,7 +4,7 @@ use crate::trace::{Sampler, ShouldSample, TraceRuntime}; use futures_util::{stream, StreamExt as _}; use http::Uri; use opentelemetry_api::trace::{Link, SamplingResult, SpanKind, TraceError, TraceId}; -use opentelemetry_api::{global, Context, Key, Value, OrderMap}; +use opentelemetry_api::{global, Context, Key, OrderMap, Value}; use opentelemetry_http::HttpClient; use std::str::FromStr; use std::sync::Arc; diff --git a/opentelemetry-sdk/src/trace/tracer.rs b/opentelemetry-sdk/src/trace/tracer.rs index 7d8d854704..830d1b0436 100644 --- a/opentelemetry-sdk/src/trace/tracer.rs +++ b/opentelemetry-sdk/src/trace/tracer.rs @@ -276,10 +276,10 @@ mod tests { }; use opentelemetry_api::{ trace::{ - Link, OrderMap, SamplingDecision, SamplingResult, Span, SpanContext, SpanId, SpanKind, + Link, SamplingDecision, SamplingResult, Span, SpanContext, SpanId, SpanKind, TraceContextExt, TraceFlags, TraceId, TraceState, Tracer, TracerProvider, }, - Context, Key, Value, + Context, Key, OrderMap, Value, }; #[derive(Clone, Debug)] From f8cdd1fd1be5f1d7de99b18ea88d70cf0aa212a3 Mon Sep 17 00:00:00 2001 From: Lalit Date: Tue, 9 May 2023 22:12:15 -0700 Subject: [PATCH 4/6] re export OrderMap --- opentelemetry-api/src/trace/mod.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/opentelemetry-api/src/trace/mod.rs b/opentelemetry-api/src/trace/mod.rs index f496d67ecf..e5db344df9 100644 --- a/opentelemetry-api/src/trace/mod.rs +++ b/opentelemetry-api/src/trace/mod.rs @@ -184,6 +184,10 @@ pub use self::{ tracer_provider::TracerProvider, }; use crate::{ExportError, KeyValue}; +use std::collections::hash_map::RandomState; + +/// re-export OrderMap to mitigate breaking change +pub type OrderMap = crate::order_map::OrderMap; /// Describe the result of operations in tracing API. pub type TraceResult = Result; From ed845acff1d1fc4b1b02f20ee723bbb53144578e Mon Sep 17 00:00:00 2001 From: Lalit Date: Tue, 9 May 2023 22:17:33 -0700 Subject: [PATCH 5/6] update changelog --- opentelemetry-api/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/opentelemetry-api/CHANGELOG.md b/opentelemetry-api/CHANGELOG.md index 145ff54c41..28868bc13e 100644 --- a/opentelemetry-api/CHANGELOG.md +++ b/opentelemetry-api/CHANGELOG.md @@ -5,6 +5,7 @@ ### Fixed - Fix `SpanRef::set_attributes` mutability requirement. [#1038](https://github.com/open-telemetry/opentelemetry-rust/pull/1038) +- Move OrderMap module to root of otel-api crate. [#1061](https://github.com/open-telemetry/opentelemetry-rust/pull/1061) ## v0.19.0 ### Added From 821ec85c1def3753567a900c657a451f387d1d56 Mon Sep 17 00:00:00 2001 From: Lalit Date: Tue, 9 May 2023 22:20:23 -0700 Subject: [PATCH 6/6] reorg use --- opentelemetry-api/src/trace/tracer.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/opentelemetry-api/src/trace/tracer.rs b/opentelemetry-api/src/trace/tracer.rs index e16329ce3d..be429872e7 100644 --- a/opentelemetry-api/src/trace/tracer.rs +++ b/opentelemetry-api/src/trace/tracer.rs @@ -1,7 +1,6 @@ -use crate::OrderMap; use crate::{ trace::{Event, Link, Span, SpanId, SpanKind, Status, TraceContextExt, TraceId, TraceState}, - Context, Key, KeyValue, Value, + Context, Key, KeyValue, OrderMap, Value, }; use std::borrow::Cow; use std::iter::FromIterator;