From 7fee0fcfd093cea1cd012f89018c38adcc6db2cc Mon Sep 17 00:00:00 2001 From: Lalit Date: Mon, 22 Jul 2024 19:35:20 -0700 Subject: [PATCH 01/55] inital commit --- opentelemetry-sdk/Cargo.toml | 5 + opentelemetry-sdk/benches/hybrid_vec.rs | 80 +++++++++ opentelemetry-sdk/src/logs/hybrid_vec.rs | 209 +++++++++++++++++++++++ opentelemetry-sdk/src/logs/mod.rs | 2 + 4 files changed, 296 insertions(+) create mode 100644 opentelemetry-sdk/benches/hybrid_vec.rs create mode 100644 opentelemetry-sdk/src/logs/hybrid_vec.rs diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index 7429e7ce0c..e8c7715154 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -91,3 +91,8 @@ required-features = ["metrics"] name = "log" harness = false required-features = ["logs"] + +[[bench]] +name = "hybrid_vec" +harness = false +required-features = ["logs"] diff --git a/opentelemetry-sdk/benches/hybrid_vec.rs b/opentelemetry-sdk/benches/hybrid_vec.rs new file mode 100644 index 0000000000..25139167df --- /dev/null +++ b/opentelemetry-sdk/benches/hybrid_vec.rs @@ -0,0 +1,80 @@ +use criterion::{criterion_group, criterion_main, Criterion}; +use opentelemetry::logs::AnyValue; +use opentelemetry::Key; +use opentelemetry_sdk::logs::HybridVec; + +#[derive(Clone, Debug, PartialEq)] +pub struct KeyValuePair(Key, AnyValue); + +impl Default for KeyValuePair { + fn default() -> Self { + KeyValuePair(Key::from_static_str(""), AnyValue::String("".into())) + } +} + +fn hybridvec_insertion_benchmark(c: &mut Criterion) { + c.bench_function("HybridVec Insertion", |b| { + b.iter(|| { + let mut collection = HybridVec::::new(); + for i in 0..8 { + let key = Key::from(format!("key{}", i)); + let value = AnyValue::Int(i as i64); + collection.push(KeyValuePair(key, value)); + } + }) + }); +} + +fn vec_insertion_benchmark(c: &mut Criterion) { + c.bench_function("Vec Insertion", |b| { + b.iter(|| { + let mut collection = Vec::new(); + for i in 0..8 { + let key = Key::from(format!("key{}", i)); + let value = AnyValue::Int(i as i64); + collection.push(KeyValuePair(key, value)); + } + }) + }); +} + +fn hybridvec_iteration_benchmark(c: &mut Criterion) { + c.bench_function("HybridVec Iteration", |b| { + let mut collection = HybridVec::::new(); + for i in 0..8 { + let key = Key::from(format!("key{}", i)); + let value = AnyValue::Int(i as i64); + collection.push(KeyValuePair(key, value)); + } + b.iter(|| { + for item in &collection { + criterion::black_box(item); + } + }) + }); +} + +fn vec_iteration_benchmark(c: &mut Criterion) { + c.bench_function("Vec Iteration", |b| { + let mut collection = Vec::new(); + for i in 0..8 { + let key = Key::from(format!("key{}", i)); + let value = AnyValue::Int(i as i64); + collection.push(KeyValuePair(key, value)); + } + b.iter(|| { + for item in &collection { + criterion::black_box(item); + } + }) + }); +} + +criterion_group!( + benches, + hybridvec_insertion_benchmark, + vec_insertion_benchmark, + hybridvec_iteration_benchmark, + vec_iteration_benchmark +); +criterion_main!(benches); diff --git a/opentelemetry-sdk/src/logs/hybrid_vec.rs b/opentelemetry-sdk/src/logs/hybrid_vec.rs new file mode 100644 index 0000000000..384ccdc89f --- /dev/null +++ b/opentelemetry-sdk/src/logs/hybrid_vec.rs @@ -0,0 +1,209 @@ +use std::array::IntoIter; + +/// The default initial capacity for `HybridVec`. +const DEFAULT_INITIAL_CAPACITY: usize = 10; + +#[derive(Debug)] +/// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. +pub struct HybridVec { + initial: [T; INITIAL_CAPACITY], + additional: Vec, + count: usize, +} + +impl HybridVec { + /// Creates a new `HybridVec` with the default initial capacity. + pub fn new() -> Self { + Self { + initial: [(); INITIAL_CAPACITY].map(|_| T::default()), + additional: Vec::new(), + count: 0, + } + } + + /// Pushes a value into the `HybridVec`. + pub fn push(&mut self, value: T) { + if self.count < INITIAL_CAPACITY { + self.initial[self.count] = value; + self.count += 1; + } else { + self.additional.push(value); + } + } + + /// Gets a reference to the value at the specified index. + pub fn get(&self, index: usize) -> Option<&T> { + if index < self.count { + Some(&self.initial[index]) + } else if index < self.count + self.additional.len() { + self.additional.get(index - INITIAL_CAPACITY) + } else { + None + } + } + + /// Returns the number of elements in the `HybridVec`. + pub fn len(&self) -> usize { + self.count + self.additional.len() + } +} + +// Implement `IntoIterator` for `HybridVec` +impl IntoIterator for HybridVec { + type Item = T; + type IntoIter = HybridVecIntoIter; + + fn into_iter(self) -> Self::IntoIter { + HybridVecIntoIter { + initial_iter: self.initial.into_iter().take(self.count), + additional_iter: self.additional.into_iter(), + } + } +} + +#[derive(Debug)] +/// Iterator for consuming a `HybridVec`. +pub struct HybridVecIntoIter { + initial_iter: std::iter::Take>, + additional_iter: std::vec::IntoIter, +} + +impl Iterator + for HybridVecIntoIter +{ + type Item = T; + + fn next(&mut self) -> Option { + self.initial_iter + .next() + .or_else(|| self.additional_iter.next()) + } +} + +// Implement `IntoIterator` for a reference to `HybridVec` +impl<'a, T: Default + 'a, const INITIAL_CAPACITY: usize> IntoIterator + for &'a HybridVec +{ + type Item = &'a T; + type IntoIter = HybridVecIter<'a, T, INITIAL_CAPACITY>; + + fn into_iter(self) -> Self::IntoIter { + HybridVecIter { + initial_iter: self.initial.iter().take(self.count), + additional_iter: self.additional.iter(), + } + } +} + +#[derive(Debug)] +/// Iterator for referencing elements in a `HybridVec`. +pub struct HybridVecIter<'a, T: Default, const INITIAL_CAPACITY: usize> { + initial_iter: std::iter::Take>, + additional_iter: std::slice::Iter<'a, T>, +} + +impl<'a, T: Default, const INITIAL_CAPACITY: usize> Iterator + for HybridVecIter<'a, T, INITIAL_CAPACITY> +{ + type Item = &'a T; + + fn next(&mut self) -> Option { + self.initial_iter + .next() + .or_else(|| self.additional_iter.next()) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use opentelemetry::logs::AnyValue; + use opentelemetry::Key; + + /// A struct to hold a key-value pair and implement `Default`. + #[derive(Clone, Debug, PartialEq)] + struct KeyValuePair(Key, AnyValue); + + impl Default for KeyValuePair { + fn default() -> Self { + KeyValuePair(Key::from_static_str(""), AnyValue::String("".into())) + } + } + + #[test] + fn test_push_and_get() { + let mut collection = HybridVec::::new(); + for i in 0..15 { + collection.push(i); + } + for i in 0..15 { + assert_eq!(collection.get(i), Some(&(i as i32))); + } + } + + #[test] + fn test_len() { + let mut collection = HybridVec::::new(); + for i in 0..15 { + collection.push(i); + } + assert_eq!(collection.len(), 15); + } + + #[test] + fn test_into_iter() { + let mut collection = HybridVec::::new(); + for i in 0..15 { + collection.push(i); + } + let mut iter = collection.into_iter(); + for i in 0..15 { + assert_eq!(iter.next(), Some(i)); + } + assert_eq!(iter.next(), None); + } + + #[test] + fn test_ref_iter() { + let mut collection = HybridVec::::new(); + for i in 0..15 { + collection.push(i); + } + let iter = &collection; + let mut count = 0; + for value in iter { + assert_eq!(*value, count); + count += 1; + } + assert_eq!(count, 15); + } + + #[test] + fn test_key_value_pair_storage_hybridvec() { + let mut collection = HybridVec::::new(); + + let key1 = Key::from("key1"); + let value1 = AnyValue::String("value1".into()); + let key2 = Key::from("key2"); + let value2 = AnyValue::Int(42); + + collection.push(KeyValuePair(key1.clone(), value1.clone())); + collection.push(KeyValuePair(key2.clone(), value2.clone())); + + assert_eq!( + collection.get(0).map(|kv| (&kv.0, &kv.1)), + Some((&key1, &value1)) + ); + assert_eq!( + collection.get(1).map(|kv| (&kv.0, &kv.1)), + Some((&key2, &value2)) + ); + assert_eq!(collection.len(), 2); + + // Test iterating over the key-value pairs + let mut iter = collection.into_iter(); + assert_eq!(iter.next(), Some(KeyValuePair(key1, value1))); + assert_eq!(iter.next(), Some(KeyValuePair(key2, value2))); + assert_eq!(iter.next(), None); + } +} diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index 207da4255c..392d04a451 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -1,9 +1,11 @@ //! # OpenTelemetry Log SDK +mod hybrid_vec; mod log_emitter; mod log_processor; mod record; +pub use hybrid_vec::HybridVec; pub use log_emitter::{Builder, Logger, LoggerProvider}; pub use log_processor::{ BatchConfig, BatchConfigBuilder, BatchLogProcessor, BatchLogProcessorBuilder, LogProcessor, From 06aee015f1ea7abd004805a1718eb44b86f5f24b Mon Sep 17 00:00:00 2001 From: Lalit Date: Mon, 22 Jul 2024 21:48:59 -0700 Subject: [PATCH 02/55] more --- opentelemetry-sdk/benches/hybrid_vec.rs | 19 +++++- opentelemetry-sdk/src/logs/hybrid_vec.rs | 76 ++++++++++++++++++------ opentelemetry-sdk/src/logs/mod.rs | 2 +- 3 files changed, 77 insertions(+), 20 deletions(-) diff --git a/opentelemetry-sdk/benches/hybrid_vec.rs b/opentelemetry-sdk/benches/hybrid_vec.rs index 25139167df..c409a2cd2e 100644 --- a/opentelemetry-sdk/benches/hybrid_vec.rs +++ b/opentelemetry-sdk/benches/hybrid_vec.rs @@ -8,7 +8,7 @@ pub struct KeyValuePair(Key, AnyValue); impl Default for KeyValuePair { fn default() -> Self { - KeyValuePair(Key::from_static_str(""), AnyValue::String("".into())) + KeyValuePair(Key::from_static_str(""), AnyValue::Int(0)) } } @@ -54,6 +54,22 @@ fn hybridvec_iteration_benchmark(c: &mut Criterion) { }); } +fn hybridvec_get_benchmark(c: &mut Criterion) { + c.bench_function("HybridVec Get Loop", |b| { + let mut collection = HybridVec::::new(); + for i in 0..8 { + let key = Key::from(format!("key{}", i)); + let value = AnyValue::Int(i as i64); + collection.push(KeyValuePair(key, value)); + } + b.iter(|| { + for i in 0..collection.len() { + criterion::black_box(collection.get(i)); + } + }) + }); +} + fn vec_iteration_benchmark(c: &mut Criterion) { c.bench_function("Vec Iteration", |b| { let mut collection = Vec::new(); @@ -75,6 +91,7 @@ criterion_group!( hybridvec_insertion_benchmark, vec_insertion_benchmark, hybridvec_iteration_benchmark, + hybridvec_get_benchmark, vec_iteration_benchmark ); criterion_main!(benches); diff --git a/opentelemetry-sdk/src/logs/hybrid_vec.rs b/opentelemetry-sdk/src/logs/hybrid_vec.rs index 384ccdc89f..0f37d45b50 100644 --- a/opentelemetry-sdk/src/logs/hybrid_vec.rs +++ b/opentelemetry-sdk/src/logs/hybrid_vec.rs @@ -54,18 +54,34 @@ impl IntoIterator for HybridVec; fn into_iter(self) -> Self::IntoIter { - HybridVecIntoIter { - initial_iter: self.initial.into_iter().take(self.count), - additional_iter: self.additional.into_iter(), + if self.count <= INITIAL_CAPACITY { + HybridVecIntoIter::StackOnly { + iter: self.initial.into_iter().take(self.count), + } + } else { + HybridVecIntoIter::Mixed { + stack_iter: self.initial.into_iter().take(self.count), + heap_iter: self.additional.into_iter(), + } } } } #[derive(Debug)] /// Iterator for consuming a `HybridVec`. -pub struct HybridVecIntoIter { - initial_iter: std::iter::Take>, - additional_iter: std::vec::IntoIter, +pub enum HybridVecIntoIter { + /// stackonly + StackOnly { + /// iter + iter: std::iter::Take>, + }, + /// hybrid + Mixed { + /// stack_iter + stack_iter: std::iter::Take>, + /// heap_iter + heap_iter: std::vec::IntoIter, + }, } impl Iterator @@ -74,9 +90,13 @@ impl Iterator type Item = T; fn next(&mut self) -> Option { - self.initial_iter - .next() - .or_else(|| self.additional_iter.next()) + match self { + HybridVecIntoIter::StackOnly { iter } => iter.next(), + HybridVecIntoIter::Mixed { + stack_iter, + heap_iter, + } => stack_iter.next().or_else(|| heap_iter.next()), + } } } @@ -88,18 +108,34 @@ impl<'a, T: Default + 'a, const INITIAL_CAPACITY: usize> IntoIterator type IntoIter = HybridVecIter<'a, T, INITIAL_CAPACITY>; fn into_iter(self) -> Self::IntoIter { - HybridVecIter { - initial_iter: self.initial.iter().take(self.count), - additional_iter: self.additional.iter(), + if self.count <= INITIAL_CAPACITY { + HybridVecIter::StackOnly { + iter: self.initial.iter().take(self.count), + } + } else { + HybridVecIter::Mixed { + stack_iter: self.initial.iter().take(self.count), + heap_iter: self.additional.iter(), + } } } } #[derive(Debug)] /// Iterator for referencing elements in a `HybridVec`. -pub struct HybridVecIter<'a, T: Default, const INITIAL_CAPACITY: usize> { - initial_iter: std::iter::Take>, - additional_iter: std::slice::Iter<'a, T>, +pub enum HybridVecIter<'a, T: Default, const INITIAL_CAPACITY: usize> { + /// stackonly + StackOnly { + /// iter + iter: std::iter::Take>, + }, + /// hybrid + Mixed { + /// stack_iter + stack_iter: std::iter::Take>, + /// heap_iter + heap_iter: std::slice::Iter<'a, T>, + }, } impl<'a, T: Default, const INITIAL_CAPACITY: usize> Iterator @@ -108,9 +144,13 @@ impl<'a, T: Default, const INITIAL_CAPACITY: usize> Iterator type Item = &'a T; fn next(&mut self) -> Option { - self.initial_iter - .next() - .or_else(|| self.additional_iter.next()) + match self { + HybridVecIter::StackOnly { iter } => iter.next(), + HybridVecIter::Mixed { + stack_iter, + heap_iter, + } => stack_iter.next().or_else(|| heap_iter.next()), + } } } diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index 392d04a451..acddc56e2e 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -5,7 +5,7 @@ mod log_emitter; mod log_processor; mod record; -pub use hybrid_vec::HybridVec; +pub use hybrid_vec::{HybridVec, HybridVecIntoIter, HybridVecIter}; pub use log_emitter::{Builder, Logger, LoggerProvider}; pub use log_processor::{ BatchConfig, BatchConfigBuilder, BatchLogProcessor, BatchLogProcessorBuilder, LogProcessor, From ea7b2f83ad3be6602f51045fdff46780047d7518 Mon Sep 17 00:00:00 2001 From: Lalit Date: Mon, 22 Jul 2024 23:48:58 -0700 Subject: [PATCH 03/55] more changes --- opentelemetry-sdk/Cargo.toml | 6 ++ opentelemetry-sdk/src/logs/hybrid_vec.rs | 64 ++++++++++++++++++- opentelemetry-sdk/src/logs/record.rs | 13 +++- .../src/testing/global_allocator.rs | 8 +++ opentelemetry-sdk/src/testing/mod.rs | 2 + 5 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 opentelemetry-sdk/src/testing/global_allocator.rs diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index e8c7715154..fe93c9c188 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -36,6 +36,9 @@ rustdoc-args = ["--cfg", "docsrs"] [dev-dependencies] criterion = { workspace = true, features = ["html_reports"] } temp-env = { workspace = true } +jemallocator = { version = "0.5"} +jemalloc-ctl = { version = "0.5"} + [target.'cfg(not(target_os = "windows"))'.dev-dependencies] pprof = { version = "0.13", features = ["flamegraph", "criterion"] } @@ -51,6 +54,9 @@ testing = ["opentelemetry/testing", "trace", "metrics", "logs", "rt-async-std", rt-tokio = ["tokio", "tokio-stream"] rt-tokio-current-thread = ["tokio", "tokio-stream"] rt-async-std = ["async-std"] +memory-profiling = [] + + [[bench]] name = "context" diff --git a/opentelemetry-sdk/src/logs/hybrid_vec.rs b/opentelemetry-sdk/src/logs/hybrid_vec.rs index 0f37d45b50..c966d07bdb 100644 --- a/opentelemetry-sdk/src/logs/hybrid_vec.rs +++ b/opentelemetry-sdk/src/logs/hybrid_vec.rs @@ -54,7 +54,7 @@ impl IntoIterator for HybridVec; fn into_iter(self) -> Self::IntoIter { - if self.count <= INITIAL_CAPACITY { + if self.additional.is_empty() { HybridVecIntoIter::StackOnly { iter: self.initial.into_iter().take(self.count), } @@ -108,7 +108,7 @@ impl<'a, T: Default + 'a, const INITIAL_CAPACITY: usize> IntoIterator type IntoIter = HybridVecIter<'a, T, INITIAL_CAPACITY>; fn into_iter(self) -> Self::IntoIter { - if self.count <= INITIAL_CAPACITY { + if self.additional.is_empty() { HybridVecIter::StackOnly { iter: self.initial.iter().take(self.count), } @@ -160,6 +160,12 @@ mod tests { use opentelemetry::logs::AnyValue; use opentelemetry::Key; + #[cfg(feature = "memory-profiling")] + use crate::testing::global_allocator; + + #[cfg(feature = "memory-profiling")] + use jemalloc_ctl::{epoch, stats}; + /// A struct to hold a key-value pair and implement `Default`. #[derive(Clone, Debug, PartialEq)] struct KeyValuePair(Key, AnyValue); @@ -246,4 +252,58 @@ mod tests { assert_eq!(iter.next(), Some(KeyValuePair(key2, value2))); assert_eq!(iter.next(), None); } + + #[cfg(feature = "memory-profiling")] + #[test] + fn test_memory_allocation_string() { + // Reset jemalloc epoch to refresh stats + let e = epoch::mib().unwrap(); + e.advance().unwrap(); + + // Get memory stats before the code block + let allocated_before = stats::allocated::read().unwrap(); + + // Code block to measure: Allocate a large string + let large_string: String = "a".repeat(100_000); + + // Refresh jemalloc stats + e.advance().unwrap(); + + // Get memory stats after the code block + let allocated_after = stats::allocated::read().unwrap(); + + // Calculate the difference + let allocated_diff = allocated_after - allocated_before; + + // Assert or print the difference + println!("Memory allocated for String: {} bytes", allocated_diff); + assert!(allocated_diff > 0); + } + + #[cfg(feature = "memory-profiling")] + #[test] + fn test_memory_allocation_int() { + // Reset jemalloc epoch to refresh stats + let e = epoch::mib().unwrap(); + e.advance().unwrap(); + + // Get memory stats before the code block + let allocated_before = stats::allocated::read().unwrap(); + + // Code block to measure: Allocate a vector of integers + let vec: Vec = (0..100_000).collect(); + + // Refresh jemalloc stats + e.advance().unwrap(); + + // Get memory stats after the code block + let allocated_after = stats::allocated::read().unwrap(); + + // Calculate the difference + let allocated_diff = allocated_after - allocated_before; + + // Assert or print the difference + println!("Memory allocated for Vec: {} bytes", allocated_diff); + assert!(allocated_diff > 0); + } } diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 16aaa70289..6b831f8f07 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -4,6 +4,17 @@ use opentelemetry::{ Key, }; use std::{borrow::Cow, time::SystemTime}; +use super::hybrid_vec::HybridVec; + +/// A struct to hold a key-value pair and implement `Default`. +#[derive(Clone, Debug, PartialEq)] +struct KeyValuePair(Key, AnyValue); + +impl Default for KeyValuePair { + fn default() -> Self { + KeyValuePair(Key::from_static_str(""), AnyValue::String("".into())) + } +} #[derive(Debug, Default, Clone, PartialEq)] #[non_exhaustive] @@ -34,7 +45,7 @@ pub struct LogRecord { pub body: Option, /// Additional attributes associated with this record - pub attributes: Option>, + pub attributes: HybridVec::, } impl opentelemetry::logs::LogRecord for LogRecord { diff --git a/opentelemetry-sdk/src/testing/global_allocator.rs b/opentelemetry-sdk/src/testing/global_allocator.rs new file mode 100644 index 0000000000..a2607f651f --- /dev/null +++ b/opentelemetry-sdk/src/testing/global_allocator.rs @@ -0,0 +1,8 @@ +// tests/global_allocator.rs +#[cfg(feature = "memory-profiling")] +mod global_allocator { + use jemallocator::Jemalloc; + + #[global_allocator] + static GLOBAL: Jemalloc = Jemalloc; +} diff --git a/opentelemetry-sdk/src/testing/mod.rs b/opentelemetry-sdk/src/testing/mod.rs index 50c79f5d49..d6f8919057 100644 --- a/opentelemetry-sdk/src/testing/mod.rs +++ b/opentelemetry-sdk/src/testing/mod.rs @@ -8,3 +8,5 @@ pub mod metrics; #[cfg(all(feature = "testing", feature = "logs"))] pub mod logs; + +pub mod global_allocator; From bfb12972809d14ff7b9a049ddb6e21a7e685eb2c Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 23 Jul 2024 16:35:54 -0700 Subject: [PATCH 04/55] changes --- .../logs/{hybrid_vec.rs => growable_array.rs} | 125 +++++++++++++----- opentelemetry-sdk/src/logs/log_emitter.rs | 10 +- opentelemetry-sdk/src/logs/log_processor.rs | 50 ++++--- opentelemetry-sdk/src/logs/mod.rs | 23 ++-- opentelemetry-sdk/src/logs/record.rs | 49 ++++--- 5 files changed, 164 insertions(+), 93 deletions(-) rename opentelemetry-sdk/src/logs/{hybrid_vec.rs => growable_array.rs} (66%) diff --git a/opentelemetry-sdk/src/logs/hybrid_vec.rs b/opentelemetry-sdk/src/logs/growable_array.rs similarity index 66% rename from opentelemetry-sdk/src/logs/hybrid_vec.rs rename to opentelemetry-sdk/src/logs/growable_array.rs index c966d07bdb..bc650cbe8b 100644 --- a/opentelemetry-sdk/src/logs/hybrid_vec.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -1,18 +1,35 @@ use std::array::IntoIter; -/// The default initial capacity for `HybridVec`. +/// The default initial capacity for `GrowableArray`. const DEFAULT_INITIAL_CAPACITY: usize = 10; -#[derive(Debug)] +#[derive(Debug, Clone, PartialEq)] /// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. -pub struct HybridVec { +pub struct GrowableArray< + T: Default + Clone + PartialEq, + const INITIAL_CAPACITY: usize = DEFAULT_INITIAL_CAPACITY, +> { initial: [T; INITIAL_CAPACITY], additional: Vec, count: usize, } -impl HybridVec { - /// Creates a new `HybridVec` with the default initial capacity. +impl Default + for GrowableArray +{ + fn default() -> Self { + Self { + initial: [(); INITIAL_CAPACITY].map(|_| T::default()), + additional: Vec::new(), + count: 0, + } + } +} + +impl + GrowableArray +{ + /// Creates a new `GrowableArray` with the default initial capacity. pub fn new() -> Self { Self { initial: [(); INITIAL_CAPACITY].map(|_| T::default()), @@ -21,7 +38,7 @@ impl HybridVec { } } - /// Pushes a value into the `HybridVec`. + /// Pushes a value into the `GrowableArray`. pub fn push(&mut self, value: T) { if self.count < INITIAL_CAPACITY { self.initial[self.count] = value; @@ -42,24 +59,60 @@ impl HybridVec { } } - /// Returns the number of elements in the `HybridVec`. + /// Returns the number of elements in the `GrowableArray`. pub fn len(&self) -> usize { self.count + self.additional.len() } + + /// Returns an iterator over the elements in the `GrowableArray`. + pub fn iter(&self) -> GrowableArrayIter<'_, T, INITIAL_CAPACITY> { + if self.additional.is_empty() { + GrowableArrayIter::StackOnly { + iter: self.initial.iter().take(self.count), + } + } else { + GrowableArrayIter::Mixed { + stack_iter: self.initial.iter().take(self.count), + heap_iter: self.additional.iter(), + } + } + } + + /// Maps each element to a new `GrowableArray` using the provided function. + pub fn map( + &self, + mut f: F, + ) -> GrowableArray + where + F: FnMut(&T) -> U, + { + let mut new_vec = GrowableArray::::new(); + + for i in 0..self.count { + new_vec.push(f(&self.initial[i])); + } + for value in &self.additional { + new_vec.push(f(value)); + } + + new_vec + } } -// Implement `IntoIterator` for `HybridVec` -impl IntoIterator for HybridVec { +// Implement `IntoIterator` for `GrowableArray` +impl IntoIterator + for GrowableArray +{ type Item = T; - type IntoIter = HybridVecIntoIter; + type IntoIter = GrowableArrayIntoIter; fn into_iter(self) -> Self::IntoIter { if self.additional.is_empty() { - HybridVecIntoIter::StackOnly { + GrowableArrayIntoIter::StackOnly { iter: self.initial.into_iter().take(self.count), } } else { - HybridVecIntoIter::Mixed { + GrowableArrayIntoIter::Mixed { stack_iter: self.initial.into_iter().take(self.count), heap_iter: self.additional.into_iter(), } @@ -68,8 +121,8 @@ impl IntoIterator for HybridVec { +/// Iterator for consuming a `GrowableArray`. +pub enum GrowableArrayIntoIter { /// stackonly StackOnly { /// iter @@ -84,15 +137,15 @@ pub enum HybridVecIntoIter { }, } -impl Iterator - for HybridVecIntoIter +impl Iterator + for GrowableArrayIntoIter { type Item = T; fn next(&mut self) -> Option { match self { - HybridVecIntoIter::StackOnly { iter } => iter.next(), - HybridVecIntoIter::Mixed { + GrowableArrayIntoIter::StackOnly { iter } => iter.next(), + GrowableArrayIntoIter::Mixed { stack_iter, heap_iter, } => stack_iter.next().or_else(|| heap_iter.next()), @@ -100,20 +153,20 @@ impl Iterator } } -// Implement `IntoIterator` for a reference to `HybridVec` -impl<'a, T: Default + 'a, const INITIAL_CAPACITY: usize> IntoIterator - for &'a HybridVec +// Implement `IntoIterator` for a reference to `GrowableArray` +impl<'a, T: Default + Clone + PartialEq + 'a, const INITIAL_CAPACITY: usize> IntoIterator + for &'a GrowableArray { type Item = &'a T; - type IntoIter = HybridVecIter<'a, T, INITIAL_CAPACITY>; + type IntoIter = GrowableArrayIter<'a, T, INITIAL_CAPACITY>; fn into_iter(self) -> Self::IntoIter { if self.additional.is_empty() { - HybridVecIter::StackOnly { + GrowableArrayIter::StackOnly { iter: self.initial.iter().take(self.count), } } else { - HybridVecIter::Mixed { + GrowableArrayIter::Mixed { stack_iter: self.initial.iter().take(self.count), heap_iter: self.additional.iter(), } @@ -122,8 +175,8 @@ impl<'a, T: Default + 'a, const INITIAL_CAPACITY: usize> IntoIterator } #[derive(Debug)] -/// Iterator for referencing elements in a `HybridVec`. -pub enum HybridVecIter<'a, T: Default, const INITIAL_CAPACITY: usize> { +/// Iterator for referencing elements in a `GrowableArray`. +pub enum GrowableArrayIter<'a, T: Default, const INITIAL_CAPACITY: usize> { /// stackonly StackOnly { /// iter @@ -138,15 +191,15 @@ pub enum HybridVecIter<'a, T: Default, const INITIAL_CAPACITY: usize> { }, } -impl<'a, T: Default, const INITIAL_CAPACITY: usize> Iterator - for HybridVecIter<'a, T, INITIAL_CAPACITY> +impl<'a, T: Default + Clone, const INITIAL_CAPACITY: usize> Iterator + for GrowableArrayIter<'a, T, INITIAL_CAPACITY> { type Item = &'a T; fn next(&mut self) -> Option { match self { - HybridVecIter::StackOnly { iter } => iter.next(), - HybridVecIter::Mixed { + GrowableArrayIter::StackOnly { iter } => iter.next(), + GrowableArrayIter::Mixed { stack_iter, heap_iter, } => stack_iter.next().or_else(|| heap_iter.next()), @@ -178,7 +231,7 @@ mod tests { #[test] fn test_push_and_get() { - let mut collection = HybridVec::::new(); + let mut collection = GrowableArray::::new(); for i in 0..15 { collection.push(i); } @@ -189,7 +242,7 @@ mod tests { #[test] fn test_len() { - let mut collection = HybridVec::::new(); + let mut collection = GrowableArray::::new(); for i in 0..15 { collection.push(i); } @@ -198,7 +251,7 @@ mod tests { #[test] fn test_into_iter() { - let mut collection = HybridVec::::new(); + let mut collection = GrowableArray::::new(); for i in 0..15 { collection.push(i); } @@ -211,7 +264,7 @@ mod tests { #[test] fn test_ref_iter() { - let mut collection = HybridVec::::new(); + let mut collection = GrowableArray::::new(); for i in 0..15 { collection.push(i); } @@ -225,8 +278,8 @@ mod tests { } #[test] - fn test_key_value_pair_storage_hybridvec() { - let mut collection = HybridVec::::new(); + fn test_key_value_pair_storage_growable_array() { + let mut collection = GrowableArray::::new(); let key1 = Key::from("key1"); let value1 = AnyValue::String("value1".into()); diff --git a/opentelemetry-sdk/src/logs/log_emitter.rs b/opentelemetry-sdk/src/logs/log_emitter.rs index faadf473b3..905dde43e3 100644 --- a/opentelemetry-sdk/src/logs/log_emitter.rs +++ b/opentelemetry-sdk/src/logs/log_emitter.rs @@ -40,10 +40,6 @@ pub struct LoggerProvider { /// Default logger name if empty string is provided. const DEFAULT_COMPONENT_NAME: &str = "rust.opentelemetry.io/sdk/logger"; -// According to a Go-specific study mentioned on https://go.dev/blog/slog, -// up to 5 attributes is the most common case. We have chosen 8 as the default -// capacity for attributes to avoid reallocation in common scenarios. -const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 8; impl opentelemetry::logs::LoggerProvider for LoggerProvider { type Logger = Logger; @@ -250,11 +246,7 @@ impl opentelemetry::logs::Logger for Logger { type LogRecord = LogRecord; fn create_log_record(&self) -> Self::LogRecord { - // Reserve attributes memory for perf optimization. This may change in future. - LogRecord { - attributes: Some(Vec::with_capacity(PREALLOCATED_ATTRIBUTE_CAPACITY)), - ..Default::default() - } + LogRecord::default() } /// Emit a `LogRecord`. diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 95a0378a2d..b9a2e258e6 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -509,6 +509,7 @@ mod tests { BatchLogProcessor, OTEL_BLRP_EXPORT_TIMEOUT, OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, }; + use crate::logs::AttributesGrowableArray; use crate::testing::logs::InMemoryLogsExporterBuilder; use crate::{ export::logs::{LogData, LogExporter}, @@ -815,15 +816,21 @@ mod tests { impl LogProcessor for FirstProcessor { fn emit(&self, data: &mut LogData) { - // add attribute - data.record.attributes.get_or_insert(vec![]).push(( + // Ensure attributes is initialized if it is empty + if data.record.attributes.len() == 0 { + data.record.attributes = AttributesGrowableArray::new(); + } + + // Add attribute + data.record.attributes.push(Some(( Key::from_static_str("processed_by"), AnyValue::String("FirstProcessor".into()), - )); - // update body - data.record.body = Some("Updated by FirstProcessor".into()); + ))); - self.logs.lock().unwrap().push(data.clone()); //clone as the LogProcessor is storing the data. + // Update body + data.record.body = Some(AnyValue::String("Updated by FirstProcessor".into())); + + self.logs.lock().unwrap().push(data.clone()); // Clone as the LogProcessor is storing the data. } #[cfg(feature = "logs_level_enabled")] @@ -847,11 +854,13 @@ mod tests { impl LogProcessor for SecondProcessor { fn emit(&self, data: &mut LogData) { - assert!(data.record.attributes.as_ref().map_or(false, |attrs| { - attrs.iter().any(|(key, value)| { + assert!(data.record.attributes.iter().any(|attr| { + if let Some((key, value)) = attr { key.as_str() == "processed_by" - && value == &AnyValue::String("FirstProcessor".into()) - }) + && *value == AnyValue::String("FirstProcessor".into()) + } else { + false + } })); assert!( data.record.body.clone().unwrap() @@ -902,19 +911,24 @@ mod tests { let first_log = &first_processor_logs.lock().unwrap()[0]; let second_log = &second_processor_logs.lock().unwrap()[0]; - assert!(first_log.record.attributes.iter().any(|attrs| { - attrs.iter().any(|(key, value)| { + assert!(first_log.record.attributes.iter().any(|attr| { + if let Some((key, value)) = attr { key.as_str() == "processed_by" - && value == &AnyValue::String("FirstProcessor".into()) - }) + && *value == AnyValue::String("FirstProcessor".into()) + } else { + false + } })); - assert!(second_log.record.attributes.iter().any(|attrs| { - attrs.iter().any(|(key, value)| { + assert!(second_log.record.attributes.iter().any(|attr| { + if let Some((key, value)) = attr { key.as_str() == "processed_by" - && value == &AnyValue::String("FirstProcessor".into()) - }) + && *value == AnyValue::String("FirstProcessor".into()) + } else { + false + } })); + assert!( first_log.record.body.clone().unwrap() == AnyValue::String("Updated by FirstProcessor".into()) diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index acddc56e2e..de8c96b7c5 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -1,17 +1,17 @@ //! # OpenTelemetry Log SDK -mod hybrid_vec; +mod growable_array; mod log_emitter; mod log_processor; mod record; -pub use hybrid_vec::{HybridVec, HybridVecIntoIter, HybridVecIter}; +pub use growable_array::{GrowableArray, GrowableArrayIntoIter, GrowableArrayIter}; pub use log_emitter::{Builder, Logger, LoggerProvider}; pub use log_processor::{ BatchConfig, BatchConfigBuilder, BatchLogProcessor, BatchLogProcessorBuilder, LogProcessor, SimpleLogProcessor, }; -pub use record::{LogRecord, TraceContext}; +pub use record::{AttributesGrowableArray, LogRecord, TraceContext}; #[cfg(all(test, feature = "testing"))] mod tests { @@ -85,14 +85,19 @@ mod tests { let attributes: Vec<(Key, AnyValue)> = log .record .attributes - .clone() - .expect("Attributes are expected"); + .iter() + .filter_map(|kv| kv.as_ref().map(|(k, v)| (k.clone(), v.clone()))) + .collect(); assert_eq!(attributes.len(), 10); for i in 1..=10 { - assert!(log.record.attributes.clone().unwrap().contains(&( - Key::new(format!("key{}", i)), - AnyValue::String(format!("value{}", i).into()) - ))); + assert!(log.record.attributes.iter().any(|kv| { + if let Some((key, value)) = kv { + key.as_str() == format!("key{}", i) + && *value == AnyValue::String(format!("value{}", i).into()) + } else { + false + } + })); } // validate Resource diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 6b831f8f07..9d9edb7bf8 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -1,20 +1,19 @@ +use super::growable_array::GrowableArray; use opentelemetry::{ logs::{AnyValue, Severity}, trace::{SpanContext, SpanId, TraceFlags, TraceId}, Key, }; use std::{borrow::Cow, time::SystemTime}; -use super::hybrid_vec::HybridVec; -/// A struct to hold a key-value pair and implement `Default`. -#[derive(Clone, Debug, PartialEq)] -struct KeyValuePair(Key, AnyValue); +// According to a Go-specific study mentioned on https://go.dev/blog/slog, +// up to 5 attributes is the most common case. We have chosen 8 as the default +// capacity for attributes to avoid reallocation in common scenarios. +const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 8; -impl Default for KeyValuePair { - fn default() -> Self { - KeyValuePair(Key::from_static_str(""), AnyValue::String("".into())) - } -} +/// A vector of `Option<(Key, AnyValue)>` with default capacity. +pub type AttributesGrowableArray = + GrowableArray, PREALLOCATED_ATTRIBUTE_CAPACITY>; #[derive(Debug, Default, Clone, PartialEq)] #[non_exhaustive] @@ -45,7 +44,7 @@ pub struct LogRecord { pub body: Option, /// Additional attributes associated with this record - pub attributes: HybridVec::, + pub attributes: AttributesGrowableArray, } impl opentelemetry::logs::LogRecord for LogRecord { @@ -100,11 +99,7 @@ impl opentelemetry::logs::LogRecord for LogRecord { K: Into, V: Into, { - if let Some(ref mut attrs) = self.attributes { - attrs.push((key.into(), value.into())); - } else { - self.attributes = Some(vec![(key.into(), value.into())]); - } + self.attributes.push(Some((key.into(), value.into()))); } } @@ -197,17 +192,25 @@ mod tests { let mut log_record = LogRecord::default(); let attributes = vec![(Key::new("key"), AnyValue::String("value".into()))]; log_record.add_attributes(attributes.clone()); - assert_eq!(log_record.attributes, Some(attributes)); + + let mut expected_attributes = AttributesGrowableArray::new(); + for (key, value) in attributes { + expected_attributes.push(Some((key, value))); + } + assert_eq!(log_record.attributes, expected_attributes); } #[test] fn test_set_attribute() { let mut log_record = LogRecord::default(); log_record.add_attribute("key", "value"); - assert_eq!( - log_record.attributes, - Some(vec![(Key::new("key"), AnyValue::String("value".into()))]) - ); + + let expected_attributes = { + let mut hybrid_vec = AttributesGrowableArray::new(); + hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); + hybrid_vec + }; + assert_eq!(log_record.attributes, expected_attributes); } #[test] @@ -241,7 +244,11 @@ mod tests { severity_text: Some(Cow::Borrowed("ERROR")), severity_number: Some(Severity::Error), body: Some(AnyValue::String("Test body".into())), - attributes: Some(vec![(Key::new("key"), AnyValue::String("value".into()))]), + attributes: { + let mut hybrid_vec = AttributesGrowableArray::new(); + hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); + hybrid_vec + }, trace_context: Some(TraceContext { trace_id: TraceId::from_u128(1), span_id: SpanId::from_u64(1), From fcb0ed8a8f6be2b5d889ca6ebf4d6b5923b706f9 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 23 Jul 2024 17:52:23 -0700 Subject: [PATCH 05/55] fix build --- opentelemetry-sdk/Cargo.toml | 2 +- .../{hybrid_vec.rs => growable_array.rs} | 26 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) rename opentelemetry-sdk/benches/{hybrid_vec.rs => growable_array.rs} (76%) diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index fe93c9c188..cb08c0ab98 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -99,6 +99,6 @@ harness = false required-features = ["logs"] [[bench]] -name = "hybrid_vec" +name = "growable_array" harness = false required-features = ["logs"] diff --git a/opentelemetry-sdk/benches/hybrid_vec.rs b/opentelemetry-sdk/benches/growable_array.rs similarity index 76% rename from opentelemetry-sdk/benches/hybrid_vec.rs rename to opentelemetry-sdk/benches/growable_array.rs index c409a2cd2e..89d64eac65 100644 --- a/opentelemetry-sdk/benches/hybrid_vec.rs +++ b/opentelemetry-sdk/benches/growable_array.rs @@ -1,7 +1,7 @@ use criterion::{criterion_group, criterion_main, Criterion}; use opentelemetry::logs::AnyValue; use opentelemetry::Key; -use opentelemetry_sdk::logs::HybridVec; +use opentelemetry_sdk::logs::GrowableArray; #[derive(Clone, Debug, PartialEq)] pub struct KeyValuePair(Key, AnyValue); @@ -12,10 +12,10 @@ impl Default for KeyValuePair { } } -fn hybridvec_insertion_benchmark(c: &mut Criterion) { - c.bench_function("HybridVec Insertion", |b| { +fn growable_array_insertion_benchmark(c: &mut Criterion) { + c.bench_function("GrowableArray Insertion", |b| { b.iter(|| { - let mut collection = HybridVec::::new(); + let mut collection = GrowableArray::::new(); for i in 0..8 { let key = Key::from(format!("key{}", i)); let value = AnyValue::Int(i as i64); @@ -38,9 +38,9 @@ fn vec_insertion_benchmark(c: &mut Criterion) { }); } -fn hybridvec_iteration_benchmark(c: &mut Criterion) { - c.bench_function("HybridVec Iteration", |b| { - let mut collection = HybridVec::::new(); +fn growable_array_iteration_benchmark(c: &mut Criterion) { + c.bench_function("GrowableArray Iteration", |b| { + let mut collection = GrowableArray::::new(); for i in 0..8 { let key = Key::from(format!("key{}", i)); let value = AnyValue::Int(i as i64); @@ -54,9 +54,9 @@ fn hybridvec_iteration_benchmark(c: &mut Criterion) { }); } -fn hybridvec_get_benchmark(c: &mut Criterion) { - c.bench_function("HybridVec Get Loop", |b| { - let mut collection = HybridVec::::new(); +fn growable_array_get_benchmark(c: &mut Criterion) { + c.bench_function("GrowableArray Get Loop", |b| { + let mut collection = GrowableArray::::new(); for i in 0..8 { let key = Key::from(format!("key{}", i)); let value = AnyValue::Int(i as i64); @@ -88,10 +88,10 @@ fn vec_iteration_benchmark(c: &mut Criterion) { criterion_group!( benches, - hybridvec_insertion_benchmark, + growable_array_insertion_benchmark, vec_insertion_benchmark, - hybridvec_iteration_benchmark, - hybridvec_get_benchmark, + growable_array_iteration_benchmark, + growable_array_get_benchmark, vec_iteration_benchmark ); criterion_main!(benches); From 40b2b5f4ca77c2af249a31211212867d76815d7e Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 24 Jul 2024 11:04:39 -0700 Subject: [PATCH 06/55] changes --- opentelemetry-appender-log/src/lib.rs | 12 ++- opentelemetry-appender-tracing/Cargo.toml | 1 + opentelemetry-appender-tracing/src/layer.rs | 101 +++++++++++-------- opentelemetry-proto/src/transform/logs.rs | 18 +++- opentelemetry-sdk/src/logs/growable_array.rs | 18 ++++ opentelemetry-stdout/src/logs/transform.rs | 17 ++-- 6 files changed, 106 insertions(+), 61 deletions(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index d4ac9e894d..ea47c16767 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -938,12 +938,16 @@ mod tests { ); let logs = exporter.get_emitted_logs().unwrap(); - let attributes = &logs[0].record.attributes.as_ref().unwrap(); + let attributes = &logs[0].record.attributes; let get = |needle: &str| { - attributes.iter().find_map(|(k, v)| { - if k.as_str() == needle { - Some(v.clone()) + attributes.iter().find_map(|attr| { + if let Some((k, v)) = attr { + if k.as_str() == needle { + Some(v.clone()) + } else { + None + } } else { None } diff --git a/opentelemetry-appender-tracing/Cargo.toml b/opentelemetry-appender-tracing/Cargo.toml index d0b237217c..74fc1deff2 100644 --- a/opentelemetry-appender-tracing/Cargo.toml +++ b/opentelemetry-appender-tracing/Cargo.toml @@ -32,6 +32,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } [features] experimental_metadata_attributes = ["dep:tracing-log"] logs_level_enabled = ["opentelemetry/logs_level_enabled"] +default = ["experimental_metadata_attributes", "logs_level_enabled"] [[bench]] diff --git a/opentelemetry-appender-tracing/src/layer.rs b/opentelemetry-appender-tracing/src/layer.rs index 91124c8464..50bedf82c2 100644 --- a/opentelemetry-appender-tracing/src/layer.rs +++ b/opentelemetry-appender-tracing/src/layer.rs @@ -252,29 +252,35 @@ mod tests { assert!(log.record.trace_context.is_none()); // Validate attributes - let attributes: Vec<(Key, AnyValue)> = log - .record - .attributes - .clone() - .expect("Attributes are expected"); + let attributes = log.record.attributes.clone(); #[cfg(not(feature = "experimental_metadata_attributes"))] assert_eq!(attributes.len(), 3); #[cfg(feature = "experimental_metadata_attributes")] assert_eq!(attributes.len(), 8); - assert!(attributes.contains(&(Key::new("event_id"), 20.into()))); - assert!(attributes.contains(&(Key::new("user_name"), "otel".into()))); - assert!(attributes.contains(&(Key::new("user_email"), "otel@opentelemetry.io".into()))); + assert!(attributes.contains(&Some((Key::new("event_id"), 20.into())))); + assert!(attributes.contains(&Some((Key::new("user_name"), "otel".into())))); + assert!(attributes.contains(&Some(( + Key::new("user_email"), + "otel@opentelemetry.io".into() + )))); #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); - assert!(attributes.contains(&( + assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); + assert!(attributes.contains(&Some(( Key::new("code.namespace"), "opentelemetry_appender_tracing::layer::tests".into() - ))); + )))); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes.iter().map(|(key, _)| key.clone()).collect(); + let attributes_key: Vec = attributes + .iter() + .filter_map(|attr| match attr { + Some((key, _)) => Some(key.clone()), + None => None, + }) + .collect(); + assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); assert!(attributes_key.contains(&Key::new("log.target"))); @@ -348,29 +354,36 @@ mod tests { ); // validate attributes. - let attributes: Vec<(Key, AnyValue)> = log - .record - .attributes - .clone() - .expect("Attributes are expected"); + let attributes = log.record.attributes.clone(); #[cfg(not(feature = "experimental_metadata_attributes"))] assert_eq!(attributes.len(), 3); #[cfg(feature = "experimental_metadata_attributes")] assert_eq!(attributes.len(), 8); - assert!(attributes.contains(&(Key::new("event_id"), 20.into()))); - assert!(attributes.contains(&(Key::new("user_name"), "otel".into()))); - assert!(attributes.contains(&(Key::new("user_email"), "otel@opentelemetry.io".into()))); + assert!(attributes.contains(&Some((Key::new("event_id"), 20.into())))); + assert!(attributes.contains(&Some((Key::new("user_name"), "otel".into())))); + assert!(attributes.contains(&Some(( + Key::new("user_email"), + "otel@opentelemetry.io".into() + )))); #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); - assert!(attributes.contains(&( + assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); + assert!(attributes.contains(&Some(( Key::new("code.namespace"), "opentelemetry_appender_tracing::layer::tests".into() - ))); + )))); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes.iter().map(|(key, _)| key.clone()).collect(); + + //let attributes_key: Vec = attributes.iter().map(|(key, _)| key.clone()).collect(); + let attributes_key: Vec = attributes + .iter() + .filter_map(|attr| match attr { + Some((key, _)) => Some(key.clone()), + None => None, + }) + .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); assert!(attributes_key.contains(&Key::new("log.target"))); @@ -415,11 +428,7 @@ mod tests { // Validate attributes #[cfg(feature = "experimental_metadata_attributes")] - let attributes: Vec<(Key, AnyValue)> = log - .record - .attributes - .clone() - .expect("Attributes are expected"); + let attributes = log.record.attributes.clone(); // Attributes can be polluted when we don't use this feature. #[cfg(feature = "experimental_metadata_attributes")] @@ -427,15 +436,21 @@ mod tests { #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); - assert!(attributes.contains(&( + assert!(attributes.contains(&(Some((Key::new("code.filename"), "layer.rs".into()))))); + assert!(attributes.contains(&Some(( Key::new("code.namespace"), "opentelemetry_appender_tracing::layer::tests".into() - ))); + )))); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes.iter().map(|(key, _)| key.clone()).collect(); + let attributes_key: Vec = attributes + .iter() + .filter_map(|attr| match attr { + Some((key, _)) => Some(key.clone()), + None => None, + }) + .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); assert!(attributes_key.contains(&Key::new("log.target"))); @@ -511,11 +526,7 @@ mod tests { // validate attributes. #[cfg(feature = "experimental_metadata_attributes")] - let attributes: Vec<(Key, AnyValue)> = log - .record - .attributes - .clone() - .expect("Attributes are expected"); + let attributes = log.record.attributes.clone(); // Attributes can be polluted when we don't use this feature. #[cfg(feature = "experimental_metadata_attributes")] @@ -523,15 +534,21 @@ mod tests { #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&(Key::new("code.filename"), "layer.rs".into()))); - assert!(attributes.contains(&( + assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); + assert!(attributes.contains(&Some(( Key::new("code.namespace"), "opentelemetry_appender_tracing::layer::tests".into() - ))); + )))); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes.iter().map(|(key, _)| key.clone()).collect(); + let attributes_key: Vec = attributes + .iter() + .filter_map(|attr| match attr { + Some((key, _)) => Some(key.clone()), + None => None, + }) + .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); assert!(attributes_key.contains(&Key::new("log.target"))); diff --git a/opentelemetry-proto/src/transform/logs.rs b/opentelemetry-proto/src/transform/logs.rs index 6e5235f1d9..1d3fdb3ca7 100644 --- a/opentelemetry-proto/src/transform/logs.rs +++ b/opentelemetry-proto/src/transform/logs.rs @@ -93,18 +93,26 @@ pub mod tonic { severity_text: log_record.severity_text.map(Into::into).unwrap_or_default(), body: log_record.body.map(Into::into), attributes: { - let mut attributes = log_record + let mut attributes: Vec = log_record .attributes - .map(Attributes::from_iter) - .unwrap_or_default() - .0; + .iter() + .filter_map(|kv| { + kv.as_ref().map(|(k, v)| KeyValue { + key: k.to_string(), + value: Some(AnyValue { + value: Some(v.clone().into()), + }), + }) + }) + .collect(); + if let Some(event_name) = log_record.event_name.as_ref() { attributes.push(KeyValue { key: "name".into(), value: Some(AnyValue { value: Some(Value::StringValue(event_name.to_string())), }), - }) + }); } attributes }, diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index bc650cbe8b..ccb1cb4c5e 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -78,6 +78,11 @@ impl } } + /// Checks if the `GrowableArray` contains the specified value. + pub fn contains(&self, value: &T) -> bool { + self.initial[..self.count].contains(value) || self.additional.contains(value) + } + /// Maps each element to a new `GrowableArray` using the provided function. pub fn map( &self, @@ -306,6 +311,19 @@ mod tests { assert_eq!(iter.next(), None); } + #[test] + fn test_contains() { + let mut collection = GrowableArray::::new(); + for i in 0..10 { + collection.push(i); + } + assert!(collection.contains(&5)); + assert!(!collection.contains(&15)); + + collection.push(15); + assert!(collection.contains(&15)); + } + #[cfg(feature = "memory-profiling")] #[test] fn test_memory_allocation_string() { diff --git a/opentelemetry-stdout/src/logs/transform.rs b/opentelemetry-stdout/src/logs/transform.rs index 80c4a877ef..945c36bd45 100644 --- a/opentelemetry-stdout/src/logs/transform.rs +++ b/opentelemetry-stdout/src/logs/transform.rs @@ -4,6 +4,7 @@ use crate::common::{ as_human_readable, as_opt_human_readable, as_opt_unix_nano, as_unix_nano, AttributeSet, KeyValue, Resource, Scope, Value, }; +use opentelemetry_sdk::logs::AttributesGrowableArray; use serde::Serialize; /// Transformed logs data that can be serialized. @@ -135,19 +136,15 @@ impl From for LogRecord { let mut attributes = value .record .attributes - .unwrap_or_default() - .into_iter() - .map(|(key, value)| (key, value).into()) + .iter() + .filter_map(|kv| kv.clone().map(|(k, v)| (k, v).into())) // Filter out None values and convert to KeyValue .collect::>(); if let Some(event_name) = &value.record.event_name { - attributes.push( - ( - opentelemetry::Key::from("name"), - opentelemetry::Value::String(event_name.clone().into()), - ) - .into(), - ) + attributes.push(KeyValue::from(( + "name".into(), + opentelemetry::Value::String(event_name.clone().into()), + ))); } attributes }, From da8b8ded9e6af2b64422a58a85f4c05bf1540244 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 24 Jul 2024 21:07:41 +0000 Subject: [PATCH 07/55] revert defaults --- opentelemetry-appender-tracing/Cargo.toml | 2 -- 1 file changed, 2 deletions(-) diff --git a/opentelemetry-appender-tracing/Cargo.toml b/opentelemetry-appender-tracing/Cargo.toml index 74fc1deff2..35bce5c6e9 100644 --- a/opentelemetry-appender-tracing/Cargo.toml +++ b/opentelemetry-appender-tracing/Cargo.toml @@ -32,8 +32,6 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } [features] experimental_metadata_attributes = ["dep:tracing-log"] logs_level_enabled = ["opentelemetry/logs_level_enabled"] -default = ["experimental_metadata_attributes", "logs_level_enabled"] - [[bench]] name = "logs" From 5019086215feb8d7ba9d60e10b2687c3310f92c5 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 24 Jul 2024 21:52:15 +0000 Subject: [PATCH 08/55] optionally create vec --- opentelemetry-sdk/src/logs/growable_array.rs | 41 ++++++++++++-------- 1 file changed, 25 insertions(+), 16 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index ccb1cb4c5e..c5915d0a2f 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -10,7 +10,7 @@ pub struct GrowableArray< const INITIAL_CAPACITY: usize = DEFAULT_INITIAL_CAPACITY, > { initial: [T; INITIAL_CAPACITY], - additional: Vec, + additional: Option>, count: usize, } @@ -20,7 +20,7 @@ impl Default fn default() -> Self { Self { initial: [(); INITIAL_CAPACITY].map(|_| T::default()), - additional: Vec::new(), + additional: None, count: 0, } } @@ -33,7 +33,7 @@ impl pub fn new() -> Self { Self { initial: [(); INITIAL_CAPACITY].map(|_| T::default()), - additional: Vec::new(), + additional: None, count: 0, } } @@ -44,7 +44,10 @@ impl self.initial[self.count] = value; self.count += 1; } else { - self.additional.push(value); + if self.additional.is_none() { + self.additional = Some(Vec::new()); + } + self.additional.as_mut().unwrap().push(value); } } @@ -52,8 +55,8 @@ impl pub fn get(&self, index: usize) -> Option<&T> { if index < self.count { Some(&self.initial[index]) - } else if index < self.count + self.additional.len() { - self.additional.get(index - INITIAL_CAPACITY) + } else if let Some(ref additional) = self.additional { + additional.get(index - INITIAL_CAPACITY) } else { None } @@ -61,26 +64,30 @@ impl /// Returns the number of elements in the `GrowableArray`. pub fn len(&self) -> usize { - self.count + self.additional.len() + self.count + self.additional.as_ref().map_or(0, Vec::len) } /// Returns an iterator over the elements in the `GrowableArray`. pub fn iter(&self) -> GrowableArrayIter<'_, T, INITIAL_CAPACITY> { - if self.additional.is_empty() { + if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { GrowableArrayIter::StackOnly { iter: self.initial.iter().take(self.count), } } else { GrowableArrayIter::Mixed { stack_iter: self.initial.iter().take(self.count), - heap_iter: self.additional.iter(), + heap_iter: self.additional.as_ref().unwrap().iter(), } } } /// Checks if the `GrowableArray` contains the specified value. pub fn contains(&self, value: &T) -> bool { - self.initial[..self.count].contains(value) || self.additional.contains(value) + self.initial[..self.count].contains(value) + || self + .additional + .as_ref() + .map_or(false, |vec| vec.contains(value)) } /// Maps each element to a new `GrowableArray` using the provided function. @@ -96,8 +103,10 @@ impl for i in 0..self.count { new_vec.push(f(&self.initial[i])); } - for value in &self.additional { - new_vec.push(f(value)); + if let Some(ref additional) = self.additional { + for value in additional { + new_vec.push(f(value)); + } } new_vec @@ -112,14 +121,14 @@ impl IntoIterator type IntoIter = GrowableArrayIntoIter; fn into_iter(self) -> Self::IntoIter { - if self.additional.is_empty() { + if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { GrowableArrayIntoIter::StackOnly { iter: self.initial.into_iter().take(self.count), } } else { GrowableArrayIntoIter::Mixed { stack_iter: self.initial.into_iter().take(self.count), - heap_iter: self.additional.into_iter(), + heap_iter: self.additional.unwrap().into_iter(), } } } @@ -166,14 +175,14 @@ impl<'a, T: Default + Clone + PartialEq + 'a, const INITIAL_CAPACITY: usize> Int type IntoIter = GrowableArrayIter<'a, T, INITIAL_CAPACITY>; fn into_iter(self) -> Self::IntoIter { - if self.additional.is_empty() { + if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { GrowableArrayIter::StackOnly { iter: self.initial.iter().take(self.count), } } else { GrowableArrayIter::Mixed { stack_iter: self.initial.iter().take(self.count), - heap_iter: self.additional.iter(), + heap_iter: self.additional.as_ref().unwrap().iter(), } } } From 17d1628bb5edca4fa13cc85ba1d3a00c07bd3f99 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 24 Jul 2024 23:50:09 +0000 Subject: [PATCH 09/55] add intial capacity for vector --- opentelemetry-sdk/src/logs/growable_array.rs | 46 +++++++++++--------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index c5915d0a2f..cd9f2c03b1 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -1,51 +1,57 @@ use std::array::IntoIter; -/// The default initial capacity for `GrowableArray`. -const DEFAULT_INITIAL_CAPACITY: usize = 10; +/// The default max capacity for the stack portation of `GrowableArray`. +const DEFAULT_MAX_STACK_CAPACITY: usize = 10; +/// The default initial capacity for the vector portion of `GrowableArray`. +const DEFAULT_INITIAL_VEC_CAPACITY: usize = 5; #[derive(Debug, Clone, PartialEq)] /// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. pub struct GrowableArray< T: Default + Clone + PartialEq, - const INITIAL_CAPACITY: usize = DEFAULT_INITIAL_CAPACITY, + const MAX_STACK_CAPACITY: usize = DEFAULT_MAX_STACK_CAPACITY, + const INITIAL_VEC_CAPACITY: usize = DEFAULT_INITIAL_VEC_CAPACITY, > { - initial: [T; INITIAL_CAPACITY], + initial: [T; MAX_STACK_CAPACITY], additional: Option>, count: usize, } -impl Default - for GrowableArray +impl< + T: Default + Clone + PartialEq, + const MAX_STACK_CAPACITY: usize, + const INITIAL_VEC_CAPACITY: usize, + > Default for GrowableArray { fn default() -> Self { Self { - initial: [(); INITIAL_CAPACITY].map(|_| T::default()), + initial: [(); MAX_STACK_CAPACITY].map(|_| T::default()), additional: None, count: 0, } } } -impl - GrowableArray +impl< + T: Default + Clone + PartialEq, + const MAX_STACK_CAPACITY: usize, + const INITIAL_VEC_CAPACITY: usize, + > GrowableArray { /// Creates a new `GrowableArray` with the default initial capacity. pub fn new() -> Self { - Self { - initial: [(); INITIAL_CAPACITY].map(|_| T::default()), - additional: None, - count: 0, - } + Self::default() } /// Pushes a value into the `GrowableArray`. pub fn push(&mut self, value: T) { - if self.count < INITIAL_CAPACITY { + if self.count < MAX_STACK_CAPACITY { self.initial[self.count] = value; self.count += 1; } else { if self.additional.is_none() { - self.additional = Some(Vec::new()); + // Initialize the vector with a specified capacity + self.additional = Some(Vec::with_capacity(INITIAL_VEC_CAPACITY)); } self.additional.as_mut().unwrap().push(value); } @@ -56,7 +62,7 @@ impl if index < self.count { Some(&self.initial[index]) } else if let Some(ref additional) = self.additional { - additional.get(index - INITIAL_CAPACITY) + additional.get(index - MAX_STACK_CAPACITY) } else { None } @@ -68,7 +74,7 @@ impl } /// Returns an iterator over the elements in the `GrowableArray`. - pub fn iter(&self) -> GrowableArrayIter<'_, T, INITIAL_CAPACITY> { + pub fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { GrowableArrayIter::StackOnly { iter: self.initial.iter().take(self.count), @@ -94,11 +100,11 @@ impl pub fn map( &self, mut f: F, - ) -> GrowableArray + ) -> GrowableArray where F: FnMut(&T) -> U, { - let mut new_vec = GrowableArray::::new(); + let mut new_vec = GrowableArray::::new(); for i in 0..self.count { new_vec.push(f(&self.initial[i])); From 781c3ed5049a8766f251c2f7ff4bf88360d33120 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 25 Jul 2024 00:33:04 +0000 Subject: [PATCH 10/55] create vec of certain capacity --- opentelemetry-sdk/benches/growable_array.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opentelemetry-sdk/benches/growable_array.rs b/opentelemetry-sdk/benches/growable_array.rs index 89d64eac65..2693271b09 100644 --- a/opentelemetry-sdk/benches/growable_array.rs +++ b/opentelemetry-sdk/benches/growable_array.rs @@ -28,7 +28,7 @@ fn growable_array_insertion_benchmark(c: &mut Criterion) { fn vec_insertion_benchmark(c: &mut Criterion) { c.bench_function("Vec Insertion", |b| { b.iter(|| { - let mut collection = Vec::new(); + let mut collection = Vec::with_capacity(10); for i in 0..8 { let key = Key::from(format!("key{}", i)); let value = AnyValue::Int(i as i64); @@ -72,7 +72,7 @@ fn growable_array_get_benchmark(c: &mut Criterion) { fn vec_iteration_benchmark(c: &mut Criterion) { c.bench_function("Vec Iteration", |b| { - let mut collection = Vec::new(); + let mut collection = Vec::with_capacity(10); for i in 0..8 { let key = Key::from(format!("key{}", i)); let value = AnyValue::Int(i as i64); From b9a90c21183792c798be9a553afe2da959f8022b Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 25 Jul 2024 05:11:59 +0000 Subject: [PATCH 11/55] changes --- opentelemetry-sdk/src/logs/growable_array.rs | 60 -------------------- 1 file changed, 60 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index cd9f2c03b1..daa8c3c391 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -233,12 +233,6 @@ mod tests { use opentelemetry::logs::AnyValue; use opentelemetry::Key; - #[cfg(feature = "memory-profiling")] - use crate::testing::global_allocator; - - #[cfg(feature = "memory-profiling")] - use jemalloc_ctl::{epoch, stats}; - /// A struct to hold a key-value pair and implement `Default`. #[derive(Clone, Debug, PartialEq)] struct KeyValuePair(Key, AnyValue); @@ -338,58 +332,4 @@ mod tests { collection.push(15); assert!(collection.contains(&15)); } - - #[cfg(feature = "memory-profiling")] - #[test] - fn test_memory_allocation_string() { - // Reset jemalloc epoch to refresh stats - let e = epoch::mib().unwrap(); - e.advance().unwrap(); - - // Get memory stats before the code block - let allocated_before = stats::allocated::read().unwrap(); - - // Code block to measure: Allocate a large string - let large_string: String = "a".repeat(100_000); - - // Refresh jemalloc stats - e.advance().unwrap(); - - // Get memory stats after the code block - let allocated_after = stats::allocated::read().unwrap(); - - // Calculate the difference - let allocated_diff = allocated_after - allocated_before; - - // Assert or print the difference - println!("Memory allocated for String: {} bytes", allocated_diff); - assert!(allocated_diff > 0); - } - - #[cfg(feature = "memory-profiling")] - #[test] - fn test_memory_allocation_int() { - // Reset jemalloc epoch to refresh stats - let e = epoch::mib().unwrap(); - e.advance().unwrap(); - - // Get memory stats before the code block - let allocated_before = stats::allocated::read().unwrap(); - - // Code block to measure: Allocate a vector of integers - let vec: Vec = (0..100_000).collect(); - - // Refresh jemalloc stats - e.advance().unwrap(); - - // Get memory stats after the code block - let allocated_after = stats::allocated::read().unwrap(); - - // Calculate the difference - let allocated_diff = allocated_after - allocated_before; - - // Assert or print the difference - println!("Memory allocated for Vec: {} bytes", allocated_diff); - assert!(allocated_diff > 0); - } } From a95e681d9b49e9a41cbfeb5b3818df06c667879b Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 25 Jul 2024 16:37:17 -0700 Subject: [PATCH 12/55] cont.. --- opentelemetry-proto/src/transform/logs.rs | 21 +++---- opentelemetry-sdk/Cargo.toml | 8 +-- opentelemetry-sdk/benches/growable_array.rs | 4 +- opentelemetry-sdk/src/logs/growable_array.rs | 61 +++----------------- opentelemetry-sdk/src/logs/log_processor.rs | 2 +- opentelemetry-sdk/src/logs/mod.rs | 7 +-- opentelemetry-sdk/src/logs/record.rs | 29 +++++++++- opentelemetry-stdout/src/logs/transform.rs | 32 +++++----- 8 files changed, 70 insertions(+), 94 deletions(-) diff --git a/opentelemetry-proto/src/transform/logs.rs b/opentelemetry-proto/src/transform/logs.rs index 1d3fdb3ca7..14e40b5d94 100644 --- a/opentelemetry-proto/src/transform/logs.rs +++ b/opentelemetry-proto/src/transform/logs.rs @@ -89,20 +89,14 @@ pub mod tonic { LogRecord { time_unix_nano: log_record.timestamp.map(to_nanos).unwrap_or_default(), observed_time_unix_nano: to_nanos(log_record.observed_timestamp.unwrap()), - severity_number: severity_number.into(), - severity_text: log_record.severity_text.map(Into::into).unwrap_or_default(), - body: log_record.body.map(Into::into), attributes: { let mut attributes: Vec = log_record - .attributes - .iter() - .filter_map(|kv| { - kv.as_ref().map(|(k, v)| KeyValue { - key: k.to_string(), - value: Some(AnyValue { - value: Some(v.clone().into()), - }), - }) + .attributes_iter() + .map(|kv| KeyValue { + key: kv.0.to_string(), + value: Some(AnyValue { + value: Some(kv.1.clone().into()), + }), }) .collect(); @@ -116,6 +110,9 @@ pub mod tonic { } attributes }, + severity_number: severity_number.into(), + severity_text: log_record.severity_text.map(Into::into).unwrap_or_default(), + body: log_record.body.map(Into::into), dropped_attributes_count: 0, flags: trace_context .map(|ctx| { diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index cb08c0ab98..ab0e244254 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -98,7 +98,7 @@ name = "log" harness = false required-features = ["logs"] -[[bench]] -name = "growable_array" -harness = false -required-features = ["logs"] +#[[bench]] +#name = "growable_array" +#harness = false +#required-features = ["logs"] diff --git a/opentelemetry-sdk/benches/growable_array.rs b/opentelemetry-sdk/benches/growable_array.rs index 2693271b09..aed33fbc4b 100644 --- a/opentelemetry-sdk/benches/growable_array.rs +++ b/opentelemetry-sdk/benches/growable_array.rs @@ -1,7 +1,8 @@ +/* use criterion::{criterion_group, criterion_main, Criterion}; use opentelemetry::logs::AnyValue; use opentelemetry::Key; -use opentelemetry_sdk::logs::GrowableArray; +use opentelemetry_sdk::logs::growable_array::GrowableArray; #[derive(Clone, Debug, PartialEq)] pub struct KeyValuePair(Key, AnyValue); @@ -95,3 +96,4 @@ criterion_group!( vec_iteration_benchmark ); criterion_main!(benches); +*/ diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index daa8c3c391..f04430c5a9 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -7,7 +7,7 @@ const DEFAULT_INITIAL_VEC_CAPACITY: usize = 5; #[derive(Debug, Clone, PartialEq)] /// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. -pub struct GrowableArray< +pub(crate) struct GrowableArray< T: Default + Clone + PartialEq, const MAX_STACK_CAPACITY: usize = DEFAULT_MAX_STACK_CAPACITY, const INITIAL_VEC_CAPACITY: usize = DEFAULT_INITIAL_VEC_CAPACITY, @@ -39,12 +39,12 @@ impl< > GrowableArray { /// Creates a new `GrowableArray` with the default initial capacity. - pub fn new() -> Self { + pub(crate) fn new() -> Self { Self::default() } /// Pushes a value into the `GrowableArray`. - pub fn push(&mut self, value: T) { + pub(crate) fn push(&mut self, value: T) { if self.count < MAX_STACK_CAPACITY { self.initial[self.count] = value; self.count += 1; @@ -58,7 +58,7 @@ impl< } /// Gets a reference to the value at the specified index. - pub fn get(&self, index: usize) -> Option<&T> { + pub(crate) fn get(&self, index: usize) -> Option<&T> { if index < self.count { Some(&self.initial[index]) } else if let Some(ref additional) = self.additional { @@ -69,12 +69,12 @@ impl< } /// Returns the number of elements in the `GrowableArray`. - pub fn len(&self) -> usize { + pub(crate) fn len(&self) -> usize { self.count + self.additional.as_ref().map_or(0, Vec::len) } /// Returns an iterator over the elements in the `GrowableArray`. - pub fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { + pub(crate) fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { GrowableArrayIter::StackOnly { iter: self.initial.iter().take(self.count), @@ -86,37 +86,6 @@ impl< } } } - - /// Checks if the `GrowableArray` contains the specified value. - pub fn contains(&self, value: &T) -> bool { - self.initial[..self.count].contains(value) - || self - .additional - .as_ref() - .map_or(false, |vec| vec.contains(value)) - } - - /// Maps each element to a new `GrowableArray` using the provided function. - pub fn map( - &self, - mut f: F, - ) -> GrowableArray - where - F: FnMut(&T) -> U, - { - let mut new_vec = GrowableArray::::new(); - - for i in 0..self.count { - new_vec.push(f(&self.initial[i])); - } - if let Some(ref additional) = self.additional { - for value in additional { - new_vec.push(f(value)); - } - } - - new_vec - } } // Implement `IntoIterator` for `GrowableArray` @@ -142,7 +111,8 @@ impl IntoIterator #[derive(Debug)] /// Iterator for consuming a `GrowableArray`. -pub enum GrowableArrayIntoIter { +pub(crate) enum GrowableArrayIntoIter +{ /// stackonly StackOnly { /// iter @@ -196,7 +166,7 @@ impl<'a, T: Default + Clone + PartialEq + 'a, const INITIAL_CAPACITY: usize> Int #[derive(Debug)] /// Iterator for referencing elements in a `GrowableArray`. -pub enum GrowableArrayIter<'a, T: Default, const INITIAL_CAPACITY: usize> { +pub(crate) enum GrowableArrayIter<'a, T: Default, const INITIAL_CAPACITY: usize> { /// stackonly StackOnly { /// iter @@ -319,17 +289,4 @@ mod tests { assert_eq!(iter.next(), Some(KeyValuePair(key2, value2))); assert_eq!(iter.next(), None); } - - #[test] - fn test_contains() { - let mut collection = GrowableArray::::new(); - for i in 0..10 { - collection.push(i); - } - assert!(collection.contains(&5)); - assert!(!collection.contains(&15)); - - collection.push(15); - assert!(collection.contains(&15)); - } } diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index b9a2e258e6..7a151794c6 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -509,7 +509,7 @@ mod tests { BatchLogProcessor, OTEL_BLRP_EXPORT_TIMEOUT, OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, }; - use crate::logs::AttributesGrowableArray; + use crate::logs::record::AttributesGrowableArray; use crate::testing::logs::InMemoryLogsExporterBuilder; use crate::{ export::logs::{LogData, LogExporter}, diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index de8c96b7c5..b44d872b72 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -1,17 +1,16 @@ //! # OpenTelemetry Log SDK -mod growable_array; +pub(crate) mod growable_array; mod log_emitter; mod log_processor; -mod record; +pub(crate) mod record; -pub use growable_array::{GrowableArray, GrowableArrayIntoIter, GrowableArrayIter}; pub use log_emitter::{Builder, Logger, LoggerProvider}; pub use log_processor::{ BatchConfig, BatchConfigBuilder, BatchLogProcessor, BatchLogProcessorBuilder, LogProcessor, SimpleLogProcessor, }; -pub use record::{AttributesGrowableArray, LogRecord, TraceContext}; +pub use record::{LogRecord, TraceContext}; #[cfg(all(test, feature = "testing"))] mod tests { diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 9d9edb7bf8..c6bfa57cf2 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -1,4 +1,4 @@ -use super::growable_array::GrowableArray; +use crate::logs::growable_array::GrowableArray; use opentelemetry::{ logs::{AnyValue, Severity}, trace::{SpanContext, SpanId, TraceFlags, TraceId}, @@ -12,7 +12,7 @@ use std::{borrow::Cow, time::SystemTime}; const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 8; /// A vector of `Option<(Key, AnyValue)>` with default capacity. -pub type AttributesGrowableArray = +pub(crate) type AttributesGrowableArray = GrowableArray, PREALLOCATED_ATTRIBUTE_CAPACITY>; #[derive(Debug, Default, Clone, PartialEq)] @@ -44,7 +44,7 @@ pub struct LogRecord { pub body: Option, /// Additional attributes associated with this record - pub attributes: AttributesGrowableArray, + pub(crate) attributes: AttributesGrowableArray, } impl opentelemetry::logs::LogRecord for LogRecord { @@ -103,6 +103,29 @@ impl opentelemetry::logs::LogRecord for LogRecord { } } +impl LogRecord { + /// Provides an iterator over the attributes. + pub fn attributes_iter(&self) -> impl Iterator { + self.attributes.iter().filter_map(|opt| opt.as_ref()) + } + + /// Returns the number of attributes in the `LogRecord`. + pub fn attributes_len(&self) -> usize { + self.attributes.len() + } + + /// Checks if the `LogRecord` contains the specified attribute. + pub fn contains_attribute(&self, key: &Key, value: &AnyValue) -> bool { + self.attributes.iter().any(|opt| { + if let Some((k, v)) = opt { + k == key && v == value + } else { + false + } + }) + } +} + /// TraceContext stores the trace context for logs that have an associated /// span. #[derive(Debug, Clone, PartialEq)] diff --git a/opentelemetry-stdout/src/logs/transform.rs b/opentelemetry-stdout/src/logs/transform.rs index 945c36bd45..45b730d5bc 100644 --- a/opentelemetry-stdout/src/logs/transform.rs +++ b/opentelemetry-stdout/src/logs/transform.rs @@ -4,7 +4,6 @@ use crate::common::{ as_human_readable, as_opt_human_readable, as_opt_unix_nano, as_unix_nano, AttributeSet, KeyValue, Resource, Scope, Value, }; -use opentelemetry_sdk::logs::AttributesGrowableArray; use serde::Serialize; /// Transformed logs data that can be serialized. @@ -108,6 +107,21 @@ struct LogRecord { impl From for LogRecord { fn from(value: opentelemetry_sdk::export::logs::LogData) -> Self { LogRecord { + attributes: { + let mut attributes = value + .record + .attributes_iter() + .map(|(k, v)| KeyValue::from((k.clone(), v.clone()))) // Map each pair to a KeyValue + .collect::>(); // Collect into a Vecs + + if let Some(event_name) = &value.record.event_name { + attributes.push(KeyValue::from(( + "name".into(), + opentelemetry::Value::String(event_name.clone().into()), + ))); + } + attributes + }, trace_id: value .record .trace_context @@ -132,22 +146,6 @@ impl From for LogRecord { .severity_number .map(|u| u as u32) .unwrap_or_default(), - attributes: { - let mut attributes = value - .record - .attributes - .iter() - .filter_map(|kv| kv.clone().map(|(k, v)| (k, v).into())) // Filter out None values and convert to KeyValue - .collect::>(); - - if let Some(event_name) = &value.record.event_name { - attributes.push(KeyValue::from(( - "name".into(), - opentelemetry::Value::String(event_name.clone().into()), - ))); - } - attributes - }, dropped_attributes_count: 0, severity_text: value.record.severity_text, body: value.record.body.map(|a| a.into()), From 9dc8a456e083d4598d4aa974897bd38165b5f31b Mon Sep 17 00:00:00 2001 From: Lalit Date: Thu, 25 Jul 2024 23:53:43 -0700 Subject: [PATCH 13/55] changes.. --- opentelemetry-appender-log/src/lib.rs | 17 +-- opentelemetry-appender-tracing/Cargo.toml | 1 + opentelemetry-appender-tracing/src/layer.rs | 147 ++++++++++---------- opentelemetry-sdk/src/logs/record.rs | 2 +- 4 files changed, 83 insertions(+), 84 deletions(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index ea47c16767..5321215da7 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -938,22 +938,17 @@ mod tests { ); let logs = exporter.get_emitted_logs().unwrap(); - let attributes = &logs[0].record.attributes; - - let get = |needle: &str| { - attributes.iter().find_map(|attr| { - if let Some((k, v)) = attr { - if k.as_str() == needle { - Some(v.clone()) - } else { - None - } + //let attributes = &logs[0].record.attributes; + + let get = |needle: &str| -> Option { + logs[0].record.attributes_iter().find_map(|(k, v)| { + if k.as_str() == needle { + Some(v.clone()) } else { None } }) }; - assert_eq!( AnyValue::String(StringValue::from("a string")), get("str_value").unwrap() diff --git a/opentelemetry-appender-tracing/Cargo.toml b/opentelemetry-appender-tracing/Cargo.toml index 35bce5c6e9..c080dbda80 100644 --- a/opentelemetry-appender-tracing/Cargo.toml +++ b/opentelemetry-appender-tracing/Cargo.toml @@ -32,6 +32,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } [features] experimental_metadata_attributes = ["dep:tracing-log"] logs_level_enabled = ["opentelemetry/logs_level_enabled"] +default = ["experimental_metadata_attributes"] [[bench]] name = "logs" diff --git a/opentelemetry-appender-tracing/src/layer.rs b/opentelemetry-appender-tracing/src/layer.rs index 50bedf82c2..e6d0a9a205 100644 --- a/opentelemetry-appender-tracing/src/layer.rs +++ b/opentelemetry-appender-tracing/src/layer.rs @@ -252,33 +252,38 @@ mod tests { assert!(log.record.trace_context.is_none()); // Validate attributes - let attributes = log.record.attributes.clone(); #[cfg(not(feature = "experimental_metadata_attributes"))] - assert_eq!(attributes.len(), 3); + assert_eq!(log.record.attributes_len(), 3); #[cfg(feature = "experimental_metadata_attributes")] - assert_eq!(attributes.len(), 8); - assert!(attributes.contains(&Some((Key::new("event_id"), 20.into())))); - assert!(attributes.contains(&Some((Key::new("user_name"), "otel".into())))); - assert!(attributes.contains(&Some(( - Key::new("user_email"), - "otel@opentelemetry.io".into() - )))); + assert_eq!(log.record.attributes_len(), 8); + assert!(log + .record + .attributes_contains(&Key::new("event_id"), &AnyValue::Int(20))); + assert!(log + .record + .attributes_contains(&Key::new("user_name"), &AnyValue::String("otel".into()))); + assert!(log.record.attributes_contains( + &Key::new("user_email"), + &AnyValue::String("otel@opentelemetry.io".into()) + )); + #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); - assert!(attributes.contains(&Some(( - Key::new("code.namespace"), - "opentelemetry_appender_tracing::layer::tests".into() - )))); + assert!(log.record.attributes_contains( + &Key::new("code.filename"), + &AnyValue::String("layer.rs".into()) + )); + assert!(log.record.attributes_contains( + &Key::new("code.namespace"), + &AnyValue::String("opentelemetry_appender_tracing::layer::tests".into()) + )); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes - .iter() - .filter_map(|attr| match attr { - Some((key, _)) => Some(key.clone()), - None => None, - }) + let attributes_key: Vec = log + .record + .attributes_iter() + .map(|(key, _)| key.clone()) .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); @@ -354,35 +359,38 @@ mod tests { ); // validate attributes. - let attributes = log.record.attributes.clone(); #[cfg(not(feature = "experimental_metadata_attributes"))] - assert_eq!(attributes.len(), 3); + assert_eq!(log.record.attributes_len(), 3); #[cfg(feature = "experimental_metadata_attributes")] - assert_eq!(attributes.len(), 8); - assert!(attributes.contains(&Some((Key::new("event_id"), 20.into())))); - assert!(attributes.contains(&Some((Key::new("user_name"), "otel".into())))); - assert!(attributes.contains(&Some(( - Key::new("user_email"), - "otel@opentelemetry.io".into() - )))); + assert_eq!(log.record.attributes_len(), 8); + assert!(log + .record + .attributes_contains(&Key::new("event_id"), &AnyValue::Int(20.into()))); + assert!(log + .record + .attributes_contains(&Key::new("user_name"), &AnyValue::String("otel".into()))); + assert!(log.record.attributes_contains( + &Key::new("user_email"), + &AnyValue::String("otel@opentelemetry.io".into()) + )); #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); - assert!(attributes.contains(&Some(( - Key::new("code.namespace"), - "opentelemetry_appender_tracing::layer::tests".into() - )))); + assert!(log.record.attributes_contains( + &Key::new("code.filename"), + &AnyValue::String("layer.rs".into()) + )); + assert!(log.record.attributes_contains( + &Key::new("code.namespace"), + &AnyValue::String("opentelemetry_appender_tracing::layer::tests".into()) + )); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - //let attributes_key: Vec = attributes.iter().map(|(key, _)| key.clone()).collect(); - let attributes_key: Vec = attributes - .iter() - .filter_map(|attr| match attr { - Some((key, _)) => Some(key.clone()), - None => None, - }) + let attributes_key: Vec = log + .record + .attributes_iter() + .map(|(key, _)| key.clone()) .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); @@ -426,30 +434,27 @@ mod tests { // Validate trace context is none. assert!(log.record.trace_context.is_none()); - // Validate attributes - #[cfg(feature = "experimental_metadata_attributes")] - let attributes = log.record.attributes.clone(); - // Attributes can be polluted when we don't use this feature. #[cfg(feature = "experimental_metadata_attributes")] - assert_eq!(attributes.len(), 5); + assert_eq!(log.record.attributes_len(), 5); #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&(Some((Key::new("code.filename"), "layer.rs".into()))))); - assert!(attributes.contains(&Some(( - Key::new("code.namespace"), - "opentelemetry_appender_tracing::layer::tests".into() - )))); + assert!(log.record.attributes_contains( + &Key::new("code.filename"), + &AnyValue::String("layer.rs".into()) + )); + assert!(log.record.attributes_contains( + &Key::new("code.namespace"), + &AnyValue::String("opentelemetry_appender_tracing::layer::tests".into()) + )); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes - .iter() - .filter_map(|attr| match attr { - Some((key, _)) => Some(key.clone()), - None => None, - }) + let attributes_key: Vec = log + .record + .attributes_iter() + .map(|(key, _)| key.clone()) .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); @@ -525,29 +530,27 @@ mod tests { ); // validate attributes. - #[cfg(feature = "experimental_metadata_attributes")] - let attributes = log.record.attributes.clone(); - // Attributes can be polluted when we don't use this feature. #[cfg(feature = "experimental_metadata_attributes")] - assert_eq!(attributes.len(), 5); + assert_eq!(log.record.attributes_len(), 5); #[cfg(feature = "experimental_metadata_attributes")] { - assert!(attributes.contains(&Some((Key::new("code.filename"), "layer.rs".into())))); - assert!(attributes.contains(&Some(( - Key::new("code.namespace"), - "opentelemetry_appender_tracing::layer::tests".into() - )))); + assert!(log.record.attributes_contains( + &Key::new("code.filename"), + &AnyValue::String("layer.rs".into()) + )); + assert!(log.record.attributes_contains( + &Key::new("code.namespace"), + &AnyValue::String("opentelemetry_appender_tracing::layer::tests".into()) + )); // The other 3 experimental_metadata_attributes are too unstable to check their value. // Ex.: The path will be different on a Windows and Linux machine. // Ex.: The line can change easily if someone makes changes in this source file. - let attributes_key: Vec = attributes - .iter() - .filter_map(|attr| match attr { - Some((key, _)) => Some(key.clone()), - None => None, - }) + let attributes_key: Vec = log + .record + .attributes_iter() + .map(|(key, _)| key.clone()) .collect(); assert!(attributes_key.contains(&Key::new("code.filepath"))); assert!(attributes_key.contains(&Key::new("code.lineno"))); diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index c6bfa57cf2..2116c54769 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -115,7 +115,7 @@ impl LogRecord { } /// Checks if the `LogRecord` contains the specified attribute. - pub fn contains_attribute(&self, key: &Key, value: &AnyValue) -> bool { + pub fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { self.attributes.iter().any(|opt| { if let Some((k, v)) = opt { k == key && v == value From df66985e2b153061f5f836a8b4cf8d29e81ea175 Mon Sep 17 00:00:00 2001 From: Lalit Date: Fri, 26 Jul 2024 11:10:08 -0700 Subject: [PATCH 14/55] box enums --- opentelemetry-proto/src/transform/logs.rs | 2 +- opentelemetry-stdout/src/common.rs | 2 +- opentelemetry/src/logs/record.rs | 12 ++++++------ 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/opentelemetry-proto/src/transform/logs.rs b/opentelemetry-proto/src/transform/logs.rs index 14e40b5d94..c163d0f9ef 100644 --- a/opentelemetry-proto/src/transform/logs.rs +++ b/opentelemetry-proto/src/transform/logs.rs @@ -50,7 +50,7 @@ pub mod tonic { }) .collect(), }), - LogsAnyValue::Bytes(v) => Value::BytesValue(v), + LogsAnyValue::Bytes(v) => Value::BytesValue(*v), } } } diff --git a/opentelemetry-stdout/src/common.rs b/opentelemetry-stdout/src/common.rs index bbf7f86251..236accea7c 100644 --- a/opentelemetry-stdout/src/common.rs +++ b/opentelemetry-stdout/src/common.rs @@ -168,7 +168,7 @@ impl From for Value { }) .collect(), ), - opentelemetry::logs::AnyValue::Bytes(b) => Value::BytesValue(b), + opentelemetry::logs::AnyValue::Bytes(b) => Value::BytesValue(*b), } } } diff --git a/opentelemetry/src/logs/record.rs b/opentelemetry/src/logs/record.rs index be00a7ab5c..a77f25c072 100644 --- a/opentelemetry/src/logs/record.rs +++ b/opentelemetry/src/logs/record.rs @@ -59,11 +59,11 @@ pub enum AnyValue { /// A boolean value Boolean(bool), /// A byte array - Bytes(Vec), + Bytes(Box>), /// An array of `Any` values - ListAny(Vec), + ListAny(Box>), /// A map of string keys to `Any` values, arbitrarily nested. - Map(HashMap), + Map(Box>), } macro_rules! impl_trivial_from { @@ -98,7 +98,7 @@ impl_trivial_from!(bool, AnyValue::Boolean); impl> FromIterator for AnyValue { /// Creates an [`AnyValue::ListAny`] value from a sequence of `Into` values. fn from_iter>(iter: I) -> Self { - AnyValue::ListAny(iter.into_iter().map(Into::into).collect()) + AnyValue::ListAny(Box::new(iter.into_iter().map(Into::into).collect())) } } @@ -106,9 +106,9 @@ impl, V: Into> FromIterator<(K, V)> for AnyValue { /// Creates an [`AnyValue::Map`] value from a sequence of key-value pairs /// that can be converted into a `Key` and `AnyValue` respectively. fn from_iter>(iter: I) -> Self { - AnyValue::Map(HashMap::from_iter( + AnyValue::Map(Box::new(HashMap::from_iter( iter.into_iter().map(|(k, v)| (k.into(), v.into())), - )) + ))) } } From 8f62fa36ea2945e8ccdac3b528045fc7a22383d0 Mon Sep 17 00:00:00 2001 From: Lalit Date: Fri, 26 Jul 2024 12:37:01 -0700 Subject: [PATCH 15/55] make growable add inline --- opentelemetry-sdk/src/logs/growable_array.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index f04430c5a9..3231f198f8 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -44,6 +44,7 @@ impl< } /// Pushes a value into the `GrowableArray`. + #[inline] pub(crate) fn push(&mut self, value: T) { if self.count < MAX_STACK_CAPACITY { self.initial[self.count] = value; @@ -74,6 +75,7 @@ impl< } /// Returns an iterator over the elements in the `GrowableArray`. + #[inline] pub(crate) fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { GrowableArrayIter::StackOnly { From fb7a44c9d18c8b9df5fcf80f6f771074e4e57c12 Mon Sep 17 00:00:00 2001 From: Lalit Date: Fri, 26 Jul 2024 13:46:20 -0700 Subject: [PATCH 16/55] update bench --- opentelemetry-sdk/benches/log.rs | 50 +++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/opentelemetry-sdk/benches/log.rs b/opentelemetry-sdk/benches/log.rs index 8983a5ac99..8a58b94ea7 100644 --- a/opentelemetry-sdk/benches/log.rs +++ b/opentelemetry-sdk/benches/log.rs @@ -14,7 +14,7 @@ use opentelemetry::logs::{ }; use opentelemetry::trace::Tracer; use opentelemetry::trace::TracerProvider as _; -use opentelemetry::Key; +use opentelemetry::{InstrumentationLibrary, Key}; use opentelemetry_sdk::export::logs::{LogData, LogExporter}; use opentelemetry_sdk::logs::{Logger, LoggerProvider}; use opentelemetry_sdk::trace; @@ -66,6 +66,20 @@ fn log_benchmark_group(c: &mut Criterion, name: &str, f: F) { } fn criterion_benchmark(c: &mut Criterion) { + let mut crit = Criterion::default() + .sample_size(100) // Set sample size + .measurement_time(std::time::Duration::new(20, 0)) // Set measurement time to 10 seconds + .warm_up_time(std::time::Duration::new(5, 0)); // Set warm-up time + /*log_benchmark_group(c, "simple-log", |logger| { + let mut log_record = logger.create_log_record(); + log_record.set_body("simple log".into()); + logger.emit(log_record); + });*/ + log_benchmark_group(&mut crit, "custom-test", |logger| { + let mut log_record = logger.create_log_record(); + logger.emit(log_record); + }); + log_benchmark_group(c, "simple-log", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -100,7 +114,7 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let bytes = AnyValue::Bytes(vec![25u8, 30u8, 40u8]); + let bytes = AnyValue::Bytes(Box::new(vec![25u8, 30u8, 40u8])); log_benchmark_group(c, "simple-log-with-bytes", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -108,14 +122,14 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let bytes = AnyValue::Bytes(vec![ + let bytes = AnyValue::Bytes(Box::new(vec![ 25u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, - ]); + ])); log_benchmark_group(c, "simple-log-with-a-lot-of-bytes", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -123,7 +137,11 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let vec_any_values = AnyValue::ListAny(vec![AnyValue::Int(25), "test".into(), true.into()]); + let vec_any_values = AnyValue::ListAny(Box::new(vec![ + AnyValue::Int(25), + "test".into(), + true.into(), + ])); log_benchmark_group(c, "simple-log-with-vec-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -131,13 +149,17 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let vec_any_values = AnyValue::ListAny(vec![AnyValue::Int(25), "test".into(), true.into()]); - let vec_any_values = AnyValue::ListAny(vec![ + let vec_any_values = AnyValue::ListAny(Box::new(vec![ + AnyValue::Int(25), + "test".into(), + true.into(), + ])); + let vec_any_values = AnyValue::ListAny(Box::new(vec![ AnyValue::Int(25), "test".into(), true.into(), vec_any_values, - ]); + ])); log_benchmark_group(c, "simple-log-with-inner-vec-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -145,11 +167,11 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let map_any_values = AnyValue::Map(HashMap::from([ + let map_any_values = AnyValue::Map(Box::new(HashMap::from([ ("testint".into(), 2.into()), ("testdouble".into(), 2.2.into()), ("teststring".into(), "test".into()), - ])); + ]))); log_benchmark_group(c, "simple-log-with-map-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -157,17 +179,17 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let map_any_values = AnyValue::Map(HashMap::from([ + let map_any_values = AnyValue::Map(Box::new(HashMap::from([ ("testint".into(), 2.into()), ("testdouble".into(), 2.2.into()), ("teststring".into(), "test".into()), - ])); - let map_any_values = AnyValue::Map(HashMap::from([ + ]))); + let map_any_values = AnyValue::Map(Box::new(HashMap::from([ ("testint".into(), 2.into()), ("testdouble".into(), 2.2.into()), ("teststring".into(), "test".into()), ("testmap".into(), map_any_values), - ])); + ]))); log_benchmark_group(c, "simple-log-with-inner-map-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); From 2fabca1833ef0d87c1c83887a27db0ab5e5280a2 Mon Sep 17 00:00:00 2001 From: Lalit Date: Fri, 26 Jul 2024 22:35:59 -0700 Subject: [PATCH 17/55] remove experimenal metadata as default --- opentelemetry-appender-tracing/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-appender-tracing/Cargo.toml b/opentelemetry-appender-tracing/Cargo.toml index c080dbda80..35bce5c6e9 100644 --- a/opentelemetry-appender-tracing/Cargo.toml +++ b/opentelemetry-appender-tracing/Cargo.toml @@ -32,7 +32,6 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } [features] experimental_metadata_attributes = ["dep:tracing-log"] logs_level_enabled = ["opentelemetry/logs_level_enabled"] -default = ["experimental_metadata_attributes"] [[bench]] name = "logs" From e52d0026fab3a644d8f78da6cc5f84572f87d16f Mon Sep 17 00:00:00 2001 From: Lalit Date: Sat, 27 Jul 2024 19:07:45 -0700 Subject: [PATCH 18/55] changes. --- .../src/proto/opentelemetry-proto | 2 +- opentelemetry-sdk/benches/log.rs | 2 +- opentelemetry-sdk/src/logs/log_processor.rs | 32 ++++++------------- opentelemetry-sdk/src/logs/mod.rs | 12 +++---- opentelemetry-sdk/src/logs/record.rs | 22 +++++-------- opentelemetry/src/common.rs | 6 ++++ opentelemetry/src/logs/record.rs | 6 ++++ 7 files changed, 35 insertions(+), 47 deletions(-) diff --git a/opentelemetry-proto/src/proto/opentelemetry-proto b/opentelemetry-proto/src/proto/opentelemetry-proto index 40b3c1b746..b3060d2104 160000 --- a/opentelemetry-proto/src/proto/opentelemetry-proto +++ b/opentelemetry-proto/src/proto/opentelemetry-proto @@ -1 +1 @@ -Subproject commit 40b3c1b746767cbc13c2e39da3eaf1a23e54ffdd +Subproject commit b3060d2104df364136d75a35779e6bd48bac449a diff --git a/opentelemetry-sdk/benches/log.rs b/opentelemetry-sdk/benches/log.rs index e02cd20f86..dea4aaec30 100644 --- a/opentelemetry-sdk/benches/log.rs +++ b/opentelemetry-sdk/benches/log.rs @@ -15,7 +15,7 @@ use opentelemetry::trace::Tracer; use opentelemetry::trace::TracerProvider as _; use opentelemetry::Key; use opentelemetry_sdk::export::logs::LogData; -use opentelemetry_sdk::logs::{Logger, LoggerProvider, LogProcessor}; +use opentelemetry_sdk::logs::{LogProcessor, Logger, LoggerProvider}; use opentelemetry_sdk::trace; use opentelemetry_sdk::trace::{Sampler, TracerProvider}; diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 7a151794c6..0216991b72 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -822,10 +822,10 @@ mod tests { } // Add attribute - data.record.attributes.push(Some(( + data.record.attributes.push(( Key::from_static_str("processed_by"), AnyValue::String("FirstProcessor".into()), - ))); + )); // Update body data.record.body = Some(AnyValue::String("Updated by FirstProcessor".into())); @@ -854,13 +854,9 @@ mod tests { impl LogProcessor for SecondProcessor { fn emit(&self, data: &mut LogData) { - assert!(data.record.attributes.iter().any(|attr| { - if let Some((key, value)) = attr { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) - } else { - false - } + assert!(data.record.attributes.iter().any(|(key, value)| { + key.as_str() == "processed_by" + && *value == AnyValue::String("FirstProcessor".into()) })); assert!( data.record.body.clone().unwrap() @@ -911,22 +907,12 @@ mod tests { let first_log = &first_processor_logs.lock().unwrap()[0]; let second_log = &second_processor_logs.lock().unwrap()[0]; - assert!(first_log.record.attributes.iter().any(|attr| { - if let Some((key, value)) = attr { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) - } else { - false - } + assert!(first_log.record.attributes.iter().any(|(key, value)| { + key.as_str() == "processed_by" && *value == AnyValue::String("FirstProcessor".into()) })); - assert!(second_log.record.attributes.iter().any(|attr| { - if let Some((key, value)) = attr { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) - } else { - false - } + assert!(second_log.record.attributes.iter().any(|(key, value)| { + key.as_str() == "processed_by" && *value == AnyValue::String("FirstProcessor".into()) })); assert!( diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index b44d872b72..e36a40399f 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -85,17 +85,13 @@ mod tests { .record .attributes .iter() - .filter_map(|kv| kv.as_ref().map(|(k, v)| (k.clone(), v.clone()))) + .map(|kv| (kv.0.clone(), kv.1.clone())) .collect(); assert_eq!(attributes.len(), 10); for i in 1..=10 { - assert!(log.record.attributes.iter().any(|kv| { - if let Some((key, value)) = kv { - key.as_str() == format!("key{}", i) - && *value == AnyValue::String(format!("value{}", i).into()) - } else { - false - } + assert!(log.record.attributes.iter().any(|(key, value)| { + key.as_str() == format!("key{}", i) + && *value == AnyValue::String(format!("value{}", i).into()) })); } diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 2116c54769..d0915d1c18 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -11,9 +11,9 @@ use std::{borrow::Cow, time::SystemTime}; // capacity for attributes to avoid reallocation in common scenarios. const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 8; -/// A vector of `Option<(Key, AnyValue)>` with default capacity. +/// A vector of `(Key, AnyValue)` with default capacity. pub(crate) type AttributesGrowableArray = - GrowableArray, PREALLOCATED_ATTRIBUTE_CAPACITY>; + GrowableArray<(Key, AnyValue), PREALLOCATED_ATTRIBUTE_CAPACITY>; #[derive(Debug, Default, Clone, PartialEq)] #[non_exhaustive] @@ -99,14 +99,14 @@ impl opentelemetry::logs::LogRecord for LogRecord { K: Into, V: Into, { - self.attributes.push(Some((key.into(), value.into()))); + self.attributes.push((key.into(), value.into())); } } impl LogRecord { /// Provides an iterator over the attributes. pub fn attributes_iter(&self) -> impl Iterator { - self.attributes.iter().filter_map(|opt| opt.as_ref()) + self.attributes.iter() } /// Returns the number of attributes in the `LogRecord`. @@ -116,13 +116,7 @@ impl LogRecord { /// Checks if the `LogRecord` contains the specified attribute. pub fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { - self.attributes.iter().any(|opt| { - if let Some((k, v)) = opt { - k == key && v == value - } else { - false - } - }) + self.attributes.iter().any(|(k, v)| k == key && v == value) } } @@ -218,7 +212,7 @@ mod tests { let mut expected_attributes = AttributesGrowableArray::new(); for (key, value) in attributes { - expected_attributes.push(Some((key, value))); + expected_attributes.push((key, value)); } assert_eq!(log_record.attributes, expected_attributes); } @@ -230,7 +224,7 @@ mod tests { let expected_attributes = { let mut hybrid_vec = AttributesGrowableArray::new(); - hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); + hybrid_vec.push((Key::new("key"), AnyValue::String("value".into()))); hybrid_vec }; assert_eq!(log_record.attributes, expected_attributes); @@ -269,7 +263,7 @@ mod tests { body: Some(AnyValue::String("Test body".into())), attributes: { let mut hybrid_vec = AttributesGrowableArray::new(); - hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); + hybrid_vec.push((Key::new("key"), AnyValue::String("value".into()))); hybrid_vec }, trace_context: Some(TraceContext { diff --git a/opentelemetry/src/common.rs b/opentelemetry/src/common.rs index 9b03ab0374..6fcdb134b7 100644 --- a/opentelemetry/src/common.rs +++ b/opentelemetry/src/common.rs @@ -10,6 +10,12 @@ use std::{fmt, hash}; #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Key(OtelString); +impl Default for Key { + fn default() -> Self { + Key::from_static_str("") + } +} + impl Key { /// Create a new `Key`. /// diff --git a/opentelemetry/src/logs/record.rs b/opentelemetry/src/logs/record.rs index a77f25c072..d3e9f7a7ab 100644 --- a/opentelemetry/src/logs/record.rs +++ b/opentelemetry/src/logs/record.rs @@ -66,6 +66,12 @@ pub enum AnyValue { Map(Box>), } +impl Default for AnyValue { + fn default() -> Self { + AnyValue::Int(0) + } +} + macro_rules! impl_trivial_from { ($t:ty, $variant:path) => { impl From<$t> for AnyValue { From 877996e1d43a5b855722131e12c54c8acdfd7cea Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 28 Jul 2024 23:26:12 -0700 Subject: [PATCH 19/55] revert back to option --- opentelemetry-sdk/src/logs/log_processor.rs | 32 +++++++++++++++------ opentelemetry-sdk/src/logs/mod.rs | 12 +++++--- opentelemetry-sdk/src/logs/record.rs | 22 ++++++++------ opentelemetry/src/common.rs | 6 ---- opentelemetry/src/logs/record.rs | 6 ---- 5 files changed, 45 insertions(+), 33 deletions(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 0216991b72..7a151794c6 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -822,10 +822,10 @@ mod tests { } // Add attribute - data.record.attributes.push(( + data.record.attributes.push(Some(( Key::from_static_str("processed_by"), AnyValue::String("FirstProcessor".into()), - )); + ))); // Update body data.record.body = Some(AnyValue::String("Updated by FirstProcessor".into())); @@ -854,9 +854,13 @@ mod tests { impl LogProcessor for SecondProcessor { fn emit(&self, data: &mut LogData) { - assert!(data.record.attributes.iter().any(|(key, value)| { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) + assert!(data.record.attributes.iter().any(|attr| { + if let Some((key, value)) = attr { + key.as_str() == "processed_by" + && *value == AnyValue::String("FirstProcessor".into()) + } else { + false + } })); assert!( data.record.body.clone().unwrap() @@ -907,12 +911,22 @@ mod tests { let first_log = &first_processor_logs.lock().unwrap()[0]; let second_log = &second_processor_logs.lock().unwrap()[0]; - assert!(first_log.record.attributes.iter().any(|(key, value)| { - key.as_str() == "processed_by" && *value == AnyValue::String("FirstProcessor".into()) + assert!(first_log.record.attributes.iter().any(|attr| { + if let Some((key, value)) = attr { + key.as_str() == "processed_by" + && *value == AnyValue::String("FirstProcessor".into()) + } else { + false + } })); - assert!(second_log.record.attributes.iter().any(|(key, value)| { - key.as_str() == "processed_by" && *value == AnyValue::String("FirstProcessor".into()) + assert!(second_log.record.attributes.iter().any(|attr| { + if let Some((key, value)) = attr { + key.as_str() == "processed_by" + && *value == AnyValue::String("FirstProcessor".into()) + } else { + false + } })); assert!( diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index e36a40399f..b44d872b72 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -85,13 +85,17 @@ mod tests { .record .attributes .iter() - .map(|kv| (kv.0.clone(), kv.1.clone())) + .filter_map(|kv| kv.as_ref().map(|(k, v)| (k.clone(), v.clone()))) .collect(); assert_eq!(attributes.len(), 10); for i in 1..=10 { - assert!(log.record.attributes.iter().any(|(key, value)| { - key.as_str() == format!("key{}", i) - && *value == AnyValue::String(format!("value{}", i).into()) + assert!(log.record.attributes.iter().any(|kv| { + if let Some((key, value)) = kv { + key.as_str() == format!("key{}", i) + && *value == AnyValue::String(format!("value{}", i).into()) + } else { + false + } })); } diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index d0915d1c18..2116c54769 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -11,9 +11,9 @@ use std::{borrow::Cow, time::SystemTime}; // capacity for attributes to avoid reallocation in common scenarios. const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 8; -/// A vector of `(Key, AnyValue)` with default capacity. +/// A vector of `Option<(Key, AnyValue)>` with default capacity. pub(crate) type AttributesGrowableArray = - GrowableArray<(Key, AnyValue), PREALLOCATED_ATTRIBUTE_CAPACITY>; + GrowableArray, PREALLOCATED_ATTRIBUTE_CAPACITY>; #[derive(Debug, Default, Clone, PartialEq)] #[non_exhaustive] @@ -99,14 +99,14 @@ impl opentelemetry::logs::LogRecord for LogRecord { K: Into, V: Into, { - self.attributes.push((key.into(), value.into())); + self.attributes.push(Some((key.into(), value.into()))); } } impl LogRecord { /// Provides an iterator over the attributes. pub fn attributes_iter(&self) -> impl Iterator { - self.attributes.iter() + self.attributes.iter().filter_map(|opt| opt.as_ref()) } /// Returns the number of attributes in the `LogRecord`. @@ -116,7 +116,13 @@ impl LogRecord { /// Checks if the `LogRecord` contains the specified attribute. pub fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { - self.attributes.iter().any(|(k, v)| k == key && v == value) + self.attributes.iter().any(|opt| { + if let Some((k, v)) = opt { + k == key && v == value + } else { + false + } + }) } } @@ -212,7 +218,7 @@ mod tests { let mut expected_attributes = AttributesGrowableArray::new(); for (key, value) in attributes { - expected_attributes.push((key, value)); + expected_attributes.push(Some((key, value))); } assert_eq!(log_record.attributes, expected_attributes); } @@ -224,7 +230,7 @@ mod tests { let expected_attributes = { let mut hybrid_vec = AttributesGrowableArray::new(); - hybrid_vec.push((Key::new("key"), AnyValue::String("value".into()))); + hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); hybrid_vec }; assert_eq!(log_record.attributes, expected_attributes); @@ -263,7 +269,7 @@ mod tests { body: Some(AnyValue::String("Test body".into())), attributes: { let mut hybrid_vec = AttributesGrowableArray::new(); - hybrid_vec.push((Key::new("key"), AnyValue::String("value".into()))); + hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); hybrid_vec }, trace_context: Some(TraceContext { diff --git a/opentelemetry/src/common.rs b/opentelemetry/src/common.rs index 6fcdb134b7..9b03ab0374 100644 --- a/opentelemetry/src/common.rs +++ b/opentelemetry/src/common.rs @@ -10,12 +10,6 @@ use std::{fmt, hash}; #[derive(Clone, PartialEq, Eq, Hash, PartialOrd, Ord)] pub struct Key(OtelString); -impl Default for Key { - fn default() -> Self { - Key::from_static_str("") - } -} - impl Key { /// Create a new `Key`. /// diff --git a/opentelemetry/src/logs/record.rs b/opentelemetry/src/logs/record.rs index d3e9f7a7ab..a77f25c072 100644 --- a/opentelemetry/src/logs/record.rs +++ b/opentelemetry/src/logs/record.rs @@ -66,12 +66,6 @@ pub enum AnyValue { Map(Box>), } -impl Default for AnyValue { - fn default() -> Self { - AnyValue::Int(0) - } -} - macro_rules! impl_trivial_from { ($t:ty, $variant:path) => { impl From<$t> for AnyValue { From 283816beab680b2e04cc127eadef3444f6e7e9db Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 28 Jul 2024 23:35:39 -0700 Subject: [PATCH 20/55] revert the checkedin proto --- .gitmodules | 4 ---- opentelemetry-proto/src/proto/opentelemetry-proto | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/.gitmodules b/.gitmodules index bd4ed5eb06..e69de29bb2 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,4 +0,0 @@ -[submodule "opentelemetry-proto/src/proto/opentelemetry-proto"] - path = opentelemetry-proto/src/proto/opentelemetry-proto - url = https://github.com/open-telemetry/opentelemetry-proto - branch = tags/v1.0.0 diff --git a/opentelemetry-proto/src/proto/opentelemetry-proto b/opentelemetry-proto/src/proto/opentelemetry-proto index b3060d2104..40b3c1b746 160000 --- a/opentelemetry-proto/src/proto/opentelemetry-proto +++ b/opentelemetry-proto/src/proto/opentelemetry-proto @@ -1 +1 @@ -Subproject commit b3060d2104df364136d75a35779e6bd48bac449a +Subproject commit 40b3c1b746767cbc13c2e39da3eaf1a23e54ffdd From 77e1ae1385e9f3b9dd8c8d6cc2a2922b71b70c1a Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 28 Jul 2024 23:37:47 -0700 Subject: [PATCH 21/55] back --- .gitmodules | 4 ++++ opentelemetry-proto/src/proto/opentelemetry-proto | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index e69de29bb2..bd4ed5eb06 100644 --- a/.gitmodules +++ b/.gitmodules @@ -0,0 +1,4 @@ +[submodule "opentelemetry-proto/src/proto/opentelemetry-proto"] + path = opentelemetry-proto/src/proto/opentelemetry-proto + url = https://github.com/open-telemetry/opentelemetry-proto + branch = tags/v1.0.0 diff --git a/opentelemetry-proto/src/proto/opentelemetry-proto b/opentelemetry-proto/src/proto/opentelemetry-proto index 40b3c1b746..b3060d2104 160000 --- a/opentelemetry-proto/src/proto/opentelemetry-proto +++ b/opentelemetry-proto/src/proto/opentelemetry-proto @@ -1 +1 @@ -Subproject commit 40b3c1b746767cbc13c2e39da3eaf1a23e54ffdd +Subproject commit b3060d2104df364136d75a35779e6bd48bac449a From ad42e0bfffd8b0c69438a761790b6783f06d4b6e Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 28 Jul 2024 23:40:49 -0700 Subject: [PATCH 22/55] trying again to revert unwanted otel-proto update --- opentelemetry-proto/src/proto/opentelemetry-proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-proto/src/proto/opentelemetry-proto b/opentelemetry-proto/src/proto/opentelemetry-proto index b3060d2104..39339ef177 160000 --- a/opentelemetry-proto/src/proto/opentelemetry-proto +++ b/opentelemetry-proto/src/proto/opentelemetry-proto @@ -1 +1 @@ -Subproject commit b3060d2104df364136d75a35779e6bd48bac449a +Subproject commit 39339ef177218cc965b8cf863d761775ec668858 From e99a957e99b3173cf94b10dad8daaf13492ede17 Mon Sep 17 00:00:00 2001 From: Lalit Date: Sun, 28 Jul 2024 23:44:07 -0700 Subject: [PATCH 23/55] another revert try --- opentelemetry-proto/src/proto/opentelemetry-proto | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-proto/src/proto/opentelemetry-proto b/opentelemetry-proto/src/proto/opentelemetry-proto index 39339ef177..40b3c1b746 160000 --- a/opentelemetry-proto/src/proto/opentelemetry-proto +++ b/opentelemetry-proto/src/proto/opentelemetry-proto @@ -1 +1 @@ -Subproject commit 39339ef177218cc965b8cf863d761775ec668858 +Subproject commit 40b3c1b746767cbc13c2e39da3eaf1a23e54ffdd From c97a948058e6dbb9e0f237ee8748a63a3bdf0bf5 Mon Sep 17 00:00:00 2001 From: Lalit Date: Mon, 29 Jul 2024 00:23:29 -0700 Subject: [PATCH 24/55] ci errors --- opentelemetry-appender-log/src/lib.rs | 52 ++++++---- opentelemetry-proto/src/transform/logs.rs | 1 - opentelemetry-sdk/Cargo.toml | 3 - opentelemetry-sdk/benches/growable_array.rs | 99 ------------------- opentelemetry-sdk/benches/log.rs | 14 --- opentelemetry-sdk/src/logs/growable_array.rs | 70 ++++++++++++- opentelemetry-sdk/src/logs/record.rs | 5 +- .../src/testing/global_allocator.rs | 8 -- opentelemetry-sdk/src/testing/mod.rs | 2 - 9 files changed, 102 insertions(+), 152 deletions(-) delete mode 100644 opentelemetry-sdk/benches/growable_array.rs delete mode 100644 opentelemetry-sdk/src/testing/global_allocator.rs diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index 5321215da7..9341a79aa1 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -429,7 +429,7 @@ mod any_value { } fn serialize_bytes(self, v: &[u8]) -> Result { - Ok(Some(AnyValue::Bytes(v.to_owned()))) + Ok(Some(AnyValue::Bytes(Box::new(v.to_owned())))) } fn serialize_none(self) -> Result { @@ -557,7 +557,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::ListAny(self.value))) + Ok(Some(AnyValue::ListAny(Box::new(self.value)))) } } @@ -578,7 +578,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::ListAny(self.value))) + Ok(Some(AnyValue::ListAny(Box::new(self.value)))) } } @@ -599,7 +599,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::ListAny(self.value))) + Ok(Some(AnyValue::ListAny(Box::new(self.value)))) } } @@ -621,8 +621,11 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = HashMap::new(); - variant.insert(Key::from(self.variant), AnyValue::ListAny(self.value)); + let mut variant = Box::new(HashMap::new()); + variant.insert( + Key::from(self.variant), + AnyValue::ListAny(Box::new(self.value)), + ); variant }))) } @@ -664,7 +667,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::Map(self.value))) + Ok(Some(AnyValue::Map(Box::new(self.value)))) } } @@ -688,7 +691,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::Map(self.value))) + Ok(Some(AnyValue::Map(Box::new(self.value)))) } } @@ -713,8 +716,8 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = HashMap::new(); - variant.insert(Key::from(self.variant), AnyValue::Map(self.value)); + let mut variant = Box::new(HashMap::new()); + variant.insert(Key::from(self.variant), AnyValue::Map(Box::new(self.value))); variant }))) } @@ -938,7 +941,6 @@ mod tests { ); let logs = exporter.get_emitted_logs().unwrap(); - //let attributes = &logs[0].record.attributes; let get = |needle: &str| -> Option { logs[0].record.attributes_iter().find_map(|(k, v)| { @@ -1025,13 +1027,17 @@ mod tests { assert_eq!(AnyValue::Int(42), get("some_value").unwrap()); assert_eq!( - AnyValue::ListAny(vec![AnyValue::Int(1), AnyValue::Int(1), AnyValue::Int(1)]), + AnyValue::ListAny(Box::new(vec![ + AnyValue::Int(1), + AnyValue::Int(1), + AnyValue::Int(1) + ])), get("slice_value").unwrap() ); assert_eq!( AnyValue::Map({ - let mut map = HashMap::new(); + let mut map = Box::new(HashMap::new()); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1044,7 +1050,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::new(); + let mut map = Box::new(HashMap::new()); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1056,7 +1062,11 @@ mod tests { ); assert_eq!( - AnyValue::ListAny(vec![AnyValue::Int(1), AnyValue::Int(1), AnyValue::Int(1)]), + AnyValue::ListAny(Box::new(vec![ + AnyValue::Int(1), + AnyValue::Int(1), + AnyValue::Int(1) + ])), get("tuple_value").unwrap() ); @@ -1067,7 +1077,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::new(); + let mut map = Box::new(HashMap::new()); map.insert(Key::from("Newtype"), AnyValue::Int(42)); @@ -1078,12 +1088,12 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::new(); + let mut map = Box::new(HashMap::new()); map.insert( Key::from("Struct"), AnyValue::Map({ - let mut map = HashMap::new(); + let mut map = Box::new(HashMap::new()); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1100,15 +1110,15 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::new(); + let mut map = Box::new(HashMap::new()); map.insert( Key::from("Tuple"), - AnyValue::ListAny(vec![ + AnyValue::ListAny(Box::new(vec![ AnyValue::Int(1), AnyValue::Int(1), AnyValue::Int(1), - ]), + ])), ); map diff --git a/opentelemetry-proto/src/transform/logs.rs b/opentelemetry-proto/src/transform/logs.rs index c163d0f9ef..880c3c0689 100644 --- a/opentelemetry-proto/src/transform/logs.rs +++ b/opentelemetry-proto/src/transform/logs.rs @@ -8,7 +8,6 @@ pub mod tonic { }, logs::v1::{LogRecord, ResourceLogs, ScopeLogs, SeverityNumber}, resource::v1::Resource, - Attributes, }, transform::common::{to_nanos, tonic::ResourceAttributesWithSchema}, }; diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index ab0e244254..f8656106aa 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -36,9 +36,6 @@ rustdoc-args = ["--cfg", "docsrs"] [dev-dependencies] criterion = { workspace = true, features = ["html_reports"] } temp-env = { workspace = true } -jemallocator = { version = "0.5"} -jemalloc-ctl = { version = "0.5"} - [target.'cfg(not(target_os = "windows"))'.dev-dependencies] pprof = { version = "0.13", features = ["flamegraph", "criterion"] } diff --git a/opentelemetry-sdk/benches/growable_array.rs b/opentelemetry-sdk/benches/growable_array.rs deleted file mode 100644 index aed33fbc4b..0000000000 --- a/opentelemetry-sdk/benches/growable_array.rs +++ /dev/null @@ -1,99 +0,0 @@ -/* -use criterion::{criterion_group, criterion_main, Criterion}; -use opentelemetry::logs::AnyValue; -use opentelemetry::Key; -use opentelemetry_sdk::logs::growable_array::GrowableArray; - -#[derive(Clone, Debug, PartialEq)] -pub struct KeyValuePair(Key, AnyValue); - -impl Default for KeyValuePair { - fn default() -> Self { - KeyValuePair(Key::from_static_str(""), AnyValue::Int(0)) - } -} - -fn growable_array_insertion_benchmark(c: &mut Criterion) { - c.bench_function("GrowableArray Insertion", |b| { - b.iter(|| { - let mut collection = GrowableArray::::new(); - for i in 0..8 { - let key = Key::from(format!("key{}", i)); - let value = AnyValue::Int(i as i64); - collection.push(KeyValuePair(key, value)); - } - }) - }); -} - -fn vec_insertion_benchmark(c: &mut Criterion) { - c.bench_function("Vec Insertion", |b| { - b.iter(|| { - let mut collection = Vec::with_capacity(10); - for i in 0..8 { - let key = Key::from(format!("key{}", i)); - let value = AnyValue::Int(i as i64); - collection.push(KeyValuePair(key, value)); - } - }) - }); -} - -fn growable_array_iteration_benchmark(c: &mut Criterion) { - c.bench_function("GrowableArray Iteration", |b| { - let mut collection = GrowableArray::::new(); - for i in 0..8 { - let key = Key::from(format!("key{}", i)); - let value = AnyValue::Int(i as i64); - collection.push(KeyValuePair(key, value)); - } - b.iter(|| { - for item in &collection { - criterion::black_box(item); - } - }) - }); -} - -fn growable_array_get_benchmark(c: &mut Criterion) { - c.bench_function("GrowableArray Get Loop", |b| { - let mut collection = GrowableArray::::new(); - for i in 0..8 { - let key = Key::from(format!("key{}", i)); - let value = AnyValue::Int(i as i64); - collection.push(KeyValuePair(key, value)); - } - b.iter(|| { - for i in 0..collection.len() { - criterion::black_box(collection.get(i)); - } - }) - }); -} - -fn vec_iteration_benchmark(c: &mut Criterion) { - c.bench_function("Vec Iteration", |b| { - let mut collection = Vec::with_capacity(10); - for i in 0..8 { - let key = Key::from(format!("key{}", i)); - let value = AnyValue::Int(i as i64); - collection.push(KeyValuePair(key, value)); - } - b.iter(|| { - for item in &collection { - criterion::black_box(item); - } - }) - }); -} - -criterion_group!( - benches, - growable_array_insertion_benchmark, - vec_insertion_benchmark, - growable_array_iteration_benchmark, - growable_array_get_benchmark, - vec_iteration_benchmark -); -criterion_main!(benches); -*/ diff --git a/opentelemetry-sdk/benches/log.rs b/opentelemetry-sdk/benches/log.rs index dea4aaec30..820c640f3e 100644 --- a/opentelemetry-sdk/benches/log.rs +++ b/opentelemetry-sdk/benches/log.rs @@ -80,20 +80,6 @@ fn log_benchmark_group(c: &mut Criterion, name: &str, f: F) { } fn criterion_benchmark(c: &mut Criterion) { - let mut crit = Criterion::default() - .sample_size(100) // Set sample size - .measurement_time(std::time::Duration::new(20, 0)) // Set measurement time to 10 seconds - .warm_up_time(std::time::Duration::new(5, 0)); // Set warm-up time - /*log_benchmark_group(c, "simple-log", |logger| { - let mut log_record = logger.create_log_record(); - log_record.set_body("simple log".into()); - logger.emit(log_record); - });*/ - log_benchmark_group(&mut crit, "custom-test", |logger| { - let mut log_record = logger.create_log_record(); - logger.emit(log_record); - }); - log_benchmark_group(c, "simple-log", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index 3231f198f8..d8c59c4ca7 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -7,6 +7,21 @@ const DEFAULT_INITIAL_VEC_CAPACITY: usize = 5; #[derive(Debug, Clone, PartialEq)] /// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. +/// +/// `GrowableArray` uses an internal fixed-size array (`initial`) for storing elements until it reaches +/// `MAX_STACK_CAPACITY`. When this capacity is exceeded, additional elements are stored in a heap-allocated +/// vector (`additional`). This structure allows for efficient use of stack memory for small numbers of elements, +/// while still supporting dynamic growth. +/// +/// # Examples +/// +/// ``` +/// let mut ga = GrowableArray::::new(); +/// ga.push(1); +/// ga.push(2); +/// assert_eq!(ga.get(0), Some(&1)); +/// assert_eq!(ga.get(1), Some(&2)); +/// ``` pub(crate) struct GrowableArray< T: Default + Clone + PartialEq, const MAX_STACK_CAPACITY: usize = DEFAULT_MAX_STACK_CAPACITY, @@ -39,12 +54,15 @@ impl< > GrowableArray { /// Creates a new `GrowableArray` with the default initial capacity. + #[allow(dead_code)] pub(crate) fn new() -> Self { Self::default() } /// Pushes a value into the `GrowableArray`. - #[inline] + /// + /// If the internal array (`initial`) has reached its capacity (`MAX_STACK_CAPACITY`), the value is pushed + /// into the heap-allocated vector (`additional`). Otherwise, it is stored in the array. #[inline] pub(crate) fn push(&mut self, value: T) { if self.count < MAX_STACK_CAPACITY { self.initial[self.count] = value; @@ -59,6 +77,9 @@ impl< } /// Gets a reference to the value at the specified index. + /// + /// Returns `None` if the index is out of bounds. + #[allow(dead_code)] pub(crate) fn get(&self, index: usize) -> Option<&T> { if index < self.count { Some(&self.initial[index]) @@ -75,6 +96,22 @@ impl< } /// Returns an iterator over the elements in the `GrowableArray`. + /// + /// The iterator yields elements from the internal array (`initial`) first, followed by elements + /// from the vector (`additional`) if present. This allows for efficient iteration over both + /// stack-allocated and heap-allocated portions. + /// + /// # Examples + /// + /// ``` + /// let mut ga = GrowableArray::::new(); + /// ga.push(1); + /// ga.push(2); + /// let mut iter = ga.iter(); + /// assert_eq!(iter.next(), Some(&1)); + /// assert_eq!(iter.next(), Some(&2)); + /// assert_eq!(iter.next(), None); + /// ``` #[inline] pub(crate) fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { @@ -113,6 +150,21 @@ impl IntoIterator #[derive(Debug)] /// Iterator for consuming a `GrowableArray`. +/// +/// The iterator consumes the `GrowableArray`, yielding each element by value. +/// It first iterates over the elements in the internal array (`initial`), and then, +/// if present, over the elements in the vector (`additional`). +/// +/// # Examples +/// +/// ``` +/// let mut ga = GrowableArray::::new(); +/// ga.push(1); +/// ga.push(2); +/// let mut iter = ga.into_iter(); +/// assert_eq!(iter.next(), Some(1)); +/// assert_eq!(iter.next(), Some(2)); +/// assert_eq!(iter.next(), None); pub(crate) enum GrowableArrayIntoIter { /// stackonly @@ -168,6 +220,22 @@ impl<'a, T: Default + Clone + PartialEq + 'a, const INITIAL_CAPACITY: usize> Int #[derive(Debug)] /// Iterator for referencing elements in a `GrowableArray`. +/// +/// This iterator allows for iterating over elements in a `GrowableArray` by reference. +/// It first yields references to the elements stored in the internal array (`initial`), +/// followed by references to the elements in the vector (`additional`) if present. +/// +/// # Examples +/// +/// ``` +/// let mut ga = GrowableArray::::new(); +/// ga.push(1); +/// ga.push(2); +/// let mut iter = ga.iter(); +/// assert_eq!(iter.next(), Some(&1)); +/// assert_eq!(iter.next(), Some(&2)); +/// assert_eq!(iter.next(), None); +/// ``` pub(crate) enum GrowableArrayIter<'a, T: Default, const INITIAL_CAPACITY: usize> { /// stackonly StackOnly { diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 2116c54769..456377784f 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -7,9 +7,8 @@ use opentelemetry::{ use std::{borrow::Cow, time::SystemTime}; // According to a Go-specific study mentioned on https://go.dev/blog/slog, -// up to 5 attributes is the most common case. We have chosen 8 as the default -// capacity for attributes to avoid reallocation in common scenarios. -const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 8; +// up to 5 attributes is the most common case. +const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 5; /// A vector of `Option<(Key, AnyValue)>` with default capacity. pub(crate) type AttributesGrowableArray = diff --git a/opentelemetry-sdk/src/testing/global_allocator.rs b/opentelemetry-sdk/src/testing/global_allocator.rs deleted file mode 100644 index a2607f651f..0000000000 --- a/opentelemetry-sdk/src/testing/global_allocator.rs +++ /dev/null @@ -1,8 +0,0 @@ -// tests/global_allocator.rs -#[cfg(feature = "memory-profiling")] -mod global_allocator { - use jemallocator::Jemalloc; - - #[global_allocator] - static GLOBAL: Jemalloc = Jemalloc; -} diff --git a/opentelemetry-sdk/src/testing/mod.rs b/opentelemetry-sdk/src/testing/mod.rs index d6f8919057..50c79f5d49 100644 --- a/opentelemetry-sdk/src/testing/mod.rs +++ b/opentelemetry-sdk/src/testing/mod.rs @@ -8,5 +8,3 @@ pub mod metrics; #[cfg(all(feature = "testing", feature = "logs"))] pub mod logs; - -pub mod global_allocator; From 660a6d8abb73590cecbb056277d4f671f9cfeb1f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 29 Jul 2024 11:39:30 -0700 Subject: [PATCH 25/55] fix tests --- opentelemetry-sdk/src/logs/growable_array.rs | 41 +------------------- 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index d8c59c4ca7..d5dfd8e28a 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -13,15 +13,6 @@ const DEFAULT_INITIAL_VEC_CAPACITY: usize = 5; /// vector (`additional`). This structure allows for efficient use of stack memory for small numbers of elements, /// while still supporting dynamic growth. /// -/// # Examples -/// -/// ``` -/// let mut ga = GrowableArray::::new(); -/// ga.push(1); -/// ga.push(2); -/// assert_eq!(ga.get(0), Some(&1)); -/// assert_eq!(ga.get(1), Some(&2)); -/// ``` pub(crate) struct GrowableArray< T: Default + Clone + PartialEq, const MAX_STACK_CAPACITY: usize = DEFAULT_MAX_STACK_CAPACITY, @@ -101,17 +92,6 @@ impl< /// from the vector (`additional`) if present. This allows for efficient iteration over both /// stack-allocated and heap-allocated portions. /// - /// # Examples - /// - /// ``` - /// let mut ga = GrowableArray::::new(); - /// ga.push(1); - /// ga.push(2); - /// let mut iter = ga.iter(); - /// assert_eq!(iter.next(), Some(&1)); - /// assert_eq!(iter.next(), Some(&2)); - /// assert_eq!(iter.next(), None); - /// ``` #[inline] pub(crate) fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { @@ -155,16 +135,6 @@ impl IntoIterator /// It first iterates over the elements in the internal array (`initial`), and then, /// if present, over the elements in the vector (`additional`). /// -/// # Examples -/// -/// ``` -/// let mut ga = GrowableArray::::new(); -/// ga.push(1); -/// ga.push(2); -/// let mut iter = ga.into_iter(); -/// assert_eq!(iter.next(), Some(1)); -/// assert_eq!(iter.next(), Some(2)); -/// assert_eq!(iter.next(), None); pub(crate) enum GrowableArrayIntoIter { /// stackonly @@ -227,15 +197,6 @@ impl<'a, T: Default + Clone + PartialEq + 'a, const INITIAL_CAPACITY: usize> Int /// /// # Examples /// -/// ``` -/// let mut ga = GrowableArray::::new(); -/// ga.push(1); -/// ga.push(2); -/// let mut iter = ga.iter(); -/// assert_eq!(iter.next(), Some(&1)); -/// assert_eq!(iter.next(), Some(&2)); -/// assert_eq!(iter.next(), None); -/// ``` pub(crate) enum GrowableArrayIter<'a, T: Default, const INITIAL_CAPACITY: usize> { /// stackonly StackOnly { @@ -269,7 +230,7 @@ impl<'a, T: Default + Clone, const INITIAL_CAPACITY: usize> Iterator #[cfg(test)] mod tests { - use super::*; + use crate::logs::growable_array::GrowableArray; use opentelemetry::logs::AnyValue; use opentelemetry::Key; From 8e0bfaafdfd47533d9909a079c57ad393b3a53ca Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 29 Jul 2024 14:05:56 -0700 Subject: [PATCH 26/55] Update opentelemetry-sdk/src/logs/growable_array.rs Co-authored-by: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> --- opentelemetry-sdk/src/logs/growable_array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index d5dfd8e28a..484c326d77 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -1,6 +1,6 @@ use std::array::IntoIter; -/// The default max capacity for the stack portation of `GrowableArray`. +/// The default max capacity for the stack portion of `GrowableArray`. const DEFAULT_MAX_STACK_CAPACITY: usize = 10; /// The default initial capacity for the vector portion of `GrowableArray`. const DEFAULT_INITIAL_VEC_CAPACITY: usize = 5; From 9d44e260481793f64237282658dfb08b621f9252 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 29 Jul 2024 16:55:40 -0700 Subject: [PATCH 27/55] Update Cargo.toml --- opentelemetry-sdk/Cargo.toml | 3 --- 1 file changed, 3 deletions(-) diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index f8656106aa..7afafa2d3a 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -51,9 +51,6 @@ testing = ["opentelemetry/testing", "trace", "metrics", "logs", "rt-async-std", rt-tokio = ["tokio", "tokio-stream"] rt-tokio-current-thread = ["tokio", "tokio-stream"] rt-async-std = ["async-std"] -memory-profiling = [] - - [[bench]] name = "context" From eed39a1b3031eb672845ee3b897fcabc570ed5d4 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 29 Jul 2024 19:02:32 -0700 Subject: [PATCH 28/55] Update Cargo.toml --- opentelemetry-sdk/Cargo.toml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index 7afafa2d3a..5acf00fcc0 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -92,7 +92,3 @@ name = "log" harness = false required-features = ["logs"] -#[[bench]] -#name = "growable_array" -#harness = false -#required-features = ["logs"] From 9275a11a4660b3e7a1c961328d0023d7827d31b9 Mon Sep 17 00:00:00 2001 From: Lalit Date: Wed, 31 Jul 2024 08:28:59 -0700 Subject: [PATCH 29/55] review comments --- opentelemetry-sdk/src/logs/growable_array.rs | 252 +++++++++++-------- 1 file changed, 149 insertions(+), 103 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index 484c326d77..538d40166f 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -1,5 +1,3 @@ -use std::array::IntoIter; - /// The default max capacity for the stack portion of `GrowableArray`. const DEFAULT_MAX_STACK_CAPACITY: usize = 10; /// The default initial capacity for the vector portion of `GrowableArray`. @@ -93,16 +91,15 @@ impl< /// stack-allocated and heap-allocated portions. /// #[inline] - pub(crate) fn iter(&self) -> GrowableArrayIter<'_, T, MAX_STACK_CAPACITY> { + pub(crate) fn iter(&self) -> impl Iterator { if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { - GrowableArrayIter::StackOnly { - iter: self.initial.iter().take(self.count), - } + self.initial.iter().take(self.count).chain([].iter()) // Chaining with an empty array + // so that both `if` and `else` branch return the same type } else { - GrowableArrayIter::Mixed { - stack_iter: self.initial.iter().take(self.count), - heap_iter: self.additional.as_ref().unwrap().iter(), - } + self.initial + .iter() + .take(self.count) + .chain(self.additional.as_ref().unwrap().iter()) } } } @@ -115,122 +112,69 @@ impl IntoIterator type IntoIter = GrowableArrayIntoIter; fn into_iter(self) -> Self::IntoIter { - if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { - GrowableArrayIntoIter::StackOnly { - iter: self.initial.into_iter().take(self.count), - } - } else { - GrowableArrayIntoIter::Mixed { - stack_iter: self.initial.into_iter().take(self.count), - heap_iter: self.additional.unwrap().into_iter(), - } - } + GrowableArrayIntoIter::::new(self) } } -#[derive(Debug)] /// Iterator for consuming a `GrowableArray`. /// -/// The iterator consumes the `GrowableArray`, yielding each element by value. -/// It first iterates over the elements in the internal array (`initial`), and then, -/// if present, over the elements in the vector (`additional`). -/// -pub(crate) enum GrowableArrayIntoIter -{ - /// stackonly - StackOnly { - /// iter - iter: std::iter::Take>, - }, - /// hybrid - Mixed { - /// stack_iter - stack_iter: std::iter::Take>, - /// heap_iter - heap_iter: std::vec::IntoIter, - }, +#[derive(Debug)] +pub(crate) struct GrowableArrayIntoIter< + T: Default + Clone + PartialEq, + const INITIAL_CAPACITY: usize, +> { + iter: std::iter::Chain< + std::iter::Take>, + std::vec::IntoIter, + >, } -impl Iterator - for GrowableArrayIntoIter +impl + GrowableArrayIntoIter { - type Item = T; - - fn next(&mut self) -> Option { - match self { - GrowableArrayIntoIter::StackOnly { iter } => iter.next(), - GrowableArrayIntoIter::Mixed { - stack_iter, - heap_iter, - } => stack_iter.next().or_else(|| heap_iter.next()), + fn new(source: GrowableArray) -> Self { + Self { + iter: Self::get_iterator(source), } } -} - -// Implement `IntoIterator` for a reference to `GrowableArray` -impl<'a, T: Default + Clone + PartialEq + 'a, const INITIAL_CAPACITY: usize> IntoIterator - for &'a GrowableArray -{ - type Item = &'a T; - type IntoIter = GrowableArrayIter<'a, T, INITIAL_CAPACITY>; - fn into_iter(self) -> Self::IntoIter { - if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { - GrowableArrayIter::StackOnly { - iter: self.initial.iter().take(self.count), - } + fn get_iterator( + source: GrowableArray, + ) -> std::iter::Chain< + std::iter::Take>, + std::vec::IntoIter, + > { + if source.additional.is_none() || source.additional.as_ref().unwrap().is_empty() { + source + .initial + .into_iter() + .take(source.count) + .chain(Vec::::new().into_iter()) } else { - GrowableArrayIter::Mixed { - stack_iter: self.initial.iter().take(self.count), - heap_iter: self.additional.as_ref().unwrap().iter(), - } + source + .initial + .into_iter() + .take(source.count) + .chain(source.additional.unwrap().into_iter()) } } } -#[derive(Debug)] -/// Iterator for referencing elements in a `GrowableArray`. -/// -/// This iterator allows for iterating over elements in a `GrowableArray` by reference. -/// It first yields references to the elements stored in the internal array (`initial`), -/// followed by references to the elements in the vector (`additional`) if present. -/// -/// # Examples -/// -pub(crate) enum GrowableArrayIter<'a, T: Default, const INITIAL_CAPACITY: usize> { - /// stackonly - StackOnly { - /// iter - iter: std::iter::Take>, - }, - /// hybrid - Mixed { - /// stack_iter - stack_iter: std::iter::Take>, - /// heap_iter - heap_iter: std::slice::Iter<'a, T>, - }, -} - -impl<'a, T: Default + Clone, const INITIAL_CAPACITY: usize> Iterator - for GrowableArrayIter<'a, T, INITIAL_CAPACITY> +impl Iterator + for GrowableArrayIntoIter { - type Item = &'a T; + type Item = T; fn next(&mut self) -> Option { - match self { - GrowableArrayIter::StackOnly { iter } => iter.next(), - GrowableArrayIter::Mixed { - stack_iter, - heap_iter, - } => stack_iter.next().or_else(|| heap_iter.next()), - } + self.iter.next() } } #[cfg(test)] mod tests { - use crate::logs::growable_array::GrowableArray; + use crate::logs::growable_array::{ + GrowableArray, DEFAULT_INITIAL_VEC_CAPACITY, DEFAULT_MAX_STACK_CAPACITY, + }; use opentelemetry::logs::AnyValue; use opentelemetry::Key; @@ -283,7 +227,7 @@ mod tests { for i in 0..15 { collection.push(i); } - let iter = &collection; + let iter = collection.iter(); let mut count = 0; for value in iter { assert_eq!(*value, count); @@ -320,4 +264,106 @@ mod tests { assert_eq!(iter.next(), Some(KeyValuePair(key2, value2))); assert_eq!(iter.next(), None); } + + #[test] + fn test_empty_attributes() { + let collection = GrowableArray::::new(); + assert_eq!(collection.len(), 0); + assert_eq!(collection.get(0), None); + + let mut iter = collection.into_iter(); + assert_eq!(iter.next(), None); + } + + #[test] + fn test_less_than_max_stack_capacity() { + let mut collection = GrowableArray::::new(); + for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { + collection.push(i as i32); + } + assert_eq!(collection.len(), DEFAULT_MAX_STACK_CAPACITY - 1); + + for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { + assert_eq!(collection.get(i), Some(&(i as i32))); + } + assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY), None); + + let mut iter = collection.into_iter(); + for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { + assert_eq!(iter.next(), Some(i as i32)); + } + assert_eq!(iter.next(), None); + } + + #[test] + fn test_exactly_max_stack_capacity() { + let mut collection = GrowableArray::::new(); + for i in 0..DEFAULT_MAX_STACK_CAPACITY { + collection.push(i as i32); + } + assert_eq!(collection.len(), DEFAULT_MAX_STACK_CAPACITY); + + for i in 0..DEFAULT_MAX_STACK_CAPACITY { + assert_eq!(collection.get(i), Some(&(i as i32))); + } + assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY), None); + + let mut iter = collection.into_iter(); + for i in 0..DEFAULT_MAX_STACK_CAPACITY { + assert_eq!(iter.next(), Some(i as i32)); + } + assert_eq!(iter.next(), None); + } + + #[test] + fn test_exceeds_stack_but_not_initial_vec_capacity() { + let mut collection = GrowableArray::::new(); + for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { + collection.push(i as i32); + } + assert_eq!( + collection.len(), + DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1 + ); + + for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { + assert_eq!(collection.get(i), Some(&(i as i32))); + } + assert_eq!( + collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY), + None + ); + + let mut iter = collection.into_iter(); + for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { + assert_eq!(iter.next(), Some(i as i32)); + } + assert_eq!(iter.next(), None); + } + + #[test] + fn test_exceeds_both_stack_and_initial_vec_capacities() { + let mut collection = GrowableArray::::new(); + for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5) { + collection.push(i as i32); + } + assert_eq!( + collection.len(), + DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5 + ); + + for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5) { + assert_eq!(collection.get(i), Some(&(i as i32))); + } + assert_eq!( + collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 6), + None + ); + + let mut iter = collection.into_iter(); + for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5) { + assert_eq!(iter.next(), Some(i as i32)); + } + assert_eq!(iter.next(), None); + } } From 0f6b699e35e89025d32a41ba3e7c7609c0ad66e6 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 31 Jul 2024 10:05:50 -0700 Subject: [PATCH 30/55] lint issues --- opentelemetry-appender-log/src/lib.rs | 17 ++++++++--------- opentelemetry-sdk/src/logs/growable_array.rs | 4 ++-- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index 9341a79aa1..5181ef1f91 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -621,7 +621,7 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = Box::new(HashMap::new()); + let mut variant = Box::>::default(); variant.insert( Key::from(self.variant), AnyValue::ListAny(Box::new(self.value)), @@ -716,7 +716,7 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = Box::new(HashMap::new()); + let mut variant = Box::>::default(); variant.insert(Key::from(self.variant), AnyValue::Map(Box::new(self.value))); variant }))) @@ -1037,7 +1037,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::new(HashMap::new()); + let mut map = Box::>::default(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1050,7 +1050,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::new(HashMap::new()); + let mut map = Box::>::default(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1077,8 +1077,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::new(HashMap::new()); - + let mut map = Box::>::default(); map.insert(Key::from("Newtype"), AnyValue::Int(42)); map @@ -1088,12 +1087,12 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::new(HashMap::new()); + let mut map = Box::>::default(); map.insert( Key::from("Struct"), AnyValue::Map({ - let mut map = Box::new(HashMap::new()); + let mut map = Box::>::default(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1110,7 +1109,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::new(HashMap::new()); + let mut map = Box::>::default(); map.insert( Key::from("Tuple"), diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index 538d40166f..53688b433f 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -149,13 +149,13 @@ impl .initial .into_iter() .take(source.count) - .chain(Vec::::new().into_iter()) + .chain(Vec::::new()) } else { source .initial .into_iter() .take(source.count) - .chain(source.additional.unwrap().into_iter()) + .chain(source.additional.unwrap()) } } } From 1a2ec1f84f72494d2b2dc8d56a68ffa5b5b1d024 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 31 Jul 2024 11:49:22 -0700 Subject: [PATCH 31/55] comments --- opentelemetry-sdk/src/logs/growable_array.rs | 31 ++++++++++---------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index 53688b433f..7f90177545 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -178,15 +178,7 @@ mod tests { use opentelemetry::logs::AnyValue; use opentelemetry::Key; - /// A struct to hold a key-value pair and implement `Default`. - #[derive(Clone, Debug, PartialEq)] - struct KeyValuePair(Key, AnyValue); - - impl Default for KeyValuePair { - fn default() -> Self { - KeyValuePair(Key::from_static_str(""), AnyValue::String("".into())) - } - } + type KeyValuePair = Option<(Key, AnyValue)>; #[test] fn test_push_and_get() { @@ -245,23 +237,27 @@ mod tests { let key2 = Key::from("key2"); let value2 = AnyValue::Int(42); - collection.push(KeyValuePair(key1.clone(), value1.clone())); - collection.push(KeyValuePair(key2.clone(), value2.clone())); + collection.push(Some((key1.clone(), value1.clone()))); + collection.push(Some((key2.clone(), value2.clone()))); assert_eq!( - collection.get(0).map(|kv| (&kv.0, &kv.1)), + collection + .get(0) + .and_then(|kv| kv.as_ref().map(|kv| (&kv.0, &kv.1))), Some((&key1, &value1)) ); assert_eq!( - collection.get(1).map(|kv| (&kv.0, &kv.1)), + collection + .get(1) + .and_then(|kv| kv.as_ref().map(|kv| (&kv.0, &kv.1))), Some((&key2, &value2)) ); assert_eq!(collection.len(), 2); // Test iterating over the key-value pairs let mut iter = collection.into_iter(); - assert_eq!(iter.next(), Some(KeyValuePair(key1, value1))); - assert_eq!(iter.next(), Some(KeyValuePair(key2, value2))); + assert_eq!(iter.next(), Some(Some((key1, value1)))); + assert_eq!(iter.next(), Some(Some((key2, value2)))); assert_eq!(iter.next(), None); } @@ -286,6 +282,7 @@ mod tests { for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { assert_eq!(collection.get(i), Some(&(i as i32))); } + assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY - 1), None); assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY), None); let mut iter = collection.into_iter(); @@ -329,6 +326,10 @@ mod tests { for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { assert_eq!(collection.get(i), Some(&(i as i32))); } + assert_eq!( + collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1), + None + ); assert_eq!( collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY), None From adc48ca28e2fcc492462101602ad102e03c8ba52 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Wed, 31 Jul 2024 12:21:40 -0700 Subject: [PATCH 32/55] Update opentelemetry-sdk/src/logs/growable_array.rs Co-authored-by: Utkarsh Umesan Pillai <66651184+utpilla@users.noreply.github.com> --- opentelemetry-sdk/src/logs/growable_array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index 7f90177545..5b9537e6ee 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -357,7 +357,7 @@ mod tests { assert_eq!(collection.get(i), Some(&(i as i32))); } assert_eq!( - collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 6), + collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5), None ); From 0a4715a83ca9a2a31b4aa8f2dc410a74342864e4 Mon Sep 17 00:00:00 2001 From: Lalit Date: Wed, 31 Jul 2024 23:49:46 -0700 Subject: [PATCH 33/55] revert back box --- opentelemetry-appender-log/src/lib.rs | 51 +++++++++-------------- opentelemetry-proto/src/transform/logs.rs | 2 +- opentelemetry-sdk/Cargo.toml | 1 - opentelemetry-sdk/benches/log.rs | 34 ++++++--------- opentelemetry-stdout/src/common.rs | 2 +- opentelemetry/src/logs/record.rs | 12 +++--- 6 files changed, 41 insertions(+), 61 deletions(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index 5181ef1f91..f5d8d3b361 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -429,7 +429,7 @@ mod any_value { } fn serialize_bytes(self, v: &[u8]) -> Result { - Ok(Some(AnyValue::Bytes(Box::new(v.to_owned())))) + Ok(Some(AnyValue::Bytes(v.to_owned()))) } fn serialize_none(self) -> Result { @@ -557,7 +557,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::ListAny(Box::new(self.value)))) + Ok(Some(AnyValue::ListAny(self.value))) } } @@ -578,7 +578,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::ListAny(Box::new(self.value)))) + Ok(Some(AnyValue::ListAny(self.value))) } } @@ -599,7 +599,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::ListAny(Box::new(self.value)))) + Ok(Some(AnyValue::ListAny(self.value))) } } @@ -621,11 +621,8 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = Box::>::default(); - variant.insert( - Key::from(self.variant), - AnyValue::ListAny(Box::new(self.value)), - ); + let mut variant = HashMap::default(); + variant.insert(Key::from(self.variant), AnyValue::ListAny(self.value)); variant }))) } @@ -667,7 +664,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::Map(Box::new(self.value)))) + Ok(Some(AnyValue::Map(self.value))) } } @@ -691,7 +688,7 @@ mod any_value { } fn end(self) -> Result { - Ok(Some(AnyValue::Map(Box::new(self.value)))) + Ok(Some(AnyValue::Map(self.value))) } } @@ -716,8 +713,8 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = Box::>::default(); - variant.insert(Key::from(self.variant), AnyValue::Map(Box::new(self.value))); + let mut variant = HashMap::default(); + variant.insert(Key::from(self.variant), AnyValue::Map(self.value)); variant }))) } @@ -1027,17 +1024,13 @@ mod tests { assert_eq!(AnyValue::Int(42), get("some_value").unwrap()); assert_eq!( - AnyValue::ListAny(Box::new(vec![ - AnyValue::Int(1), - AnyValue::Int(1), - AnyValue::Int(1) - ])), + AnyValue::ListAny(vec![AnyValue::Int(1), AnyValue::Int(1), AnyValue::Int(1)]), get("slice_value").unwrap() ); assert_eq!( AnyValue::Map({ - let mut map = Box::>::default(); + let mut map = HashMap::default(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1050,7 +1043,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::>::default(); + let mut map = HashMap::default(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1062,11 +1055,7 @@ mod tests { ); assert_eq!( - AnyValue::ListAny(Box::new(vec![ - AnyValue::Int(1), - AnyValue::Int(1), - AnyValue::Int(1) - ])), + AnyValue::ListAny(vec![AnyValue::Int(1), AnyValue::Int(1), AnyValue::Int(1)]), get("tuple_value").unwrap() ); @@ -1077,7 +1066,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::>::default(); + let mut map = HashMap::default(); map.insert(Key::from("Newtype"), AnyValue::Int(42)); map @@ -1087,12 +1076,12 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::>::default(); + let mut map = HashMap::default(); map.insert( Key::from("Struct"), AnyValue::Map({ - let mut map = Box::>::default(); + let mut map = HashMap::default(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1109,15 +1098,15 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = Box::>::default(); + let mut map = HashMap::default(); map.insert( Key::from("Tuple"), - AnyValue::ListAny(Box::new(vec![ + AnyValue::ListAny(vec![ AnyValue::Int(1), AnyValue::Int(1), AnyValue::Int(1), - ])), + ]), ); map diff --git a/opentelemetry-proto/src/transform/logs.rs b/opentelemetry-proto/src/transform/logs.rs index 880c3c0689..773f8e3913 100644 --- a/opentelemetry-proto/src/transform/logs.rs +++ b/opentelemetry-proto/src/transform/logs.rs @@ -49,7 +49,7 @@ pub mod tonic { }) .collect(), }), - LogsAnyValue::Bytes(v) => Value::BytesValue(*v), + LogsAnyValue::Bytes(v) => Value::BytesValue(v), } } } diff --git a/opentelemetry-sdk/Cargo.toml b/opentelemetry-sdk/Cargo.toml index 5acf00fcc0..7429e7ce0c 100644 --- a/opentelemetry-sdk/Cargo.toml +++ b/opentelemetry-sdk/Cargo.toml @@ -91,4 +91,3 @@ required-features = ["metrics"] name = "log" harness = false required-features = ["logs"] - diff --git a/opentelemetry-sdk/benches/log.rs b/opentelemetry-sdk/benches/log.rs index 820c640f3e..c98ee2d1af 100644 --- a/opentelemetry-sdk/benches/log.rs +++ b/opentelemetry-sdk/benches/log.rs @@ -114,7 +114,7 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let bytes = AnyValue::Bytes(Box::new(vec![25u8, 30u8, 40u8])); + let bytes = AnyValue::Bytes(vec![25u8, 30u8, 40u8]); log_benchmark_group(c, "simple-log-with-bytes", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -122,14 +122,14 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let bytes = AnyValue::Bytes(Box::new(vec![ + let bytes = AnyValue::Bytes(vec![ 25u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, 30u8, 40u8, - ])); + ]); log_benchmark_group(c, "simple-log-with-a-lot-of-bytes", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -137,11 +137,7 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let vec_any_values = AnyValue::ListAny(Box::new(vec![ - AnyValue::Int(25), - "test".into(), - true.into(), - ])); + let vec_any_values = AnyValue::ListAny(vec![AnyValue::Int(25), "test".into(), true.into()]); log_benchmark_group(c, "simple-log-with-vec-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -149,17 +145,13 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let vec_any_values = AnyValue::ListAny(Box::new(vec![ - AnyValue::Int(25), - "test".into(), - true.into(), - ])); - let vec_any_values = AnyValue::ListAny(Box::new(vec![ + let vec_any_values = AnyValue::ListAny(vec![AnyValue::Int(25), "test".into(), true.into()]); + let vec_any_values = AnyValue::ListAny(vec![ AnyValue::Int(25), "test".into(), true.into(), vec_any_values, - ])); + ]); log_benchmark_group(c, "simple-log-with-inner-vec-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -167,11 +159,11 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let map_any_values = AnyValue::Map(Box::new(HashMap::from([ + let map_any_values = AnyValue::Map(HashMap::from([ ("testint".into(), 2.into()), ("testdouble".into(), 2.2.into()), ("teststring".into(), "test".into()), - ]))); + ])); log_benchmark_group(c, "simple-log-with-map-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); @@ -179,17 +171,17 @@ fn criterion_benchmark(c: &mut Criterion) { logger.emit(log_record); }); - let map_any_values = AnyValue::Map(Box::new(HashMap::from([ + let map_any_values = AnyValue::Map(HashMap::from([ ("testint".into(), 2.into()), ("testdouble".into(), 2.2.into()), ("teststring".into(), "test".into()), - ]))); - let map_any_values = AnyValue::Map(Box::new(HashMap::from([ + ])); + let map_any_values = AnyValue::Map(HashMap::from([ ("testint".into(), 2.into()), ("testdouble".into(), 2.2.into()), ("teststring".into(), "test".into()), ("testmap".into(), map_any_values), - ]))); + ])); log_benchmark_group(c, "simple-log-with-inner-map-any-value", |logger| { let mut log_record = logger.create_log_record(); log_record.set_body("simple log".into()); diff --git a/opentelemetry-stdout/src/common.rs b/opentelemetry-stdout/src/common.rs index 236accea7c..bbf7f86251 100644 --- a/opentelemetry-stdout/src/common.rs +++ b/opentelemetry-stdout/src/common.rs @@ -168,7 +168,7 @@ impl From for Value { }) .collect(), ), - opentelemetry::logs::AnyValue::Bytes(b) => Value::BytesValue(*b), + opentelemetry::logs::AnyValue::Bytes(b) => Value::BytesValue(b), } } } diff --git a/opentelemetry/src/logs/record.rs b/opentelemetry/src/logs/record.rs index a77f25c072..be00a7ab5c 100644 --- a/opentelemetry/src/logs/record.rs +++ b/opentelemetry/src/logs/record.rs @@ -59,11 +59,11 @@ pub enum AnyValue { /// A boolean value Boolean(bool), /// A byte array - Bytes(Box>), + Bytes(Vec), /// An array of `Any` values - ListAny(Box>), + ListAny(Vec), /// A map of string keys to `Any` values, arbitrarily nested. - Map(Box>), + Map(HashMap), } macro_rules! impl_trivial_from { @@ -98,7 +98,7 @@ impl_trivial_from!(bool, AnyValue::Boolean); impl> FromIterator for AnyValue { /// Creates an [`AnyValue::ListAny`] value from a sequence of `Into` values. fn from_iter>(iter: I) -> Self { - AnyValue::ListAny(Box::new(iter.into_iter().map(Into::into).collect())) + AnyValue::ListAny(iter.into_iter().map(Into::into).collect()) } } @@ -106,9 +106,9 @@ impl, V: Into> FromIterator<(K, V)> for AnyValue { /// Creates an [`AnyValue::Map`] value from a sequence of key-value pairs /// that can be converted into a `Key` and `AnyValue` respectively. fn from_iter>(iter: I) -> Self { - AnyValue::Map(Box::new(HashMap::from_iter( + AnyValue::Map(HashMap::from_iter( iter.into_iter().map(|(k, v)| (k.into(), v.into())), - ))) + )) } } From 6136678c2ca8603d1e45c56ce2c4c687b7839c21 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 1 Aug 2024 07:23:05 +0000 Subject: [PATCH 34/55] change var names --- opentelemetry-sdk/src/logs/growable_array.rs | 140 +++++++++---------- 1 file changed, 70 insertions(+), 70 deletions(-) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/logs/growable_array.rs index 5b9537e6ee..0b32e15895 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/logs/growable_array.rs @@ -1,36 +1,36 @@ /// The default max capacity for the stack portion of `GrowableArray`. -const DEFAULT_MAX_STACK_CAPACITY: usize = 10; +const DEFAULT_MAX_INLINE_CAPACITY: usize = 10; /// The default initial capacity for the vector portion of `GrowableArray`. -const DEFAULT_INITIAL_VEC_CAPACITY: usize = 5; +const DEFAULT_INITIAL_OVERFLOW_CAPACITY: usize = 5; #[derive(Debug, Clone, PartialEq)] /// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. /// /// `GrowableArray` uses an internal fixed-size array (`initial`) for storing elements until it reaches -/// `MAX_STACK_CAPACITY`. When this capacity is exceeded, additional elements are stored in a heap-allocated +/// `MAX_INLINE_CAPACITY`. When this capacity is exceeded, additional elements are stored in a heap-allocated /// vector (`additional`). This structure allows for efficient use of stack memory for small numbers of elements, /// while still supporting dynamic growth. /// pub(crate) struct GrowableArray< T: Default + Clone + PartialEq, - const MAX_STACK_CAPACITY: usize = DEFAULT_MAX_STACK_CAPACITY, - const INITIAL_VEC_CAPACITY: usize = DEFAULT_INITIAL_VEC_CAPACITY, + const MAX_INLINE_CAPACITY: usize = DEFAULT_MAX_INLINE_CAPACITY, + const INITIAL_OVERFLOW_CAPACITY: usize = DEFAULT_INITIAL_OVERFLOW_CAPACITY, > { - initial: [T; MAX_STACK_CAPACITY], - additional: Option>, + inline: [T; MAX_INLINE_CAPACITY], + overflow: Option>, count: usize, } impl< T: Default + Clone + PartialEq, - const MAX_STACK_CAPACITY: usize, - const INITIAL_VEC_CAPACITY: usize, - > Default for GrowableArray + const MAX_INLINE_CAPACITY: usize, + const INITIAL_OVERFLOW_CAPACITY: usize, + > Default for GrowableArray { fn default() -> Self { Self { - initial: [(); MAX_STACK_CAPACITY].map(|_| T::default()), - additional: None, + inline: [(); MAX_INLINE_CAPACITY].map(|_| T::default()), + overflow: None, count: 0, } } @@ -38,9 +38,9 @@ impl< impl< T: Default + Clone + PartialEq, - const MAX_STACK_CAPACITY: usize, - const INITIAL_VEC_CAPACITY: usize, - > GrowableArray + const MAX_INLINE_CAPACITY: usize, + const INITIAL_OVERFLOW_CAPACITY: usize, + > GrowableArray { /// Creates a new `GrowableArray` with the default initial capacity. #[allow(dead_code)] @@ -50,18 +50,18 @@ impl< /// Pushes a value into the `GrowableArray`. /// - /// If the internal array (`initial`) has reached its capacity (`MAX_STACK_CAPACITY`), the value is pushed - /// into the heap-allocated vector (`additional`). Otherwise, it is stored in the array. #[inline] + /// If the internal array (`inline`) has reached its capacity (`MAX_INLINE_CAPACITY`), the value is pushed + /// into the heap-allocated vector (`overflow`). Otherwise, it is stored in the array. #[inline] pub(crate) fn push(&mut self, value: T) { - if self.count < MAX_STACK_CAPACITY { - self.initial[self.count] = value; + if self.count < MAX_INLINE_CAPACITY { + self.inline[self.count] = value; self.count += 1; } else { - if self.additional.is_none() { + if self.overflow.is_none() { // Initialize the vector with a specified capacity - self.additional = Some(Vec::with_capacity(INITIAL_VEC_CAPACITY)); + self.overflow = Some(Vec::with_capacity(INITIAL_OVERFLOW_CAPACITY)); } - self.additional.as_mut().unwrap().push(value); + self.overflow.as_mut().unwrap().push(value); } } @@ -71,9 +71,9 @@ impl< #[allow(dead_code)] pub(crate) fn get(&self, index: usize) -> Option<&T> { if index < self.count { - Some(&self.initial[index]) - } else if let Some(ref additional) = self.additional { - additional.get(index - MAX_STACK_CAPACITY) + Some(&self.inline[index]) + } else if let Some(ref overflow) = self.overflow { + overflow.get(index - MAX_INLINE_CAPACITY) } else { None } @@ -81,38 +81,38 @@ impl< /// Returns the number of elements in the `GrowableArray`. pub(crate) fn len(&self) -> usize { - self.count + self.additional.as_ref().map_or(0, Vec::len) + self.count + self.overflow.as_ref().map_or(0, Vec::len) } /// Returns an iterator over the elements in the `GrowableArray`. /// /// The iterator yields elements from the internal array (`initial`) first, followed by elements - /// from the vector (`additional`) if present. This allows for efficient iteration over both + /// from the vector (`overflow`) if present. This allows for efficient iteration over both /// stack-allocated and heap-allocated portions. /// #[inline] pub(crate) fn iter(&self) -> impl Iterator { - if self.additional.is_none() || self.additional.as_ref().unwrap().is_empty() { - self.initial.iter().take(self.count).chain([].iter()) // Chaining with an empty array - // so that both `if` and `else` branch return the same type + if self.overflow.is_none() || self.overflow.as_ref().unwrap().is_empty() { + self.inline.iter().take(self.count).chain([].iter()) // Chaining with an empty array + // so that both `if` and `else` branch return the same type } else { - self.initial + self.inline .iter() .take(self.count) - .chain(self.additional.as_ref().unwrap().iter()) + .chain(self.overflow.as_ref().unwrap().iter()) } } } // Implement `IntoIterator` for `GrowableArray` -impl IntoIterator - for GrowableArray +impl IntoIterator + for GrowableArray { type Item = T; - type IntoIter = GrowableArrayIntoIter; + type IntoIter = GrowableArrayIntoIter; fn into_iter(self) -> Self::IntoIter { - GrowableArrayIntoIter::::new(self) + GrowableArrayIntoIter::::new(self) } } @@ -121,41 +121,41 @@ impl IntoIterator #[derive(Debug)] pub(crate) struct GrowableArrayIntoIter< T: Default + Clone + PartialEq, - const INITIAL_CAPACITY: usize, + const INLINE_CAPACITY: usize, > { iter: std::iter::Chain< - std::iter::Take>, + std::iter::Take>, std::vec::IntoIter, >, } -impl - GrowableArrayIntoIter +impl + GrowableArrayIntoIter { - fn new(source: GrowableArray) -> Self { + fn new(source: GrowableArray) -> Self { Self { iter: Self::get_iterator(source), } } fn get_iterator( - source: GrowableArray, + source: GrowableArray, ) -> std::iter::Chain< - std::iter::Take>, + std::iter::Take>, std::vec::IntoIter, > { - if source.additional.is_none() || source.additional.as_ref().unwrap().is_empty() { + if source.overflow.is_none() || source.overflow.as_ref().unwrap().is_empty() { source - .initial + .inline .into_iter() .take(source.count) .chain(Vec::::new()) } else { source - .initial + .inline .into_iter() .take(source.count) - .chain(source.additional.unwrap()) + .chain(source.overflow.unwrap()) } } } @@ -173,7 +173,7 @@ impl Iterator #[cfg(test)] mod tests { use crate::logs::growable_array::{ - GrowableArray, DEFAULT_INITIAL_VEC_CAPACITY, DEFAULT_MAX_STACK_CAPACITY, + GrowableArray, DEFAULT_INITIAL_OVERFLOW_CAPACITY, DEFAULT_MAX_INLINE_CAPACITY, }; use opentelemetry::logs::AnyValue; use opentelemetry::Key; @@ -274,19 +274,19 @@ mod tests { #[test] fn test_less_than_max_stack_capacity() { let mut collection = GrowableArray::::new(); - for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { + for i in 0..DEFAULT_MAX_INLINE_CAPACITY - 1 { collection.push(i as i32); } - assert_eq!(collection.len(), DEFAULT_MAX_STACK_CAPACITY - 1); + assert_eq!(collection.len(), DEFAULT_MAX_INLINE_CAPACITY - 1); - for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { + for i in 0..DEFAULT_MAX_INLINE_CAPACITY - 1 { assert_eq!(collection.get(i), Some(&(i as i32))); } - assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY - 1), None); - assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY), None); + assert_eq!(collection.get(DEFAULT_MAX_INLINE_CAPACITY - 1), None); + assert_eq!(collection.get(DEFAULT_MAX_INLINE_CAPACITY), None); let mut iter = collection.into_iter(); - for i in 0..DEFAULT_MAX_STACK_CAPACITY - 1 { + for i in 0..DEFAULT_MAX_INLINE_CAPACITY - 1 { assert_eq!(iter.next(), Some(i as i32)); } assert_eq!(iter.next(), None); @@ -295,18 +295,18 @@ mod tests { #[test] fn test_exactly_max_stack_capacity() { let mut collection = GrowableArray::::new(); - for i in 0..DEFAULT_MAX_STACK_CAPACITY { + for i in 0..DEFAULT_MAX_INLINE_CAPACITY { collection.push(i as i32); } - assert_eq!(collection.len(), DEFAULT_MAX_STACK_CAPACITY); + assert_eq!(collection.len(), DEFAULT_MAX_INLINE_CAPACITY); - for i in 0..DEFAULT_MAX_STACK_CAPACITY { + for i in 0..DEFAULT_MAX_INLINE_CAPACITY { assert_eq!(collection.get(i), Some(&(i as i32))); } - assert_eq!(collection.get(DEFAULT_MAX_STACK_CAPACITY), None); + assert_eq!(collection.get(DEFAULT_MAX_INLINE_CAPACITY), None); let mut iter = collection.into_iter(); - for i in 0..DEFAULT_MAX_STACK_CAPACITY { + for i in 0..DEFAULT_MAX_INLINE_CAPACITY { assert_eq!(iter.next(), Some(i as i32)); } assert_eq!(iter.next(), None); @@ -315,28 +315,28 @@ mod tests { #[test] fn test_exceeds_stack_but_not_initial_vec_capacity() { let mut collection = GrowableArray::::new(); - for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { + for i in 0..(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY - 1) { collection.push(i as i32); } assert_eq!( collection.len(), - DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1 + DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY - 1 ); - for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { + for i in 0..(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY - 1) { assert_eq!(collection.get(i), Some(&(i as i32))); } assert_eq!( - collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1), + collection.get(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY - 1), None ); assert_eq!( - collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY), + collection.get(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY), None ); let mut iter = collection.into_iter(); - for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY - 1) { + for i in 0..(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY - 1) { assert_eq!(iter.next(), Some(i as i32)); } assert_eq!(iter.next(), None); @@ -345,24 +345,24 @@ mod tests { #[test] fn test_exceeds_both_stack_and_initial_vec_capacities() { let mut collection = GrowableArray::::new(); - for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5) { + for i in 0..(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY + 5) { collection.push(i as i32); } assert_eq!( collection.len(), - DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5 + DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY + 5 ); - for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5) { + for i in 0..(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY + 5) { assert_eq!(collection.get(i), Some(&(i as i32))); } assert_eq!( - collection.get(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5), + collection.get(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY + 5), None ); let mut iter = collection.into_iter(); - for i in 0..(DEFAULT_MAX_STACK_CAPACITY + DEFAULT_INITIAL_VEC_CAPACITY + 5) { + for i in 0..(DEFAULT_MAX_INLINE_CAPACITY + DEFAULT_INITIAL_OVERFLOW_CAPACITY + 5) { assert_eq!(iter.next(), Some(i as i32)); } assert_eq!(iter.next(), None); From cb0d05d9448cd78733b567f1f96d3930b1a38fd3 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 2 Aug 2024 01:01:52 +0000 Subject: [PATCH 35/55] move growable array outside logs --- opentelemetry-sdk/src/{logs => }/growable_array.rs | 2 +- opentelemetry-sdk/src/lib.rs | 1 + opentelemetry-sdk/src/logs/mod.rs | 2 -- opentelemetry-sdk/src/logs/record.rs | 2 +- 4 files changed, 3 insertions(+), 4 deletions(-) rename opentelemetry-sdk/src/{logs => }/growable_array.rs (99%) diff --git a/opentelemetry-sdk/src/logs/growable_array.rs b/opentelemetry-sdk/src/growable_array.rs similarity index 99% rename from opentelemetry-sdk/src/logs/growable_array.rs rename to opentelemetry-sdk/src/growable_array.rs index 0b32e15895..eafb2522f2 100644 --- a/opentelemetry-sdk/src/logs/growable_array.rs +++ b/opentelemetry-sdk/src/growable_array.rs @@ -172,7 +172,7 @@ impl Iterator #[cfg(test)] mod tests { - use crate::logs::growable_array::{ + use crate::growable_array::{ GrowableArray, DEFAULT_INITIAL_OVERFLOW_CAPACITY, DEFAULT_MAX_INLINE_CAPACITY, }; use opentelemetry::logs::AnyValue; diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index 852f0b8327..5ce2be9474 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -121,6 +121,7 @@ #![cfg_attr(test, deny(warnings))] pub mod export; +pub(crate) mod growable_array; mod instrumentation; #[cfg(feature = "logs")] #[cfg_attr(docsrs, doc(cfg(feature = "logs")))] diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index b44d872b72..1dbd11096b 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -1,6 +1,4 @@ //! # OpenTelemetry Log SDK - -pub(crate) mod growable_array; mod log_emitter; mod log_processor; pub(crate) mod record; diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 456377784f..1eda281f33 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -1,4 +1,4 @@ -use crate::logs::growable_array::GrowableArray; +use crate::growable_array::GrowableArray; use opentelemetry::{ logs::{AnyValue, Severity}, trace::{SpanContext, SpanId, TraceFlags, TraceId}, From c9816f09fa6f060213b4332d19567be189823122 Mon Sep 17 00:00:00 2001 From: Lalit Date: Thu, 1 Aug 2024 22:33:01 -0700 Subject: [PATCH 36/55] review comments --- opentelemetry-sdk/src/growable_array.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/growable_array.rs b/opentelemetry-sdk/src/growable_array.rs index eafb2522f2..c2be984497 100644 --- a/opentelemetry-sdk/src/growable_array.rs +++ b/opentelemetry-sdk/src/growable_array.rs @@ -51,7 +51,9 @@ impl< /// Pushes a value into the `GrowableArray`. /// /// If the internal array (`inline`) has reached its capacity (`MAX_INLINE_CAPACITY`), the value is pushed - /// into the heap-allocated vector (`overflow`). Otherwise, it is stored in the array. #[inline] + /// into the heap-allocated vector (`overflow`). Otherwise, it is stored in the array. + #[allow(dead_code)] + #[inline] pub(crate) fn push(&mut self, value: T) { if self.count < MAX_INLINE_CAPACITY { self.inline[self.count] = value; @@ -80,6 +82,8 @@ impl< } /// Returns the number of elements in the `GrowableArray`. + #[inline] + #[allow(dead_code)] pub(crate) fn len(&self) -> usize { self.count + self.overflow.as_ref().map_or(0, Vec::len) } From 2a149f95613a349d1199722bbfffd703723bdb5f Mon Sep 17 00:00:00 2001 From: Lalit Date: Thu, 1 Aug 2024 22:42:03 -0700 Subject: [PATCH 37/55] use get_or_insert_with --- opentelemetry-sdk/src/growable_array.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/opentelemetry-sdk/src/growable_array.rs b/opentelemetry-sdk/src/growable_array.rs index c2be984497..717347e33c 100644 --- a/opentelemetry-sdk/src/growable_array.rs +++ b/opentelemetry-sdk/src/growable_array.rs @@ -59,11 +59,9 @@ impl< self.inline[self.count] = value; self.count += 1; } else { - if self.overflow.is_none() { - // Initialize the vector with a specified capacity - self.overflow = Some(Vec::with_capacity(INITIAL_OVERFLOW_CAPACITY)); - } - self.overflow.as_mut().unwrap().push(value); + self.overflow + .get_or_insert_with(|| Vec::with_capacity(INITIAL_OVERFLOW_CAPACITY)) + .push(value); } } From 3caf8b4fddff26f5df2deb1a5eafafd5755bcf4c Mon Sep 17 00:00:00 2001 From: Lalit Date: Thu, 1 Aug 2024 22:51:17 -0700 Subject: [PATCH 38/55] clioppy warning --- opentelemetry-sdk/src/growable_array.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/growable_array.rs b/opentelemetry-sdk/src/growable_array.rs index 717347e33c..94103bae7e 100644 --- a/opentelemetry-sdk/src/growable_array.rs +++ b/opentelemetry-sdk/src/growable_array.rs @@ -69,6 +69,7 @@ impl< /// /// Returns `None` if the index is out of bounds. #[allow(dead_code)] + #[inline] pub(crate) fn get(&self, index: usize) -> Option<&T> { if index < self.count { Some(&self.inline[index]) @@ -80,8 +81,8 @@ impl< } /// Returns the number of elements in the `GrowableArray`. - #[inline] #[allow(dead_code)] + #[inline] pub(crate) fn len(&self) -> usize { self.count + self.overflow.as_ref().map_or(0, Vec::len) } @@ -92,6 +93,7 @@ impl< /// from the vector (`overflow`) if present. This allows for efficient iteration over both /// stack-allocated and heap-allocated portions. /// + #[allow(dead_code)] #[inline] pub(crate) fn iter(&self) -> impl Iterator { if self.overflow.is_none() || self.overflow.as_ref().unwrap().is_empty() { From 0a876bfa3e9de0a0248260538ea227e4bb74360d Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 5 Aug 2024 11:39:03 -0700 Subject: [PATCH 39/55] remove growablearray from test --- opentelemetry-sdk/src/logs/record.rs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 1eda281f33..17a7dede2b 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -215,11 +215,9 @@ mod tests { let attributes = vec![(Key::new("key"), AnyValue::String("value".into()))]; log_record.add_attributes(attributes.clone()); - let mut expected_attributes = AttributesGrowableArray::new(); for (key, value) in attributes { - expected_attributes.push(Some((key, value))); + assert!(log_record.attributes_contains(&key, &value)); } - assert_eq!(log_record.attributes, expected_attributes); } #[test] @@ -227,12 +225,9 @@ mod tests { let mut log_record = LogRecord::default(); log_record.add_attribute("key", "value"); - let expected_attributes = { - let mut hybrid_vec = AttributesGrowableArray::new(); - hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); - hybrid_vec - }; - assert_eq!(log_record.attributes, expected_attributes); + let key = Key::new("key"); + let value = AnyValue::String("value".into()); + assert!(log_record.attributes_contains(&key, &value)); } #[test] From 6c468e0ee1809ed35fe9466e1b07a3b0893ea17f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 5 Aug 2024 20:38:04 -0700 Subject: [PATCH 40/55] Update lib.rs --- opentelemetry-appender-log/src/lib.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index f5d8d3b361..5a8d52f2fa 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -621,7 +621,7 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = HashMap::default(); + let mut variant = HashMap::new(); variant.insert(Key::from(self.variant), AnyValue::ListAny(self.value)); variant }))) @@ -713,7 +713,7 @@ mod any_value { fn end(self) -> Result { Ok(Some(AnyValue::Map({ - let mut variant = HashMap::default(); + let mut variant = HashMap::new(); variant.insert(Key::from(self.variant), AnyValue::Map(self.value)); variant }))) @@ -1030,7 +1030,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::default(); + let mut map = HashMap::new(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1043,7 +1043,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::default(); + let mut map = HashMap::new(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1066,7 +1066,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::default(); + let mut map = HashMap::new(); map.insert(Key::from("Newtype"), AnyValue::Int(42)); map @@ -1076,12 +1076,12 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::default(); + let mut map = HashMap::new(); map.insert( Key::from("Struct"), AnyValue::Map({ - let mut map = HashMap::default(); + let mut map = HashMap::new(); map.insert(Key::from("a"), AnyValue::Int(1)); map.insert(Key::from("b"), AnyValue::Int(1)); @@ -1098,7 +1098,7 @@ mod tests { assert_eq!( AnyValue::Map({ - let mut map = HashMap::default(); + let mut map = HashMap::new(); map.insert( Key::from("Tuple"), From 6f58225474bc00f3ee86d1890e49862acb7bdecc Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 5 Aug 2024 20:38:58 -0700 Subject: [PATCH 41/55] Update lib.rs --- opentelemetry-appender-log/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index 5a8d52f2fa..b858fea544 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -948,6 +948,7 @@ mod tests { } }) }; + assert_eq!( AnyValue::String(StringValue::from("a string")), get("str_value").unwrap() From b7ca124b79b73d271ad6692ea6aa53e3be3859e5 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 5 Aug 2024 20:41:50 -0700 Subject: [PATCH 42/55] Update lib.rs --- opentelemetry-appender-log/src/lib.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/opentelemetry-appender-log/src/lib.rs b/opentelemetry-appender-log/src/lib.rs index b858fea544..9a10a6aeb0 100644 --- a/opentelemetry-appender-log/src/lib.rs +++ b/opentelemetry-appender-log/src/lib.rs @@ -948,7 +948,7 @@ mod tests { } }) }; - + assert_eq!( AnyValue::String(StringValue::from("a string")), get("str_value").unwrap() @@ -1068,6 +1068,7 @@ mod tests { assert_eq!( AnyValue::Map({ let mut map = HashMap::new(); + map.insert(Key::from("Newtype"), AnyValue::Int(42)); map From 846ca89e4c08d98544f04761bb44772312999b6e Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Mon, 5 Aug 2024 20:42:40 -0700 Subject: [PATCH 43/55] Update Cargo.toml --- opentelemetry-appender-tracing/Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/opentelemetry-appender-tracing/Cargo.toml b/opentelemetry-appender-tracing/Cargo.toml index 35bce5c6e9..d0b237217c 100644 --- a/opentelemetry-appender-tracing/Cargo.toml +++ b/opentelemetry-appender-tracing/Cargo.toml @@ -33,6 +33,7 @@ pprof = { version = "0.13", features = ["flamegraph", "criterion"] } experimental_metadata_attributes = ["dep:tracing-log"] logs_level_enabled = ["opentelemetry/logs_level_enabled"] + [[bench]] name = "logs" harness = false From ee57967c2f1d22d3766fb3229a6e2eda768b75e0 Mon Sep 17 00:00:00 2001 From: Lalit Date: Mon, 5 Aug 2024 20:47:54 -0700 Subject: [PATCH 44/55] merge conflict --- opentelemetry-sdk/src/logs/record.rs | 29 ++++------------------------ 1 file changed, 4 insertions(+), 25 deletions(-) diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 0f0cecf822..c7ba045fdc 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -108,13 +108,15 @@ impl LogRecord { self.attributes.iter().filter_map(|opt| opt.as_ref()) } + #[allow(dead_code)] /// Returns the number of attributes in the `LogRecord`. - pub fn attributes_len(&self) -> usize { + pub(crate) fn attributes_len(&self) -> usize { self.attributes.len() } + #[allow(dead_code)] /// Checks if the `LogRecord` contains the specified attribute. - pub fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { + pub(crate) fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { self.attributes.iter().any(|opt| { if let Some((k, v)) = opt { k == key && v == value @@ -125,29 +127,6 @@ impl LogRecord { } } -impl LogRecord { - /// Provides an iterator over the attributes in the `LogRecord`. - pub fn attributes_iter(&self) -> impl Iterator { - self.attributes - .as_ref() - .map_or_else(|| [].iter(), |attrs| attrs.iter()) - } - - #[allow(dead_code)] - /// Returns the number of attributes in the `LogRecord`. - pub(crate) fn attributes_len(&self) -> usize { - self.attributes.as_ref().map_or(0, |attrs| attrs.len()) - } - - #[allow(dead_code)] - /// Returns true if the `LogRecord` contains the specified attribute. - pub(crate) fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { - self.attributes.as_ref().map_or(false, |attrs| { - attrs.iter().any(|(k, v)| k == key && v == value) - }) - } -} - /// TraceContext stores the trace context for logs that have an associated /// span. #[derive(Debug, Clone, PartialEq)] From 8911c39cfad17b26d72fac0a8ca4ce1bc22a13b4 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Tue, 6 Aug 2024 23:05:35 -0700 Subject: [PATCH 45/55] Update record.rs --- opentelemetry-sdk/src/logs/record.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index c7ba045fdc..623a368a53 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -117,13 +117,7 @@ impl LogRecord { #[allow(dead_code)] /// Checks if the `LogRecord` contains the specified attribute. pub(crate) fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { - self.attributes.iter().any(|opt| { - if let Some((k, v)) = opt { - k == key && v == value - } else { - false - } - }) + self.attributes.iter().flatten().any(|(k, v)| k == key && v == value) } } From bbe5689c894cf07d275b3c3967e341a7bee9cb88 Mon Sep 17 00:00:00 2001 From: Lalit Date: Tue, 6 Aug 2024 23:08:12 -0700 Subject: [PATCH 46/55] modify attributes_contain --- opentelemetry-sdk/src/logs/record.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 623a368a53..f6ebc25b54 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -117,7 +117,10 @@ impl LogRecord { #[allow(dead_code)] /// Checks if the `LogRecord` contains the specified attribute. pub(crate) fn attributes_contains(&self, key: &Key, value: &AnyValue) -> bool { - self.attributes.iter().flatten().any(|(k, v)| k == key && v == value) + self.attributes + .iter() + .flatten() + .any(|(k, v)| k == key && v == value) } } From b2561959816aa80de805984a325dae5fa9de42ee Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 8 Aug 2024 10:29:38 -0700 Subject: [PATCH 47/55] Update opentelemetry-sdk/src/growable_array.rs Co-authored-by: Cijo Thomas --- opentelemetry-sdk/src/growable_array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/growable_array.rs b/opentelemetry-sdk/src/growable_array.rs index 94103bae7e..fd3947c198 100644 --- a/opentelemetry-sdk/src/growable_array.rs +++ b/opentelemetry-sdk/src/growable_array.rs @@ -8,7 +8,7 @@ const DEFAULT_INITIAL_OVERFLOW_CAPACITY: usize = 5; /// /// `GrowableArray` uses an internal fixed-size array (`initial`) for storing elements until it reaches /// `MAX_INLINE_CAPACITY`. When this capacity is exceeded, additional elements are stored in a heap-allocated -/// vector (`additional`). This structure allows for efficient use of stack memory for small numbers of elements, +/// vector (`overflow`). This structure allows for efficient use of stack memory for small numbers of elements, /// while still supporting dynamic growth. /// pub(crate) struct GrowableArray< From 40a97ac32fe139c5a286a6bd94720be4afd8976a Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 8 Aug 2024 18:10:24 +0000 Subject: [PATCH 48/55] fix --- opentelemetry-sdk/src/logs/log_processor.rs | 49 +++++++-------------- 1 file changed, 15 insertions(+), 34 deletions(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index adf6deb25a..fb5ee42647 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -513,7 +513,6 @@ mod tests { BatchLogProcessor, OTEL_BLRP_EXPORT_TIMEOUT, OTEL_BLRP_MAX_EXPORT_BATCH_SIZE, OTEL_BLRP_MAX_QUEUE_SIZE, OTEL_BLRP_SCHEDULE_DELAY, }; - use crate::logs::record::AttributesGrowableArray; use crate::testing::logs::InMemoryLogsExporterBuilder; use crate::{ export::logs::{LogData, LogExporter}, @@ -529,9 +528,9 @@ mod tests { Resource, }; use async_trait::async_trait; - use opentelemetry::logs::AnyValue; #[cfg(feature = "logs_level_enabled")] use opentelemetry::logs::Severity; + use opentelemetry::logs::{AnyValue, LogRecord}; use opentelemetry::logs::{Logger, LoggerProvider as _}; use opentelemetry::Key; use opentelemetry::{logs::LogResult, KeyValue}; @@ -820,16 +819,11 @@ mod tests { impl LogProcessor for FirstProcessor { fn emit(&self, data: &mut LogData) { - // Ensure attributes is initialized if it is empty - if data.record.attributes.len() == 0 { - data.record.attributes = AttributesGrowableArray::new(); - } - // Add attribute - data.record.attributes.push(Some(( + data.record.add_attribute( Key::from_static_str("processed_by"), AnyValue::String("FirstProcessor".into()), - ))); + ); // Update body data.record.body = Some(AnyValue::String("Updated by FirstProcessor".into())); @@ -858,14 +852,10 @@ mod tests { impl LogProcessor for SecondProcessor { fn emit(&self, data: &mut LogData) { - assert!(data.record.attributes.iter().any(|attr| { - if let Some((key, value)) = attr { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) - } else { - false - } - })); + assert!(data.record.attributes_contains( + &Key::from_static_str("processed_by"), + &AnyValue::String("FirstProcessor".into()) + )); assert!( data.record.body.clone().unwrap() == AnyValue::String("Updated by FirstProcessor".into()) @@ -915,23 +905,14 @@ mod tests { let first_log = &first_processor_logs.lock().unwrap()[0]; let second_log = &second_processor_logs.lock().unwrap()[0]; - assert!(first_log.record.attributes.iter().any(|attr| { - if let Some((key, value)) = attr { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) - } else { - false - } - })); - - assert!(second_log.record.attributes.iter().any(|attr| { - if let Some((key, value)) = attr { - key.as_str() == "processed_by" - && *value == AnyValue::String("FirstProcessor".into()) - } else { - false - } - })); + assert!(first_log.record.attributes_contains( + &Key::from_static_str("processed_by"), + &AnyValue::String("FirstProcessor".into()) + )); + assert!(second_log.record.attributes_contains( + &Key::from_static_str("processed_by"), + &AnyValue::String("FirstProcessor".into()) + )); assert!( first_log.record.body.clone().unwrap() From 085f001c1efcb358bff6389fc722ceccf627470f Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 8 Aug 2024 11:27:43 -0700 Subject: [PATCH 49/55] Update opentelemetry-sdk/src/growable_array.rs Co-authored-by: Cijo Thomas --- opentelemetry-sdk/src/growable_array.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/growable_array.rs b/opentelemetry-sdk/src/growable_array.rs index fd3947c198..f174bedea2 100644 --- a/opentelemetry-sdk/src/growable_array.rs +++ b/opentelemetry-sdk/src/growable_array.rs @@ -6,7 +6,7 @@ const DEFAULT_INITIAL_OVERFLOW_CAPACITY: usize = 5; #[derive(Debug, Clone, PartialEq)] /// A hybrid vector that starts with a fixed-size array and grows dynamically with a vector. /// -/// `GrowableArray` uses an internal fixed-size array (`initial`) for storing elements until it reaches +/// `GrowableArray` uses an internal fixed-size array (`inline`) for storing elements until it reaches /// `MAX_INLINE_CAPACITY`. When this capacity is exceeded, additional elements are stored in a heap-allocated /// vector (`overflow`). This structure allows for efficient use of stack memory for small numbers of elements, /// while still supporting dynamic growth. From cb200a5ba57ee9feb1983f85dc866826b668ebe8 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 8 Aug 2024 18:43:56 +0000 Subject: [PATCH 50/55] fix attributes --- opentelemetry-sdk/src/logs/mod.rs | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/opentelemetry-sdk/src/logs/mod.rs b/opentelemetry-sdk/src/logs/mod.rs index 1dbd11096b..23063d7d06 100644 --- a/opentelemetry-sdk/src/logs/mod.rs +++ b/opentelemetry-sdk/src/logs/mod.rs @@ -79,22 +79,12 @@ mod tests { .expect("Atleast one log is expected to be present."); assert_eq!(log.instrumentation.name, "test-logger"); assert_eq!(log.record.severity_number, Some(Severity::Error)); - let attributes: Vec<(Key, AnyValue)> = log - .record - .attributes - .iter() - .filter_map(|kv| kv.as_ref().map(|(k, v)| (k.clone(), v.clone()))) - .collect(); - assert_eq!(attributes.len(), 10); + assert_eq!(log.record.attributes_len(), 10); for i in 1..=10 { - assert!(log.record.attributes.iter().any(|kv| { - if let Some((key, value)) = kv { - key.as_str() == format!("key{}", i) - && *value == AnyValue::String(format!("value{}", i).into()) - } else { - false - } - })); + assert!(log.record.attributes_contains( + &Key::new(format!("key{}", i)), + &AnyValue::String(format!("value{}", i).into()) + )); } // validate Resource From f3b63fb8692040ba3cc23e58ca4f7d068379b5b2 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Thu, 8 Aug 2024 18:55:36 +0000 Subject: [PATCH 51/55] fix --- opentelemetry-sdk/src/logs/record.rs | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index f6ebc25b54..4699623e50 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -11,7 +11,7 @@ use std::{borrow::Cow, time::SystemTime}; const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 5; /// A vector of `Option<(Key, AnyValue)>` with default capacity. -pub(crate) type AttributesGrowableArray = +pub(crate) type LogRecordAttributes = GrowableArray, PREALLOCATED_ATTRIBUTE_CAPACITY>; #[derive(Debug, Default, Clone, PartialEq)] @@ -43,7 +43,7 @@ pub struct LogRecord { pub body: Option, /// Additional attributes associated with this record - pub(crate) attributes: AttributesGrowableArray, + pub(crate) attributes: LogRecordAttributes, } impl opentelemetry::logs::LogRecord for LogRecord { @@ -250,7 +250,7 @@ mod tests { #[test] fn compare_log_record() { - let log_record = LogRecord { + let mut log_record = LogRecord { event_name: Some(Cow::Borrowed("test_event")), target: Some(Cow::Borrowed("foo::bar")), timestamp: Some(SystemTime::now()), @@ -258,17 +258,14 @@ mod tests { severity_text: Some(Cow::Borrowed("ERROR")), severity_number: Some(Severity::Error), body: Some(AnyValue::String("Test body".into())), - attributes: { - let mut hybrid_vec = AttributesGrowableArray::new(); - hybrid_vec.push(Some((Key::new("key"), AnyValue::String("value".into())))); - hybrid_vec - }, + attributes: LogRecordAttributes::new(), trace_context: Some(TraceContext { trace_id: TraceId::from_u128(1), span_id: SpanId::from_u64(1), trace_flags: Some(TraceFlags::default()), }), }; + log_record.add_attribute(Key::new("key"), AnyValue::String("value".into())); let log_record_cloned = log_record.clone(); From e95d5503e4a0f5bf8a99adde791124451de27ce9 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Sun, 18 Aug 2024 18:36:19 -0700 Subject: [PATCH 52/55] merge conflict --- opentelemetry-sdk/src/logs/record.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index 489abd9dc8..a3368fcf29 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -247,7 +247,7 @@ mod tests { #[test] fn compare_log_record() { - let log_record = LogRecord { + let mut log_record = LogRecord { event_name: Some("test_event"), target: Some(Cow::Borrowed("foo::bar")), timestamp: Some(SystemTime::now()), From 93b477540b7d5e302e79231a099e234aa3f30021 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 23 Aug 2024 01:04:50 -0700 Subject: [PATCH 53/55] fix lint --- opentelemetry-sdk/src/logs/log_processor.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/opentelemetry-sdk/src/logs/log_processor.rs b/opentelemetry-sdk/src/logs/log_processor.rs index 49d3e59ffc..ce1032ec62 100644 --- a/opentelemetry-sdk/src/logs/log_processor.rs +++ b/opentelemetry-sdk/src/logs/log_processor.rs @@ -531,7 +531,8 @@ mod tests { Resource, }; use async_trait::async_trait; - use opentelemetry::logs::{AnyValue, LogRecord}; + use opentelemetry::logs::AnyValue; + use opentelemetry::logs::LogRecord as _; use opentelemetry::logs::{Logger, LoggerProvider as _}; use opentelemetry::InstrumentationLibrary; use opentelemetry::Key; @@ -822,7 +823,7 @@ mod tests { impl LogProcessor for FirstProcessor { fn emit(&self, record: &mut LogRecord, instrumentation: &InstrumentationLibrary) { // add attribute - data.record.add_attribute( + record.add_attribute( Key::from_static_str("processed_by"), AnyValue::String("FirstProcessor".into()), ); @@ -850,7 +851,7 @@ mod tests { } impl LogProcessor for SecondProcessor { - fn emit(&self, record: &mut LogRecord, _instrumentation: &InstrumentationLibrary) { + fn emit(&self, record: &mut LogRecord, instrumentation: &InstrumentationLibrary) { assert!(record.attributes_contains( &Key::from_static_str("processed_by"), &AnyValue::String("FirstProcessor".into()) From e697b0d8b30262e7807adefc399f8eba5f91ae08 Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 23 Aug 2024 01:59:38 -0700 Subject: [PATCH 54/55] update results --- opentelemetry-appender-tracing/benches/logs.rs | 2 +- opentelemetry-sdk/benches/log.rs | 2 +- stress/src/logs.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opentelemetry-appender-tracing/benches/logs.rs b/opentelemetry-appender-tracing/benches/logs.rs index 69d6cdabdd..93cbbb88e8 100644 --- a/opentelemetry-appender-tracing/benches/logs.rs +++ b/opentelemetry-appender-tracing/benches/logs.rs @@ -10,7 +10,7 @@ | noop_layer_disabled | 12 ns | | noop_layer_enabled | 25 ns | | ot_layer_disabled | 19 ns | - | ot_layer_enabled | 250 ns | + | ot_layer_enabled | 219 ns | */ use async_trait::async_trait; diff --git a/opentelemetry-sdk/benches/log.rs b/opentelemetry-sdk/benches/log.rs index 6c2ea330bf..0cfcf3de47 100644 --- a/opentelemetry-sdk/benches/log.rs +++ b/opentelemetry-sdk/benches/log.rs @@ -12,7 +12,7 @@ RAM: 64.0 GB |--------------------------------|-------------| | Logger_Creation | 30 ns | | LoggerProvider_Creation | 909 ns | -| Logging_Comparable_To_Appender | 135 ns | +| Logging_Comparable_To_Appender | 97 ns | */ use std::collections::HashMap; diff --git a/stress/src/logs.rs b/stress/src/logs.rs index ea813b7138..7744708db9 100644 --- a/stress/src/logs.rs +++ b/stress/src/logs.rs @@ -6,7 +6,7 @@ ~31 M/sec Hardware: AMD EPYC 7763 64-Core Processor - 2.44 GHz, 16vCPUs, - ~38 M /sec + ~44 M /sec */ use opentelemetry::InstrumentationLibrary; From e516abebc90edff369112d25cb63d48f1fe983ab Mon Sep 17 00:00:00 2001 From: Lalit Kumar Bhasin Date: Fri, 23 Aug 2024 08:48:09 -0700 Subject: [PATCH 55/55] comment --- opentelemetry-appender-tracing/benches/logs.rs | 2 +- opentelemetry-sdk/src/logs/record.rs | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/opentelemetry-appender-tracing/benches/logs.rs b/opentelemetry-appender-tracing/benches/logs.rs index 93cbbb88e8..1252e73e79 100644 --- a/opentelemetry-appender-tracing/benches/logs.rs +++ b/opentelemetry-appender-tracing/benches/logs.rs @@ -10,7 +10,7 @@ | noop_layer_disabled | 12 ns | | noop_layer_enabled | 25 ns | | ot_layer_disabled | 19 ns | - | ot_layer_enabled | 219 ns | + | ot_layer_enabled | 203 ns | */ use async_trait::async_trait; diff --git a/opentelemetry-sdk/src/logs/record.rs b/opentelemetry-sdk/src/logs/record.rs index a3368fcf29..78713598d8 100644 --- a/opentelemetry-sdk/src/logs/record.rs +++ b/opentelemetry-sdk/src/logs/record.rs @@ -10,7 +10,11 @@ use std::{borrow::Cow, time::SystemTime}; // up to 5 attributes is the most common case. const PREALLOCATED_ATTRIBUTE_CAPACITY: usize = 5; -/// A vector of `Option<(Key, AnyValue)>` with default capacity. +/// Represents a collection of log record attributes with a predefined capacity. +/// +/// This type uses `GrowableArray` to store key-value pairs of log attributes, where each attribute is an `Option<(Key, AnyValue)>`. +/// The initial attributes are allocated in a fixed-size array of capacity `PREALLOCATED_ATTRIBUTE_CAPACITY`. +/// If more attributes are added beyond this capacity, additional storage is handled by dynamically growing a vector. pub(crate) type LogRecordAttributes = GrowableArray, PREALLOCATED_ATTRIBUTE_CAPACITY>;