From 6f42c3a8a2642eee1c94622546b162a4ab280592 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Thu, 30 Nov 2023 09:58:39 -0500 Subject: [PATCH 01/31] Move attribute set to root crate --- .idea/vcs.xml | 7 + .idea/workspace.xml | 357 ++++++++++++++++++ opentelemetry-sdk/src/attributes/mod.rs | 1 - opentelemetry-sdk/src/attributes/set.rs | 178 +-------- opentelemetry-sdk/src/metrics/data/mod.rs | 3 +- opentelemetry-sdk/src/metrics/instrument.rs | 2 +- .../src/metrics/internal/aggregate.rs | 3 +- .../metrics/internal/exponential_histogram.rs | 3 +- .../src/metrics/internal/histogram.rs | 4 +- .../src/metrics/internal/last_value.rs | 4 +- opentelemetry-sdk/src/metrics/internal/sum.rs | 3 +- opentelemetry-stdout/src/common.rs | 4 +- opentelemetry-stdout/src/logs/transform.rs | 2 +- opentelemetry/Cargo.toml | 1 + opentelemetry/src/attributes/mod.rs | 3 + opentelemetry/src/attributes/set.rs | 169 +++++++++ opentelemetry/src/lib.rs | 2 + 17 files changed, 557 insertions(+), 189 deletions(-) create mode 100644 .idea/vcs.xml create mode 100644 .idea/workspace.xml create mode 100644 opentelemetry/src/attributes/mod.rs create mode 100644 opentelemetry/src/attributes/set.rs diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000000..68f1366ee5 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000000..850efe0a8b --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,357 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + { + "associatedIndex": 1 +} + + + + + + + { + "keyToString": { + "ASKED_ADD_EXTERNAL_FILES": "true", + "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", + "RunOnceActivity.OpenProjectViewOnStart": "true", + "RunOnceActivity.ShowReadmeOnStart": "true", + "RunOnceActivity.cidr.known.project.marker": "true", + "WebServerToolWindowFactoryState": "false", + "cf.first.check.clang-format": "false", + "cidr.known.project.marker": "true", + "git-widget-placeholder": "premade__attribute__sets", + "last_opened_file_path": "/home/mshapiro/code/opentelemetry-rust", + "node.js.detected.package.eslint": "true", + "node.js.detected.package.tslint": "true", + "node.js.selected.package.eslint": "(autodetect)", + "node.js.selected.package.tslint": "(autodetect)", + "nodejs_package_manager_path": "npm", + "org.rust.cargo.project.model.PROJECT_DISCOVERY": "true", + "settings.editor.selected.configurable": "com.maddyhome.idea.vim.ui.VimEmulationConfigurable", + "vue.rearranger.settings.migration": "true" + } +} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 1699976529165 + + + + + + \ No newline at end of file diff --git a/opentelemetry-sdk/src/attributes/mod.rs b/opentelemetry-sdk/src/attributes/mod.rs index 1182e996fb..466aa2e241 100644 --- a/opentelemetry-sdk/src/attributes/mod.rs +++ b/opentelemetry-sdk/src/attributes/mod.rs @@ -1,3 +1,2 @@ mod set; -pub use set::AttributeSet; diff --git a/opentelemetry-sdk/src/attributes/set.rs b/opentelemetry-sdk/src/attributes/set.rs index ae5d5a4a73..48124fdd98 100644 --- a/opentelemetry-sdk/src/attributes/set.rs +++ b/opentelemetry-sdk/src/attributes/set.rs @@ -1,181 +1,13 @@ -use std::collections::hash_map::DefaultHasher; -use std::collections::HashSet; -use std::{ - cmp::Ordering, - hash::{Hash, Hasher}, -}; - -use opentelemetry::{Array, Key, KeyValue, Value}; -use ordered_float::OrderedFloat; - +use opentelemetry::attributes::AttributeSet; +use opentelemetry::KeyValue; use crate::Resource; -#[derive(Clone, Debug)] -struct HashKeyValue(KeyValue); - -impl Hash for HashKeyValue { - fn hash(&self, state: &mut H) { - self.0.key.hash(state); - match &self.0.value { - Value::F64(f) => OrderedFloat(*f).hash(state), - Value::Array(a) => match a { - Array::Bool(b) => b.hash(state), - Array::I64(i) => i.hash(state), - Array::F64(f) => f.iter().for_each(|f| OrderedFloat(*f).hash(state)), - Array::String(s) => s.hash(state), - }, - Value::Bool(b) => b.hash(state), - Value::I64(i) => i.hash(state), - Value::String(s) => s.hash(state), - }; - } -} - -impl PartialOrd for HashKeyValue { - fn partial_cmp(&self, other: &Self) -> Option { - Some(self.cmp(other)) - } -} - -impl Ord for HashKeyValue { - fn cmp(&self, other: &Self) -> Ordering { - match self.0.key.cmp(&other.0.key) { - Ordering::Equal => match type_order(&self.0.value).cmp(&type_order(&other.0.value)) { - Ordering::Equal => match (&self.0.value, &other.0.value) { - (Value::F64(f), Value::F64(of)) => OrderedFloat(*f).cmp(&OrderedFloat(*of)), - (Value::Array(Array::Bool(b)), Value::Array(Array::Bool(ob))) => b.cmp(ob), - (Value::Array(Array::I64(i)), Value::Array(Array::I64(oi))) => i.cmp(oi), - (Value::Array(Array::String(s)), Value::Array(Array::String(os))) => s.cmp(os), - (Value::Array(Array::F64(f)), Value::Array(Array::F64(of))) => { - match f.len().cmp(&of.len()) { - Ordering::Equal => f - .iter() - .map(|x| OrderedFloat(*x)) - .collect::>() - .cmp(&of.iter().map(|x| OrderedFloat(*x)).collect()), - other => other, - } - } - (Value::Bool(b), Value::Bool(ob)) => b.cmp(ob), - (Value::I64(i), Value::I64(oi)) => i.cmp(oi), - (Value::String(s), Value::String(os)) => s.cmp(os), - _ => Ordering::Equal, - }, - other => other, // 2nd order by value types - }, - other => other, // 1st order by key - } - } -} - -fn type_order(v: &Value) -> u8 { - match v { - Value::Bool(_) => 1, - Value::I64(_) => 2, - Value::F64(_) => 3, - Value::String(_) => 4, - Value::Array(a) => match a { - Array::Bool(_) => 5, - Array::I64(_) => 6, - Array::F64(_) => 7, - Array::String(_) => 8, - }, - } -} - -impl PartialEq for HashKeyValue { - fn eq(&self, other: &Self) -> bool { - self.0.key == other.0.key - && match (&self.0.value, &other.0.value) { - (Value::F64(f), Value::F64(of)) => OrderedFloat(*f).eq(&OrderedFloat(*of)), - (Value::Array(Array::F64(f)), Value::Array(Array::F64(of))) => { - f.len() == of.len() - && f.iter() - .zip(of.iter()) - .all(|(f, of)| OrderedFloat(*f).eq(&OrderedFloat(*of))) - } - (non_float, other_non_float) => non_float.eq(other_non_float), - } - } -} - -impl Eq for HashKeyValue {} - -/// A unique set of attributes that can be used as instrument identifiers. -/// -/// This must implement [Hash], [PartialEq], and [Eq] so it may be used as -/// HashMap keys and other de-duplication methods. -#[derive(Clone, Default, Debug, PartialEq, Eq)] -pub struct AttributeSet(Vec, u64); - -impl From<&[KeyValue]> for AttributeSet { - fn from(values: &[KeyValue]) -> Self { - let mut seen_keys = HashSet::with_capacity(values.len()); - let vec = values - .iter() - .rev() - .filter_map(|kv| { - if seen_keys.insert(kv.key.clone()) { - Some(HashKeyValue(kv.clone())) - } else { - None - } - }) - .collect::>(); - - AttributeSet::new(vec) - } -} - impl From<&Resource> for AttributeSet { fn from(values: &Resource) -> Self { - let vec = values - .iter() - .map(|(key, value)| HashKeyValue(KeyValue::new(key.clone(), value.clone()))) + let key_values = values.iter() + .map(|(key, value)| KeyValue::new(key.clone(), value.clone())) .collect::>(); - AttributeSet::new(vec) - } -} - -impl AttributeSet { - fn new(mut values: Vec) -> Self { - values.sort_unstable(); - let mut hasher = DefaultHasher::new(); - values.iter().fold(&mut hasher, |mut hasher, item| { - item.hash(&mut hasher); - hasher - }); - - AttributeSet(values, hasher.finish()) - } - - /// Returns the number of elements in the set. - pub fn len(&self) -> usize { - self.0.len() - } - - /// Returns `true` if the set contains no elements. - pub fn is_empty(&self) -> bool { - self.0.is_empty() - } - - /// Retains only the attributes specified by the predicate. - pub fn retain(&mut self, f: F) - where - F: Fn(&KeyValue) -> bool, - { - self.0.retain(|kv| f(&kv.0)) - } - - /// Iterate over key value pairs in the set - pub fn iter(&self) -> impl Iterator { - self.0.iter().map(|kv| (&kv.0.key, &kv.0.value)) - } -} - -impl Hash for AttributeSet { - fn hash(&self, state: &mut H) { - state.write_u64(self.1) + AttributeSet::from(key_values.as_slice()) } } diff --git a/opentelemetry-sdk/src/metrics/data/mod.rs b/opentelemetry-sdk/src/metrics/data/mod.rs index e827006c95..555391a999 100644 --- a/opentelemetry-sdk/src/metrics/data/mod.rs +++ b/opentelemetry-sdk/src/metrics/data/mod.rs @@ -4,7 +4,8 @@ use std::{any, borrow::Cow, fmt, time::SystemTime}; use opentelemetry::{metrics::Unit, KeyValue}; -use crate::{attributes::AttributeSet, instrumentation::Scope, Resource}; +use opentelemetry::attributes::AttributeSet; +use crate::{instrumentation::Scope, Resource}; pub use self::temporality::Temporality; diff --git a/opentelemetry-sdk/src/metrics/instrument.rs b/opentelemetry-sdk/src/metrics/instrument.rs index 7971d47d3c..4114574a85 100644 --- a/opentelemetry-sdk/src/metrics/instrument.rs +++ b/opentelemetry-sdk/src/metrics/instrument.rs @@ -1,6 +1,7 @@ use std::{any::Any, borrow::Cow, collections::HashSet, hash::Hash, marker, sync::Arc}; use opentelemetry::{ + attributes::AttributeSet, metrics::{ AsyncInstrument, MetricsError, Result, SyncCounter, SyncHistogram, SyncUpDownCounter, Unit, }, @@ -8,7 +9,6 @@ use opentelemetry::{ }; use crate::{ - attributes::AttributeSet, instrumentation::Scope, metrics::{aggregation::Aggregation, internal::Measure}, }; diff --git a/opentelemetry-sdk/src/metrics/internal/aggregate.rs b/opentelemetry-sdk/src/metrics/internal/aggregate.rs index ccd0f26f88..aae3ffbce7 100644 --- a/opentelemetry-sdk/src/metrics/internal/aggregate.rs +++ b/opentelemetry-sdk/src/metrics/internal/aggregate.rs @@ -1,11 +1,10 @@ use std::{marker, sync::Arc}; use once_cell::sync::Lazy; -use opentelemetry::KeyValue; +use opentelemetry::{KeyValue, attributes::AttributeSet}; use crate::{ metrics::data::{Aggregation, Gauge, Temporality}, - AttributeSet, }; use super::{ diff --git a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs index ec0b70d003..581f49dfb6 100644 --- a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs @@ -6,11 +6,10 @@ use std::{ }; use once_cell::sync::Lazy; -use opentelemetry::metrics::MetricsError; +use opentelemetry::{attributes::AttributeSet, metrics::MetricsError}; use crate::{ metrics::data::{self, Aggregation, Temporality}, - AttributeSet, }; use super::Number; diff --git a/opentelemetry-sdk/src/metrics/internal/histogram.rs b/opentelemetry-sdk/src/metrics/internal/histogram.rs index 535b9a8586..65e65e6e12 100644 --- a/opentelemetry-sdk/src/metrics/internal/histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/histogram.rs @@ -1,8 +1,8 @@ use std::{collections::HashMap, sync::Mutex, time::SystemTime}; use crate::metrics::data::{self, Aggregation, Temporality}; -use crate::{attributes::AttributeSet, metrics::data::HistogramDataPoint}; -use opentelemetry::{global, metrics::MetricsError}; +use crate::{metrics::data::HistogramDataPoint}; +use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; use super::{ aggregate::{is_under_cardinality_limit, STREAM_OVERFLOW_ATTRIBUTE_SET}, diff --git a/opentelemetry-sdk/src/metrics/internal/last_value.rs b/opentelemetry-sdk/src/metrics/internal/last_value.rs index 57f35fc166..d5b4415163 100644 --- a/opentelemetry-sdk/src/metrics/internal/last_value.rs +++ b/opentelemetry-sdk/src/metrics/internal/last_value.rs @@ -4,8 +4,8 @@ use std::{ time::SystemTime, }; -use crate::{attributes::AttributeSet, metrics::data::DataPoint}; -use opentelemetry::{global, metrics::MetricsError}; +use crate::{metrics::data::DataPoint}; +use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; use super::{ aggregate::{is_under_cardinality_limit, STREAM_OVERFLOW_ATTRIBUTE_SET}, diff --git a/opentelemetry-sdk/src/metrics/internal/sum.rs b/opentelemetry-sdk/src/metrics/internal/sum.rs index 3adcd24d23..0a035e79e8 100644 --- a/opentelemetry-sdk/src/metrics/internal/sum.rs +++ b/opentelemetry-sdk/src/metrics/internal/sum.rs @@ -4,9 +4,8 @@ use std::{ time::SystemTime, }; -use crate::attributes::AttributeSet; use crate::metrics::data::{self, Aggregation, DataPoint, Temporality}; -use opentelemetry::{global, metrics::MetricsError}; +use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; use super::{ aggregate::{is_under_cardinality_limit, STREAM_OVERFLOW_ATTRIBUTE_SET}, diff --git a/opentelemetry-stdout/src/common.rs b/opentelemetry-stdout/src/common.rs index 27b105e70b..b2e969a030 100644 --- a/opentelemetry-stdout/src/common.rs +++ b/opentelemetry-stdout/src/common.rs @@ -12,8 +12,8 @@ use serde::{Serialize, Serializer}; #[derive(Debug, Serialize, Clone, Hash, Eq, PartialEq)] pub(crate) struct AttributeSet(pub BTreeMap); -impl From<&opentelemetry_sdk::AttributeSet> for AttributeSet { - fn from(value: &opentelemetry_sdk::AttributeSet) -> Self { +impl From<&opentelemetry::attributes::AttributeSet> for AttributeSet { + fn from(value: &opentelemetry::attributes::AttributeSet) -> Self { AttributeSet( value .iter() diff --git a/opentelemetry-stdout/src/logs/transform.rs b/opentelemetry-stdout/src/logs/transform.rs index 9612cf1ff6..debb1b662a 100644 --- a/opentelemetry-stdout/src/logs/transform.rs +++ b/opentelemetry-stdout/src/logs/transform.rs @@ -4,7 +4,7 @@ use crate::common::{ as_human_readable, as_opt_human_readable, as_opt_unix_nano, as_unix_nano, KeyValue, Resource, Scope, Value, }; -use opentelemetry_sdk::AttributeSet; +use opentelemetry::attributes::AttributeSet; use serde::Serialize; /// Transformed logs data that can be serialized. diff --git a/opentelemetry/Cargo.toml b/opentelemetry/Cargo.toml index 957d2d6a49..ed79ee5423 100644 --- a/opentelemetry/Cargo.toml +++ b/opentelemetry/Cargo.toml @@ -24,6 +24,7 @@ rustdoc-args = ["--cfg", "docsrs"] futures-core = "0.3" futures-sink = "0.3" once_cell = "1.12.0" +ordered-float = "4.0" pin-project-lite = { version = "0.2", optional = true } thiserror = "1.0.7" urlencoding = "2.1.2" diff --git a/opentelemetry/src/attributes/mod.rs b/opentelemetry/src/attributes/mod.rs new file mode 100644 index 0000000000..1182e996fb --- /dev/null +++ b/opentelemetry/src/attributes/mod.rs @@ -0,0 +1,3 @@ +mod set; + +pub use set::AttributeSet; diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs new file mode 100644 index 0000000000..5548add54c --- /dev/null +++ b/opentelemetry/src/attributes/set.rs @@ -0,0 +1,169 @@ +use std::collections::hash_map::DefaultHasher; +use std::collections::HashSet; +use std::{ + cmp::Ordering, + hash::{Hash, Hasher}, +}; + +use crate::{Array, Key, KeyValue, Value}; +use ordered_float::OrderedFloat; + +#[derive(Clone, Debug)] +struct HashKeyValue(KeyValue); + +impl Hash for HashKeyValue { + fn hash(&self, state: &mut H) { + self.0.key.hash(state); + match &self.0.value { + Value::F64(f) => OrderedFloat(*f).hash(state), + Value::Array(a) => match a { + Array::Bool(b) => b.hash(state), + Array::I64(i) => i.hash(state), + Array::F64(f) => f.iter().for_each(|f| OrderedFloat(*f).hash(state)), + Array::String(s) => s.hash(state), + }, + Value::Bool(b) => b.hash(state), + Value::I64(i) => i.hash(state), + Value::String(s) => s.hash(state), + }; + } +} + +impl PartialOrd for HashKeyValue { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for HashKeyValue { + fn cmp(&self, other: &Self) -> Ordering { + match self.0.key.cmp(&other.0.key) { + Ordering::Equal => match type_order(&self.0.value).cmp(&type_order(&other.0.value)) { + Ordering::Equal => match (&self.0.value, &other.0.value) { + (Value::F64(f), Value::F64(of)) => OrderedFloat(*f).cmp(&OrderedFloat(*of)), + (Value::Array(Array::Bool(b)), Value::Array(Array::Bool(ob))) => b.cmp(ob), + (Value::Array(Array::I64(i)), Value::Array(Array::I64(oi))) => i.cmp(oi), + (Value::Array(Array::String(s)), Value::Array(Array::String(os))) => s.cmp(os), + (Value::Array(Array::F64(f)), Value::Array(Array::F64(of))) => { + match f.len().cmp(&of.len()) { + Ordering::Equal => f + .iter() + .map(|x| OrderedFloat(*x)) + .collect::>() + .cmp(&of.iter().map(|x| OrderedFloat(*x)).collect()), + other => other, + } + } + (Value::Bool(b), Value::Bool(ob)) => b.cmp(ob), + (Value::I64(i), Value::I64(oi)) => i.cmp(oi), + (Value::String(s), Value::String(os)) => s.cmp(os), + _ => Ordering::Equal, + }, + other => other, // 2nd order by value types + }, + other => other, // 1st order by key + } + } +} + +fn type_order(v: &Value) -> u8 { + match v { + Value::Bool(_) => 1, + Value::I64(_) => 2, + Value::F64(_) => 3, + Value::String(_) => 4, + Value::Array(a) => match a { + Array::Bool(_) => 5, + Array::I64(_) => 6, + Array::F64(_) => 7, + Array::String(_) => 8, + }, + } +} + +impl PartialEq for HashKeyValue { + fn eq(&self, other: &Self) -> bool { + self.0.key == other.0.key + && match (&self.0.value, &other.0.value) { + (Value::F64(f), Value::F64(of)) => OrderedFloat(*f).eq(&OrderedFloat(*of)), + (Value::Array(Array::F64(f)), Value::Array(Array::F64(of))) => { + f.len() == of.len() + && f.iter() + .zip(of.iter()) + .all(|(f, of)| OrderedFloat(*f).eq(&OrderedFloat(*of))) + } + (non_float, other_non_float) => non_float.eq(other_non_float), + } + } +} + +impl Eq for HashKeyValue {} + +/// A unique set of attributes that can be used as instrument identifiers. +/// +/// This must implement [Hash], [PartialEq], and [Eq] so it may be used as +/// HashMap keys and other de-duplication methods. +#[derive(Clone, Default, Debug, PartialEq, Eq)] +pub struct AttributeSet(Vec, u64); + +impl From<&[KeyValue]> for AttributeSet { + fn from(values: &[KeyValue]) -> Self { + let mut seen_keys = HashSet::with_capacity(values.len()); + let vec = values + .iter() + .rev() + .filter_map(|kv| { + if seen_keys.insert(kv.key.clone()) { + Some(HashKeyValue(kv.clone())) + } else { + None + } + }) + .collect::>(); + + AttributeSet::new(vec) + } +} + + +impl AttributeSet { + fn new(mut values: Vec) -> Self { + values.sort_unstable(); + let mut hasher = DefaultHasher::new(); + values.iter().fold(&mut hasher, |mut hasher, item| { + item.hash(&mut hasher); + hasher + }); + + AttributeSet(values, hasher.finish()) + } + + /// Returns the number of elements in the set. + pub fn len(&self) -> usize { + self.0.len() + } + + /// Returns `true` if the set contains no elements. + pub fn is_empty(&self) -> bool { + self.0.is_empty() + } + + /// Retains only the attributes specified by the predicate. + pub fn retain(&mut self, f: F) + where + F: Fn(&KeyValue) -> bool, + { + self.0.retain(|kv| f(&kv.0)) + } + + /// Iterate over key value pairs in the set + pub fn iter(&self) -> impl Iterator { + self.0.iter().map(|kv| (&kv.0.key, &kv.0.value)) + } +} + +impl Hash for AttributeSet { + fn hash(&self, state: &mut H) { + state.write_u64(self.1) + } +} diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index 9d2088f2ac..70396699ba 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -206,6 +206,8 @@ pub mod global; pub mod baggage; +pub mod attributes; + mod context; pub use context::{Context, ContextGuard}; From 92977cd7901ce6c5ec1999eb3802c1b4491194e8 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Thu, 30 Nov 2023 15:14:49 -0500 Subject: [PATCH 02/31] Attribute set passed in as argument --- examples/metrics-advanced/src/main.rs | 15 +- examples/metrics-basic/src/main.rs | 18 +- .../examples/basic-otlp-http/src/main.rs | 7 +- .../examples/basic-otlp/src/main.rs | 24 +- opentelemetry-prometheus/examples/hyper.rs | 7 +- opentelemetry-prometheus/src/lib.rs | 9 +- .../tests/integration_test.rs | 259 ++++++++++-------- opentelemetry-sdk/src/attributes/mod.rs | 1 - opentelemetry-sdk/src/attributes/set.rs | 5 +- opentelemetry-sdk/src/lib.rs | 9 +- opentelemetry-sdk/src/metrics/data/mod.rs | 2 +- opentelemetry-sdk/src/metrics/instrument.rs | 18 +- .../src/metrics/internal/aggregate.rs | 8 +- .../metrics/internal/exponential_histogram.rs | 4 +- .../src/metrics/internal/histogram.rs | 2 +- .../src/metrics/internal/last_value.rs | 2 +- opentelemetry-sdk/src/metrics/meter.rs | 8 +- opentelemetry-sdk/src/metrics/mod.rs | 27 +- .../src/testing/metrics/in_memory_exporter.rs | 4 +- opentelemetry-stdout/examples/basic.rs | 5 +- opentelemetry-stdout/src/trace/transform.rs | 2 +- opentelemetry/src/attributes/set.rs | 107 +++++--- opentelemetry/src/global/mod.rs | 10 +- opentelemetry/src/lib.rs | 7 +- .../src/metrics/instruments/counter.rs | 14 +- .../src/metrics/instruments/gauge.rs | 10 +- .../src/metrics/instruments/histogram.rs | 10 +- opentelemetry/src/metrics/instruments/mod.rs | 4 +- .../metrics/instruments/up_down_counter.rs | 14 +- opentelemetry/src/metrics/meter.rs | 133 ++------- opentelemetry/src/metrics/noop.rs | 9 +- stress/src/metrics.rs | 6 +- 32 files changed, 392 insertions(+), 368 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index 760ed1b7e1..d9cb9b812e 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -86,7 +86,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_ref(), + .as_slice() + .into(), ); // Example 2 - Drop unwanted attributes using view. @@ -104,7 +105,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_ref(), + .as_slice() + .into(), ); // Example 3 - Change Aggregation configuration using View. @@ -128,7 +130,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_ref(), + .as_slice() + .into(), ); histogram2.record( @@ -139,7 +142,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_ref(), + .as_slice() + .into(), ); histogram2.record( @@ -150,7 +154,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_ref(), + .as_slice() + .into(), ); // Metrics are exported by default every 30 seconds when using stdout exporter, diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index c3307d1f3a..03769901f9 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -38,7 +38,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_ref(), + .as_slice() + .into(), ); // Create a ObservableCounter instrument and register a callback that reports the measurement. @@ -56,7 +57,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_ref(), + .as_slice() + .into(), ) })?; @@ -70,7 +72,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_ref(), + .as_slice() + .into(), ); // Create a Observable UpDownCounter instrument and register a callback that reports the measurement. @@ -88,7 +91,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_ref(), + .as_slice() + .into(), ) })?; @@ -105,7 +109,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_ref(), + .as_slice() + .into(), ); // Note that there is no ObservableHistogram instrument. @@ -126,7 +131,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_ref(), + .as_slice() + .into(), ) })?; diff --git a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs index 0f320dcb8d..901fa9df9a 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs @@ -11,6 +11,7 @@ use opentelemetry_sdk::metrics as sdkmetrics; use opentelemetry_sdk::resource; use opentelemetry_sdk::trace as sdktrace; +use opentelemetry::attributes::AttributeSet; use std::error::Error; use tracing::info; use tracing_subscriber::prelude::*; @@ -62,13 +63,15 @@ fn init_metrics() -> metrics::Result { const LEMONS_KEY: Key = Key::from_static_str("ex.com/lemons"); const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another"); -static COMMON_ATTRIBUTES: Lazy<[KeyValue; 4]> = Lazy::new(|| { +static COMMON_ATTRIBUTES: Lazy = Lazy::new(|| { [ LEMONS_KEY.i64(10), KeyValue::new("A", "1"), KeyValue::new("B", "2"), KeyValue::new("C", "3"), ] + .as_slice() + .into() }); #[tokio::main] @@ -104,7 +107,7 @@ async fn main() -> Result<(), Box> { info!(target: "my-target", "hello from {}. My price is {}", "apple", 1.99); let histogram = meter.f64_histogram("ex.com.two").init(); - histogram.record(5.5, COMMON_ATTRIBUTES.as_ref()); + histogram.record(5.5, COMMON_ATTRIBUTES.clone()); global::shutdown_tracer_provider(); global::shutdown_logger_provider(); diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index 1bf5f7e421..9a471d52cd 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -1,5 +1,6 @@ use log::{info, Level}; use once_cell::sync::Lazy; +use opentelemetry::attributes::AttributeSet; use opentelemetry::global; use opentelemetry::global::{logger_provider, shutdown_logger_provider, shutdown_tracer_provider}; use opentelemetry::logs::LogError; @@ -72,13 +73,16 @@ fn init_logs() -> Result { const LEMONS_KEY: Key = Key::from_static_str("lemons"); const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another"); -static COMMON_ATTRIBUTES: Lazy<[KeyValue; 4]> = Lazy::new(|| { - [ - LEMONS_KEY.i64(10), - KeyValue::new("A", "1"), - KeyValue::new("B", "2"), - KeyValue::new("C", "3"), - ] +static COMMON_ATTRIBUTES: Lazy = Lazy::new(|| { + AttributeSet::from( + [ + LEMONS_KEY.i64(10), + KeyValue::new("A", "1"), + KeyValue::new("B", "2"), + KeyValue::new("C", "3"), + ] + .as_slice(), + ) }); #[tokio::main] @@ -109,11 +113,11 @@ async fn main() -> Result<(), Box> { .init(); meter.register_callback(&[gauge.as_any()], move |observer| { - observer.observe_f64(&gauge, 1.0, COMMON_ATTRIBUTES.as_ref()) + observer.observe_f64(&gauge, 1.0, COMMON_ATTRIBUTES.clone()) })?; let histogram = meter.f64_histogram("ex.com.two").init(); - histogram.record(5.5, COMMON_ATTRIBUTES.as_ref()); + histogram.record(5.5, COMMON_ATTRIBUTES.clone()); tracer.in_span("operation", |cx| { let span = cx.span(); @@ -131,7 +135,7 @@ async fn main() -> Result<(), Box> { span.add_event("Sub span event", vec![]); - histogram.record(1.3, &[]); + histogram.record(1.3, AttributeSet::default()); }); }); diff --git a/opentelemetry-prometheus/examples/hyper.rs b/opentelemetry-prometheus/examples/hyper.rs index 943ba617b6..446732223f 100644 --- a/opentelemetry-prometheus/examples/hyper.rs +++ b/opentelemetry-prometheus/examples/hyper.rs @@ -4,6 +4,7 @@ use hyper::{ Body, Method, Request, Response, Server, }; use once_cell::sync::Lazy; +use opentelemetry::attributes::AttributeSet; use opentelemetry::{ metrics::{Counter, Histogram, MeterProvider as _, Unit}, KeyValue, @@ -23,7 +24,7 @@ async fn serve_req( println!("Receiving request at path {}", req.uri()); let request_start = SystemTime::now(); - state.http_counter.add(1, HANDLER_ALL.as_ref()); + state.http_counter.add(1, HANDLER_ALL.as_ref().into()); let response = match (req.method(), req.uri().path()) { (&Method::GET, "/metrics") => { @@ -33,7 +34,7 @@ async fn serve_req( encoder.encode(&metric_families, &mut buffer).unwrap(); state .http_body_gauge - .record(buffer.len() as u64, HANDLER_ALL.as_ref()); + .record(buffer.len() as u64, HANDLER_ALL.as_ref().into()); Response::builder() .status(200) @@ -53,7 +54,7 @@ async fn serve_req( state.http_req_histogram.record( request_start.elapsed().map_or(0.0, |d| d.as_secs_f64()), - &[], + AttributeSet::default(), ); Ok(response) } diff --git a/opentelemetry-prometheus/src/lib.rs b/opentelemetry-prometheus/src/lib.rs index bb637f52b2..a3127b46b9 100644 --- a/opentelemetry-prometheus/src/lib.rs +++ b/opentelemetry-prometheus/src/lib.rs @@ -3,13 +3,14 @@ //! [Prometheus]: https://prometheus.io //! //! ``` -//! use opentelemetry::{metrics::MeterProvider, KeyValue}; +//! use opentelemetry::{attributes::AttributeSet, metrics::MeterProvider, KeyValue}; //! use opentelemetry_sdk::metrics::SdkMeterProvider; //! use prometheus::{Encoder, TextEncoder}; //! //! # fn main() -> Result<(), Box> { //! //! // create a new prometheus registry +//! use opentelemetry::attributes::AttributeSet; //! let registry = prometheus::Registry::new(); //! //! // configure OpenTelemetry to use this registry @@ -31,8 +32,10 @@ //! .with_description("Records values") //! .init(); //! -//! counter.add(100, &[KeyValue::new("key", "value")]); -//! histogram.record(100, &[KeyValue::new("key", "value")]); +//! let attributes = AttributeSet::from([KeyValue::new("key", "value")].as_slice()); +//! +//! counter.add(100, attributes.clone()); +//! histogram.record(100, attributes); //! //! // Encode data as text or protobuf //! let encoder = TextEncoder::new(); diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs index aff4c43a99..5f2465b851 100644 --- a/opentelemetry-prometheus/tests/integration_test.rs +++ b/opentelemetry-prometheus/tests/integration_test.rs @@ -2,6 +2,7 @@ use std::fs; use std::path::Path; use std::time::Duration; +use opentelemetry::attributes::AttributeSet; use opentelemetry::metrics::{Meter, MeterProvider as _, Unit}; use opentelemetry::Key; use opentelemetry::KeyValue; @@ -44,27 +45,32 @@ fn prometheus_exporter_integration() { name: "counter", expected_file: "counter.txt", record_metrics: Box::new(|meter| { - let attrs = vec![ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ]; + let attrs = AttributeSet::from( + [ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ] + .as_slice(), + ); + let counter = meter .f64_counter("foo") .with_description("a simple counter") .with_unit(Unit::new("ms")) .init(); - counter.add(5.0, &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); + counter.add(5.0, attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs.clone()); + let attrs2 = vec![ Key::new("A").string("D"), Key::new("C").string("B"), Key::new("E").bool(true), Key::new("F").i64(42), ]; - counter.add(5.0, &attrs2); + counter.add(5.0, attrs2.as_slice().into()); }), ..Default::default() }, @@ -73,27 +79,31 @@ fn prometheus_exporter_integration() { expected_file: "counter_disabled_suffix.txt", builder: ExporterBuilder::default().without_counter_suffixes(), record_metrics: Box::new(|meter| { - let attrs = vec![ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ]; + let attrs = AttributeSet::from( + [ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ] + .as_slice(), + ); + let counter = meter .f64_counter("foo") .with_description("a simple counter without a total suffix") .with_unit(Unit::new("ms")) .init(); - counter.add(5.0, &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); - let attrs2 = vec![ + counter.add(5.0, attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs.clone()); + let attrs2 = [ Key::new("A").string("D"), Key::new("C").string("B"), Key::new("E").bool(true), Key::new("F").i64(42), ]; - counter.add(5.0, &attrs2); + counter.add(5.0, attrs2.as_slice().into()); }), ..Default::default() }, @@ -101,14 +111,16 @@ fn prometheus_exporter_integration() { name: "gauge", expected_file: "gauge.txt", record_metrics: Box::new(|meter| { - let attrs = vec![Key::new("A").string("B"), Key::new("C").string("D")]; + let attrs = AttributeSet::from( + [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), + ); let gauge = meter .f64_up_down_counter("bar") .with_description("a fun little gauge") .with_unit(Unit::new("1")) .init(); - gauge.add(1.0, &attrs); - gauge.add(-0.25, &attrs); + gauge.add(1.0, attrs.clone()); + gauge.add(-0.25, attrs); }), ..Default::default() }, @@ -116,16 +128,18 @@ fn prometheus_exporter_integration() { name: "histogram", expected_file: "histogram.txt", record_metrics: Box::new(|meter| { - let attrs = vec![Key::new("A").string("B"), Key::new("C").string("D")]; + let attrs = AttributeSet::from( + [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), + ); let histogram = meter .f64_histogram("histogram_baz") .with_description("a very nice histogram") .with_unit(Unit::new("By")) .init(); - histogram.record(23.0, &attrs); - histogram.record(7.0, &attrs); - histogram.record(101.0, &attrs); - histogram.record(105.0, &attrs); + histogram.record(23.0, attrs.clone()); + histogram.record(7.0, attrs.clone()); + histogram.record(101.0, attrs.clone()); + histogram.record(105.0, attrs); }), ..Default::default() }, @@ -134,23 +148,26 @@ fn prometheus_exporter_integration() { expected_file: "sanitized_labels.txt", builder: ExporterBuilder::default().without_units(), record_metrics: Box::new(|meter| { - let attrs = vec![ - // exact match, value should be overwritten - Key::new("A.B").string("X"), - Key::new("A.B").string("Q"), - // unintended match due to sanitization, values should be concatenated - Key::new("C.D").string("Y"), - Key::new("C/D").string("Z"), - ]; + let attrs = AttributeSet::from( + [ + // exact match, value should be overwritten + Key::new("A.B").string("X"), + Key::new("A.B").string("Q"), + // unintended match due to sanitization, values should be concatenated + Key::new("C.D").string("Y"), + Key::new("C/D").string("Z"), + ] + .as_slice(), + ); let counter = meter .f64_counter("foo") .with_description("a sanitary counter") // This unit is not added to .with_unit(Unit::new("By")) .init(); - counter.add(5.0, &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); + counter.add(5.0, attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs); }), ..Default::default() }, @@ -158,33 +175,35 @@ fn prometheus_exporter_integration() { name: "invalid instruments are renamed", expected_file: "sanitized_names.txt", record_metrics: Box::new(|meter| { - let attrs = vec![Key::new("A").string("B"), Key::new("C").string("D")]; + let attrs = AttributeSet::from( + [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), + ); // Valid. let mut gauge = meter .f64_up_down_counter("bar") .with_description("a fun little gauge") .init(); - gauge.add(100., &attrs); - gauge.add(-25.0, &attrs); + gauge.add(100., attrs.clone()); + gauge.add(-25.0, attrs.clone()); // Invalid, will be renamed. gauge = meter .f64_up_down_counter("invalid.gauge.name") .with_description("a gauge with an invalid name") .init(); - gauge.add(100.0, &attrs); + gauge.add(100.0, attrs.clone()); let counter = meter .f64_counter("0invalid.counter.name") .with_description("a counter with an invalid name") .init(); - counter.add(100.0, &attrs); + counter.add(100.0, attrs.clone()); let histogram = meter .f64_histogram("invalid.hist.name") .with_description("a histogram with an invalid name") .init(); - histogram.record(23.0, &attrs); + histogram.record(23.0, attrs); }), ..Default::default() }, @@ -193,19 +212,22 @@ fn prometheus_exporter_integration() { empty_resource: true, expected_file: "empty_resource.txt", record_metrics: Box::new(|meter| { - let attrs = vec![ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ]; + let attrs = AttributeSet::from( + [ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ] + .as_slice(), + ); let counter = meter .f64_counter("foo") .with_description("a simple counter") .init(); - counter.add(5.0, &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); + counter.add(5.0, attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs.clone()); }), ..Default::default() }, @@ -214,19 +236,22 @@ fn prometheus_exporter_integration() { custom_resource_attrs: vec![Key::new("A").string("B"), Key::new("C").string("D")], expected_file: "custom_resource.txt", record_metrics: Box::new(|meter| { - let attrs = vec![ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ]; + let attrs = AttributeSet::from( + [ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ] + .as_slice(), + ); let counter = meter .f64_counter("foo") .with_description("a simple counter") .init(); - counter.add(5., &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); + counter.add(5., attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs); }), ..Default::default() }, @@ -235,19 +260,22 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().without_target_info(), expected_file: "without_target_info.txt", record_metrics: Box::new(|meter| { - let attrs = vec![ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ]; + let attrs = AttributeSet::from( + [ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ] + .as_slice(), + ); let counter = meter .f64_counter("foo") .with_description("a simple counter") .init(); - counter.add(5.0, &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); + counter.add(5.0, attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs); }), ..Default::default() }, @@ -256,14 +284,16 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().without_scope_info(), expected_file: "without_scope_info.txt", record_metrics: Box::new(|meter| { - let attrs = vec![Key::new("A").string("B"), Key::new("C").string("D")]; + let attrs = AttributeSet::from( + [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), + ); let gauge = meter .i64_up_down_counter("bar") .with_description("a fun little gauge") .with_unit(Unit::new("1")) .init(); - gauge.add(2, &attrs); - gauge.add(-1, &attrs); + gauge.add(2, attrs.clone()); + gauge.add(-1, attrs); }), ..Default::default() }, @@ -274,14 +304,16 @@ fn prometheus_exporter_integration() { .without_target_info(), expected_file: "without_scope_and_target_info.txt", record_metrics: Box::new(|meter| { - let attrs = vec![Key::new("A").string("B"), Key::new("C").string("D")]; + let attrs = AttributeSet::from( + [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), + ); let counter = meter .u64_counter("bar") .with_description("a fun little counter") .with_unit(Unit::new("By")) .init(); - counter.add(2, &attrs); - counter.add(1, &attrs); + counter.add(2, attrs.clone()); + counter.add(1, attrs); }), ..Default::default() }, @@ -290,20 +322,23 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().with_namespace("test"), expected_file: "with_namespace.txt", record_metrics: Box::new(|meter| { - let attrs = vec![ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ]; + let attrs = AttributeSet::from( + [ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ] + .as_slice(), + ); let counter = meter .f64_counter("foo") .with_description("a simple counter") .init(); - counter.add(5.0, &attrs); - counter.add(10.3, &attrs); - counter.add(9.0, &attrs); + counter.add(5.0, attrs.clone()); + counter.add(10.3, attrs.clone()); + counter.add(9.0, attrs); }), ..Default::default() }, @@ -406,7 +441,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter foo counter") .init(); - foo_counter.add(100, &[KeyValue::new("type", "foo")]); + foo_counter.add(100, [KeyValue::new("type", "foo")].as_slice().into()); let bar_counter = provider .versioned_meter("meterbar", Some("v0.1.0"), None::<&'static str>, None) @@ -414,7 +449,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter bar counter") .init(); - bar_counter.add(200, &[KeyValue::new("type", "bar")]); + bar_counter.add(200, [KeyValue::new("type", "bar")].as_slice().into()); let content = fs::read_to_string("./tests/data/multi_scopes.txt").unwrap(); gather_and_compare(registry, content, "multi_scope"); @@ -453,7 +488,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_a.add(100, &[KeyValue::new("A", "B")]); + foo_a.add(100, [KeyValue::new("A", "B")].as_slice().into()); let foo_b = meter_b .u64_counter("foo") @@ -461,7 +496,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_b.add(100, &[KeyValue::new("A", "B")]); + foo_b.add(100, [KeyValue::new("A", "B")].as_slice().into()); }), expected_files: vec!["no_conflict_two_counters.txt"], ..Default::default() @@ -475,7 +510,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, &[KeyValue::new("A", "B")]); + foo_a.add(100, [KeyValue::new("A", "B")].as_slice().into()); let foo_b = meter_b .i64_up_down_counter("foo") @@ -483,7 +518,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_b.add(100, &[KeyValue::new("A", "B")]); + foo_b.add(100, [KeyValue::new("A", "B")].as_slice().into()); }), expected_files: vec!["no_conflict_two_updowncounters.txt"], ..Default::default() @@ -497,7 +532,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_a.record(100, &[KeyValue::new("A", "B")]); + foo_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); let foo_b = meter_b .u64_histogram("foo") @@ -505,7 +540,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_b.record(100, &[KeyValue::new("A", "B")]); + foo_b.record(100, [KeyValue::new("A", "B")].as_slice().into()); }), expected_files: vec!["no_conflict_two_histograms.txt"], ..Default::default() @@ -519,7 +554,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, &[KeyValue::new("type", "bar")]); + bar_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); let bar_b = meter_b .u64_counter("bar") @@ -527,7 +562,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, &[KeyValue::new("type", "bar")]); + bar_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); }), expected_files: vec![ "conflict_help_two_counters_1.txt", @@ -544,7 +579,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, &[KeyValue::new("type", "bar")]); + bar_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); let bar_b = meter_b .i64_up_down_counter("bar") @@ -552,7 +587,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, &[KeyValue::new("type", "bar")]); + bar_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); }), expected_files: vec![ "conflict_help_two_updowncounters_1.txt", @@ -569,7 +604,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.record(100, &[KeyValue::new("A", "B")]); + bar_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); let bar_b = meter_b .u64_histogram("bar") @@ -577,7 +612,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.record(100, &[KeyValue::new("A", "B")]); + bar_b.record(100, [KeyValue::new("A", "B")].as_slice().into()); }), expected_files: vec![ "conflict_help_two_histograms_1.txt", @@ -594,7 +629,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_a.add(100, &[KeyValue::new("type", "bar")]); + baz_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); let baz_b = meter_b .u64_counter("bar") @@ -602,7 +637,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_b.add(100, &[KeyValue::new("type", "bar")]); + baz_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_counters.txt"], @@ -617,7 +652,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_a.add(100, &[KeyValue::new("type", "bar")]); + bar_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); let bar_b = meter_b .i64_up_down_counter("bar") @@ -625,7 +660,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_b.add(100, &[KeyValue::new("type", "bar")]); + bar_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_updowncounters.txt"], @@ -640,7 +675,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_a.record(100, &[KeyValue::new("A", "B")]); + bar_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); let bar_b = meter_b .u64_histogram("bar") @@ -648,7 +683,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_b.record(100, &[KeyValue::new("A", "B")]); + bar_b.record(100, [KeyValue::new("A", "B")].as_slice().into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_histograms.txt"], @@ -663,7 +698,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - counter.add(100, &[KeyValue::new("type", "foo")]); + counter.add(100, [KeyValue::new("type", "foo")].as_slice().into()); let gauge = meter_a .i64_up_down_counter("foo_total") @@ -671,7 +706,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - gauge.add(200, &[KeyValue::new("type", "foo")]); + gauge.add(200, [KeyValue::new("type", "foo")].as_slice().into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec![ @@ -689,7 +724,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, &[KeyValue::new("A", "B")]); + foo_a.add(100, [KeyValue::new("A", "B")].as_slice().into()); let foo_histogram_a = meter_a .u64_histogram("foo") @@ -697,7 +732,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_histogram_a.record(100, &[KeyValue::new("A", "B")]); + foo_histogram_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); }), expected_files: vec![ "conflict_type_histogram_and_updowncounter_1.txt", diff --git a/opentelemetry-sdk/src/attributes/mod.rs b/opentelemetry-sdk/src/attributes/mod.rs index 466aa2e241..372602983d 100644 --- a/opentelemetry-sdk/src/attributes/mod.rs +++ b/opentelemetry-sdk/src/attributes/mod.rs @@ -1,2 +1 @@ mod set; - diff --git a/opentelemetry-sdk/src/attributes/set.rs b/opentelemetry-sdk/src/attributes/set.rs index 48124fdd98..3990845a97 100644 --- a/opentelemetry-sdk/src/attributes/set.rs +++ b/opentelemetry-sdk/src/attributes/set.rs @@ -1,10 +1,11 @@ +use crate::Resource; use opentelemetry::attributes::AttributeSet; use opentelemetry::KeyValue; -use crate::Resource; impl From<&Resource> for AttributeSet { fn from(values: &Resource) -> Self { - let key_values = values.iter() + let key_values = values + .iter() .map(|(key, value)| KeyValue::new(key.clone(), value.clone())) .collect::>(); diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index b021ea5bcd..162f196d31 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -52,9 +52,10 @@ //! ### Creating instruments and recording measurements //! //! ``` -//! # #[cfg(feature = "metrics")] +//! # use opentelemetry::attributes::AttributeSet; +//! #[cfg(feature = "metrics")] //! # { -//! use opentelemetry::{global, KeyValue}; +//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; //! //! // get a meter from a provider //! let meter = global::meter("my_service"); @@ -63,7 +64,8 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // record a measurement -//! counter.add(1, &[KeyValue::new("http.client_ip", "83.164.160.102")]); +//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")].as_slice()); +//! counter.add(1, attributes); //! # } //! ``` //! @@ -135,7 +137,6 @@ pub mod trace; #[doc(hidden)] pub mod util; -pub use attributes::*; pub use instrumentation::{InstrumentationLibrary, Scope}; #[doc(inline)] pub use resource::Resource; diff --git a/opentelemetry-sdk/src/metrics/data/mod.rs b/opentelemetry-sdk/src/metrics/data/mod.rs index 555391a999..a94e35fd60 100644 --- a/opentelemetry-sdk/src/metrics/data/mod.rs +++ b/opentelemetry-sdk/src/metrics/data/mod.rs @@ -4,8 +4,8 @@ use std::{any, borrow::Cow, fmt, time::SystemTime}; use opentelemetry::{metrics::Unit, KeyValue}; -use opentelemetry::attributes::AttributeSet; use crate::{instrumentation::Scope, Resource}; +use opentelemetry::attributes::AttributeSet; pub use self::temporality::Temporality; diff --git a/opentelemetry-sdk/src/metrics/instrument.rs b/opentelemetry-sdk/src/metrics/instrument.rs index 4114574a85..a6f462ab1d 100644 --- a/opentelemetry-sdk/src/metrics/instrument.rs +++ b/opentelemetry-sdk/src/metrics/instrument.rs @@ -5,7 +5,7 @@ use opentelemetry::{ metrics::{ AsyncInstrument, MetricsError, Result, SyncCounter, SyncHistogram, SyncUpDownCounter, Unit, }, - Key, KeyValue, + Key, }; use crate::{ @@ -253,25 +253,25 @@ pub(crate) struct ResolvedMeasures { } impl SyncCounter for ResolvedMeasures { - fn add(&self, val: T, attrs: &[KeyValue]) { + fn add(&self, val: T, attrs: AttributeSet) { for measure in &self.measures { - measure.call(val, AttributeSet::from(attrs)) + measure.call(val, attrs.clone()) } } } impl SyncUpDownCounter for ResolvedMeasures { - fn add(&self, val: T, attrs: &[KeyValue]) { + fn add(&self, val: T, attrs: AttributeSet) { for measure in &self.measures { - measure.call(val, AttributeSet::from(attrs)) + measure.call(val, attrs.clone()) } } } impl SyncHistogram for ResolvedMeasures { - fn record(&self, val: T, attrs: &[KeyValue]) { + fn record(&self, val: T, attrs: AttributeSet) { for measure in &self.measures { - measure.call(val, AttributeSet::from(attrs)) + measure.call(val, attrs.clone()) } } } @@ -363,9 +363,9 @@ impl Observable { } impl AsyncInstrument for Observable { - fn observe(&self, measurement: T, attrs: &[KeyValue]) { + fn observe(&self, measurement: T, attrs: AttributeSet) { for measure in &self.measures { - measure.call(measurement, AttributeSet::from(attrs)) + measure.call(measurement, attrs.clone()) } } diff --git a/opentelemetry-sdk/src/metrics/internal/aggregate.rs b/opentelemetry-sdk/src/metrics/internal/aggregate.rs index aae3ffbce7..7e65de5f5c 100644 --- a/opentelemetry-sdk/src/metrics/internal/aggregate.rs +++ b/opentelemetry-sdk/src/metrics/internal/aggregate.rs @@ -1,11 +1,9 @@ use std::{marker, sync::Arc}; use once_cell::sync::Lazy; -use opentelemetry::{KeyValue, attributes::AttributeSet}; +use opentelemetry::{attributes::AttributeSet, KeyValue}; -use crate::{ - metrics::data::{Aggregation, Gauge, Temporality}, -}; +use crate::metrics::data::{Aggregation, Gauge, Temporality}; use super::{ exponential_histogram::ExpoHistogram, @@ -95,7 +93,7 @@ impl> AggregateBuilder { let filter = self.filter.as_ref().map(Arc::clone); move |n, mut attrs: AttributeSet| { if let Some(filter) = &filter { - attrs.retain(filter.as_ref()); + attrs = attrs.clone_with(filter.as_ref()); } f.call(n, attrs) } diff --git a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs index 581f49dfb6..1d458fa167 100644 --- a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs @@ -8,9 +8,7 @@ use std::{ use once_cell::sync::Lazy; use opentelemetry::{attributes::AttributeSet, metrics::MetricsError}; -use crate::{ - metrics::data::{self, Aggregation, Temporality}, -}; +use crate::metrics::data::{self, Aggregation, Temporality}; use super::Number; diff --git a/opentelemetry-sdk/src/metrics/internal/histogram.rs b/opentelemetry-sdk/src/metrics/internal/histogram.rs index 65e65e6e12..e71983f94e 100644 --- a/opentelemetry-sdk/src/metrics/internal/histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/histogram.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, sync::Mutex, time::SystemTime}; +use crate::metrics::data::HistogramDataPoint; use crate::metrics::data::{self, Aggregation, Temporality}; -use crate::{metrics::data::HistogramDataPoint}; use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; use super::{ diff --git a/opentelemetry-sdk/src/metrics/internal/last_value.rs b/opentelemetry-sdk/src/metrics/internal/last_value.rs index d5b4415163..db02ab3a8e 100644 --- a/opentelemetry-sdk/src/metrics/internal/last_value.rs +++ b/opentelemetry-sdk/src/metrics/internal/last_value.rs @@ -4,7 +4,7 @@ use std::{ time::SystemTime, }; -use crate::{metrics::data::DataPoint}; +use crate::metrics::data::DataPoint; use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; use super::{ diff --git a/opentelemetry-sdk/src/metrics/meter.rs b/opentelemetry-sdk/src/metrics/meter.rs index 5eaeba7745..b08e2d624f 100644 --- a/opentelemetry-sdk/src/metrics/meter.rs +++ b/opentelemetry-sdk/src/metrics/meter.rs @@ -1,6 +1,7 @@ use core::fmt; use std::{any::Any, borrow::Cow, collections::HashSet, sync::Arc}; +use opentelemetry::attributes::AttributeSet; use opentelemetry::{ global, metrics::{ @@ -9,7 +10,6 @@ use opentelemetry::{ MetricsError, ObservableCounter, ObservableGauge, ObservableUpDownCounter, Observer as ApiObserver, Result, Unit, UpDownCounter, }, - KeyValue, }; use crate::instrumentation::Scope; @@ -596,7 +596,7 @@ impl Observer { } impl ApiObserver for Observer { - fn observe_f64(&self, inst: &dyn AsyncInstrument, measurement: f64, attrs: &[KeyValue]) { + fn observe_f64(&self, inst: &dyn AsyncInstrument, measurement: f64, attrs: AttributeSet) { if let Some(f64_obs) = inst.as_any().downcast_ref::>() { if self.f64s.contains(&f64_obs.id) { f64_obs.observe(measurement, attrs) @@ -615,7 +615,7 @@ impl ApiObserver for Observer { } } - fn observe_u64(&self, inst: &dyn AsyncInstrument, measurement: u64, attrs: &[KeyValue]) { + fn observe_u64(&self, inst: &dyn AsyncInstrument, measurement: u64, attrs: AttributeSet) { if let Some(u64_obs) = inst.as_any().downcast_ref::>() { if self.u64s.contains(&u64_obs.id) { u64_obs.observe(measurement, attrs) @@ -634,7 +634,7 @@ impl ApiObserver for Observer { } } - fn observe_i64(&self, inst: &dyn AsyncInstrument, measurement: i64, attrs: &[KeyValue]) { + fn observe_i64(&self, inst: &dyn AsyncInstrument, measurement: i64, attrs: AttributeSet) { if let Some(i64_obs) = inst.as_any().downcast_ref::>() { if self.i64s.contains(&i64_obs.id) { i64_obs.observe(measurement, attrs) diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 9eb34d9303..4108559cb3 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -13,6 +13,7 @@ //! metrics::{MeterProvider, Unit}, //! KeyValue, //! }; +//! use opentelemetry::attributes::AttributeSet; //! use opentelemetry_sdk::{metrics::SdkMeterProvider, Resource}; //! //! // Generate SDK configuration, resource, views, etc @@ -31,7 +32,8 @@ //! .init(); //! //! // use instruments to record measurements -//! counter.add(10, &[KeyValue::new("rate", "standard")]); +//! let attributes = AttributeSet::from([KeyValue::new("rate", "standard")].as_slice()); +//! counter.add(10, attributes); //! ``` //! //! [Resource]: crate::Resource @@ -62,6 +64,7 @@ pub use view::*; mod tests { use super::*; use crate::{runtime, testing::metrics::InMemoryMetricsExporter}; + use opentelemetry::attributes::AttributeSet; use opentelemetry::{ metrics::{MeterProvider as _, Unit}, KeyValue, @@ -85,15 +88,15 @@ mod tests { .u64_counter("my_counter") .with_unit(Unit::new("my_unit")) .init(); - counter.add(1, &[KeyValue::new("key1", "value1")]); - counter.add(1, &[KeyValue::new("key1", "value1")]); - counter.add(1, &[KeyValue::new("key1", "value1")]); - counter.add(1, &[KeyValue::new("key1", "value1")]); - counter.add(1, &[KeyValue::new("key1", "value1")]); + counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); - counter.add(1, &[KeyValue::new("key1", "value2")]); - counter.add(1, &[KeyValue::new("key1", "value2")]); - counter.add(1, &[KeyValue::new("key1", "value2")]); + counter.add(1, [KeyValue::new("key1", "value2")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value2")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value2")].as_slice().into()); meter_provider.force_flush().unwrap(); @@ -180,9 +183,9 @@ mod tests { .with_description("my_description") .init(); - let attribute = vec![KeyValue::new("key1", "value1")]; - counter.add(10, &attribute); - counter_duplicated.add(5, &attribute); + let attribute = AttributeSet::from([KeyValue::new("key1", "value1")].as_slice()); + counter.add(10, attribute.clone()); + counter_duplicated.add(5, attribute); meter_provider.force_flush().unwrap(); diff --git a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs index d28cd4062f..40c84e8272 100644 --- a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs +++ b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs @@ -29,6 +29,7 @@ use std::sync::{Arc, Mutex}; /// ``` ///# use opentelemetry_sdk::{metrics, runtime}; ///# use opentelemetry::{KeyValue}; +///# use opentelemetry::attributes::AttributeSet; ///# use opentelemetry::metrics::MeterProvider; ///# use opentelemetry_sdk::testing::metrics::InMemoryMetricsExporter; ///# use opentelemetry_sdk::metrics::PeriodicReader; @@ -46,7 +47,8 @@ use std::sync::{Arc, Mutex}; /// // Create and record metrics using the MeterProvider /// let meter = meter_provider.meter(std::borrow::Cow::Borrowed("example")); /// let counter = meter.u64_counter("my_counter").init(); -/// counter.add(1, &[KeyValue::new("key", "value")]); +/// let attributes = AttributeSet::from([KeyValue::new("key", "value")].as_slice()); +/// counter.add(1, attributes); /// /// meter_provider.force_flush().unwrap(); /// diff --git a/opentelemetry-stdout/examples/basic.rs b/opentelemetry-stdout/examples/basic.rs index 41cfa7a30f..65fd54b229 100644 --- a/opentelemetry-stdout/examples/basic.rs +++ b/opentelemetry-stdout/examples/basic.rs @@ -45,7 +45,10 @@ async fn main() -> Result<(), Box> { let meter = meter_provider.meter("stdout-test"); let c = meter.u64_counter("test_events").init(); - c.add(1, &[KeyValue::new("test_key", "test_value")]); + c.add( + 1, + [KeyValue::new("test_key", "test_value")].as_slice().into(), + ); meter_provider.shutdown()?; diff --git a/opentelemetry-stdout/src/trace/transform.rs b/opentelemetry-stdout/src/trace/transform.rs index 8a83c41629..a7ed682980 100644 --- a/opentelemetry-stdout/src/trace/transform.rs +++ b/opentelemetry-stdout/src/trace/transform.rs @@ -1,5 +1,5 @@ use crate::common::{as_human_readable, as_unix_nano, KeyValue, Resource, Scope}; -use opentelemetry_sdk::AttributeSet; +use opentelemetry::attributes::AttributeSet; use serde::{Serialize, Serializer}; use std::{borrow::Cow, collections::HashMap, time::SystemTime}; diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 5548add54c..80bb82dd39 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -1,5 +1,7 @@ +use once_cell::sync::Lazy; use std::collections::hash_map::DefaultHasher; use std::collections::HashSet; +use std::sync::Arc; use std::{ cmp::Ordering, hash::{Hash, Hasher}, @@ -85,28 +87,46 @@ impl PartialEq for HashKeyValue { fn eq(&self, other: &Self) -> bool { self.0.key == other.0.key && match (&self.0.value, &other.0.value) { - (Value::F64(f), Value::F64(of)) => OrderedFloat(*f).eq(&OrderedFloat(*of)), - (Value::Array(Array::F64(f)), Value::Array(Array::F64(of))) => { - f.len() == of.len() - && f.iter() - .zip(of.iter()) - .all(|(f, of)| OrderedFloat(*f).eq(&OrderedFloat(*of))) + (Value::F64(f), Value::F64(of)) => OrderedFloat(*f).eq(&OrderedFloat(*of)), + (Value::Array(Array::F64(f)), Value::Array(Array::F64(of))) => { + f.len() == of.len() + && f.iter() + .zip(of.iter()) + .all(|(f, of)| OrderedFloat(*f).eq(&OrderedFloat(*of))) + } + (non_float, other_non_float) => non_float.eq(other_non_float), } - (non_float, other_non_float) => non_float.eq(other_non_float), - } } } impl Eq for HashKeyValue {} -/// A unique set of attributes that can be used as instrument identifiers. -/// -/// This must implement [Hash], [PartialEq], and [Eq] so it may be used as -/// HashMap keys and other de-duplication methods. -#[derive(Clone, Default, Debug, PartialEq, Eq)] -pub struct AttributeSet(Vec, u64); +static EMPTY_SET: Lazy> = + Lazy::new(|| Arc::new(InternalAttributeSet::new(Vec::with_capacity(0)))); -impl From<&[KeyValue]> for AttributeSet { +#[derive(Eq, PartialEq, Debug)] +struct InternalAttributeSet { + key_values: Vec, + hash: u64, +} + +impl InternalAttributeSet { + fn new(mut values: Vec) -> Self { + values.sort_unstable(); + let mut hasher = DefaultHasher::new(); + values.iter().fold(&mut hasher, |mut hasher, item| { + item.hash(&mut hasher); + hasher + }); + + InternalAttributeSet { + key_values: values, + hash: hasher.finish(), + } + } +} + +impl From<&[KeyValue]> for InternalAttributeSet { fn from(values: &[KeyValue]) -> Self { let mut seen_keys = HashSet::with_capacity(values.len()); let vec = values @@ -121,49 +141,64 @@ impl From<&[KeyValue]> for AttributeSet { }) .collect::>(); - AttributeSet::new(vec) + InternalAttributeSet::new(vec) } } +impl Hash for InternalAttributeSet { + fn hash(&self, state: &mut H) { + state.write_u64(self.hash) + } +} -impl AttributeSet { - fn new(mut values: Vec) -> Self { - values.sort_unstable(); - let mut hasher = DefaultHasher::new(); - values.iter().fold(&mut hasher, |mut hasher, item| { - item.hash(&mut hasher); - hasher - }); +/// A unique set of attributes that can be used as instrument identifiers. +/// +/// This must implement [Hash], [PartialEq], and [Eq] so it may be used as +/// HashMap keys and other de-duplication methods. +#[derive(Clone, Debug, Hash, PartialEq, Eq)] +pub struct AttributeSet(Arc); - AttributeSet(values, hasher.finish()) +impl From<&[KeyValue]> for AttributeSet { + fn from(values: &[KeyValue]) -> Self { + AttributeSet(Arc::new(InternalAttributeSet::from(values))) } +} +impl AttributeSet { /// Returns the number of elements in the set. pub fn len(&self) -> usize { - self.0.len() + self.0.key_values.len() } /// Returns `true` if the set contains no elements. pub fn is_empty(&self) -> bool { - self.0.is_empty() + self.0.key_values.is_empty() } - /// Retains only the attributes specified by the predicate. - pub fn retain(&mut self, f: F) - where - F: Fn(&KeyValue) -> bool, + /// Creates a new attribute set that retains only the attributes specified by the predicate. + pub fn clone_with(&self, f: F) -> AttributeSet + where + F: Fn(&KeyValue) -> bool, { - self.0.retain(|kv| f(&kv.0)) + let key_values = self + .0 + .key_values + .iter() + .filter(|kv| f(&kv.0)) + .cloned() + .collect::>(); + + AttributeSet(Arc::new(InternalAttributeSet::new(key_values))) } /// Iterate over key value pairs in the set pub fn iter(&self) -> impl Iterator { - self.0.iter().map(|kv| (&kv.0.key, &kv.0.value)) + self.0.key_values.iter().map(|kv| (&kv.0.key, &kv.0.value)) } } -impl Hash for AttributeSet { - fn hash(&self, state: &mut H) { - state.write_u64(self.1) +impl Default for AttributeSet { + fn default() -> Self { + AttributeSet(EMPTY_SET.clone()) } } diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index 790343968c..acb693136c 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -92,7 +92,7 @@ //! # #[cfg(feature="metrics")] //! # { //! use opentelemetry::metrics::{Meter, noop::NoopMeterProvider}; -//! use opentelemetry::{global, KeyValue}; +//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; //! //! fn init_meter() { //! let provider = NoopMeterProvider::new(); @@ -108,7 +108,8 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // record metrics -//! counter.add(1, &[KeyValue::new("mykey", "myvalue")]); +//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")].as_slice()); +//! counter.add(1, attributes); //! } //! //! // in main or other app start @@ -122,7 +123,7 @@ //! ``` //! # #[cfg(feature="metrics")] //! # { -//! use opentelemetry::{global, KeyValue}; +//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; //! //! pub fn my_traced_library_function() { //! // End users of your library will configure their global meter provider @@ -131,7 +132,8 @@ //! let counter = tracer.u64_counter("my_counter").init(); //! //! // record metrics -//! counter.add(1, &[KeyValue::new("mykey", "myvalue")]); +//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")].as_slice()); +//! counter.add(1, attributes); //! } //! # } //! ``` diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index 70396699ba..e454d66fb4 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -72,7 +72,7 @@ //! ``` //! # #[cfg(feature = "metrics")] //! # { -//! use opentelemetry::{global, KeyValue}; +//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; //! //! // get a meter from a provider //! let meter = global::meter("my_service"); @@ -80,8 +80,11 @@ //! // create an instrument //! let counter = meter.u64_counter("my_counter").init(); //! +//! // Form the attributes +//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")].as_slice()); +//! //! // record a measurement -//! counter.add(1, &[KeyValue::new("http.client_ip", "83.164.160.102")]); +//! counter.add(1, attributes); //! # } //! ``` //! diff --git a/opentelemetry/src/metrics/instruments/counter.rs b/opentelemetry/src/metrics/instruments/counter.rs index 171b6a49ea..e99c023ecb 100644 --- a/opentelemetry/src/metrics/instruments/counter.rs +++ b/opentelemetry/src/metrics/instruments/counter.rs @@ -1,7 +1,5 @@ -use crate::{ - metrics::{AsyncInstrument, AsyncInstrumentBuilder, InstrumentBuilder, MetricsError}, - KeyValue, -}; +use crate::attributes::AttributeSet; +use crate::metrics::{AsyncInstrument, AsyncInstrumentBuilder, InstrumentBuilder, MetricsError}; use core::fmt; use std::sync::Arc; use std::{any::Any, convert::TryFrom}; @@ -9,7 +7,7 @@ use std::{any::Any, convert::TryFrom}; /// An SDK implemented instrument that records increasing values. pub trait SyncCounter { /// Records an increment to the counter. - fn add(&self, value: T, attributes: &[KeyValue]); + fn add(&self, value: T, attributes: AttributeSet); } /// An instrument that records increasing values. @@ -32,7 +30,7 @@ impl Counter { } /// Records an increment to the counter. - pub fn add(&self, value: T, attributes: &[KeyValue]) { + pub fn add(&self, value: T, attributes: AttributeSet) { self.0.add(value, attributes) } } @@ -87,7 +85,7 @@ impl ObservableCounter { /// It is only valid to call this within a callback. If called outside of the /// registered callback it should have no effect on the instrument, and an /// error will be reported via the error handler. - pub fn observe(&self, value: T, attributes: &[KeyValue]) { + pub fn observe(&self, value: T, attributes: AttributeSet) { self.0.observe(value, attributes) } @@ -98,7 +96,7 @@ impl ObservableCounter { } impl AsyncInstrument for ObservableCounter { - fn observe(&self, measurement: T, attributes: &[KeyValue]) { + fn observe(&self, measurement: T, attributes: AttributeSet) { self.0.observe(measurement, attributes) } diff --git a/opentelemetry/src/metrics/instruments/gauge.rs b/opentelemetry/src/metrics/instruments/gauge.rs index b9f082d83a..9c96e2c751 100644 --- a/opentelemetry/src/metrics/instruments/gauge.rs +++ b/opentelemetry/src/metrics/instruments/gauge.rs @@ -1,7 +1,5 @@ -use crate::{ - metrics::{AsyncInstrument, AsyncInstrumentBuilder, MetricsError}, - KeyValue, -}; +use crate::attributes::AttributeSet; +use crate::metrics::{AsyncInstrument, AsyncInstrumentBuilder, MetricsError}; use core::fmt; use std::sync::Arc; use std::{any::Any, convert::TryFrom}; @@ -28,7 +26,7 @@ impl ObservableGauge { /// It is only valid to call this within a callback. If called outside of the /// registered callback it should have no effect on the instrument, and an /// error will be reported via the error handler. - pub fn observe(&self, measurement: T, attributes: &[KeyValue]) { + pub fn observe(&self, measurement: T, attributes: AttributeSet) { self.0.observe(measurement, attributes) } @@ -39,7 +37,7 @@ impl ObservableGauge { } impl AsyncInstrument for ObservableGauge { - fn observe(&self, measurement: M, attributes: &[KeyValue]) { + fn observe(&self, measurement: M, attributes: AttributeSet) { self.observe(measurement, attributes) } diff --git a/opentelemetry/src/metrics/instruments/histogram.rs b/opentelemetry/src/metrics/instruments/histogram.rs index c6246ebee2..3aa4346300 100644 --- a/opentelemetry/src/metrics/instruments/histogram.rs +++ b/opentelemetry/src/metrics/instruments/histogram.rs @@ -1,7 +1,5 @@ -use crate::{ - metrics::{InstrumentBuilder, MetricsError}, - KeyValue, -}; +use crate::attributes::AttributeSet; +use crate::metrics::{InstrumentBuilder, MetricsError}; use core::fmt; use std::convert::TryFrom; use std::sync::Arc; @@ -9,7 +7,7 @@ use std::sync::Arc; /// An SDK implemented instrument that records a distribution of values. pub trait SyncHistogram { /// Adds an additional value to the distribution. - fn record(&self, value: T, attributes: &[KeyValue]); + fn record(&self, value: T, attributes: AttributeSet); } /// An instrument that records a distribution of values. @@ -32,7 +30,7 @@ impl Histogram { } /// Adds an additional value to the distribution. - pub fn record(&self, value: T, attributes: &[KeyValue]) { + pub fn record(&self, value: T, attributes: AttributeSet) { self.0.record(value, attributes) } } diff --git a/opentelemetry/src/metrics/instruments/mod.rs b/opentelemetry/src/metrics/instruments/mod.rs index 137712d735..446e60c705 100644 --- a/opentelemetry/src/metrics/instruments/mod.rs +++ b/opentelemetry/src/metrics/instruments/mod.rs @@ -1,5 +1,5 @@ +use crate::attributes::AttributeSet; use crate::metrics::{Meter, MetricsError, Result, Unit}; -use crate::KeyValue; use core::fmt; use std::any::Any; use std::borrow::Cow; @@ -17,7 +17,7 @@ pub trait AsyncInstrument: Send + Sync { /// Observes the state of the instrument. /// /// It is only valid to call this within a callback. - fn observe(&self, measurement: T, attributes: &[KeyValue]); + fn observe(&self, measurement: T, attributes: AttributeSet); /// Used for SDKs to downcast instruments in callbacks. fn as_any(&self) -> Arc; diff --git a/opentelemetry/src/metrics/instruments/up_down_counter.rs b/opentelemetry/src/metrics/instruments/up_down_counter.rs index 1134ecedad..b864c7a054 100644 --- a/opentelemetry/src/metrics/instruments/up_down_counter.rs +++ b/opentelemetry/src/metrics/instruments/up_down_counter.rs @@ -1,7 +1,5 @@ -use crate::{ - metrics::{InstrumentBuilder, MetricsError}, - KeyValue, -}; +use crate::attributes::AttributeSet; +use crate::metrics::{InstrumentBuilder, MetricsError}; use core::fmt; use std::sync::Arc; use std::{any::Any, convert::TryFrom}; @@ -11,7 +9,7 @@ use super::{AsyncInstrument, AsyncInstrumentBuilder}; /// An SDK implemented instrument that records increasing or decreasing values. pub trait SyncUpDownCounter { /// Records an increment or decrement to the counter. - fn add(&self, value: T, attributes: &[KeyValue]); + fn add(&self, value: T, attributes: AttributeSet); } /// An instrument that records increasing or decreasing values. @@ -37,7 +35,7 @@ impl UpDownCounter { } /// Records an increment or decrement to the counter. - pub fn add(&self, value: T, attributes: &[KeyValue]) { + pub fn add(&self, value: T, attributes: AttributeSet) { self.0.add(value, attributes) } } @@ -93,7 +91,7 @@ impl ObservableUpDownCounter { /// It is only valid to call this within a callback. If called outside of the /// registered callback it should have no effect on the instrument, and an /// error will be reported via the error handler. - pub fn observe(&self, value: T, attributes: &[KeyValue]) { + pub fn observe(&self, value: T, attributes: AttributeSet) { self.0.observe(value, attributes) } @@ -104,7 +102,7 @@ impl ObservableUpDownCounter { } impl AsyncInstrument for ObservableUpDownCounter { - fn observe(&self, measurement: T, attributes: &[KeyValue]) { + fn observe(&self, measurement: T, attributes: AttributeSet) { self.0.observe(measurement, attributes) } diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index a66a77e55c..7b8160a531 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -1,3 +1,4 @@ +use crate::attributes::AttributeSet; use core::fmt; use std::any::Any; use std::borrow::Cow; @@ -69,7 +70,7 @@ pub trait MeterProvider { /// Provides access to instrument instances for recording measurements. /// /// ``` -/// use opentelemetry::{global, KeyValue}; +/// use opentelemetry::{attributes::AttributeSet, global, KeyValue}; /// /// let meter = global::meter("my-meter"); /// @@ -78,181 +79,107 @@ pub trait MeterProvider { /// // u64 Counter /// let u64_counter = meter.u64_counter("my_u64_counter").init(); /// -/// // Record measurements using the counter instrument add() -/// u64_counter.add( -/// 10, -/// [ +/// // Define the attributes the counters will use +/// let attributes = AttributeSet::from([ /// KeyValue::new("mykey1", "myvalue1"), /// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref() -/// ); +/// ].as_slice()); +/// +/// // Record measurements using the counter instrument add() +/// u64_counter.add(10, attributes.clone()); /// /// // f64 Counter /// let f64_counter = meter.f64_counter("my_f64_counter").init(); /// /// // Record measurements using the counter instrument add() -/// f64_counter.add( -/// 3.15, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref() -/// ); +/// f64_counter.add(3.15, attributes.clone()); /// /// // u6 observable counter /// let observable_u4_counter = meter.u64_observable_counter("my_observable_u64_counter").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[observable_u4_counter.as_any()], move |observer| { -/// observer.observe_u64( -/// &observable_u4_counter, -/// 1, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_u64(&observable_u4_counter, 1, observer_attributes.clone()) /// }); /// /// // f64 observable counter /// let observable_f64_counter = meter.f64_observable_counter("my_observable_f64_counter").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[observable_f64_counter.as_any()], move |observer| { -/// observer.observe_f64( -/// &observable_f64_counter, -/// 1.55, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_f64(&observable_f64_counter, 1.55, observer_attributes.clone()) /// }); /// /// // i64 updown counter /// let updown_i64_counter = meter.i64_up_down_counter("my_updown_i64_counter").init(); /// /// // Record measurements using the updown counter instrument add() -/// updown_i64_counter.add( -/// -10, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ); +/// updown_i64_counter.add(-10, attributes.clone()); /// /// // f64 updown counter /// let updown_f64_counter = meter.f64_up_down_counter("my_updown_f64_counter").init(); /// /// // Record measurements using the updown counter instrument add() -/// updown_f64_counter.add( -/// -10.67, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ); +/// updown_f64_counter.add(-10.67, attributes.clone()); /// /// // i64 observable updown counter /// let observable_i64_up_down_counter = meter.i64_observable_up_down_counter("my_observable_i64_updown_counter").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[observable_i64_up_down_counter.as_any()], move |observer| { -/// observer.observe_i64( -/// &observable_i64_up_down_counter, -/// 1, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_i64(&observable_i64_up_down_counter, 1, observer_attributes.clone()) /// }); /// /// // f64 observable updown counter /// let observable_f64_up_down_counter = meter.f64_observable_up_down_counter("my_observable_f64_updown_counter").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[observable_f64_up_down_counter.as_any()], move |observer| { -/// observer.observe_f64( -/// &observable_f64_up_down_counter, -/// 1.16, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_f64(&observable_f64_up_down_counter, 1.16, observer_attributes.clone()) /// }); /// /// // Observable f64 gauge /// let f64_gauge = meter.f64_observable_gauge("my_f64_gauge").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[f64_gauge.as_any()], move |observer| { -/// observer.observe_f64( -/// &f64_gauge, -/// 2.32, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_f64(&f64_gauge, 2.32, observer_attributes.clone()) /// }); /// /// // Observable i64 gauge /// let i64_gauge = meter.i64_observable_gauge("my_i64_gauge").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[i64_gauge.as_any()], move |observer| { -/// observer.observe_i64( -/// &i64_gauge, -/// 12, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_i64(&i64_gauge, 12, observer_attributes.clone()) /// }); /// /// // Observable u64 gauge /// let u64_gauge = meter.u64_observable_gauge("my_u64_gauge").init(); /// /// // Register a callback to this meter for an asynchronous instrument to record measurements +/// let observer_attributes = attributes.clone(); /// meter.register_callback(&[u64_gauge.as_any()], move |observer| { -/// observer.observe_u64( -/// &u64_gauge, -/// 1, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ].as_ref(), -/// ) +/// observer.observe_u64(&u64_gauge, 1, observer_attributes.clone()) /// }); /// /// // f64 histogram /// let f64_histogram = meter.f64_histogram("my_f64_histogram").init(); /// /// // Record measurements using the histogram instrument record() -/// f64_histogram.record( -/// 10.5, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ] -/// .as_ref(), -/// ); +/// f64_histogram.record(10.5, attributes.clone()); /// /// // u64 histogram /// let u64_histogram = meter.u64_histogram("my_u64_histogram").init(); /// /// // Record measurements using the histogram instrument record() -/// u64_histogram.record( -/// 12, -/// [ -/// KeyValue::new("mykey1", "myvalue1"), -/// KeyValue::new("mykey2", "myvalue2"), -/// ] -/// .as_ref(), -/// ); +/// u64_histogram.record(12, attributes); /// /// ``` #[derive(Clone)] @@ -403,13 +330,13 @@ pub trait CallbackRegistration: Send + Sync { /// Records measurements for multiple instruments in a callback. pub trait Observer { /// Records the f64 value with attributes for the observable. - fn observe_f64(&self, inst: &dyn AsyncInstrument, measurement: f64, attrs: &[KeyValue]); + fn observe_f64(&self, inst: &dyn AsyncInstrument, measurement: f64, attrs: AttributeSet); /// Records the u64 value with attributes for the observable. - fn observe_u64(&self, inst: &dyn AsyncInstrument, measurement: u64, attrs: &[KeyValue]); + fn observe_u64(&self, inst: &dyn AsyncInstrument, measurement: u64, attrs: AttributeSet); /// Records the i64 value with attributes for the observable. - fn observe_i64(&self, inst: &dyn AsyncInstrument, measurement: i64, attrs: &[KeyValue]); + fn observe_i64(&self, inst: &dyn AsyncInstrument, measurement: i64, attrs: AttributeSet); } impl fmt::Debug for Meter { diff --git a/opentelemetry/src/metrics/noop.rs b/opentelemetry/src/metrics/noop.rs index 361bed29e7..d0401165b6 100644 --- a/opentelemetry/src/metrics/noop.rs +++ b/opentelemetry/src/metrics/noop.rs @@ -3,6 +3,7 @@ //! This implementation is returned as the global Meter if no `Meter` //! has been set. It is also useful for testing purposes as it is intended //! to have minimal resource utilization and runtime impact. +use crate::attributes::AttributeSet; use crate::{ metrics::{ AsyncInstrument, CallbackRegistration, InstrumentProvider, Meter, MeterProvider, Observer, @@ -93,19 +94,19 @@ impl NoopSyncInstrument { } impl SyncCounter for NoopSyncInstrument { - fn add(&self, _value: T, _attributes: &[KeyValue]) { + fn add(&self, _value: T, _attributes: AttributeSet) { // Ignored } } impl SyncUpDownCounter for NoopSyncInstrument { - fn add(&self, _value: T, _attributes: &[KeyValue]) { + fn add(&self, _value: T, _attributes: AttributeSet) { // Ignored } } impl SyncHistogram for NoopSyncInstrument { - fn record(&self, _value: T, _attributes: &[KeyValue]) { + fn record(&self, _value: T, _attributes: AttributeSet) { // Ignored } } @@ -124,7 +125,7 @@ impl NoopAsyncInstrument { } impl AsyncInstrument for NoopAsyncInstrument { - fn observe(&self, _value: T, _attributes: &[KeyValue]) { + fn observe(&self, _value: T, _attributes: AttributeSet) { // Ignored } diff --git a/stress/src/metrics.rs b/stress/src/metrics.rs index 9f7d2d2349..2c124ed7ab 100644 --- a/stress/src/metrics.rs +++ b/stress/src/metrics.rs @@ -37,10 +37,12 @@ fn test_counter() { // each attribute has 10 possible values, so there are 1000 possible combinations (time-series) COUNTER.add( 1, - &[ + [ KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]), KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]), KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]), - ], + ] + .as_slice() + .into(), ); } From 9f9905bb02ce7fa40d895f5f4a5294d98642b8f8 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Thu, 30 Nov 2023 15:15:54 -0500 Subject: [PATCH 03/31] Removed idea files --- .idea/vcs.xml | 7 - .idea/workspace.xml | 357 -------------------------------------------- 2 files changed, 364 deletions(-) delete mode 100644 .idea/vcs.xml delete mode 100644 .idea/workspace.xml diff --git a/.idea/vcs.xml b/.idea/vcs.xml deleted file mode 100644 index 68f1366ee5..0000000000 --- a/.idea/vcs.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml deleted file mode 100644 index 850efe0a8b..0000000000 --- a/.idea/workspace.xml +++ /dev/null @@ -1,357 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - { - "associatedIndex": 1 -} - - - - - - - { - "keyToString": { - "ASKED_ADD_EXTERNAL_FILES": "true", - "ASKED_SHARE_PROJECT_CONFIGURATION_FILES": "true", - "RunOnceActivity.OpenProjectViewOnStart": "true", - "RunOnceActivity.ShowReadmeOnStart": "true", - "RunOnceActivity.cidr.known.project.marker": "true", - "WebServerToolWindowFactoryState": "false", - "cf.first.check.clang-format": "false", - "cidr.known.project.marker": "true", - "git-widget-placeholder": "premade__attribute__sets", - "last_opened_file_path": "/home/mshapiro/code/opentelemetry-rust", - "node.js.detected.package.eslint": "true", - "node.js.detected.package.tslint": "true", - "node.js.selected.package.eslint": "(autodetect)", - "node.js.selected.package.tslint": "(autodetect)", - "nodejs_package_manager_path": "npm", - "org.rust.cargo.project.model.PROJECT_DISCOVERY": "true", - "settings.editor.selected.configurable": "com.maddyhome.idea.vim.ui.VimEmulationConfigurable", - "vue.rearranger.settings.migration": "true" - } -} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 1699976529165 - - - - - - \ No newline at end of file From 8fe79b9982752c417a1f09de3b72540de24089b3 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Thu, 30 Nov 2023 16:18:46 -0500 Subject: [PATCH 04/31] From trait utilizing iterators instead of reference slices --- examples/metrics-advanced/src/main.rs | 5 - examples/metrics-basic/src/main.rs | 6 - .../examples/basic-otlp-http/src/main.rs | 1 - .../examples/basic-otlp/src/main.rs | 16 +- opentelemetry-prometheus/examples/hyper.rs | 6 +- opentelemetry-prometheus/src/lib.rs | 2 +- .../tests/integration_test.rs | 186 ++++++++---------- opentelemetry-sdk/src/attributes/set.rs | 2 +- opentelemetry-sdk/src/lib.rs | 2 +- .../src/metrics/internal/aggregate.rs | 2 +- .../metrics/internal/exponential_histogram.rs | 4 +- opentelemetry-sdk/src/metrics/mod.rs | 20 +- .../src/testing/metrics/in_memory_exporter.rs | 2 +- opentelemetry-stdout/examples/basic.rs | 5 +- opentelemetry/src/attributes/set.rs | 51 ++++- opentelemetry/src/global/mod.rs | 4 +- opentelemetry/src/lib.rs | 2 +- opentelemetry/src/metrics/meter.rs | 2 +- stress/src/metrics.rs | 1 - 19 files changed, 156 insertions(+), 163 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index d9cb9b812e..4394cf1453 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -86,7 +86,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_slice() .into(), ); @@ -105,7 +104,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_slice() .into(), ); @@ -130,7 +128,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_slice() .into(), ); @@ -142,7 +139,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_slice() .into(), ); @@ -154,7 +150,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), ] - .as_slice() .into(), ); diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 03769901f9..e89355882f 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -38,7 +38,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_slice() .into(), ); @@ -57,7 +56,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_slice() .into(), ) })?; @@ -72,7 +70,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_slice() .into(), ); @@ -91,7 +88,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_slice() .into(), ) })?; @@ -109,7 +105,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_slice() .into(), ); @@ -131,7 +126,6 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), ] - .as_slice() .into(), ) })?; diff --git a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs index 901fa9df9a..88f03a04d5 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs @@ -70,7 +70,6 @@ static COMMON_ATTRIBUTES: Lazy = Lazy::new(|| { KeyValue::new("B", "2"), KeyValue::new("C", "3"), ] - .as_slice() .into() }); diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index 9a471d52cd..1691ac1caf 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -74,15 +74,13 @@ const LEMONS_KEY: Key = Key::from_static_str("lemons"); const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another"); static COMMON_ATTRIBUTES: Lazy = Lazy::new(|| { - AttributeSet::from( - [ - LEMONS_KEY.i64(10), - KeyValue::new("A", "1"), - KeyValue::new("B", "2"), - KeyValue::new("C", "3"), - ] - .as_slice(), - ) + [ + LEMONS_KEY.i64(10), + KeyValue::new("A", "1"), + KeyValue::new("B", "2"), + KeyValue::new("C", "3"), + ] + .into() }); #[tokio::main] diff --git a/opentelemetry-prometheus/examples/hyper.rs b/opentelemetry-prometheus/examples/hyper.rs index 446732223f..1b8be797ab 100644 --- a/opentelemetry-prometheus/examples/hyper.rs +++ b/opentelemetry-prometheus/examples/hyper.rs @@ -15,7 +15,7 @@ use std::convert::Infallible; use std::sync::Arc; use std::time::SystemTime; -static HANDLER_ALL: Lazy<[KeyValue; 1]> = Lazy::new(|| [KeyValue::new("handler", "all")]); +static HANDLER_ALL: Lazy = Lazy::new(|| [KeyValue::new("handler", "all")].into()); async fn serve_req( req: Request, @@ -24,7 +24,7 @@ async fn serve_req( println!("Receiving request at path {}", req.uri()); let request_start = SystemTime::now(); - state.http_counter.add(1, HANDLER_ALL.as_ref().into()); + state.http_counter.add(1, HANDLER_ALL.clone()); let response = match (req.method(), req.uri().path()) { (&Method::GET, "/metrics") => { @@ -34,7 +34,7 @@ async fn serve_req( encoder.encode(&metric_families, &mut buffer).unwrap(); state .http_body_gauge - .record(buffer.len() as u64, HANDLER_ALL.as_ref().into()); + .record(buffer.len() as u64, HANDLER_ALL.clone()); Response::builder() .status(200) diff --git a/opentelemetry-prometheus/src/lib.rs b/opentelemetry-prometheus/src/lib.rs index a3127b46b9..f473ccbabd 100644 --- a/opentelemetry-prometheus/src/lib.rs +++ b/opentelemetry-prometheus/src/lib.rs @@ -32,7 +32,7 @@ //! .with_description("Records values") //! .init(); //! -//! let attributes = AttributeSet::from([KeyValue::new("key", "value")].as_slice()); +//! let attributes = AttributeSet::from([KeyValue::new("key", "value")]); //! //! counter.add(100, attributes.clone()); //! histogram.record(100, attributes); diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs index 5f2465b851..d9c26cceb3 100644 --- a/opentelemetry-prometheus/tests/integration_test.rs +++ b/opentelemetry-prometheus/tests/integration_test.rs @@ -45,15 +45,12 @@ fn prometheus_exporter_integration() { name: "counter", expected_file: "counter.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ]); let counter = meter .f64_counter("foo") @@ -70,7 +67,7 @@ fn prometheus_exporter_integration() { Key::new("E").bool(true), Key::new("F").i64(42), ]; - counter.add(5.0, attrs2.as_slice().into()); + counter.add(5.0, attrs2.into()); }), ..Default::default() }, @@ -79,15 +76,12 @@ fn prometheus_exporter_integration() { expected_file: "counter_disabled_suffix.txt", builder: ExporterBuilder::default().without_counter_suffixes(), record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ]); let counter = meter .f64_counter("foo") @@ -103,7 +97,7 @@ fn prometheus_exporter_integration() { Key::new("E").bool(true), Key::new("F").i64(42), ]; - counter.add(5.0, attrs2.as_slice().into()); + counter.add(5.0, attrs2.into()); }), ..Default::default() }, @@ -111,9 +105,8 @@ fn prometheus_exporter_integration() { name: "gauge", expected_file: "gauge.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), - ); + let attrs = + AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); let gauge = meter .f64_up_down_counter("bar") .with_description("a fun little gauge") @@ -128,9 +121,8 @@ fn prometheus_exporter_integration() { name: "histogram", expected_file: "histogram.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), - ); + let attrs = + AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); let histogram = meter .f64_histogram("histogram_baz") .with_description("a very nice histogram") @@ -148,17 +140,14 @@ fn prometheus_exporter_integration() { expected_file: "sanitized_labels.txt", builder: ExporterBuilder::default().without_units(), record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - // exact match, value should be overwritten - Key::new("A.B").string("X"), - Key::new("A.B").string("Q"), - // unintended match due to sanitization, values should be concatenated - Key::new("C.D").string("Y"), - Key::new("C/D").string("Z"), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + // exact match, value should be overwritten + Key::new("A.B").string("X"), + Key::new("A.B").string("Q"), + // unintended match due to sanitization, values should be concatenated + Key::new("C.D").string("Y"), + Key::new("C/D").string("Z"), + ]); let counter = meter .f64_counter("foo") .with_description("a sanitary counter") @@ -175,9 +164,8 @@ fn prometheus_exporter_integration() { name: "invalid instruments are renamed", expected_file: "sanitized_names.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), - ); + let attrs = + AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); // Valid. let mut gauge = meter .f64_up_down_counter("bar") @@ -212,15 +200,12 @@ fn prometheus_exporter_integration() { empty_resource: true, expected_file: "empty_resource.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ]); let counter = meter .f64_counter("foo") .with_description("a simple counter") @@ -236,15 +221,12 @@ fn prometheus_exporter_integration() { custom_resource_attrs: vec![Key::new("A").string("B"), Key::new("C").string("D")], expected_file: "custom_resource.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ]); let counter = meter .f64_counter("foo") .with_description("a simple counter") @@ -260,15 +242,12 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().without_target_info(), expected_file: "without_target_info.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ]); let counter = meter .f64_counter("foo") .with_description("a simple counter") @@ -284,9 +263,8 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().without_scope_info(), expected_file: "without_scope_info.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), - ); + let attrs = + AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); let gauge = meter .i64_up_down_counter("bar") .with_description("a fun little gauge") @@ -304,9 +282,8 @@ fn prometheus_exporter_integration() { .without_target_info(), expected_file: "without_scope_and_target_info.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [Key::new("A").string("B"), Key::new("C").string("D")].as_slice(), - ); + let attrs = + AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); let counter = meter .u64_counter("bar") .with_description("a fun little counter") @@ -322,15 +299,12 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().with_namespace("test"), expected_file: "with_namespace.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from( - [ - Key::new("A").string("B"), - Key::new("C").string("D"), - Key::new("E").bool(true), - Key::new("F").i64(42), - ] - .as_slice(), - ); + let attrs = AttributeSet::from([ + Key::new("A").string("B"), + Key::new("C").string("D"), + Key::new("E").bool(true), + Key::new("F").i64(42), + ]); let counter = meter .f64_counter("foo") .with_description("a simple counter") @@ -441,7 +415,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter foo counter") .init(); - foo_counter.add(100, [KeyValue::new("type", "foo")].as_slice().into()); + foo_counter.add(100, [KeyValue::new("type", "foo")].into()); let bar_counter = provider .versioned_meter("meterbar", Some("v0.1.0"), None::<&'static str>, None) @@ -449,7 +423,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter bar counter") .init(); - bar_counter.add(200, [KeyValue::new("type", "bar")].as_slice().into()); + bar_counter.add(200, [KeyValue::new("type", "bar")].into()); let content = fs::read_to_string("./tests/data/multi_scopes.txt").unwrap(); gather_and_compare(registry, content, "multi_scope"); @@ -488,7 +462,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_a.add(100, [KeyValue::new("A", "B")].into()); let foo_b = meter_b .u64_counter("foo") @@ -496,7 +470,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_b.add(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_b.add(100, [KeyValue::new("A", "B")].into()); }), expected_files: vec!["no_conflict_two_counters.txt"], ..Default::default() @@ -510,7 +484,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_a.add(100, [KeyValue::new("A", "B")].into()); let foo_b = meter_b .i64_up_down_counter("foo") @@ -518,7 +492,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_b.add(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_b.add(100, [KeyValue::new("A", "B")].into()); }), expected_files: vec!["no_conflict_two_updowncounters.txt"], ..Default::default() @@ -532,7 +506,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_a.record(100, [KeyValue::new("A", "B")].into()); let foo_b = meter_b .u64_histogram("foo") @@ -540,7 +514,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_b.record(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_b.record(100, [KeyValue::new("A", "B")].into()); }), expected_files: vec!["no_conflict_two_histograms.txt"], ..Default::default() @@ -554,7 +528,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + bar_a.add(100, [KeyValue::new("type", "bar")].into()); let bar_b = meter_b .u64_counter("bar") @@ -562,7 +536,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + bar_b.add(100, [KeyValue::new("type", "bar")].into()); }), expected_files: vec![ "conflict_help_two_counters_1.txt", @@ -579,7 +553,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + bar_a.add(100, [KeyValue::new("type", "bar")].into()); let bar_b = meter_b .i64_up_down_counter("bar") @@ -587,7 +561,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + bar_b.add(100, [KeyValue::new("type", "bar")].into()); }), expected_files: vec![ "conflict_help_two_updowncounters_1.txt", @@ -604,7 +578,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); + bar_a.record(100, [KeyValue::new("A", "B")].into()); let bar_b = meter_b .u64_histogram("bar") @@ -612,7 +586,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.record(100, [KeyValue::new("A", "B")].as_slice().into()); + bar_b.record(100, [KeyValue::new("A", "B")].into()); }), expected_files: vec![ "conflict_help_two_histograms_1.txt", @@ -629,7 +603,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + baz_a.add(100, [KeyValue::new("type", "bar")].into()); let baz_b = meter_b .u64_counter("bar") @@ -637,7 +611,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + baz_b.add(100, [KeyValue::new("type", "bar")].into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_counters.txt"], @@ -652,7 +626,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + bar_a.add(100, [KeyValue::new("type", "bar")].into()); let bar_b = meter_b .i64_up_down_counter("bar") @@ -660,7 +634,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")].as_slice().into()); + bar_b.add(100, [KeyValue::new("type", "bar")].into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_updowncounters.txt"], @@ -675,7 +649,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); + bar_a.record(100, [KeyValue::new("A", "B")].into()); let bar_b = meter_b .u64_histogram("bar") @@ -683,7 +657,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_b.record(100, [KeyValue::new("A", "B")].as_slice().into()); + bar_b.record(100, [KeyValue::new("A", "B")].into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_histograms.txt"], @@ -698,7 +672,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - counter.add(100, [KeyValue::new("type", "foo")].as_slice().into()); + counter.add(100, [KeyValue::new("type", "foo")].into()); let gauge = meter_a .i64_up_down_counter("foo_total") @@ -706,7 +680,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - gauge.add(200, [KeyValue::new("type", "foo")].as_slice().into()); + gauge.add(200, [KeyValue::new("type", "foo")].into()); }), builder: ExporterBuilder::default().without_units(), expected_files: vec![ @@ -724,7 +698,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_a.add(100, [KeyValue::new("A", "B")].into()); let foo_histogram_a = meter_a .u64_histogram("foo") @@ -732,7 +706,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_histogram_a.record(100, [KeyValue::new("A", "B")].as_slice().into()); + foo_histogram_a.record(100, [KeyValue::new("A", "B")].into()); }), expected_files: vec![ "conflict_type_histogram_and_updowncounter_1.txt", diff --git a/opentelemetry-sdk/src/attributes/set.rs b/opentelemetry-sdk/src/attributes/set.rs index 3990845a97..58007809b4 100644 --- a/opentelemetry-sdk/src/attributes/set.rs +++ b/opentelemetry-sdk/src/attributes/set.rs @@ -9,6 +9,6 @@ impl From<&Resource> for AttributeSet { .map(|(key, value)| KeyValue::new(key.clone(), value.clone())) .collect::>(); - AttributeSet::from(key_values.as_slice()) + AttributeSet::from(key_values) } } diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index 162f196d31..3659549079 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -64,7 +64,7 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // record a measurement -//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")].as_slice()); +//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")]); //! counter.add(1, attributes); //! # } //! ``` diff --git a/opentelemetry-sdk/src/metrics/internal/aggregate.rs b/opentelemetry-sdk/src/metrics/internal/aggregate.rs index 7e65de5f5c..9ecf1fd7a6 100644 --- a/opentelemetry-sdk/src/metrics/internal/aggregate.rs +++ b/opentelemetry-sdk/src/metrics/internal/aggregate.rs @@ -16,7 +16,7 @@ use super::{ const STREAM_CARDINALITY_LIMIT: u32 = 2000; pub(crate) static STREAM_OVERFLOW_ATTRIBUTE_SET: Lazy = Lazy::new(|| { let key_values: [KeyValue; 1] = [KeyValue::new("otel.metric.overflow", "true")]; - AttributeSet::from(&key_values[..]) + AttributeSet::from(key_values) }); /// Checks whether aggregator has hit cardinality limit for metric streams diff --git a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs index 1d458fa167..d25d2d00b8 100644 --- a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs @@ -675,7 +675,7 @@ mod tests { } fn run_min_max_sum_f64() { - let alice = AttributeSet::from(&[KeyValue::new("user", "alice")][..]); + let alice = AttributeSet::from([KeyValue::new("user", "alice")]); struct Expected { min: f64, max: f64, @@ -736,7 +736,7 @@ mod tests { } fn run_min_max_sum + From>() { - let alice = AttributeSet::from(&[KeyValue::new("user", "alice")][..]); + let alice = AttributeSet::from([KeyValue::new("user", "alice")]); struct Expected { min: T, max: T, diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 4108559cb3..9d502eb043 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -32,7 +32,7 @@ //! .init(); //! //! // use instruments to record measurements -//! let attributes = AttributeSet::from([KeyValue::new("rate", "standard")].as_slice()); +//! let attributes = AttributeSet::from([KeyValue::new("rate", "standard")]); //! counter.add(10, attributes); //! ``` //! @@ -88,15 +88,15 @@ mod tests { .u64_counter("my_counter") .with_unit(Unit::new("my_unit")) .init(); - counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); - counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); - counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); - counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); - counter.add(1, [KeyValue::new("key1", "value1")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value1")].into()); + counter.add(1, [KeyValue::new("key1", "value1")].into()); + counter.add(1, [KeyValue::new("key1", "value1")].into()); + counter.add(1, [KeyValue::new("key1", "value1")].into()); + counter.add(1, [KeyValue::new("key1", "value1")].into()); - counter.add(1, [KeyValue::new("key1", "value2")].as_slice().into()); - counter.add(1, [KeyValue::new("key1", "value2")].as_slice().into()); - counter.add(1, [KeyValue::new("key1", "value2")].as_slice().into()); + counter.add(1, [KeyValue::new("key1", "value2")].into()); + counter.add(1, [KeyValue::new("key1", "value2")].into()); + counter.add(1, [KeyValue::new("key1", "value2")].into()); meter_provider.force_flush().unwrap(); @@ -183,7 +183,7 @@ mod tests { .with_description("my_description") .init(); - let attribute = AttributeSet::from([KeyValue::new("key1", "value1")].as_slice()); + let attribute = AttributeSet::from([KeyValue::new("key1", "value1")]); counter.add(10, attribute.clone()); counter_duplicated.add(5, attribute); diff --git a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs index 40c84e8272..ec31e4cac2 100644 --- a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs +++ b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs @@ -47,7 +47,7 @@ use std::sync::{Arc, Mutex}; /// // Create and record metrics using the MeterProvider /// let meter = meter_provider.meter(std::borrow::Cow::Borrowed("example")); /// let counter = meter.u64_counter("my_counter").init(); -/// let attributes = AttributeSet::from([KeyValue::new("key", "value")].as_slice()); +/// let attributes = AttributeSet::from([KeyValue::new("key", "value")]); /// counter.add(1, attributes); /// /// meter_provider.force_flush().unwrap(); diff --git a/opentelemetry-stdout/examples/basic.rs b/opentelemetry-stdout/examples/basic.rs index 65fd54b229..462144e47f 100644 --- a/opentelemetry-stdout/examples/basic.rs +++ b/opentelemetry-stdout/examples/basic.rs @@ -45,10 +45,7 @@ async fn main() -> Result<(), Box> { let meter = meter_provider.meter("stdout-test"); let c = meter.u64_counter("test_events").init(); - c.add( - 1, - [KeyValue::new("test_key", "test_value")].as_slice().into(), - ); + c.add(1, [KeyValue::new("test_key", "test_value")].into()); meter_provider.shutdown()?; diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 80bb82dd39..a1a5b4c246 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -124,13 +124,39 @@ impl InternalAttributeSet { hash: hasher.finish(), } } + + fn from_key_values>(iter: T) -> Self + where + ::IntoIter: DoubleEndedIterator + ExactSizeIterator, + { + // Note: this doesn't implement `FromIter` because of the additional constraints + let iter = iter.into_iter(); + let mut seen_keys = HashSet::with_capacity(iter.len()); + let vec = iter + .into_iter() + .rev() + .filter_map(|kv| { + if seen_keys.insert(kv.key.clone()) { + Some(HashKeyValue(kv.clone())) + } else { + None + } + }) + .collect::>(); + + InternalAttributeSet::new(vec) + } } -impl From<&[KeyValue]> for InternalAttributeSet { - fn from(values: &[KeyValue]) -> Self { - let mut seen_keys = HashSet::with_capacity(values.len()); - let vec = values - .iter() +impl> From for InternalAttributeSet +where + ::IntoIter: DoubleEndedIterator + ExactSizeIterator, +{ + fn from(value: I) -> Self { + let iter = value.into_iter(); + let mut seen_keys = HashSet::with_capacity(iter.len()); + let vec = iter + .into_iter() .rev() .filter_map(|kv| { if seen_keys.insert(kv.key.clone()) { @@ -158,13 +184,24 @@ impl Hash for InternalAttributeSet { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct AttributeSet(Arc); -impl From<&[KeyValue]> for AttributeSet { - fn from(values: &[KeyValue]) -> Self { +impl> From for AttributeSet +where + ::IntoIter: DoubleEndedIterator + ExactSizeIterator, +{ + fn from(values: I) -> Self { AttributeSet(Arc::new(InternalAttributeSet::from(values))) } } impl AttributeSet { + /// Creates an attribute set from an iterator of `KeyValue`s + pub fn from_key_values>(iter: T) -> Self + where + ::IntoIter: DoubleEndedIterator + ExactSizeIterator, + { + AttributeSet(Arc::new(InternalAttributeSet::from_key_values(iter))) + } + /// Returns the number of elements in the set. pub fn len(&self) -> usize { self.0.key_values.len() diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index acb693136c..0b111c6304 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -108,7 +108,7 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // record metrics -//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")].as_slice()); +//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")]); //! counter.add(1, attributes); //! } //! @@ -132,7 +132,7 @@ //! let counter = tracer.u64_counter("my_counter").init(); //! //! // record metrics -//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")].as_slice()); +//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")]); //! counter.add(1, attributes); //! } //! # } diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index e454d66fb4..203ead7fcc 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -81,7 +81,7 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // Form the attributes -//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")].as_slice()); +//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")]); //! //! // record a measurement //! counter.add(1, attributes); diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index 7b8160a531..4a4557f6aa 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -83,7 +83,7 @@ pub trait MeterProvider { /// let attributes = AttributeSet::from([ /// KeyValue::new("mykey1", "myvalue1"), /// KeyValue::new("mykey2", "myvalue2"), -/// ].as_slice()); +/// ]); /// /// // Record measurements using the counter instrument add() /// u64_counter.add(10, attributes.clone()); diff --git a/stress/src/metrics.rs b/stress/src/metrics.rs index 2c124ed7ab..55b2b80b3c 100644 --- a/stress/src/metrics.rs +++ b/stress/src/metrics.rs @@ -42,7 +42,6 @@ fn test_counter() { KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]), KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]), ] - .as_slice() .into(), ); } From 4b61676a129e3b23b57df91524ecdf0200e2fe8b Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Thu, 30 Nov 2023 16:24:26 -0500 Subject: [PATCH 05/31] Initial mod comment --- opentelemetry/src/attributes/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/opentelemetry/src/attributes/mod.rs b/opentelemetry/src/attributes/mod.rs index 1182e996fb..8f7d51d17d 100644 --- a/opentelemetry/src/attributes/mod.rs +++ b/opentelemetry/src/attributes/mod.rs @@ -1,3 +1,5 @@ +//! Utilities for managing attributes for metrics + mod set; pub use set::AttributeSet; From d47e9dfd709f1e4b2a2556ace6b0a7c8225a0ed7 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Fri, 1 Dec 2023 14:34:27 -0500 Subject: [PATCH 06/31] Update benchmarks --- opentelemetry-sdk/benches/attribute_set.rs | 10 +-- opentelemetry-sdk/benches/metric.rs | 67 +++++++++++++-------- opentelemetry-sdk/benches/metric_counter.rs | 10 +-- 3 files changed, 52 insertions(+), 35 deletions(-) diff --git a/opentelemetry-sdk/benches/attribute_set.rs b/opentelemetry-sdk/benches/attribute_set.rs index 6f3360b9cf..cd9eb0063f 100644 --- a/opentelemetry-sdk/benches/attribute_set.rs +++ b/opentelemetry-sdk/benches/attribute_set.rs @@ -1,6 +1,6 @@ use criterion::{criterion_group, criterion_main, Criterion}; +use opentelemetry::attributes::AttributeSet; use opentelemetry::KeyValue; -use opentelemetry_sdk::AttributeSet; // Run this benchmark with: // cargo bench --bench metric_counter @@ -12,25 +12,25 @@ fn criterion_benchmark(c: &mut Criterion) { fn attribute_set(c: &mut Criterion) { c.bench_function("AttributeSet_without_duplicates", |b| { b.iter(|| { - let attributes: &[KeyValue] = &[ + let attributes = [ KeyValue::new("attribute1", "value1"), KeyValue::new("attribute2", "value2"), KeyValue::new("attribute3", "value3"), KeyValue::new("attribute4", "value4"), ]; - let _attribute_set: AttributeSet = attributes.into(); + let _attribute_set: AttributeSet = AttributeSet::from(attributes); }); }); c.bench_function("AttributeSet_with_duplicates", |b| { b.iter(|| { - let attributes: &[KeyValue] = &[ + let attributes = [ KeyValue::new("attribute1", "value1"), KeyValue::new("attribute3", "value3"), KeyValue::new("attribute3", "value3"), KeyValue::new("attribute4", "value4"), ]; - let _attribute_set: AttributeSet = attributes.into(); + let _attribute_set: AttributeSet = AttributeSet::from(attributes); }); }); } diff --git a/opentelemetry-sdk/benches/metric.rs b/opentelemetry-sdk/benches/metric.rs index d018634e04..055cd086d8 100644 --- a/opentelemetry-sdk/benches/metric.rs +++ b/opentelemetry-sdk/benches/metric.rs @@ -2,6 +2,7 @@ use rand::Rng; use std::sync::{Arc, Weak}; use criterion::{criterion_group, criterion_main, Bencher, Criterion}; +use opentelemetry::attributes::AttributeSet; use opentelemetry::{ metrics::{Counter, Histogram, MeterProvider as _, Result}, Key, KeyValue, @@ -166,24 +167,29 @@ fn counters(c: &mut Criterion) { let (_, cntr3) = bench_counter(None, "cumulative"); let mut group = c.benchmark_group("Counter"); - group.bench_function("AddNoAttrs", |b| b.iter(|| cntr.add(1, &[]))); - group.bench_function("AddNoAttrsDelta", |b| b.iter(|| cntr2.add(1, &[]))); + group.bench_function("AddNoAttrs", |b| { + b.iter(|| cntr.add(1, AttributeSet::default())) + }); + group.bench_function("AddNoAttrsDelta", |b| { + b.iter(|| cntr2.add(1, AttributeSet::default())) + }); group.bench_function("AddOneAttr", |b| { - b.iter(|| cntr.add(1, &[KeyValue::new("K", "V")])) + b.iter(|| cntr.add(1, [KeyValue::new("K", "V")].into())) }); group.bench_function("AddOneAttrDelta", |b| { - b.iter(|| cntr2.add(1, &[KeyValue::new("K1", "V1")])) + b.iter(|| cntr2.add(1, [KeyValue::new("K1", "V1")].into())) }); group.bench_function("AddThreeAttr", |b| { b.iter(|| { cntr.add( 1, - &[ + [ KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ], + ] + .into(), ) }) }); @@ -191,11 +197,12 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - &[ + [ KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ], + ] + .into(), ) }) }); @@ -203,13 +210,14 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - &[ + [ KeyValue::new("K5", "V5"), KeyValue::new("K6", "V6"), KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ], + ] + .into(), ) }) }); @@ -217,13 +225,14 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - &[ + [ KeyValue::new("K5", "V5"), KeyValue::new("K6", "V6"), KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ], + ] + .into(), ) }) }); @@ -231,7 +240,7 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - &[ + [ KeyValue::new("K10", "V10"), KeyValue::new("K11", "V11"), KeyValue::new("K12", "V12"), @@ -242,7 +251,8 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ], + ] + .into(), ) }) }); @@ -250,7 +260,7 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - &[ + [ KeyValue::new("K10", "V10"), KeyValue::new("K11", "V11"), KeyValue::new("K12", "V12"), @@ -261,7 +271,8 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ], + ] + .into(), ) }) }); @@ -274,29 +285,31 @@ fn counters(c: &mut Criterion) { } group.bench_function("AddOneTillMaxAttr", |b| { - b.iter(|| cntr3.add(1, &max_attributes)) + b.iter(|| cntr3.add(1, max_attributes.clone().into())) }); for i in MAX_DATA_POINTS..MAX_DATA_POINTS * 2 { max_attributes.push(KeyValue::new(i.to_string(), i)) } - group.bench_function("AddMaxAttr", |b| b.iter(|| cntr3.add(1, &max_attributes))); + group.bench_function("AddMaxAttr", |b| { + b.iter(|| cntr3.add(1, max_attributes.clone().into())) + }); group.bench_function("AddInvalidAttr", |b| { - b.iter(|| cntr.add(1, &[KeyValue::new("", "V"), KeyValue::new("K", "V")])) + b.iter(|| cntr.add(1, [KeyValue::new("", "V"), KeyValue::new("K", "V")].into())) }); group.bench_function("AddSingleUseAttrs", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, &[KeyValue::new("K", v)]); + cntr.add(1, [KeyValue::new("K", v)].into()); v += 1; }) }); group.bench_function("AddSingleUseInvalid", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, &[KeyValue::new("", v), KeyValue::new("K", v)]); + cntr.add(1, [KeyValue::new("", v), KeyValue::new("K", v)].into()); v += 1; }) }); @@ -315,7 +328,7 @@ fn counters(c: &mut Criterion) { group.bench_function("AddSingleUseFiltered", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, &[KeyValue::new("L", v), KeyValue::new("K", v)]); + cntr.add(1, [KeyValue::new("L", v), KeyValue::new("K", v)].into()); v += 1; }) }); @@ -329,7 +342,7 @@ fn counters(c: &mut Criterion) { group.bench_function("CollectOneAttr", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, &[KeyValue::new("K", v)]); + cntr.add(1, [KeyValue::new("K", v)].into()); let _ = rdr.collect(&mut rm); v += 1; }) @@ -339,7 +352,7 @@ fn counters(c: &mut Criterion) { let mut v = 0; b.iter(|| { for i in 0..10 { - cntr.add(1, &[KeyValue::new("K", i)]); + cntr.add(1, [KeyValue::new("K", i)].into()); } let _ = rdr.collect(&mut rm); v += 1; @@ -393,10 +406,12 @@ fn histograms(c: &mut Criterion) { format!("V,{},{},{}", bound_size, attr_size, i), )) } + + let attributes = AttributeSet::from(attributes); let value: u64 = rng.gen_range(0..MAX_BOUND).try_into().unwrap(); group.bench_function( format!("Record{}Attrs{}bounds", attr_size, bound_size), - |b| b.iter(|| hist.record(value, &attributes)), + |b| b.iter(|| hist.record(value, attributes.clone())), ); } } @@ -415,7 +430,7 @@ fn benchmark_collect_histogram(b: &mut Bencher, n: usize) { for i in 0..n { let h = mtr.u64_histogram(format!("fake_data_{i}")).init(); - h.record(1, &[]); + h.record(1, AttributeSet::default()); } let mut rm = ResourceMetrics { diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index ba21da07c8..08ec5a2fb8 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -38,12 +38,13 @@ fn counter_add(c: &mut Criterion) { let index_forth_attribute = rng.gen_range(0..10); counter.add( 1, - &[ + [ KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ], + ] + .into(), ); }); }); @@ -58,12 +59,13 @@ fn counter_add(c: &mut Criterion) { let index_forth_attribute = rng.gen_range(0..10); counter.add( 1, - &[ + [ KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ], + ] + .into(), ); }); }); From 3cf8b13425a5a8618ad4ba6ca08c6c61cdca501e Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Fri, 1 Dec 2023 14:59:28 -0500 Subject: [PATCH 07/31] Add benchmark and stress test --- opentelemetry-sdk/benches/metric_counter.rs | 14 ++++++ opentelemetry/src/attributes/set.rs | 3 ++ stress/Cargo.toml | 5 ++ stress/src/metrics_cached_attrs.rs | 53 +++++++++++++++++++++ 4 files changed, 75 insertions(+) create mode 100644 stress/src/metrics_cached_attrs.rs diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index 08ec5a2fb8..7654e7d98a 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -1,4 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; +use opentelemetry::attributes::AttributeSet; use opentelemetry::{ metrics::{Counter, MeterProvider as _}, KeyValue, @@ -69,6 +70,19 @@ fn counter_add(c: &mut Criterion) { ); }); }); + + c.bench_function("Counter_Add_Cached_Attributes", |b| { + let attributes = AttributeSet::from([ + KeyValue::new("attribute2", attribute_values[0]), + KeyValue::new("attribute3", attribute_values[1]), + KeyValue::new("attribute1", attribute_values[2]), + KeyValue::new("attribute4", attribute_values[3]), + ]); + + b.iter(|| { + counter.add(1, attributes); + }); + }); } criterion_group!(benches, criterion_benchmark); diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index a1a5b4c246..07be117f4a 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -179,6 +179,9 @@ impl Hash for InternalAttributeSet { /// A unique set of attributes that can be used as instrument identifiers. /// +/// Cloning of an attribute set is cheap, as all clones share a reference to the underlying +/// attribute data. +/// /// This must implement [Hash], [PartialEq], and [Eq] so it may be used as /// HashMap keys and other de-duplication methods. #[derive(Clone, Debug, Hash, PartialEq, Eq)] diff --git a/stress/Cargo.toml b/stress/Cargo.toml index b3b6211b04..7d42d0c737 100644 --- a/stress/Cargo.toml +++ b/stress/Cargo.toml @@ -9,6 +9,11 @@ name = "metrics" path = "src/metrics.rs" doc = false +[[bin]] # Bin to run the metrics cached attributes stress tests +name = "metrics_cached_attrs" +path = "src/metrics_cached_attrs.rs" +doc = false + [[bin]] # Bin to run the logs stress tests name = "logs" path = "src/logs.rs" diff --git a/stress/src/metrics_cached_attrs.rs b/stress/src/metrics_cached_attrs.rs new file mode 100644 index 0000000000..5d5e019879 --- /dev/null +++ b/stress/src/metrics_cached_attrs.rs @@ -0,0 +1,53 @@ +use lazy_static::lazy_static; +use opentelemetry::attributes::AttributeSet; +use opentelemetry::{ + metrics::{Counter, MeterProvider as _}, + KeyValue, +}; +use opentelemetry_sdk::metrics::{ManualReader, SdkMeterProvider}; +use rand::{rngs::SmallRng, Rng, SeedableRng}; +use std::borrow::Cow; + +mod throughput; + +lazy_static! { + static ref PROVIDER: SdkMeterProvider = SdkMeterProvider::builder() + .with_reader(ManualReader::builder().build()) + .build(); + static ref ATTRIBUTE_VALUES: [&'static str; 10] = [ + "value1", "value2", "value3", "value4", "value5", "value6", "value7", "value8", "value9", + "value10" + ]; + static ref COUNTER: Counter = PROVIDER + .meter(<&str as Into>>::into("test")) + .u64_counter("hello") + .init(); + static ref ATTRIBUTE_SETS: Vec = { + let mut vec = Vec::new(); + for i0 in 0..ATTRIBUTE_VALUES.len() { + for i1 in 0..ATTRIBUTE_VALUES.len() { + for i2 in 0..ATTRIBUTE_VALUES.len() { + vec.push([ + KeyValue::new("attribute1", ATTRIBUTE_VALUES[i0]), + KeyValue::new("attribute2", ATTRIBUTE_VALUES[i1]), + KeyValue::new("attribute3", ATTRIBUTE_VALUES[i2]), + ].into()) + } + } + } + + vec + }; +} + +fn main() { + throughput::test_throughput(test_counter); +} + +fn test_counter() { + let mut rng = SmallRng::from_entropy(); + let len = ATTRIBUTE_SETS.len(); + let index = rng.gen_range(0..len); + + COUNTER.add(1, ATTRIBUTE_SETS[index].clone()); +} From 1cb67fc264c19fbcda6514dddc7c1e49a43e1739 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Fri, 1 Dec 2023 15:18:23 -0500 Subject: [PATCH 08/31] counter compile error --- opentelemetry-sdk/benches/metric_counter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index 7654e7d98a..a2c2850168 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -80,7 +80,7 @@ fn counter_add(c: &mut Criterion) { ]); b.iter(|| { - counter.add(1, attributes); + counter.add(1, attributes.clone()); }); }); } From 3160dad5bcaa667dd5db40fc27937ea79c1121ee Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Fri, 1 Dec 2023 16:20:11 -0500 Subject: [PATCH 09/31] Unignore spatial aggregation test as requested --- opentelemetry-sdk/src/metrics/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 35c5cecd0f..3861955534 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -269,7 +269,6 @@ mod tests { // "multi_thread" tokio flavor must be used else flush won't // be able to make progress! #[tokio::test(flavor = "multi_thread", worker_threads = 1)] - #[ignore = "Spatial aggregation is not yet implemented."] async fn spatial_aggregation_when_view_drops_attributes_observable_counter() { // cargo test spatial_aggregation_when_view_drops_attributes_observable_counter --features=metrics,testing From 5ad5b7bf57ea73121a587a480d127429664c6413 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Fri, 1 Dec 2023 16:21:14 -0500 Subject: [PATCH 10/31] Fmt fix --- stress/src/metrics_cached_attrs.rs | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/stress/src/metrics_cached_attrs.rs b/stress/src/metrics_cached_attrs.rs index 5d5e019879..7c2d605092 100644 --- a/stress/src/metrics_cached_attrs.rs +++ b/stress/src/metrics_cached_attrs.rs @@ -27,11 +27,14 @@ lazy_static! { for i0 in 0..ATTRIBUTE_VALUES.len() { for i1 in 0..ATTRIBUTE_VALUES.len() { for i2 in 0..ATTRIBUTE_VALUES.len() { - vec.push([ - KeyValue::new("attribute1", ATTRIBUTE_VALUES[i0]), - KeyValue::new("attribute2", ATTRIBUTE_VALUES[i1]), - KeyValue::new("attribute3", ATTRIBUTE_VALUES[i2]), - ].into()) + vec.push( + [ + KeyValue::new("attribute1", ATTRIBUTE_VALUES[i0]), + KeyValue::new("attribute2", ATTRIBUTE_VALUES[i1]), + KeyValue::new("attribute3", ATTRIBUTE_VALUES[i2]), + ] + .into(), + ) } } } From c0e9878096826858afeb9a73ef3a90ad15c56386 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Fri, 1 Dec 2023 16:23:52 -0500 Subject: [PATCH 11/31] Fixed compile errors after merge --- opentelemetry-sdk/src/metrics/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 3861955534..72613cce3e 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -246,7 +246,7 @@ mod tests { .with_unit(Unit::new("test_unit")) .init(); - histogram.record(1.5, &[KeyValue::new("key1", "value1")]); + histogram.record(1.5, [KeyValue::new("key1", "value1")].into()); meter_provider.force_flush().unwrap(); // Assert @@ -301,7 +301,7 @@ mod tests { KeyValue::new("statusCode", "200"), KeyValue::new("verb", "get"), ] - .as_ref(), + .into(), ); observer.observe_u64( @@ -311,7 +311,7 @@ mod tests { KeyValue::new("statusCode", "200"), KeyValue::new("verb", "post"), ] - .as_ref(), + .into(), ); observer.observe_u64( @@ -321,7 +321,7 @@ mod tests { KeyValue::new("statusCode", "500"), KeyValue::new("verb", "get"), ] - .as_ref(), + .into(), ); }) .expect("Expected to register callback"); @@ -385,7 +385,7 @@ mod tests { KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Get"), ] - .as_ref(), + .into(), ); counter.add( @@ -394,7 +394,7 @@ mod tests { KeyValue::new("statusCode", "500"), KeyValue::new("verb", "Get"), ] - .as_ref(), + .into(), ); counter.add( @@ -403,7 +403,7 @@ mod tests { KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Post"), ] - .as_ref(), + .into(), ); meter_provider.force_flush().unwrap(); From 5b2ef1a06d6a445601a6451dfd3f88f4a2636f8f Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Tue, 5 Dec 2023 12:09:55 -0500 Subject: [PATCH 12/31] Counters and histograms can now have any value that can be converted into an attribute set --- examples/metrics-advanced/src/main.rs | 15 ++---- examples/metrics-basic/src/main.rs | 9 ++-- .../tests/integration_test.rs | 52 +++++++++---------- opentelemetry-sdk/benches/metric.rs | 38 ++++++-------- opentelemetry-sdk/benches/metric_counter.rs | 6 +-- opentelemetry-sdk/src/metrics/mod.rs | 27 +++++----- opentelemetry-stdout/examples/basic.rs | 2 +- .../src/metrics/instruments/counter.rs | 4 +- .../src/metrics/instruments/histogram.rs | 4 +- .../metrics/instruments/up_down_counter.rs | 4 +- stress/src/metrics.rs | 3 +- 11 files changed, 72 insertions(+), 92 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index 4394cf1453..a71546080f 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -85,8 +85,7 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ] - .into(), + ], ); // Example 2 - Drop unwanted attributes using view. @@ -103,8 +102,7 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ] - .into(), + ], ); // Example 3 - Change Aggregation configuration using View. @@ -127,8 +125,7 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ] - .into(), + ], ); histogram2.record( @@ -138,8 +135,7 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ] - .into(), + ], ); histogram2.record( @@ -149,8 +145,7 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ] - .into(), + ], ); // Metrics are exported by default every 30 seconds when using stdout exporter, diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index e89355882f..1a3ebd7063 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -37,8 +37,7 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ], ); // Create a ObservableCounter instrument and register a callback that reports the measurement. @@ -69,8 +68,7 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ], ); // Create a Observable UpDownCounter instrument and register a callback that reports the measurement. @@ -104,8 +102,7 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ], ); // Note that there is no ObservableHistogram instrument. diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs index d9c26cceb3..83c4315709 100644 --- a/opentelemetry-prometheus/tests/integration_test.rs +++ b/opentelemetry-prometheus/tests/integration_test.rs @@ -67,7 +67,7 @@ fn prometheus_exporter_integration() { Key::new("E").bool(true), Key::new("F").i64(42), ]; - counter.add(5.0, attrs2.into()); + counter.add(5.0, attrs2); }), ..Default::default() }, @@ -97,7 +97,7 @@ fn prometheus_exporter_integration() { Key::new("E").bool(true), Key::new("F").i64(42), ]; - counter.add(5.0, attrs2.into()); + counter.add(5.0, attrs2); }), ..Default::default() }, @@ -415,7 +415,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter foo counter") .init(); - foo_counter.add(100, [KeyValue::new("type", "foo")].into()); + foo_counter.add(100, [KeyValue::new("type", "foo")]); let bar_counter = provider .versioned_meter("meterbar", Some("v0.1.0"), None::<&'static str>, None) @@ -423,7 +423,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter bar counter") .init(); - bar_counter.add(200, [KeyValue::new("type", "bar")].into()); + bar_counter.add(200, [KeyValue::new("type", "bar")]); let content = fs::read_to_string("./tests/data/multi_scopes.txt").unwrap(); gather_and_compare(registry, content, "multi_scope"); @@ -462,7 +462,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")].into()); + foo_a.add(100, [KeyValue::new("A", "B")]); let foo_b = meter_b .u64_counter("foo") @@ -470,7 +470,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_b.add(100, [KeyValue::new("A", "B")].into()); + foo_b.add(100, [KeyValue::new("A", "B")]); }), expected_files: vec!["no_conflict_two_counters.txt"], ..Default::default() @@ -484,7 +484,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")].into()); + foo_a.add(100, [KeyValue::new("A", "B")]); let foo_b = meter_b .i64_up_down_counter("foo") @@ -492,7 +492,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_b.add(100, [KeyValue::new("A", "B")].into()); + foo_b.add(100, [KeyValue::new("A", "B")]); }), expected_files: vec!["no_conflict_two_updowncounters.txt"], ..Default::default() @@ -506,7 +506,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_a.record(100, [KeyValue::new("A", "B")].into()); + foo_a.record(100, [KeyValue::new("A", "B")]); let foo_b = meter_b .u64_histogram("foo") @@ -514,7 +514,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_b.record(100, [KeyValue::new("A", "B")].into()); + foo_b.record(100, [KeyValue::new("A", "B")]); }), expected_files: vec!["no_conflict_two_histograms.txt"], ..Default::default() @@ -528,7 +528,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")].into()); + bar_a.add(100, [KeyValue::new("type", "bar")]); let bar_b = meter_b .u64_counter("bar") @@ -536,7 +536,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")].into()); + bar_b.add(100, [KeyValue::new("type", "bar")]); }), expected_files: vec![ "conflict_help_two_counters_1.txt", @@ -553,7 +553,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")].into()); + bar_a.add(100, [KeyValue::new("type", "bar")]); let bar_b = meter_b .i64_up_down_counter("bar") @@ -561,7 +561,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")].into()); + bar_b.add(100, [KeyValue::new("type", "bar")]); }), expected_files: vec![ "conflict_help_two_updowncounters_1.txt", @@ -578,7 +578,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.record(100, [KeyValue::new("A", "B")].into()); + bar_a.record(100, [KeyValue::new("A", "B")]); let bar_b = meter_b .u64_histogram("bar") @@ -586,7 +586,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.record(100, [KeyValue::new("A", "B")].into()); + bar_b.record(100, [KeyValue::new("A", "B")]); }), expected_files: vec![ "conflict_help_two_histograms_1.txt", @@ -603,7 +603,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_a.add(100, [KeyValue::new("type", "bar")].into()); + baz_a.add(100, [KeyValue::new("type", "bar")]); let baz_b = meter_b .u64_counter("bar") @@ -611,7 +611,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_b.add(100, [KeyValue::new("type", "bar")].into()); + baz_b.add(100, [KeyValue::new("type", "bar")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_counters.txt"], @@ -626,7 +626,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")].into()); + bar_a.add(100, [KeyValue::new("type", "bar")]); let bar_b = meter_b .i64_up_down_counter("bar") @@ -634,7 +634,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")].into()); + bar_b.add(100, [KeyValue::new("type", "bar")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_updowncounters.txt"], @@ -649,7 +649,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_a.record(100, [KeyValue::new("A", "B")].into()); + bar_a.record(100, [KeyValue::new("A", "B")]); let bar_b = meter_b .u64_histogram("bar") @@ -657,7 +657,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_b.record(100, [KeyValue::new("A", "B")].into()); + bar_b.record(100, [KeyValue::new("A", "B")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_histograms.txt"], @@ -672,7 +672,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - counter.add(100, [KeyValue::new("type", "foo")].into()); + counter.add(100, [KeyValue::new("type", "foo")]); let gauge = meter_a .i64_up_down_counter("foo_total") @@ -680,7 +680,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - gauge.add(200, [KeyValue::new("type", "foo")].into()); + gauge.add(200, [KeyValue::new("type", "foo")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec![ @@ -698,7 +698,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")].into()); + foo_a.add(100, [KeyValue::new("A", "B")]); let foo_histogram_a = meter_a .u64_histogram("foo") @@ -706,7 +706,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_histogram_a.record(100, [KeyValue::new("A", "B")].into()); + foo_histogram_a.record(100, [KeyValue::new("A", "B")]); }), expected_files: vec![ "conflict_type_histogram_and_updowncounter_1.txt", diff --git a/opentelemetry-sdk/benches/metric.rs b/opentelemetry-sdk/benches/metric.rs index 055cd086d8..2ad0834cb9 100644 --- a/opentelemetry-sdk/benches/metric.rs +++ b/opentelemetry-sdk/benches/metric.rs @@ -175,10 +175,10 @@ fn counters(c: &mut Criterion) { }); group.bench_function("AddOneAttr", |b| { - b.iter(|| cntr.add(1, [KeyValue::new("K", "V")].into())) + b.iter(|| cntr.add(1, [KeyValue::new("K", "V")])) }); group.bench_function("AddOneAttrDelta", |b| { - b.iter(|| cntr2.add(1, [KeyValue::new("K1", "V1")].into())) + b.iter(|| cntr2.add(1, [KeyValue::new("K1", "V1")])) }); group.bench_function("AddThreeAttr", |b| { b.iter(|| { @@ -188,8 +188,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ] - .into(), + ], ) }) }); @@ -201,8 +200,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ] - .into(), + ], ) }) }); @@ -216,8 +214,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ] - .into(), + ], ) }) }); @@ -231,8 +228,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ] - .into(), + ], ) }) }); @@ -251,8 +247,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ] - .into(), + ], ) }) }); @@ -271,8 +266,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ] - .into(), + ], ) }) }); @@ -285,7 +279,7 @@ fn counters(c: &mut Criterion) { } group.bench_function("AddOneTillMaxAttr", |b| { - b.iter(|| cntr3.add(1, max_attributes.clone().into())) + b.iter(|| cntr3.add(1, max_attributes.clone())) }); for i in MAX_DATA_POINTS..MAX_DATA_POINTS * 2 { @@ -293,23 +287,23 @@ fn counters(c: &mut Criterion) { } group.bench_function("AddMaxAttr", |b| { - b.iter(|| cntr3.add(1, max_attributes.clone().into())) + b.iter(|| cntr3.add(1, max_attributes.clone())) }); group.bench_function("AddInvalidAttr", |b| { - b.iter(|| cntr.add(1, [KeyValue::new("", "V"), KeyValue::new("K", "V")].into())) + b.iter(|| cntr.add(1, [KeyValue::new("", "V"), KeyValue::new("K", "V")])) }); group.bench_function("AddSingleUseAttrs", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("K", v)].into()); + cntr.add(1, [KeyValue::new("K", v)]); v += 1; }) }); group.bench_function("AddSingleUseInvalid", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("", v), KeyValue::new("K", v)].into()); + cntr.add(1, [KeyValue::new("", v), KeyValue::new("K", v)]); v += 1; }) }); @@ -328,7 +322,7 @@ fn counters(c: &mut Criterion) { group.bench_function("AddSingleUseFiltered", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("L", v), KeyValue::new("K", v)].into()); + cntr.add(1, [KeyValue::new("L", v), KeyValue::new("K", v)]); v += 1; }) }); @@ -342,7 +336,7 @@ fn counters(c: &mut Criterion) { group.bench_function("CollectOneAttr", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("K", v)].into()); + cntr.add(1, [KeyValue::new("K", v)]); let _ = rdr.collect(&mut rm); v += 1; }) @@ -352,7 +346,7 @@ fn counters(c: &mut Criterion) { let mut v = 0; b.iter(|| { for i in 0..10 { - cntr.add(1, [KeyValue::new("K", i)].into()); + cntr.add(1, [KeyValue::new("K", i)]); } let _ = rdr.collect(&mut rm); v += 1; diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index 123047ed35..1307f459dd 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -44,8 +44,7 @@ fn counter_add(c: &mut Criterion) { KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ] - .into(), + ], ); }); }); @@ -65,8 +64,7 @@ fn counter_add(c: &mut Criterion) { KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ] - .into(), + ], ); }); }); diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 72613cce3e..a95bdd78ac 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -88,15 +88,15 @@ mod tests { .u64_counter("my_counter") .with_unit(Unit::new("my_unit")) .init(); - counter.add(1, [KeyValue::new("key1", "value1")].into()); - counter.add(1, [KeyValue::new("key1", "value1")].into()); - counter.add(1, [KeyValue::new("key1", "value1")].into()); - counter.add(1, [KeyValue::new("key1", "value1")].into()); - counter.add(1, [KeyValue::new("key1", "value1")].into()); + counter.add(1, [KeyValue::new("key1", "value1")]); + counter.add(1, [KeyValue::new("key1", "value1")]); + counter.add(1, [KeyValue::new("key1", "value1")]); + counter.add(1, [KeyValue::new("key1", "value1")]); + counter.add(1, [KeyValue::new("key1", "value1")]); - counter.add(1, [KeyValue::new("key1", "value2")].into()); - counter.add(1, [KeyValue::new("key1", "value2")].into()); - counter.add(1, [KeyValue::new("key1", "value2")].into()); + counter.add(1, [KeyValue::new("key1", "value2")]); + counter.add(1, [KeyValue::new("key1", "value2")]); + counter.add(1, [KeyValue::new("key1", "value2")]); meter_provider.force_flush().unwrap(); @@ -246,7 +246,7 @@ mod tests { .with_unit(Unit::new("test_unit")) .init(); - histogram.record(1.5, [KeyValue::new("key1", "value1")].into()); + histogram.record(1.5, [KeyValue::new("key1", "value1")]); meter_provider.force_flush().unwrap(); // Assert @@ -384,8 +384,7 @@ mod tests { [ KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Get"), - ] - .into(), + ], ); counter.add( @@ -393,8 +392,7 @@ mod tests { [ KeyValue::new("statusCode", "500"), KeyValue::new("verb", "Get"), - ] - .into(), + ], ); counter.add( @@ -402,8 +400,7 @@ mod tests { [ KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Post"), - ] - .into(), + ], ); meter_provider.force_flush().unwrap(); diff --git a/opentelemetry-stdout/examples/basic.rs b/opentelemetry-stdout/examples/basic.rs index 462144e47f..3e9733bc2d 100644 --- a/opentelemetry-stdout/examples/basic.rs +++ b/opentelemetry-stdout/examples/basic.rs @@ -45,7 +45,7 @@ async fn main() -> Result<(), Box> { let meter = meter_provider.meter("stdout-test"); let c = meter.u64_counter("test_events").init(); - c.add(1, [KeyValue::new("test_key", "test_value")].into()); + c.add(1, [KeyValue::new("test_key", "test_value")]); meter_provider.shutdown()?; diff --git a/opentelemetry/src/metrics/instruments/counter.rs b/opentelemetry/src/metrics/instruments/counter.rs index e99c023ecb..f437e08099 100644 --- a/opentelemetry/src/metrics/instruments/counter.rs +++ b/opentelemetry/src/metrics/instruments/counter.rs @@ -30,8 +30,8 @@ impl Counter { } /// Records an increment to the counter. - pub fn add(&self, value: T, attributes: AttributeSet) { - self.0.add(value, attributes) + pub fn add(&self, value: T, attributes: impl Into) { + self.0.add(value, attributes.into()) } } diff --git a/opentelemetry/src/metrics/instruments/histogram.rs b/opentelemetry/src/metrics/instruments/histogram.rs index 3aa4346300..d4ec5cad61 100644 --- a/opentelemetry/src/metrics/instruments/histogram.rs +++ b/opentelemetry/src/metrics/instruments/histogram.rs @@ -30,8 +30,8 @@ impl Histogram { } /// Adds an additional value to the distribution. - pub fn record(&self, value: T, attributes: AttributeSet) { - self.0.record(value, attributes) + pub fn record(&self, value: T, attributes: impl Into) { + self.0.record(value, attributes.into()) } } diff --git a/opentelemetry/src/metrics/instruments/up_down_counter.rs b/opentelemetry/src/metrics/instruments/up_down_counter.rs index b864c7a054..0ac1833d55 100644 --- a/opentelemetry/src/metrics/instruments/up_down_counter.rs +++ b/opentelemetry/src/metrics/instruments/up_down_counter.rs @@ -35,8 +35,8 @@ impl UpDownCounter { } /// Records an increment or decrement to the counter. - pub fn add(&self, value: T, attributes: AttributeSet) { - self.0.add(value, attributes) + pub fn add(&self, value: T, attributes: impl Into) { + self.0.add(value, attributes.into()) } } diff --git a/stress/src/metrics.rs b/stress/src/metrics.rs index 55b2b80b3c..0c78e9cc8e 100644 --- a/stress/src/metrics.rs +++ b/stress/src/metrics.rs @@ -41,7 +41,6 @@ fn test_counter() { KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]), KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]), KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]), - ] - .into(), + ], ); } From 26afa6ebd1332958f4cd8cbcf7fa2536f4f734d2 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Tue, 5 Dec 2023 16:08:13 -0500 Subject: [PATCH 13/31] Added attribute set test coverage --- opentelemetry-sdk/src/attributes/set.rs | 26 ++++++ opentelemetry/src/attributes/set.rs | 108 ++++++++++++++++++++++++ 2 files changed, 134 insertions(+) diff --git a/opentelemetry-sdk/src/attributes/set.rs b/opentelemetry-sdk/src/attributes/set.rs index 58007809b4..23230dd3e1 100644 --- a/opentelemetry-sdk/src/attributes/set.rs +++ b/opentelemetry-sdk/src/attributes/set.rs @@ -12,3 +12,29 @@ impl From<&Resource> for AttributeSet { AttributeSet::from(key_values) } } + +#[cfg(test)] +mod tests { + use super::*; + use opentelemetry::{Key, Value}; + + #[test] + fn can_create_attribute_set_from_resource() { + let resource = Resource::new([KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]); + + let set = AttributeSet::from(&resource); + let mut kvs = set.iter().collect::>(); + + assert_eq!(kvs.len(), 2, "Incorrect number of attributes"); + + kvs.sort_by(|kv1, kv2| kv1.0.cmp(kv2.0)); + assert_eq!(kvs[0].0, &Key::from("key1"), "Unexpected first key"); + assert_eq!( + kvs[0].1, + &Value::String("value1".into()), + "Unexpected first value" + ); + assert_eq!(kvs[1].0, &Key::from("key2"), "Unexpected second key"); + assert_eq!(kvs[1].1, &Value::I64(3), "Unexpected second value"); + } +} diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 07be117f4a..544a0bf2ac 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -242,3 +242,111 @@ impl Default for AttributeSet { AttributeSet(EMPTY_SET.clone()) } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_create_attribute_set_from_array() { + let array = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + + let set = AttributeSet::from(array); + let mut kvs = set.iter().collect::>(); + + assert_eq!(kvs.len(), 2, "Incorrect number of attributes"); + + kvs.sort_by(|kv1, kv2| kv1.0.cmp(kv2.0)); + assert_eq!(kvs[0].0, &Key::from("key1"), "Unexpected first key"); + assert_eq!( + kvs[0].1, + &Value::String("value1".into()), + "Unexpected first value" + ); + assert_eq!(kvs[1].0, &Key::from("key2"), "Unexpected second key"); + assert_eq!(kvs[1].1, &Value::I64(3), "Unexpected second value"); + } + + #[test] + fn two_sets_with_same_key_values_in_different_orders_are_equal() { + let array1 = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + + let array2 = [KeyValue::new("key2", 3), KeyValue::new("key1", "value1")]; + + let set1 = AttributeSet::from(array1); + let set2 = AttributeSet::from(array2); + + assert_eq!(set1, set2); + } + + #[test] + fn two_sets_with_same_key_values_in_different_orders_have_same_hash() { + let array1 = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + + let array2 = [KeyValue::new("key2", 3), KeyValue::new("key1", "value1")]; + + let set1 = AttributeSet::from(array1); + let set2 = AttributeSet::from(array2); + + let mut hasher1 = DefaultHasher::new(); + let mut hasher2 = DefaultHasher::new(); + set1.hash(&mut hasher1); + set2.hash(&mut hasher2); + + assert_eq!(hasher1.finish(), hasher2.finish()); + } + + #[test] + fn clone_with_removes_unspecified_key_values() { + let array = [ + KeyValue::new("key1", "value1"), + KeyValue::new("key2", 3), + KeyValue::new("key3", 4), + ]; + + let set = AttributeSet::from(array); + let set2 = set.clone_with(|kv| kv.key == Key::new("key2")); + + assert_ne!(set, set2, "Both sets were unexpectedly equal"); + assert_eq!(set2.len(), 1, "Expected only one attribute in new set"); + + let kvs = set2.iter().collect::>(); + assert_eq!(kvs[0].0, &Key::from("key2"), "Unexpected key"); + assert_eq!(kvs[0].1, &Value::I64(3), "Unexpected value"); + } + + #[test] + fn len_returns_accurate_value() { + let array = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + + let set = AttributeSet::from(array); + let kvs = set.iter().collect::>(); + + assert_eq!(set.len(), kvs.len()); + } + + #[test] + fn empty_when_no_attributes_provided() { + let set = AttributeSet::from([]); + assert!(set.is_empty()); + } + + #[test] + fn default_set_has_no_attributes() { + let set = AttributeSet::default(); + assert!(set.is_empty()); + assert_eq!(set.len(), 0); + } + + #[test] + fn last_key_wins_for_deduplication() { + let array = [KeyValue::new("key1", "value1"), KeyValue::new("key1", 3)]; + + let set = AttributeSet::from(array); + let kvs = set.iter().collect::>(); + + assert_eq!(set.len(), 1, "Expected only a single key value pair"); + assert_eq!(kvs[0].0, &Key::new("key1"), "Unexpected key"); + assert_eq!(kvs[0].1, &Value::I64(3), "Unexpected value"); + } +} From 841798496e08d4f59ca664bdaf6c1819b6536b5e Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Tue, 5 Dec 2023 16:27:59 -0500 Subject: [PATCH 14/31] Removed unused `from_key_values()` function --- opentelemetry/src/attributes/set.rs | 30 ----------------------------- 1 file changed, 30 deletions(-) diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 544a0bf2ac..209aff60e7 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -124,28 +124,6 @@ impl InternalAttributeSet { hash: hasher.finish(), } } - - fn from_key_values>(iter: T) -> Self - where - ::IntoIter: DoubleEndedIterator + ExactSizeIterator, - { - // Note: this doesn't implement `FromIter` because of the additional constraints - let iter = iter.into_iter(); - let mut seen_keys = HashSet::with_capacity(iter.len()); - let vec = iter - .into_iter() - .rev() - .filter_map(|kv| { - if seen_keys.insert(kv.key.clone()) { - Some(HashKeyValue(kv.clone())) - } else { - None - } - }) - .collect::>(); - - InternalAttributeSet::new(vec) - } } impl> From for InternalAttributeSet @@ -197,14 +175,6 @@ where } impl AttributeSet { - /// Creates an attribute set from an iterator of `KeyValue`s - pub fn from_key_values>(iter: T) -> Self - where - ::IntoIter: DoubleEndedIterator + ExactSizeIterator, - { - AttributeSet(Arc::new(InternalAttributeSet::from_key_values(iter))) - } - /// Returns the number of elements in the set. pub fn len(&self) -> usize { self.0.key_values.len() From 9e85ddc3914a4de81eed37c996470697c5342fd9 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Tue, 5 Dec 2023 16:38:32 -0500 Subject: [PATCH 15/31] Added more value types for better equality checks --- opentelemetry/src/attributes/set.rs | 49 ++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 4 deletions(-) diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 209aff60e7..21241ea6dd 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -216,6 +216,7 @@ impl Default for AttributeSet { #[cfg(test)] mod tests { use super::*; + use crate::StringValue; #[test] fn can_create_attribute_set_from_array() { @@ -239,9 +240,29 @@ mod tests { #[test] fn two_sets_with_same_key_values_in_different_orders_are_equal() { - let array1 = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + let array1 = [ + KeyValue::new("key1", "value1"), + KeyValue::new("key2", 3), + KeyValue::new("key3", Value::Array(Array::Bool(vec![true]))), + KeyValue::new("key4", Value::Array(Array::F64(vec![1.5]))), + KeyValue::new("key5", Value::Array(Array::I64(vec![15]))), + KeyValue::new( + "key6", + Value::Array(Array::String(vec![StringValue::from("test")])), + ), + ]; - let array2 = [KeyValue::new("key2", 3), KeyValue::new("key1", "value1")]; + let array2 = [ + KeyValue::new( + "key6", + Value::Array(Array::String(vec![StringValue::from("test")])), + ), + KeyValue::new("key1", "value1"), + KeyValue::new("key3", Value::Array(Array::Bool(vec![true]))), + KeyValue::new("key4", Value::Array(Array::F64(vec![1.5]))), + KeyValue::new("key5", Value::Array(Array::I64(vec![15]))), + KeyValue::new("key2", 3), + ]; let set1 = AttributeSet::from(array1); let set2 = AttributeSet::from(array2); @@ -251,9 +272,29 @@ mod tests { #[test] fn two_sets_with_same_key_values_in_different_orders_have_same_hash() { - let array1 = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + let array1 = [ + KeyValue::new("key1", "value1"), + KeyValue::new("key2", 3), + KeyValue::new("key3", Value::Array(Array::Bool(vec![true]))), + KeyValue::new("key4", Value::Array(Array::F64(vec![1.5]))), + KeyValue::new("key5", Value::Array(Array::I64(vec![15]))), + KeyValue::new( + "key6", + Value::Array(Array::String(vec![StringValue::from("test")])), + ), + ]; - let array2 = [KeyValue::new("key2", 3), KeyValue::new("key1", "value1")]; + let array2 = [ + KeyValue::new( + "key6", + Value::Array(Array::String(vec![StringValue::from("test")])), + ), + KeyValue::new("key1", "value1"), + KeyValue::new("key3", Value::Array(Array::Bool(vec![true]))), + KeyValue::new("key4", Value::Array(Array::F64(vec![1.5]))), + KeyValue::new("key5", Value::Array(Array::I64(vec![15]))), + KeyValue::new("key2", 3), + ]; let set1 = AttributeSet::from(array1); let set2 = AttributeSet::from(array2); From 46994cb3d593764a2ae2f5a01be38a4b016d2fd5 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 13 Dec 2023 16:35:50 -0500 Subject: [PATCH 16/31] Post merge clippy --- opentelemetry-sdk/src/metrics/instrument.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry-sdk/src/metrics/instrument.rs b/opentelemetry-sdk/src/metrics/instrument.rs index f67109f851..fab4bfbaa3 100644 --- a/opentelemetry-sdk/src/metrics/instrument.rs +++ b/opentelemetry-sdk/src/metrics/instrument.rs @@ -277,7 +277,7 @@ impl SyncUpDownCounter for ResolvedMeasures { impl SyncGauge for ResolvedMeasures { fn record(&self, val: T, attrs: AttributeSet) { for measure in &self.measures { - measure.call(val, AttributeSet::from(attrs.clone())) + measure.call(val, attrs.clone()) } } } From 83f10d323d1dd3d297e6145115c5c55ae4995cca Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 20 Dec 2023 10:15:56 -0500 Subject: [PATCH 17/31] Take shared reference iterators, one less clone --- examples/metrics-advanced/src/main.rs | 21 ++--- examples/metrics-basic/src/main.rs | 33 ++++---- .../examples/basic-otlp-http/src/main.rs | 5 +- .../examples/basic-otlp/src/main.rs | 5 +- opentelemetry-prometheus/examples/hyper.rs | 3 +- .../tests/integration_test.rs | 80 +++++++++---------- opentelemetry-sdk/benches/attribute_set.rs | 4 +- opentelemetry-sdk/benches/metric.rs | 57 +++++++------ opentelemetry-sdk/benches/metric_counter.rs | 10 +-- opentelemetry-sdk/src/attributes/set.rs | 2 +- .../src/metrics/internal/aggregate.rs | 40 +++++----- .../metrics/internal/exponential_histogram.rs | 4 +- opentelemetry-sdk/src/metrics/mod.rs | 35 ++++---- opentelemetry-stdout/examples/basic.rs | 6 +- opentelemetry/src/attributes/set.rs | 31 +++---- stress/src/metrics.rs | 5 +- stress/src/metrics_cached_attrs.rs | 13 ++- 17 files changed, 184 insertions(+), 170 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index a71546080f..74431275e1 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -1,3 +1,4 @@ +use opentelemetry::attributes::AttributeSet; use opentelemetry::metrics::Unit; use opentelemetry::Key; use opentelemetry::{metrics::MeterProvider as _, KeyValue}; @@ -80,12 +81,12 @@ async fn main() -> Result<(), Box> { // Record measurements using the histogram instrument. histogram.record( 10.5, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ]), ); // Example 2 - Drop unwanted attributes using view. @@ -97,12 +98,12 @@ async fn main() -> Result<(), Box> { // attribute. counter.add( 10, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ]), ); // Example 3 - Change Aggregation configuration using View. @@ -120,32 +121,32 @@ async fn main() -> Result<(), Box> { // the change of boundaries. histogram2.record( 1.5, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ]), ); histogram2.record( 1.2, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ]), ); histogram2.record( 1.23, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ]), ); // Metrics are exported by default every 30 seconds when using stdout exporter, diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index c12d4d286f..65e8940b4f 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -1,3 +1,4 @@ +use opentelemetry::attributes::AttributeSet; use opentelemetry::metrics::Unit; use opentelemetry::{metrics::MeterProvider as _, KeyValue}; use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider}; @@ -34,10 +35,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the Counter instrument. counter.add( 10, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ], + ]), ); // Create a ObservableCounter instrument and register a callback that reports the measurement. @@ -51,11 +52,10 @@ async fn main() -> Result<(), Box> { observer.observe_u64( &observable_counter, 100, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ]), ) })?; @@ -65,10 +65,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the UpCounter instrument. updown_counter.add( -10, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ], + ]), ); // Create a Observable UpDownCounter instrument and register a callback that reports the measurement. @@ -82,11 +82,10 @@ async fn main() -> Result<(), Box> { observer.observe_i64( &observable_up_down_counter, 100, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ]), ) })?; @@ -99,10 +98,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the histogram instrument. histogram.record( 10.5, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ], + ]), ); // Note that there is no ObservableHistogram instrument. @@ -119,11 +118,10 @@ async fn main() -> Result<(), Box> { gauge.record( 1.0, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ]), ); } @@ -139,11 +137,10 @@ async fn main() -> Result<(), Box> { observer.observe_f64( &observable_gauge, 1.0, - [ + AttributeSet::from(&[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ] - .into(), + ]), ) })?; diff --git a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs index 88f03a04d5..736a4528f5 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs @@ -64,13 +64,12 @@ const LEMONS_KEY: Key = Key::from_static_str("ex.com/lemons"); const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another"); static COMMON_ATTRIBUTES: Lazy = Lazy::new(|| { - [ + AttributeSet::from(&[ LEMONS_KEY.i64(10), KeyValue::new("A", "1"), KeyValue::new("B", "2"), KeyValue::new("C", "3"), - ] - .into() + ]) }); #[tokio::main] diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index 1691ac1caf..d620419e7d 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -74,13 +74,12 @@ const LEMONS_KEY: Key = Key::from_static_str("lemons"); const ANOTHER_KEY: Key = Key::from_static_str("ex.com/another"); static COMMON_ATTRIBUTES: Lazy = Lazy::new(|| { - [ + AttributeSet::from(&[ LEMONS_KEY.i64(10), KeyValue::new("A", "1"), KeyValue::new("B", "2"), KeyValue::new("C", "3"), - ] - .into() + ]) }); #[tokio::main] diff --git a/opentelemetry-prometheus/examples/hyper.rs b/opentelemetry-prometheus/examples/hyper.rs index 1b8be797ab..ad6e3b7f37 100644 --- a/opentelemetry-prometheus/examples/hyper.rs +++ b/opentelemetry-prometheus/examples/hyper.rs @@ -15,7 +15,8 @@ use std::convert::Infallible; use std::sync::Arc; use std::time::SystemTime; -static HANDLER_ALL: Lazy = Lazy::new(|| [KeyValue::new("handler", "all")].into()); +static HANDLER_ALL: Lazy = + Lazy::new(|| AttributeSet::from(&[KeyValue::new("handler", "all")])); async fn serve_req( req: Request, diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs index 5a59d84dbd..dca301c034 100644 --- a/opentelemetry-prometheus/tests/integration_test.rs +++ b/opentelemetry-prometheus/tests/integration_test.rs @@ -45,7 +45,7 @@ fn prometheus_exporter_integration() { name: "counter", expected_file: "counter.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ Key::new("A").string("B"), Key::new("C").string("D"), Key::new("E").bool(true), @@ -61,12 +61,12 @@ fn prometheus_exporter_integration() { counter.add(10.3, attrs.clone()); counter.add(9.0, attrs.clone()); - let attrs2 = vec![ + let attrs2 = AttributeSet::from(&[ Key::new("A").string("D"), Key::new("C").string("B"), Key::new("E").bool(true), Key::new("F").i64(42), - ]; + ]); counter.add(5.0, attrs2); }), ..Default::default() @@ -76,7 +76,7 @@ fn prometheus_exporter_integration() { expected_file: "counter_disabled_suffix.txt", builder: ExporterBuilder::default().without_counter_suffixes(), record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ Key::new("A").string("B"), Key::new("C").string("D"), Key::new("E").bool(true), @@ -91,12 +91,12 @@ fn prometheus_exporter_integration() { counter.add(5.0, attrs.clone()); counter.add(10.3, attrs.clone()); counter.add(9.0, attrs.clone()); - let attrs2 = [ + let attrs2 = AttributeSet::from(&[ Key::new("A").string("D"), Key::new("C").string("B"), Key::new("E").bool(true), Key::new("F").i64(42), - ]; + ]); counter.add(5.0, attrs2); }), ..Default::default() @@ -106,7 +106,7 @@ fn prometheus_exporter_integration() { expected_file: "gauge.txt", record_metrics: Box::new(|meter| { let attrs = - AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); + AttributeSet::from(&[Key::new("A").string("B"), Key::new("C").string("D")]); let gauge = meter .f64_up_down_counter("bar") .with_description("a fun little gauge") @@ -122,7 +122,7 @@ fn prometheus_exporter_integration() { expected_file: "histogram.txt", record_metrics: Box::new(|meter| { let attrs = - AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); + AttributeSet::from(&[Key::new("A").string("B"), Key::new("C").string("D")]); let histogram = meter .f64_histogram("histogram_baz") .with_description("a very nice histogram") @@ -140,7 +140,7 @@ fn prometheus_exporter_integration() { expected_file: "sanitized_labels.txt", builder: ExporterBuilder::default().without_units(), record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ // exact match, value should be overwritten Key::new("A.B").string("X"), Key::new("A.B").string("Q"), @@ -165,7 +165,7 @@ fn prometheus_exporter_integration() { expected_file: "sanitized_names.txt", record_metrics: Box::new(|meter| { let attrs = - AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); + AttributeSet::from(&[Key::new("A").string("B"), Key::new("C").string("D")]); // Valid. let mut gauge = meter .f64_up_down_counter("bar") @@ -200,7 +200,7 @@ fn prometheus_exporter_integration() { empty_resource: true, expected_file: "empty_resource.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ Key::new("A").string("B"), Key::new("C").string("D"), Key::new("E").bool(true), @@ -221,7 +221,7 @@ fn prometheus_exporter_integration() { custom_resource_attrs: vec![Key::new("A").string("B"), Key::new("C").string("D")], expected_file: "custom_resource.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ Key::new("A").string("B"), Key::new("C").string("D"), Key::new("E").bool(true), @@ -242,7 +242,7 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().without_target_info(), expected_file: "without_target_info.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ Key::new("A").string("B"), Key::new("C").string("D"), Key::new("E").bool(true), @@ -264,7 +264,7 @@ fn prometheus_exporter_integration() { expected_file: "without_scope_info.txt", record_metrics: Box::new(|meter| { let attrs = - AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); + AttributeSet::from(&[Key::new("A").string("B"), Key::new("C").string("D")]); let gauge = meter .i64_up_down_counter("bar") .with_description("a fun little gauge") @@ -283,7 +283,7 @@ fn prometheus_exporter_integration() { expected_file: "without_scope_and_target_info.txt", record_metrics: Box::new(|meter| { let attrs = - AttributeSet::from([Key::new("A").string("B"), Key::new("C").string("D")]); + AttributeSet::from(&[Key::new("A").string("B"), Key::new("C").string("D")]); let counter = meter .u64_counter("bar") .with_description("a fun little counter") @@ -299,7 +299,7 @@ fn prometheus_exporter_integration() { builder: ExporterBuilder::default().with_namespace("test"), expected_file: "with_namespace.txt", record_metrics: Box::new(|meter| { - let attrs = AttributeSet::from([ + let attrs = AttributeSet::from(&[ Key::new("A").string("B"), Key::new("C").string("D"), Key::new("E").bool(true), @@ -424,7 +424,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter foo counter") .init(); - foo_counter.add(100, [KeyValue::new("type", "foo")]); + foo_counter.add(100, &[KeyValue::new("type", "foo")]); let bar_counter = provider .versioned_meter( @@ -437,7 +437,7 @@ fn multiple_scopes() { .with_unit(Unit::new("ms")) .with_description("meter bar counter") .init(); - bar_counter.add(200, [KeyValue::new("type", "bar")]); + bar_counter.add(200, &[KeyValue::new("type", "bar")]); let content = fs::read_to_string("./tests/data/multi_scopes.txt").unwrap(); gather_and_compare(registry, content, "multi_scope"); @@ -476,7 +476,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")]); + foo_a.add(100, &[KeyValue::new("A", "B")]); let foo_b = meter_b .u64_counter("foo") @@ -484,7 +484,7 @@ fn duplicate_metrics() { .with_description("meter counter foo") .init(); - foo_b.add(100, [KeyValue::new("A", "B")]); + foo_b.add(100, &[KeyValue::new("A", "B")]); }), expected_files: vec!["no_conflict_two_counters.txt"], ..Default::default() @@ -498,7 +498,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")]); + foo_a.add(100, &[KeyValue::new("A", "B")]); let foo_b = meter_b .i64_up_down_counter("foo") @@ -506,7 +506,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_b.add(100, [KeyValue::new("A", "B")]); + foo_b.add(100, &[KeyValue::new("A", "B")]); }), expected_files: vec!["no_conflict_two_updowncounters.txt"], ..Default::default() @@ -520,7 +520,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_a.record(100, [KeyValue::new("A", "B")]); + foo_a.record(100, &[KeyValue::new("A", "B")]); let foo_b = meter_b .u64_histogram("foo") @@ -528,7 +528,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_b.record(100, [KeyValue::new("A", "B")]); + foo_b.record(100, &[KeyValue::new("A", "B")]); }), expected_files: vec!["no_conflict_two_histograms.txt"], ..Default::default() @@ -542,7 +542,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")]); + bar_a.add(100, &[KeyValue::new("type", "bar")]); let bar_b = meter_b .u64_counter("bar") @@ -550,7 +550,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")]); + bar_b.add(100, &[KeyValue::new("type", "bar")]); }), expected_files: vec![ "conflict_help_two_counters_1.txt", @@ -567,7 +567,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")]); + bar_a.add(100, &[KeyValue::new("type", "bar")]); let bar_b = meter_b .i64_up_down_counter("bar") @@ -575,7 +575,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")]); + bar_b.add(100, &[KeyValue::new("type", "bar")]); }), expected_files: vec![ "conflict_help_two_updowncounters_1.txt", @@ -592,7 +592,7 @@ fn duplicate_metrics() { .with_description("meter a bar") .init(); - bar_a.record(100, [KeyValue::new("A", "B")]); + bar_a.record(100, &[KeyValue::new("A", "B")]); let bar_b = meter_b .u64_histogram("bar") @@ -600,7 +600,7 @@ fn duplicate_metrics() { .with_description("meter b bar") .init(); - bar_b.record(100, [KeyValue::new("A", "B")]); + bar_b.record(100, &[KeyValue::new("A", "B")]); }), expected_files: vec![ "conflict_help_two_histograms_1.txt", @@ -617,7 +617,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_a.add(100, [KeyValue::new("type", "bar")]); + baz_a.add(100, &[KeyValue::new("type", "bar")]); let baz_b = meter_b .u64_counter("bar") @@ -625,7 +625,7 @@ fn duplicate_metrics() { .with_description("meter bar") .init(); - baz_b.add(100, [KeyValue::new("type", "bar")]); + baz_b.add(100, &[KeyValue::new("type", "bar")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_counters.txt"], @@ -640,7 +640,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_a.add(100, [KeyValue::new("type", "bar")]); + bar_a.add(100, &[KeyValue::new("type", "bar")]); let bar_b = meter_b .i64_up_down_counter("bar") @@ -648,7 +648,7 @@ fn duplicate_metrics() { .with_description("meter gauge bar") .init(); - bar_b.add(100, [KeyValue::new("type", "bar")]); + bar_b.add(100, &[KeyValue::new("type", "bar")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_updowncounters.txt"], @@ -663,7 +663,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_a.record(100, [KeyValue::new("A", "B")]); + bar_a.record(100, &[KeyValue::new("A", "B")]); let bar_b = meter_b .u64_histogram("bar") @@ -671,7 +671,7 @@ fn duplicate_metrics() { .with_description("meter histogram bar") .init(); - bar_b.record(100, [KeyValue::new("A", "B")]); + bar_b.record(100, &[KeyValue::new("A", "B")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec!["conflict_unit_two_histograms.txt"], @@ -686,7 +686,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - counter.add(100, [KeyValue::new("type", "foo")]); + counter.add(100, &[KeyValue::new("type", "foo")]); let gauge = meter_a .i64_up_down_counter("foo_total") @@ -694,7 +694,7 @@ fn duplicate_metrics() { .with_description("meter foo") .init(); - gauge.add(200, [KeyValue::new("type", "foo")]); + gauge.add(200, &[KeyValue::new("type", "foo")]); }), builder: ExporterBuilder::default().without_units(), expected_files: vec![ @@ -712,7 +712,7 @@ fn duplicate_metrics() { .with_description("meter gauge foo") .init(); - foo_a.add(100, [KeyValue::new("A", "B")]); + foo_a.add(100, &[KeyValue::new("A", "B")]); let foo_histogram_a = meter_a .u64_histogram("foo") @@ -720,7 +720,7 @@ fn duplicate_metrics() { .with_description("meter histogram foo") .init(); - foo_histogram_a.record(100, [KeyValue::new("A", "B")]); + foo_histogram_a.record(100, &[KeyValue::new("A", "B")]); }), expected_files: vec![ "conflict_type_histogram_and_updowncounter_1.txt", diff --git a/opentelemetry-sdk/benches/attribute_set.rs b/opentelemetry-sdk/benches/attribute_set.rs index cd9eb0063f..2ed2a3a44b 100644 --- a/opentelemetry-sdk/benches/attribute_set.rs +++ b/opentelemetry-sdk/benches/attribute_set.rs @@ -18,7 +18,7 @@ fn attribute_set(c: &mut Criterion) { KeyValue::new("attribute3", "value3"), KeyValue::new("attribute4", "value4"), ]; - let _attribute_set: AttributeSet = AttributeSet::from(attributes); + let _attribute_set: AttributeSet = AttributeSet::from(&attributes); }); }); @@ -30,7 +30,7 @@ fn attribute_set(c: &mut Criterion) { KeyValue::new("attribute3", "value3"), KeyValue::new("attribute4", "value4"), ]; - let _attribute_set: AttributeSet = AttributeSet::from(attributes); + let _attribute_set: AttributeSet = AttributeSet::from(&attributes); }); }); } diff --git a/opentelemetry-sdk/benches/metric.rs b/opentelemetry-sdk/benches/metric.rs index 2ad0834cb9..eb4ce7d688 100644 --- a/opentelemetry-sdk/benches/metric.rs +++ b/opentelemetry-sdk/benches/metric.rs @@ -175,20 +175,20 @@ fn counters(c: &mut Criterion) { }); group.bench_function("AddOneAttr", |b| { - b.iter(|| cntr.add(1, [KeyValue::new("K", "V")])) + b.iter(|| cntr.add(1, &[KeyValue::new("K", "V")])) }); group.bench_function("AddOneAttrDelta", |b| { - b.iter(|| cntr2.add(1, [KeyValue::new("K1", "V1")])) + b.iter(|| cntr2.add(1, &[KeyValue::new("K1", "V1")])) }); group.bench_function("AddThreeAttr", |b| { b.iter(|| { cntr.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ], + ]), ) }) }); @@ -196,11 +196,11 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ], + ]), ) }) }); @@ -208,13 +208,13 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("K5", "V5"), KeyValue::new("K6", "V6"), KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ], + ]), ) }) }); @@ -222,13 +222,13 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("K5", "V5"), KeyValue::new("K6", "V6"), KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ], + ]), ) }) }); @@ -236,7 +236,7 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("K10", "V10"), KeyValue::new("K11", "V11"), KeyValue::new("K12", "V12"), @@ -247,7 +247,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ], + ]), ) }) }); @@ -255,7 +255,7 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("K10", "V10"), KeyValue::new("K11", "V11"), KeyValue::new("K12", "V12"), @@ -266,7 +266,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ], + ]), ) }) }); @@ -279,7 +279,7 @@ fn counters(c: &mut Criterion) { } group.bench_function("AddOneTillMaxAttr", |b| { - b.iter(|| cntr3.add(1, max_attributes.clone())) + b.iter(|| cntr3.add(1, max_attributes.as_slice())) }); for i in MAX_DATA_POINTS..MAX_DATA_POINTS * 2 { @@ -287,23 +287,31 @@ fn counters(c: &mut Criterion) { } group.bench_function("AddMaxAttr", |b| { - b.iter(|| cntr3.add(1, max_attributes.clone())) + b.iter(|| cntr3.add(1, max_attributes.as_slice())) }); group.bench_function("AddInvalidAttr", |b| { - b.iter(|| cntr.add(1, [KeyValue::new("", "V"), KeyValue::new("K", "V")])) + b.iter(|| { + cntr.add( + 1, + AttributeSet::from(&[KeyValue::new("", "V"), KeyValue::new("K", "V")]), + ) + }) }); group.bench_function("AddSingleUseAttrs", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("K", v)]); + cntr.add(1, AttributeSet::from(&[KeyValue::new("K", v)])); v += 1; }) }); group.bench_function("AddSingleUseInvalid", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("", v), KeyValue::new("K", v)]); + cntr.add( + 1, + AttributeSet::from(&[KeyValue::new("", v), KeyValue::new("K", v)]), + ); v += 1; }) }); @@ -322,7 +330,10 @@ fn counters(c: &mut Criterion) { group.bench_function("AddSingleUseFiltered", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("L", v), KeyValue::new("K", v)]); + cntr.add( + 1, + AttributeSet::from(&[KeyValue::new("L", v), KeyValue::new("K", v)]), + ); v += 1; }) }); @@ -336,7 +347,7 @@ fn counters(c: &mut Criterion) { group.bench_function("CollectOneAttr", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, [KeyValue::new("K", v)]); + cntr.add(1, AttributeSet::from(&[KeyValue::new("K", v)])); let _ = rdr.collect(&mut rm); v += 1; }) @@ -346,7 +357,7 @@ fn counters(c: &mut Criterion) { let mut v = 0; b.iter(|| { for i in 0..10 { - cntr.add(1, [KeyValue::new("K", i)]); + cntr.add(1, AttributeSet::from(&[KeyValue::new("K", i)])); } let _ = rdr.collect(&mut rm); v += 1; @@ -401,7 +412,7 @@ fn histograms(c: &mut Criterion) { )) } - let attributes = AttributeSet::from(attributes); + let attributes = AttributeSet::from(&attributes); let value: u64 = rng.gen_range(0..MAX_BOUND).try_into().unwrap(); group.bench_function( format!("Record{}Attrs{}bounds", attr_size, bound_size), diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index 1307f459dd..4189ad23ba 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -39,12 +39,12 @@ fn counter_add(c: &mut Criterion) { let index_forth_attribute = rng.gen_range(0..10); counter.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ], + ]), ); }); }); @@ -59,18 +59,18 @@ fn counter_add(c: &mut Criterion) { let index_forth_attribute = rng.gen_range(0..10); counter.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ], + ]), ); }); }); c.bench_function("Counter_Add_Cached_Attributes", |b| { - let attributes = AttributeSet::from([ + let attributes = AttributeSet::from(&[ KeyValue::new("attribute2", attribute_values[0]), KeyValue::new("attribute3", attribute_values[1]), KeyValue::new("attribute1", attribute_values[2]), diff --git a/opentelemetry-sdk/src/attributes/set.rs b/opentelemetry-sdk/src/attributes/set.rs index 23230dd3e1..b322a36280 100644 --- a/opentelemetry-sdk/src/attributes/set.rs +++ b/opentelemetry-sdk/src/attributes/set.rs @@ -9,7 +9,7 @@ impl From<&Resource> for AttributeSet { .map(|(key, value)| KeyValue::new(key.clone(), value.clone())) .collect::>(); - AttributeSet::from(key_values) + AttributeSet::from(&key_values) } } diff --git a/opentelemetry-sdk/src/metrics/internal/aggregate.rs b/opentelemetry-sdk/src/metrics/internal/aggregate.rs index 09a672d0b7..1022c1d5e8 100644 --- a/opentelemetry-sdk/src/metrics/internal/aggregate.rs +++ b/opentelemetry-sdk/src/metrics/internal/aggregate.rs @@ -14,10 +14,8 @@ use super::{ }; const STREAM_CARDINALITY_LIMIT: u32 = 2000; -pub(crate) static STREAM_OVERFLOW_ATTRIBUTE_SET: Lazy = Lazy::new(|| { - let key_values: [KeyValue; 1] = [KeyValue::new("otel.metric.overflow", "true")]; - AttributeSet::from(key_values) -}); +pub(crate) static STREAM_OVERFLOW_ATTRIBUTE_SET: Lazy = + Lazy::new(|| AttributeSet::from(&[KeyValue::new("otel.metric.overflow", "true")])); /// Checks whether aggregator has hit cardinality limit for metric streams pub(crate) fn is_under_cardinality_limit(size: usize) -> bool { @@ -223,7 +221,7 @@ mod tests { let (measure, agg) = AggregateBuilder::::new(None, None).last_value(); let mut a = Gauge { data_points: vec![DataPoint { - attributes: AttributeSet::from([KeyValue::new("a", 1)]), + attributes: AttributeSet::from(&[KeyValue::new("a", 1)]), start_time: Some(SystemTime::now()), time: Some(SystemTime::now()), value: 1u64, @@ -231,7 +229,7 @@ mod tests { }], }; let new_attributes = [KeyValue::new("b", 2)]; - measure.call(2, AttributeSet::from(new_attributes.clone())); + measure.call(2, AttributeSet::from(&new_attributes)); let (count, new_agg) = agg.call(Some(&mut a)); @@ -240,7 +238,7 @@ mod tests { assert_eq!(a.data_points.len(), 1); assert_eq!( a.data_points[0].attributes, - AttributeSet::from(new_attributes) + AttributeSet::from(&new_attributes) ); assert_eq!(a.data_points[0].value, 2); } @@ -253,14 +251,14 @@ mod tests { let mut a = Sum { data_points: vec![ DataPoint { - attributes: AttributeSet::from([KeyValue::new("a1", 1)]), + attributes: AttributeSet::from(&[KeyValue::new("a1", 1)]), start_time: Some(SystemTime::now()), time: Some(SystemTime::now()), value: 1u64, exemplars: vec![], }, DataPoint { - attributes: AttributeSet::from([KeyValue::new("a2", 2)]), + attributes: AttributeSet::from(&[KeyValue::new("a2", 2)]), start_time: Some(SystemTime::now()), time: Some(SystemTime::now()), value: 2u64, @@ -275,7 +273,7 @@ mod tests { is_monotonic: false, }; let new_attributes = [KeyValue::new("b", 2)]; - measure.call(3, AttributeSet::from(new_attributes.clone())); + measure.call(3, AttributeSet::from(&new_attributes)); let (count, new_agg) = agg.call(Some(&mut a)); @@ -286,7 +284,7 @@ mod tests { assert_eq!(a.data_points.len(), 1); assert_eq!( a.data_points[0].attributes, - AttributeSet::from(new_attributes) + AttributeSet::from(&new_attributes) ); assert_eq!(a.data_points[0].value, 3); } @@ -299,14 +297,14 @@ mod tests { let mut a = Sum { data_points: vec![ DataPoint { - attributes: AttributeSet::from([KeyValue::new("a1", 1)]), + attributes: AttributeSet::from(&[KeyValue::new("a1", 1)]), start_time: Some(SystemTime::now()), time: Some(SystemTime::now()), value: 1u64, exemplars: vec![], }, DataPoint { - attributes: AttributeSet::from([KeyValue::new("a2", 2)]), + attributes: AttributeSet::from(&[KeyValue::new("a2", 2)]), start_time: Some(SystemTime::now()), time: Some(SystemTime::now()), value: 2u64, @@ -321,7 +319,7 @@ mod tests { is_monotonic: false, }; let new_attributes = [KeyValue::new("b", 2)]; - measure.call(3, AttributeSet::from(new_attributes.clone())); + measure.call(3, AttributeSet::from(&new_attributes)); let (count, new_agg) = agg.call(Some(&mut a)); @@ -332,7 +330,7 @@ mod tests { assert_eq!(a.data_points.len(), 1); assert_eq!( a.data_points[0].attributes, - AttributeSet::from(new_attributes) + AttributeSet::from(&new_attributes) ); assert_eq!(a.data_points[0].value, 3); } @@ -345,7 +343,7 @@ mod tests { .explicit_bucket_histogram(vec![1.0], true, true); let mut a = Histogram { data_points: vec![HistogramDataPoint { - attributes: AttributeSet::from([KeyValue::new("a2", 2)]), + attributes: AttributeSet::from(&[KeyValue::new("a2", 2)]), start_time: SystemTime::now(), time: SystemTime::now(), count: 2, @@ -363,7 +361,7 @@ mod tests { }, }; let new_attributes = [KeyValue::new("b", 2)]; - measure.call(3, AttributeSet::from(new_attributes.clone())); + measure.call(3, AttributeSet::from(&new_attributes)); let (count, new_agg) = agg.call(Some(&mut a)); @@ -373,7 +371,7 @@ mod tests { assert_eq!(a.data_points.len(), 1); assert_eq!( a.data_points[0].attributes, - AttributeSet::from(new_attributes) + AttributeSet::from(&new_attributes) ); assert_eq!(a.data_points[0].count, 1); assert_eq!(a.data_points[0].bounds, vec![1.0]); @@ -391,7 +389,7 @@ mod tests { .exponential_bucket_histogram(4, 20, true, true); let mut a = ExponentialHistogram { data_points: vec![ExponentialHistogramDataPoint { - attributes: AttributeSet::from([KeyValue::new("a2", 2)]), + attributes: AttributeSet::from(&[KeyValue::new("a2", 2)]), start_time: SystemTime::now(), time: SystemTime::now(), count: 2, @@ -418,7 +416,7 @@ mod tests { }, }; let new_attributes = [KeyValue::new("b", 2)]; - measure.call(3, AttributeSet::from(new_attributes.clone())); + measure.call(3, AttributeSet::from(&new_attributes.clone())); let (count, new_agg) = agg.call(Some(&mut a)); @@ -428,7 +426,7 @@ mod tests { assert_eq!(a.data_points.len(), 1); assert_eq!( a.data_points[0].attributes, - AttributeSet::from(new_attributes) + AttributeSet::from(&new_attributes) ); assert_eq!(a.data_points[0].count, 1); assert_eq!(a.data_points[0].min, Some(3)); diff --git a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs index 9552ed9944..bb16d2a540 100644 --- a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs @@ -624,7 +624,7 @@ mod tests { } fn run_min_max_sum_f64() { - let alice = AttributeSet::from([KeyValue::new("user", "alice")]); + let alice = AttributeSet::from(&[KeyValue::new("user", "alice")]); struct Expected { min: f64, max: f64, @@ -685,7 +685,7 @@ mod tests { } fn run_min_max_sum + From>() { - let alice = AttributeSet::from([KeyValue::new("user", "alice")]); + let alice = AttributeSet::from(&[KeyValue::new("user", "alice")]); struct Expected { min: T, max: T, diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index a95bdd78ac..5855f4ef13 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -88,15 +88,15 @@ mod tests { .u64_counter("my_counter") .with_unit(Unit::new("my_unit")) .init(); - counter.add(1, [KeyValue::new("key1", "value1")]); - counter.add(1, [KeyValue::new("key1", "value1")]); - counter.add(1, [KeyValue::new("key1", "value1")]); - counter.add(1, [KeyValue::new("key1", "value1")]); - counter.add(1, [KeyValue::new("key1", "value1")]); + counter.add(1, &[KeyValue::new("key1", "value1")]); + counter.add(1, &[KeyValue::new("key1", "value1")]); + counter.add(1, &[KeyValue::new("key1", "value1")]); + counter.add(1, &[KeyValue::new("key1", "value1")]); + counter.add(1, &[KeyValue::new("key1", "value1")]); - counter.add(1, [KeyValue::new("key1", "value2")]); - counter.add(1, [KeyValue::new("key1", "value2")]); - counter.add(1, [KeyValue::new("key1", "value2")]); + counter.add(1, &[KeyValue::new("key1", "value2")]); + counter.add(1, &[KeyValue::new("key1", "value2")]); + counter.add(1, &[KeyValue::new("key1", "value2")]); meter_provider.force_flush().unwrap(); @@ -183,7 +183,7 @@ mod tests { .with_description("my_description") .init(); - let attribute = AttributeSet::from([KeyValue::new("key1", "value1")]); + let attribute = AttributeSet::from(&[KeyValue::new("key1", "value1")]); counter.add(10, attribute.clone()); counter_duplicated.add(5, attribute); @@ -246,7 +246,7 @@ mod tests { .with_unit(Unit::new("test_unit")) .init(); - histogram.record(1.5, [KeyValue::new("key1", "value1")]); + histogram.record(1.5, &[KeyValue::new("key1", "value1")]); meter_provider.force_flush().unwrap(); // Assert @@ -301,6 +301,7 @@ mod tests { KeyValue::new("statusCode", "200"), KeyValue::new("verb", "get"), ] + .as_slice() .into(), ); @@ -311,6 +312,7 @@ mod tests { KeyValue::new("statusCode", "200"), KeyValue::new("verb", "post"), ] + .as_slice() .into(), ); @@ -321,6 +323,7 @@ mod tests { KeyValue::new("statusCode", "500"), KeyValue::new("verb", "get"), ] + .as_slice() .into(), ); }) @@ -381,26 +384,26 @@ mod tests { // drops all attributes, we expect only 1 time-series. counter.add( 10, - [ + AttributeSet::from(&[ KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Get"), - ], + ]), ); counter.add( 10, - [ + AttributeSet::from(&[ KeyValue::new("statusCode", "500"), KeyValue::new("verb", "Get"), - ], + ]), ); counter.add( 10, - [ + AttributeSet::from(&[ KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Post"), - ], + ]), ); meter_provider.force_flush().unwrap(); diff --git a/opentelemetry-stdout/examples/basic.rs b/opentelemetry-stdout/examples/basic.rs index 3e9733bc2d..1cc00f3283 100644 --- a/opentelemetry-stdout/examples/basic.rs +++ b/opentelemetry-stdout/examples/basic.rs @@ -1,5 +1,6 @@ //! run with `$ cargo run --example basic --all-features +use opentelemetry::attributes::AttributeSet; #[cfg(all(feature = "metrics", feature = "trace"))] use opentelemetry::{ metrics::MeterProvider as _, @@ -45,7 +46,10 @@ async fn main() -> Result<(), Box> { let meter = meter_provider.meter("stdout-test"); let c = meter.u64_counter("test_events").init(); - c.add(1, [KeyValue::new("test_key", "test_value")]); + c.add( + 1, + AttributeSet::from(&[KeyValue::new("test_key", "test_value")]), + ); meter_provider.shutdown()?; diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 21241ea6dd..f44a16f98e 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -137,10 +137,11 @@ where .into_iter() .rev() .filter_map(|kv| { - if seen_keys.insert(kv.key.clone()) { - Some(HashKeyValue(kv.clone())) - } else { + if seen_keys.contains(&kv.key) { None + } else { + seen_keys.insert(kv.key.clone()); + Some(HashKeyValue(kv)) } }) .collect::>(); @@ -165,12 +166,14 @@ impl Hash for InternalAttributeSet { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct AttributeSet(Arc); -impl> From for AttributeSet +impl<'a, I: IntoIterator> From for AttributeSet where ::IntoIter: DoubleEndedIterator + ExactSizeIterator, { fn from(values: I) -> Self { - AttributeSet(Arc::new(InternalAttributeSet::from(values))) + AttributeSet(Arc::new(InternalAttributeSet::from( + values.into_iter().cloned(), + ))) } } @@ -222,7 +225,7 @@ mod tests { fn can_create_attribute_set_from_array() { let array = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; - let set = AttributeSet::from(array); + let set = AttributeSet::from(&array); let mut kvs = set.iter().collect::>(); assert_eq!(kvs.len(), 2, "Incorrect number of attributes"); @@ -264,8 +267,8 @@ mod tests { KeyValue::new("key2", 3), ]; - let set1 = AttributeSet::from(array1); - let set2 = AttributeSet::from(array2); + let set1 = AttributeSet::from(&array1); + let set2 = AttributeSet::from(&array2); assert_eq!(set1, set2); } @@ -296,8 +299,8 @@ mod tests { KeyValue::new("key2", 3), ]; - let set1 = AttributeSet::from(array1); - let set2 = AttributeSet::from(array2); + let set1 = AttributeSet::from(&array1); + let set2 = AttributeSet::from(&array2); let mut hasher1 = DefaultHasher::new(); let mut hasher2 = DefaultHasher::new(); @@ -315,7 +318,7 @@ mod tests { KeyValue::new("key3", 4), ]; - let set = AttributeSet::from(array); + let set = AttributeSet::from(&array); let set2 = set.clone_with(|kv| kv.key == Key::new("key2")); assert_ne!(set, set2, "Both sets were unexpectedly equal"); @@ -330,7 +333,7 @@ mod tests { fn len_returns_accurate_value() { let array = [KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; - let set = AttributeSet::from(array); + let set = AttributeSet::from(&array); let kvs = set.iter().collect::>(); assert_eq!(set.len(), kvs.len()); @@ -338,7 +341,7 @@ mod tests { #[test] fn empty_when_no_attributes_provided() { - let set = AttributeSet::from([]); + let set = AttributeSet::from(&[]); assert!(set.is_empty()); } @@ -353,7 +356,7 @@ mod tests { fn last_key_wins_for_deduplication() { let array = [KeyValue::new("key1", "value1"), KeyValue::new("key1", 3)]; - let set = AttributeSet::from(array); + let set = AttributeSet::from(&array); let kvs = set.iter().collect::>(); assert_eq!(set.len(), 1, "Expected only a single key value pair"); diff --git a/stress/src/metrics.rs b/stress/src/metrics.rs index 0c78e9cc8e..6aaf429961 100644 --- a/stress/src/metrics.rs +++ b/stress/src/metrics.rs @@ -1,4 +1,5 @@ use lazy_static::lazy_static; +use opentelemetry::attributes::AttributeSet; use opentelemetry::{ metrics::{Counter, MeterProvider as _}, KeyValue, @@ -37,10 +38,10 @@ fn test_counter() { // each attribute has 10 possible values, so there are 1000 possible combinations (time-series) COUNTER.add( 1, - [ + AttributeSet::from(&[ KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]), KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]), KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]), - ], + ]), ); } diff --git a/stress/src/metrics_cached_attrs.rs b/stress/src/metrics_cached_attrs.rs index 7c2d605092..49d5024057 100644 --- a/stress/src/metrics_cached_attrs.rs +++ b/stress/src/metrics_cached_attrs.rs @@ -27,14 +27,11 @@ lazy_static! { for i0 in 0..ATTRIBUTE_VALUES.len() { for i1 in 0..ATTRIBUTE_VALUES.len() { for i2 in 0..ATTRIBUTE_VALUES.len() { - vec.push( - [ - KeyValue::new("attribute1", ATTRIBUTE_VALUES[i0]), - KeyValue::new("attribute2", ATTRIBUTE_VALUES[i1]), - KeyValue::new("attribute3", ATTRIBUTE_VALUES[i2]), - ] - .into(), - ) + vec.push(AttributeSet::from(&[ + KeyValue::new("attribute1", ATTRIBUTE_VALUES[i0]), + KeyValue::new("attribute2", ATTRIBUTE_VALUES[i1]), + KeyValue::new("attribute3", ATTRIBUTE_VALUES[i2]), + ])) } } } From 6b6e9e0c3ab600f4f57d8a0dc4368c87389d155d Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 20 Dec 2023 10:34:21 -0500 Subject: [PATCH 18/31] Removed unneeded `AttributeSet::from` calls --- examples/metrics-advanced/src/main.rs | 21 +++++---- examples/metrics-basic/src/main.rs | 12 +++--- opentelemetry-sdk/benches/attribute_set.rs | 8 ++-- opentelemetry-sdk/benches/metric.rs | 47 ++++++++------------- opentelemetry-sdk/benches/metric_counter.rs | 8 ++-- opentelemetry-sdk/src/metrics/mod.rs | 15 ++++--- opentelemetry-stdout/examples/basic.rs | 6 +-- stress/src/metrics.rs | 5 +-- 8 files changed, 54 insertions(+), 68 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index 74431275e1..e5d03a9213 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -1,4 +1,3 @@ -use opentelemetry::attributes::AttributeSet; use opentelemetry::metrics::Unit; use opentelemetry::Key; use opentelemetry::{metrics::MeterProvider as _, KeyValue}; @@ -81,12 +80,12 @@ async fn main() -> Result<(), Box> { // Record measurements using the histogram instrument. histogram.record( 10.5, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ]), + ], ); // Example 2 - Drop unwanted attributes using view. @@ -98,12 +97,12 @@ async fn main() -> Result<(), Box> { // attribute. counter.add( 10, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ]), + ], ); // Example 3 - Change Aggregation configuration using View. @@ -121,32 +120,32 @@ async fn main() -> Result<(), Box> { // the change of boundaries. histogram2.record( 1.5, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ]), + ], ); histogram2.record( 1.2, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ]), + ], ); histogram2.record( 1.23, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ]), + ], ); // Metrics are exported by default every 30 seconds when using stdout exporter, diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 65e8940b4f..16be6817ac 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -35,10 +35,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the Counter instrument. counter.add( 10, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ]), + ], ); // Create a ObservableCounter instrument and register a callback that reports the measurement. @@ -65,10 +65,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the UpCounter instrument. updown_counter.add( -10, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ]), + ], ); // Create a Observable UpDownCounter instrument and register a callback that reports the measurement. @@ -98,10 +98,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the histogram instrument. histogram.record( 10.5, - AttributeSet::from(&[ + &[ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ]), + ], ); // Note that there is no ObservableHistogram instrument. diff --git a/opentelemetry-sdk/benches/attribute_set.rs b/opentelemetry-sdk/benches/attribute_set.rs index 2ed2a3a44b..f3932f7ac1 100644 --- a/opentelemetry-sdk/benches/attribute_set.rs +++ b/opentelemetry-sdk/benches/attribute_set.rs @@ -12,25 +12,25 @@ fn criterion_benchmark(c: &mut Criterion) { fn attribute_set(c: &mut Criterion) { c.bench_function("AttributeSet_without_duplicates", |b| { b.iter(|| { - let attributes = [ + let attributes = &[ KeyValue::new("attribute1", "value1"), KeyValue::new("attribute2", "value2"), KeyValue::new("attribute3", "value3"), KeyValue::new("attribute4", "value4"), ]; - let _attribute_set: AttributeSet = AttributeSet::from(&attributes); + let _attribute_set: AttributeSet = attributes.into(); }); }); c.bench_function("AttributeSet_with_duplicates", |b| { b.iter(|| { - let attributes = [ + let attributes = &[ KeyValue::new("attribute1", "value1"), KeyValue::new("attribute3", "value3"), KeyValue::new("attribute3", "value3"), KeyValue::new("attribute4", "value4"), ]; - let _attribute_set: AttributeSet = AttributeSet::from(&attributes); + let _attribute_set: AttributeSet = attributes.into(); }); }); } diff --git a/opentelemetry-sdk/benches/metric.rs b/opentelemetry-sdk/benches/metric.rs index eb4ce7d688..ae67183970 100644 --- a/opentelemetry-sdk/benches/metric.rs +++ b/opentelemetry-sdk/benches/metric.rs @@ -184,11 +184,11 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ]), + ], ) }) }); @@ -196,11 +196,11 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("K2", "V2"), KeyValue::new("K3", "V3"), KeyValue::new("K4", "V4"), - ]), + ], ) }) }); @@ -208,13 +208,13 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("K5", "V5"), KeyValue::new("K6", "V6"), KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ]), + ], ) }) }); @@ -222,13 +222,13 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("K5", "V5"), KeyValue::new("K6", "V6"), KeyValue::new("K7", "V7"), KeyValue::new("K8", "V8"), KeyValue::new("K9", "V9"), - ]), + ], ) }) }); @@ -236,7 +236,7 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("K10", "V10"), KeyValue::new("K11", "V11"), KeyValue::new("K12", "V12"), @@ -247,7 +247,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ]), + ], ) }) }); @@ -255,7 +255,7 @@ fn counters(c: &mut Criterion) { b.iter(|| { cntr2.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("K10", "V10"), KeyValue::new("K11", "V11"), KeyValue::new("K12", "V12"), @@ -266,7 +266,7 @@ fn counters(c: &mut Criterion) { KeyValue::new("K17", "V17"), KeyValue::new("K18", "V18"), KeyValue::new("K19", "V19"), - ]), + ], ) }) }); @@ -291,27 +291,19 @@ fn counters(c: &mut Criterion) { }); group.bench_function("AddInvalidAttr", |b| { - b.iter(|| { - cntr.add( - 1, - AttributeSet::from(&[KeyValue::new("", "V"), KeyValue::new("K", "V")]), - ) - }) + b.iter(|| cntr.add(1, &[KeyValue::new("", "V"), KeyValue::new("K", "V")])) }); group.bench_function("AddSingleUseAttrs", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, AttributeSet::from(&[KeyValue::new("K", v)])); + cntr.add(1, &[KeyValue::new("K", v)]); v += 1; }) }); group.bench_function("AddSingleUseInvalid", |b| { let mut v = 0; b.iter(|| { - cntr.add( - 1, - AttributeSet::from(&[KeyValue::new("", v), KeyValue::new("K", v)]), - ); + cntr.add(1, &[KeyValue::new("", v), KeyValue::new("K", v)]); v += 1; }) }); @@ -330,10 +322,7 @@ fn counters(c: &mut Criterion) { group.bench_function("AddSingleUseFiltered", |b| { let mut v = 0; b.iter(|| { - cntr.add( - 1, - AttributeSet::from(&[KeyValue::new("L", v), KeyValue::new("K", v)]), - ); + cntr.add(1, &[KeyValue::new("L", v), KeyValue::new("K", v)]); v += 1; }) }); @@ -347,7 +336,7 @@ fn counters(c: &mut Criterion) { group.bench_function("CollectOneAttr", |b| { let mut v = 0; b.iter(|| { - cntr.add(1, AttributeSet::from(&[KeyValue::new("K", v)])); + cntr.add(1, &[KeyValue::new("K", v)]); let _ = rdr.collect(&mut rm); v += 1; }) @@ -357,7 +346,7 @@ fn counters(c: &mut Criterion) { let mut v = 0; b.iter(|| { for i in 0..10 { - cntr.add(1, AttributeSet::from(&[KeyValue::new("K", i)])); + cntr.add(1, &[KeyValue::new("K", i)]); } let _ = rdr.collect(&mut rm); v += 1; diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index 4189ad23ba..36b880216c 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -39,12 +39,12 @@ fn counter_add(c: &mut Criterion) { let index_forth_attribute = rng.gen_range(0..10); counter.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ]), + ], ); }); }); @@ -59,12 +59,12 @@ fn counter_add(c: &mut Criterion) { let index_forth_attribute = rng.gen_range(0..10); counter.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("attribute2", attribute_values[index_second_attribute]), KeyValue::new("attribute3", attribute_values[index_third_attribute]), KeyValue::new("attribute1", attribute_values[index_first_attribute]), KeyValue::new("attribute4", attribute_values[index_forth_attribute]), - ]), + ], ); }); }); diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 5855f4ef13..e61a36c8b4 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -384,26 +384,29 @@ mod tests { // drops all attributes, we expect only 1 time-series. counter.add( 10, - AttributeSet::from(&[ + [ KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Get"), - ]), + ] + .as_ref(), ); counter.add( 10, - AttributeSet::from(&[ + [ KeyValue::new("statusCode", "500"), KeyValue::new("verb", "Get"), - ]), + ] + .as_ref(), ); counter.add( 10, - AttributeSet::from(&[ + [ KeyValue::new("statusCode", "200"), KeyValue::new("verb", "Post"), - ]), + ] + .as_ref(), ); meter_provider.force_flush().unwrap(); diff --git a/opentelemetry-stdout/examples/basic.rs b/opentelemetry-stdout/examples/basic.rs index 1cc00f3283..41cfa7a30f 100644 --- a/opentelemetry-stdout/examples/basic.rs +++ b/opentelemetry-stdout/examples/basic.rs @@ -1,6 +1,5 @@ //! run with `$ cargo run --example basic --all-features -use opentelemetry::attributes::AttributeSet; #[cfg(all(feature = "metrics", feature = "trace"))] use opentelemetry::{ metrics::MeterProvider as _, @@ -46,10 +45,7 @@ async fn main() -> Result<(), Box> { let meter = meter_provider.meter("stdout-test"); let c = meter.u64_counter("test_events").init(); - c.add( - 1, - AttributeSet::from(&[KeyValue::new("test_key", "test_value")]), - ); + c.add(1, &[KeyValue::new("test_key", "test_value")]); meter_provider.shutdown()?; diff --git a/stress/src/metrics.rs b/stress/src/metrics.rs index 6aaf429961..9f7d2d2349 100644 --- a/stress/src/metrics.rs +++ b/stress/src/metrics.rs @@ -1,5 +1,4 @@ use lazy_static::lazy_static; -use opentelemetry::attributes::AttributeSet; use opentelemetry::{ metrics::{Counter, MeterProvider as _}, KeyValue, @@ -38,10 +37,10 @@ fn test_counter() { // each attribute has 10 possible values, so there are 1000 possible combinations (time-series) COUNTER.add( 1, - AttributeSet::from(&[ + &[ KeyValue::new("attribute1", ATTRIBUTE_VALUES[index_first_attribute]), KeyValue::new("attribute2", ATTRIBUTE_VALUES[index_second_attribute]), KeyValue::new("attribute3", ATTRIBUTE_VALUES[index_third_attribute]), - ]), + ], ); } From 377e8b00381a8ed00a97c639308a0b8736bb1624 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 20 Dec 2023 10:40:28 -0500 Subject: [PATCH 19/31] revert of some minor changes to lower diff volume --- examples/metrics-advanced/src/main.rs | 20 +++++++++---------- examples/metrics-basic/src/main.rs | 16 +++++++-------- .../src/metrics/instruments/gauge.rs | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index e5d03a9213..1b75f177a7 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -80,12 +80,12 @@ async fn main() -> Result<(), Box> { // Record measurements using the histogram instrument. histogram.record( 10.5, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ].as_ref(), ); // Example 2 - Drop unwanted attributes using view. @@ -97,12 +97,12 @@ async fn main() -> Result<(), Box> { // attribute. counter.add( 10, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ].as_ref(), ); // Example 3 - Change Aggregation configuration using View. @@ -120,32 +120,32 @@ async fn main() -> Result<(), Box> { // the change of boundaries. histogram2.record( 1.5, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ].as_ref(), ); histogram2.record( 1.2, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ].as_ref(), ); histogram2.record( 1.23, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ], + ].as_ref(), ); // Metrics are exported by default every 30 seconds when using stdout exporter, diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 16be6817ac..b3acb838e6 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -35,10 +35,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the Counter instrument. counter.add( 10, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ], + ].as_ref(), ); // Create a ObservableCounter instrument and register a callback that reports the measurement. @@ -65,10 +65,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the UpCounter instrument. updown_counter.add( -10, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ], + ].as_ref(), ); // Create a Observable UpDownCounter instrument and register a callback that reports the measurement. @@ -98,10 +98,10 @@ async fn main() -> Result<(), Box> { // Record measurements using the histogram instrument. histogram.record( 10.5, - &[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ], + ].as_ref(), ); // Note that there is no ObservableHistogram instrument. @@ -118,10 +118,10 @@ async fn main() -> Result<(), Box> { gauge.record( 1.0, - AttributeSet::from(&[ + [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ]), + ].as_ref(), ); } diff --git a/opentelemetry/src/metrics/instruments/gauge.rs b/opentelemetry/src/metrics/instruments/gauge.rs index ada1a341c9..0f64c01018 100644 --- a/opentelemetry/src/metrics/instruments/gauge.rs +++ b/opentelemetry/src/metrics/instruments/gauge.rs @@ -32,8 +32,8 @@ impl Gauge { } /// Records an independent value. - pub fn record(&self, value: T, attributes: AttributeSet) { - self.0.record(value, attributes) + pub fn record(&self, value: T, attributes: impl Into) { + self.0.record(value, attributes.into()) } } From 7869fa77dccc2ed3f6fc956b2e7d071b2f45bd64 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 20 Dec 2023 10:43:37 -0500 Subject: [PATCH 20/31] Fixed doc tests --- opentelemetry-prometheus/src/lib.rs | 2 +- opentelemetry-sdk/src/lib.rs | 2 +- opentelemetry-sdk/src/metrics/mod.rs | 2 +- opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs | 2 +- opentelemetry/src/global/mod.rs | 2 +- opentelemetry/src/lib.rs | 2 +- opentelemetry/src/metrics/meter.rs | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/opentelemetry-prometheus/src/lib.rs b/opentelemetry-prometheus/src/lib.rs index e044bd89bc..270aee8f2b 100644 --- a/opentelemetry-prometheus/src/lib.rs +++ b/opentelemetry-prometheus/src/lib.rs @@ -32,7 +32,7 @@ //! .with_description("Records values") //! .init(); //! -//! let attributes = AttributeSet::from([KeyValue::new("key", "value")]); +//! let attributes = AttributeSet::from(&[KeyValue::new("key", "value")]); //! //! counter.add(100, attributes.clone()); //! histogram.record(100, attributes); diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index 3659549079..eabb475577 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -64,7 +64,7 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // record a measurement -//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")]); +//! let attributes = AttributeSet::from(&[KeyValue::new("http.client_ip", "83.164.160.102")]); //! counter.add(1, attributes); //! # } //! ``` diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index e61a36c8b4..81552909d0 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -32,7 +32,7 @@ //! .init(); //! //! // use instruments to record measurements -//! let attributes = AttributeSet::from([KeyValue::new("rate", "standard")]); +//! let attributes = AttributeSet::from(&[KeyValue::new("rate", "standard")]); //! counter.add(10, attributes); //! ``` //! diff --git a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs index ec31e4cac2..86b41d6c83 100644 --- a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs +++ b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs @@ -47,7 +47,7 @@ use std::sync::{Arc, Mutex}; /// // Create and record metrics using the MeterProvider /// let meter = meter_provider.meter(std::borrow::Cow::Borrowed("example")); /// let counter = meter.u64_counter("my_counter").init(); -/// let attributes = AttributeSet::from([KeyValue::new("key", "value")]); +/// let attributes = AttributeSet::from(&[KeyValue::new("key", "value")]); /// counter.add(1, attributes); /// /// meter_provider.force_flush().unwrap(); diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index 0b111c6304..293d8eeb66 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -132,7 +132,7 @@ //! let counter = tracer.u64_counter("my_counter").init(); //! //! // record metrics -//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")]); +//! let attributes = AttributeSet::from(&[KeyValue::new("mykey", "myvalue")]); //! counter.add(1, attributes); //! } //! # } diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index 203ead7fcc..ec02c4b661 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -81,7 +81,7 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // Form the attributes -//! let attributes = AttributeSet::from([KeyValue::new("http.client_ip", "83.164.160.102")]); +//! let attributes = AttributeSet::from(&[KeyValue::new("http.client_ip", "83.164.160.102")]); //! //! // record a measurement //! counter.add(1, attributes); diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index 839a47e495..94e6797a61 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -82,7 +82,7 @@ pub trait MeterProvider { /// let u64_counter = meter.u64_counter("my_u64_counter").init(); /// /// // Define the attributes the counters will use -/// let attributes = AttributeSet::from([ +/// let attributes = AttributeSet::from(&[ /// KeyValue::new("mykey1", "myvalue1"), /// KeyValue::new("mykey2", "myvalue2"), /// ]); From 70cbdbb52862b679889fb0db17533307e2b92641 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 20 Dec 2023 10:56:53 -0500 Subject: [PATCH 21/31] missed doctest --- opentelemetry/src/global/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index 293d8eeb66..0efff241c1 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -108,7 +108,7 @@ //! let counter = meter.u64_counter("my_counter").init(); //! //! // record metrics -//! let attributes = AttributeSet::from([KeyValue::new("mykey", "myvalue")]); +//! let attributes = AttributeSet::from(&[KeyValue::new("mykey", "myvalue")]); //! counter.add(1, attributes); //! } //! From 18a001fd619aa03b3918b15cb1c41f2fe0fbd5ea Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 20 Dec 2023 11:01:44 -0500 Subject: [PATCH 22/31] missed fmt --- examples/metrics-advanced/src/main.rs | 15 ++++++++++----- examples/metrics-basic/src/main.rs | 12 ++++++++---- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/examples/metrics-advanced/src/main.rs b/examples/metrics-advanced/src/main.rs index 1b75f177a7..760ed1b7e1 100644 --- a/examples/metrics-advanced/src/main.rs +++ b/examples/metrics-advanced/src/main.rs @@ -85,7 +85,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ].as_ref(), + ] + .as_ref(), ); // Example 2 - Drop unwanted attributes using view. @@ -102,7 +103,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ].as_ref(), + ] + .as_ref(), ); // Example 3 - Change Aggregation configuration using View. @@ -125,7 +127,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ].as_ref(), + ] + .as_ref(), ); histogram2.record( @@ -135,7 +138,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ].as_ref(), + ] + .as_ref(), ); histogram2.record( @@ -145,7 +149,8 @@ async fn main() -> Result<(), Box> { KeyValue::new("mykey2", "myvalue2"), KeyValue::new("mykey3", "myvalue3"), KeyValue::new("mykey4", "myvalue4"), - ].as_ref(), + ] + .as_ref(), ); // Metrics are exported by default every 30 seconds when using stdout exporter, diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index b3acb838e6..2cd252578d 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -38,7 +38,8 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ].as_ref(), + ] + .as_ref(), ); // Create a ObservableCounter instrument and register a callback that reports the measurement. @@ -68,7 +69,8 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ].as_ref(), + ] + .as_ref(), ); // Create a Observable UpDownCounter instrument and register a callback that reports the measurement. @@ -101,7 +103,8 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ].as_ref(), + ] + .as_ref(), ); // Note that there is no ObservableHistogram instrument. @@ -121,7 +124,8 @@ async fn main() -> Result<(), Box> { [ KeyValue::new("mykey1", "myvalue1"), KeyValue::new("mykey2", "myvalue2"), - ].as_ref(), + ] + .as_ref(), ); } From a37bf5a796987292ddb3596fe75eca4ca34d17dc Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Mon, 8 Jan 2024 16:15:03 -0500 Subject: [PATCH 23/31] Allow owned and borrowed key value iterators to create attribute sets --- opentelemetry-sdk/src/attributes/mod.rs | 1 - opentelemetry-sdk/src/attributes/set.rs | 40 -------------------- opentelemetry-sdk/src/lib.rs | 1 - opentelemetry-sdk/src/resource/mod.rs | 30 +++++++++++++++ opentelemetry-stdout/src/logs/transform.rs | 2 +- opentelemetry-stdout/src/trace/transform.rs | 2 +- opentelemetry/src/attributes/mod.rs | 2 +- opentelemetry/src/attributes/set.rs | 42 ++++++++++++++++++++- 8 files changed, 73 insertions(+), 47 deletions(-) delete mode 100644 opentelemetry-sdk/src/attributes/mod.rs delete mode 100644 opentelemetry-sdk/src/attributes/set.rs diff --git a/opentelemetry-sdk/src/attributes/mod.rs b/opentelemetry-sdk/src/attributes/mod.rs deleted file mode 100644 index 372602983d..0000000000 --- a/opentelemetry-sdk/src/attributes/mod.rs +++ /dev/null @@ -1 +0,0 @@ -mod set; diff --git a/opentelemetry-sdk/src/attributes/set.rs b/opentelemetry-sdk/src/attributes/set.rs deleted file mode 100644 index b322a36280..0000000000 --- a/opentelemetry-sdk/src/attributes/set.rs +++ /dev/null @@ -1,40 +0,0 @@ -use crate::Resource; -use opentelemetry::attributes::AttributeSet; -use opentelemetry::KeyValue; - -impl From<&Resource> for AttributeSet { - fn from(values: &Resource) -> Self { - let key_values = values - .iter() - .map(|(key, value)| KeyValue::new(key.clone(), value.clone())) - .collect::>(); - - AttributeSet::from(&key_values) - } -} - -#[cfg(test)] -mod tests { - use super::*; - use opentelemetry::{Key, Value}; - - #[test] - fn can_create_attribute_set_from_resource() { - let resource = Resource::new([KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]); - - let set = AttributeSet::from(&resource); - let mut kvs = set.iter().collect::>(); - - assert_eq!(kvs.len(), 2, "Incorrect number of attributes"); - - kvs.sort_by(|kv1, kv2| kv1.0.cmp(kv2.0)); - assert_eq!(kvs[0].0, &Key::from("key1"), "Unexpected first key"); - assert_eq!( - kvs[0].1, - &Value::String("value1".into()), - "Unexpected first value" - ); - assert_eq!(kvs[1].0, &Key::from("key2"), "Unexpected second key"); - assert_eq!(kvs[1].1, &Value::I64(3), "Unexpected second value"); - } -} diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index eabb475577..a2a8fb58de 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -113,7 +113,6 @@ )] #![cfg_attr(test, deny(warnings))] -pub(crate) mod attributes; pub mod export; mod instrumentation; #[cfg(feature = "logs")] diff --git a/opentelemetry-sdk/src/resource/mod.rs b/opentelemetry-sdk/src/resource/mod.rs index 79ce0122eb..ab7c202def 100644 --- a/opentelemetry-sdk/src/resource/mod.rs +++ b/opentelemetry-sdk/src/resource/mod.rs @@ -30,6 +30,7 @@ pub use os::OsResourceDetector; pub use process::ProcessResourceDetector; pub use telemetry::TelemetryResourceDetector; +use opentelemetry::attributes::AttributeSet; use opentelemetry::{Key, KeyValue, Value}; use std::borrow::Cow; use std::collections::{hash_map, HashMap}; @@ -190,6 +191,15 @@ impl Resource { pub fn get(&self, key: Key) -> Option { self.attrs.get(&key).cloned() } + + pub fn to_attribute_set(&self) -> AttributeSet { + let key_values = self + .iter() + .map(|(key, value)| KeyValue::new(key.clone(), value.clone())) + .collect::>(); + + AttributeSet::from(&key_values) + } } /// An owned iterator over the entries of a `Resource`. @@ -365,4 +375,24 @@ mod tests { }, ) } + + #[test] + fn can_create_attribute_set_from_resource() { + let resource = Resource::new([KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]); + + let set = resource.to_attribute_set(); + let mut kvs = set.iter().collect::>(); + + assert_eq!(kvs.len(), 2, "Incorrect number of attributes"); + + kvs.sort_by(|kv1, kv2| kv1.0.cmp(kv2.0)); + assert_eq!(kvs[0].0, &Key::from("key1"), "Unexpected first key"); + assert_eq!( + kvs[0].1, + &Value::String("value1".into()), + "Unexpected first value" + ); + assert_eq!(kvs[1].0, &Key::from("key2"), "Unexpected second key"); + assert_eq!(kvs[1].1, &Value::I64(3), "Unexpected second value"); + } } diff --git a/opentelemetry-stdout/src/logs/transform.rs b/opentelemetry-stdout/src/logs/transform.rs index debb1b662a..71453d0535 100644 --- a/opentelemetry-stdout/src/logs/transform.rs +++ b/opentelemetry-stdout/src/logs/transform.rs @@ -26,7 +26,7 @@ impl From> for LogData { let resource: Resource = sdk_log.resource.as_ref().into(); let rl = resource_logs - .entry(sdk_log.resource.as_ref().into()) + .entry(sdk_log.resource.as_ref().to_attribute_set()) .or_insert_with(move || ResourceLogs { resource, scope_logs: Vec::with_capacity(1), diff --git a/opentelemetry-stdout/src/trace/transform.rs b/opentelemetry-stdout/src/trace/transform.rs index e88ae2c4fb..7c4347f351 100644 --- a/opentelemetry-stdout/src/trace/transform.rs +++ b/opentelemetry-stdout/src/trace/transform.rs @@ -20,7 +20,7 @@ impl From> for SpanData { let resource = sdk_span.resource.as_ref().into(); let rs = resource_spans - .entry(sdk_span.resource.as_ref().into()) + .entry(sdk_span.resource.as_ref().to_attribute_set()) .or_insert_with(move || ResourceSpans { resource, scope_spans: Vec::with_capacity(1), diff --git a/opentelemetry/src/attributes/mod.rs b/opentelemetry/src/attributes/mod.rs index 8f7d51d17d..ca3029549b 100644 --- a/opentelemetry/src/attributes/mod.rs +++ b/opentelemetry/src/attributes/mod.rs @@ -2,4 +2,4 @@ mod set; -pub use set::AttributeSet; +pub use set::{AttributeSet, ToKeyValue}; diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index f44a16f98e..88a82c38a6 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -156,6 +156,22 @@ impl Hash for InternalAttributeSet { } } +pub trait ToKeyValue { + fn to_key_value(self) -> KeyValue; +} + +impl ToKeyValue for KeyValue { + fn to_key_value(self) -> KeyValue { + self + } +} + +impl ToKeyValue for &KeyValue { + fn to_key_value(self) -> KeyValue { + self.clone() + } +} + /// A unique set of attributes that can be used as instrument identifiers. /// /// Cloning of an attribute set is cheap, as all clones share a reference to the underlying @@ -166,13 +182,15 @@ impl Hash for InternalAttributeSet { #[derive(Clone, Debug, Hash, PartialEq, Eq)] pub struct AttributeSet(Arc); -impl<'a, I: IntoIterator> From for AttributeSet +impl From for AttributeSet where + KV: ToKeyValue, + I: IntoIterator, ::IntoIter: DoubleEndedIterator + ExactSizeIterator, { fn from(values: I) -> Self { AttributeSet(Arc::new(InternalAttributeSet::from( - values.into_iter().cloned(), + values.into_iter().map(ToKeyValue::to_key_value), ))) } } @@ -241,6 +259,26 @@ mod tests { assert_eq!(kvs[1].1, &Value::I64(3), "Unexpected second value"); } + #[test] + fn can_create_attribute_set_from_owned_vec() { + let vec = vec![KeyValue::new("key1", "value1"), KeyValue::new("key2", 3)]; + + let set = AttributeSet::from(vec); + let mut kvs = set.iter().collect::>(); + + assert_eq!(kvs.len(), 2, "Incorrect number of attributes"); + + kvs.sort_by(|kv1, kv2| kv1.0.cmp(kv2.0)); + assert_eq!(kvs[0].0, &Key::from("key1"), "Unexpected first key"); + assert_eq!( + kvs[0].1, + &Value::String("value1".into()), + "Unexpected first value" + ); + assert_eq!(kvs[1].0, &Key::from("key2"), "Unexpected second key"); + assert_eq!(kvs[1].1, &Value::I64(3), "Unexpected second value"); + } + #[test] fn two_sets_with_same_key_values_in_different_orders_are_equal() { let array1 = [ From ae482c34ac7b273d5c5728ecd2bc6d2148c082c3 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Mon, 8 Jan 2024 16:18:48 -0500 Subject: [PATCH 24/31] Moved `AttributeSet` reference to opentelemetry root --- examples/metrics-basic/src/main.rs | 2 +- opentelemetry-otlp/examples/basic-otlp-http/src/main.rs | 2 +- opentelemetry-otlp/examples/basic-otlp/src/main.rs | 2 +- opentelemetry-prometheus/examples/hyper.rs | 2 +- opentelemetry-prometheus/tests/integration_test.rs | 2 +- opentelemetry-sdk/benches/attribute_set.rs | 2 +- opentelemetry-sdk/benches/metric.rs | 2 +- opentelemetry-sdk/benches/metric_counter.rs | 2 +- opentelemetry-sdk/src/metrics/data/mod.rs | 2 +- opentelemetry-sdk/src/metrics/instrument.rs | 3 +-- opentelemetry-sdk/src/metrics/internal/aggregate.rs | 2 +- .../src/metrics/internal/exponential_histogram.rs | 2 +- opentelemetry-sdk/src/metrics/internal/histogram.rs | 2 +- opentelemetry-sdk/src/metrics/internal/last_value.rs | 2 +- opentelemetry-sdk/src/metrics/internal/sum.rs | 2 +- opentelemetry-sdk/src/metrics/meter.rs | 2 +- opentelemetry-sdk/src/metrics/mod.rs | 2 +- opentelemetry-sdk/src/resource/mod.rs | 2 +- opentelemetry-stdout/src/common.rs | 4 ++-- opentelemetry-stdout/src/logs/transform.rs | 2 +- opentelemetry-stdout/src/trace/transform.rs | 2 +- opentelemetry/src/lib.rs | 3 ++- stress/src/metrics_cached_attrs.rs | 2 +- 23 files changed, 25 insertions(+), 25 deletions(-) diff --git a/examples/metrics-basic/src/main.rs b/examples/metrics-basic/src/main.rs index 2cd252578d..a923234273 100644 --- a/examples/metrics-basic/src/main.rs +++ b/examples/metrics-basic/src/main.rs @@ -1,5 +1,5 @@ -use opentelemetry::attributes::AttributeSet; use opentelemetry::metrics::Unit; +use opentelemetry::AttributeSet; use opentelemetry::{metrics::MeterProvider as _, KeyValue}; use opentelemetry_sdk::metrics::{PeriodicReader, SdkMeterProvider}; use opentelemetry_sdk::{runtime, Resource}; diff --git a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs index 736a4528f5..aa028b920b 100644 --- a/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp-http/src/main.rs @@ -11,7 +11,7 @@ use opentelemetry_sdk::metrics as sdkmetrics; use opentelemetry_sdk::resource; use opentelemetry_sdk::trace as sdktrace; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use std::error::Error; use tracing::info; use tracing_subscriber::prelude::*; diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index d620419e7d..55ae98b030 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -1,10 +1,10 @@ use log::{info, Level}; use once_cell::sync::Lazy; -use opentelemetry::attributes::AttributeSet; use opentelemetry::global; use opentelemetry::global::{logger_provider, shutdown_logger_provider, shutdown_tracer_provider}; use opentelemetry::logs::LogError; use opentelemetry::trace::TraceError; +use opentelemetry::AttributeSet; use opentelemetry::{ metrics, trace::{TraceContextExt, Tracer}, diff --git a/opentelemetry-prometheus/examples/hyper.rs b/opentelemetry-prometheus/examples/hyper.rs index ad6e3b7f37..a97bb4320e 100644 --- a/opentelemetry-prometheus/examples/hyper.rs +++ b/opentelemetry-prometheus/examples/hyper.rs @@ -4,7 +4,7 @@ use hyper::{ Body, Method, Request, Response, Server, }; use once_cell::sync::Lazy; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::{ metrics::{Counter, Histogram, MeterProvider as _, Unit}, KeyValue, diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs index dca301c034..dec40b0edb 100644 --- a/opentelemetry-prometheus/tests/integration_test.rs +++ b/opentelemetry-prometheus/tests/integration_test.rs @@ -2,8 +2,8 @@ use std::fs; use std::path::Path; use std::time::Duration; -use opentelemetry::attributes::AttributeSet; use opentelemetry::metrics::{Meter, MeterProvider as _, Unit}; +use opentelemetry::AttributeSet; use opentelemetry::Key; use opentelemetry::KeyValue; use opentelemetry_prometheus::ExporterBuilder; diff --git a/opentelemetry-sdk/benches/attribute_set.rs b/opentelemetry-sdk/benches/attribute_set.rs index f3932f7ac1..1fb6dccc1e 100644 --- a/opentelemetry-sdk/benches/attribute_set.rs +++ b/opentelemetry-sdk/benches/attribute_set.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::KeyValue; // Run this benchmark with: diff --git a/opentelemetry-sdk/benches/metric.rs b/opentelemetry-sdk/benches/metric.rs index ae67183970..3c668d58a8 100644 --- a/opentelemetry-sdk/benches/metric.rs +++ b/opentelemetry-sdk/benches/metric.rs @@ -2,7 +2,7 @@ use rand::Rng; use std::sync::{Arc, Weak}; use criterion::{criterion_group, criterion_main, Bencher, Criterion}; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::{ metrics::{Counter, Histogram, MeterProvider as _, Result}, Key, KeyValue, diff --git a/opentelemetry-sdk/benches/metric_counter.rs b/opentelemetry-sdk/benches/metric_counter.rs index 36b880216c..9e12243fdf 100644 --- a/opentelemetry-sdk/benches/metric_counter.rs +++ b/opentelemetry-sdk/benches/metric_counter.rs @@ -1,5 +1,5 @@ use criterion::{criterion_group, criterion_main, Criterion}; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::{ metrics::{Counter, MeterProvider as _}, KeyValue, diff --git a/opentelemetry-sdk/src/metrics/data/mod.rs b/opentelemetry-sdk/src/metrics/data/mod.rs index a94e35fd60..ec429ba1f8 100644 --- a/opentelemetry-sdk/src/metrics/data/mod.rs +++ b/opentelemetry-sdk/src/metrics/data/mod.rs @@ -5,7 +5,7 @@ use std::{any, borrow::Cow, fmt, time::SystemTime}; use opentelemetry::{metrics::Unit, KeyValue}; use crate::{instrumentation::Scope, Resource}; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; pub use self::temporality::Temporality; diff --git a/opentelemetry-sdk/src/metrics/instrument.rs b/opentelemetry-sdk/src/metrics/instrument.rs index fab4bfbaa3..5b342fd3ff 100644 --- a/opentelemetry-sdk/src/metrics/instrument.rs +++ b/opentelemetry-sdk/src/metrics/instrument.rs @@ -1,12 +1,11 @@ use std::{any::Any, borrow::Cow, collections::HashSet, hash::Hash, marker, sync::Arc}; use opentelemetry::{ - attributes::AttributeSet, metrics::{ AsyncInstrument, MetricsError, Result, SyncCounter, SyncGauge, SyncHistogram, SyncUpDownCounter, Unit, }, - Key, + AttributeSet, Key, }; use crate::{ diff --git a/opentelemetry-sdk/src/metrics/internal/aggregate.rs b/opentelemetry-sdk/src/metrics/internal/aggregate.rs index 1022c1d5e8..8486892701 100644 --- a/opentelemetry-sdk/src/metrics/internal/aggregate.rs +++ b/opentelemetry-sdk/src/metrics/internal/aggregate.rs @@ -1,7 +1,7 @@ use std::{marker, sync::Arc}; use once_cell::sync::Lazy; -use opentelemetry::{attributes::AttributeSet, KeyValue}; +use opentelemetry::{AttributeSet, KeyValue}; use crate::metrics::data::{Aggregation, Gauge, Temporality}; diff --git a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs index bb16d2a540..5411637e05 100644 --- a/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs @@ -1,7 +1,7 @@ use std::{collections::HashMap, f64::consts::LOG2_E, sync::Mutex, time::SystemTime}; use once_cell::sync::Lazy; -use opentelemetry::{attributes::AttributeSet, metrics::MetricsError}; +use opentelemetry::{metrics::MetricsError, AttributeSet}; use crate::metrics::data::{self, Aggregation, Temporality}; diff --git a/opentelemetry-sdk/src/metrics/internal/histogram.rs b/opentelemetry-sdk/src/metrics/internal/histogram.rs index 47ec585b0d..75acfe3f9e 100644 --- a/opentelemetry-sdk/src/metrics/internal/histogram.rs +++ b/opentelemetry-sdk/src/metrics/internal/histogram.rs @@ -2,7 +2,7 @@ use std::{collections::HashMap, sync::Mutex, time::SystemTime}; use crate::metrics::data::HistogramDataPoint; use crate::metrics::data::{self, Aggregation, Temporality}; -use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; +use opentelemetry::{global, metrics::MetricsError, AttributeSet}; use super::{ aggregate::{is_under_cardinality_limit, STREAM_OVERFLOW_ATTRIBUTE_SET}, diff --git a/opentelemetry-sdk/src/metrics/internal/last_value.rs b/opentelemetry-sdk/src/metrics/internal/last_value.rs index ab4cd4a3ac..f5d9f8d997 100644 --- a/opentelemetry-sdk/src/metrics/internal/last_value.rs +++ b/opentelemetry-sdk/src/metrics/internal/last_value.rs @@ -5,7 +5,7 @@ use std::{ }; use crate::metrics::data::DataPoint; -use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; +use opentelemetry::{global, metrics::MetricsError, AttributeSet}; use super::{ aggregate::{is_under_cardinality_limit, STREAM_OVERFLOW_ATTRIBUTE_SET}, diff --git a/opentelemetry-sdk/src/metrics/internal/sum.rs b/opentelemetry-sdk/src/metrics/internal/sum.rs index 239c4fde4e..b6d3233217 100644 --- a/opentelemetry-sdk/src/metrics/internal/sum.rs +++ b/opentelemetry-sdk/src/metrics/internal/sum.rs @@ -5,7 +5,7 @@ use std::{ }; use crate::metrics::data::{self, Aggregation, DataPoint, Temporality}; -use opentelemetry::{attributes::AttributeSet, global, metrics::MetricsError}; +use opentelemetry::{global, metrics::MetricsError, AttributeSet}; use super::{ aggregate::{is_under_cardinality_limit, STREAM_OVERFLOW_ATTRIBUTE_SET}, diff --git a/opentelemetry-sdk/src/metrics/meter.rs b/opentelemetry-sdk/src/metrics/meter.rs index 12bac46f62..26501f85d7 100644 --- a/opentelemetry-sdk/src/metrics/meter.rs +++ b/opentelemetry-sdk/src/metrics/meter.rs @@ -1,7 +1,7 @@ use core::fmt; use std::{any::Any, borrow::Cow, collections::HashSet, sync::Arc}; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::{ global, metrics::{ diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 81552909d0..25b1f07c3c 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -64,7 +64,7 @@ pub use view::*; mod tests { use super::*; use crate::{runtime, testing::metrics::InMemoryMetricsExporter}; - use opentelemetry::attributes::AttributeSet; + use opentelemetry::AttributeSet; use opentelemetry::{ metrics::{MeterProvider as _, Unit}, KeyValue, diff --git a/opentelemetry-sdk/src/resource/mod.rs b/opentelemetry-sdk/src/resource/mod.rs index ab7c202def..59d8debc45 100644 --- a/opentelemetry-sdk/src/resource/mod.rs +++ b/opentelemetry-sdk/src/resource/mod.rs @@ -30,7 +30,7 @@ pub use os::OsResourceDetector; pub use process::ProcessResourceDetector; pub use telemetry::TelemetryResourceDetector; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::{Key, KeyValue, Value}; use std::borrow::Cow; use std::collections::{hash_map, HashMap}; diff --git a/opentelemetry-stdout/src/common.rs b/opentelemetry-stdout/src/common.rs index 79c65ce324..0897fbb22a 100644 --- a/opentelemetry-stdout/src/common.rs +++ b/opentelemetry-stdout/src/common.rs @@ -12,8 +12,8 @@ use serde::{Serialize, Serializer}; #[derive(Debug, Serialize, Clone, Hash, Eq, PartialEq)] pub(crate) struct AttributeSet(pub BTreeMap); -impl From<&opentelemetry::attributes::AttributeSet> for AttributeSet { - fn from(value: &opentelemetry::attributes::AttributeSet) -> Self { +impl From<&opentelemetry::AttributeSet> for AttributeSet { + fn from(value: &opentelemetry::AttributeSet) -> Self { AttributeSet( value .iter() diff --git a/opentelemetry-stdout/src/logs/transform.rs b/opentelemetry-stdout/src/logs/transform.rs index 71453d0535..dba3b830ca 100644 --- a/opentelemetry-stdout/src/logs/transform.rs +++ b/opentelemetry-stdout/src/logs/transform.rs @@ -4,7 +4,7 @@ use crate::common::{ as_human_readable, as_opt_human_readable, as_opt_unix_nano, as_unix_nano, KeyValue, Resource, Scope, Value, }; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use serde::Serialize; /// Transformed logs data that can be serialized. diff --git a/opentelemetry-stdout/src/trace/transform.rs b/opentelemetry-stdout/src/trace/transform.rs index 7c4347f351..9af26986c6 100644 --- a/opentelemetry-stdout/src/trace/transform.rs +++ b/opentelemetry-stdout/src/trace/transform.rs @@ -1,5 +1,5 @@ use crate::common::{as_human_readable, as_unix_nano, KeyValue, Resource, Scope}; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use serde::{Serialize, Serializer}; use std::{borrow::Cow, collections::HashMap, time::SystemTime}; diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index ec02c4b661..dfafa22a1c 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -209,7 +209,8 @@ pub mod global; pub mod baggage; -pub mod attributes; +mod attributes; +pub use attributes::{AttributeSet, ToKeyValue}; mod context; diff --git a/stress/src/metrics_cached_attrs.rs b/stress/src/metrics_cached_attrs.rs index 49d5024057..867ffa2e3e 100644 --- a/stress/src/metrics_cached_attrs.rs +++ b/stress/src/metrics_cached_attrs.rs @@ -1,5 +1,5 @@ use lazy_static::lazy_static; -use opentelemetry::attributes::AttributeSet; +use opentelemetry::AttributeSet; use opentelemetry::{ metrics::{Counter, MeterProvider as _}, KeyValue, From 440a5bc7935f90c0b068b13e0dd8da5a491c86ca Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Mon, 8 Jan 2024 16:46:15 -0500 Subject: [PATCH 25/31] Added missing docs --- opentelemetry-sdk/src/resource/mod.rs | 1 + opentelemetry/src/attributes/set.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/opentelemetry-sdk/src/resource/mod.rs b/opentelemetry-sdk/src/resource/mod.rs index 59d8debc45..cf6f18440a 100644 --- a/opentelemetry-sdk/src/resource/mod.rs +++ b/opentelemetry-sdk/src/resource/mod.rs @@ -192,6 +192,7 @@ impl Resource { self.attrs.get(&key).cloned() } + /// Creates a new attribute set from the resource's current attributes pub fn to_attribute_set(&self) -> AttributeSet { let key_values = self .iter() diff --git a/opentelemetry/src/attributes/set.rs b/opentelemetry/src/attributes/set.rs index 88a82c38a6..4f20c8fdcb 100644 --- a/opentelemetry/src/attributes/set.rs +++ b/opentelemetry/src/attributes/set.rs @@ -156,7 +156,9 @@ impl Hash for InternalAttributeSet { } } +/// Trait declaring that a type can be converted into a `KeyValue` pub trait ToKeyValue { + /// Create a `KeyValue` from the current instance. fn to_key_value(self) -> KeyValue; } From a34194d1713f01eaa50e88941215c6c270ad220d Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Mon, 8 Jan 2024 16:57:34 -0500 Subject: [PATCH 26/31] Fix doctests pointing to changed module location --- opentelemetry-prometheus/src/lib.rs | 4 ++-- opentelemetry-sdk/src/lib.rs | 4 ++-- opentelemetry-sdk/src/metrics/mod.rs | 2 +- opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs | 2 +- opentelemetry/src/global/mod.rs | 4 ++-- opentelemetry/src/lib.rs | 2 +- opentelemetry/src/metrics/meter.rs | 2 +- 7 files changed, 10 insertions(+), 10 deletions(-) diff --git a/opentelemetry-prometheus/src/lib.rs b/opentelemetry-prometheus/src/lib.rs index 270aee8f2b..a28061e513 100644 --- a/opentelemetry-prometheus/src/lib.rs +++ b/opentelemetry-prometheus/src/lib.rs @@ -3,14 +3,14 @@ //! [Prometheus]: https://prometheus.io //! //! ``` -//! use opentelemetry::{attributes::AttributeSet, metrics::MeterProvider, KeyValue}; +//! use opentelemetry::{AttributeSet, metrics::MeterProvider, KeyValue}; //! use opentelemetry_sdk::metrics::SdkMeterProvider; //! use prometheus::{Encoder, TextEncoder}; //! //! # fn main() -> Result<(), Box> { //! //! // create a new prometheus registry -//! use opentelemetry::attributes::AttributeSet; +//! use opentelemetry::AttributeSet; //! let registry = prometheus::Registry::new(); //! //! // configure OpenTelemetry to use this registry diff --git a/opentelemetry-sdk/src/lib.rs b/opentelemetry-sdk/src/lib.rs index a2a8fb58de..aefcd6f93c 100644 --- a/opentelemetry-sdk/src/lib.rs +++ b/opentelemetry-sdk/src/lib.rs @@ -52,10 +52,10 @@ //! ### Creating instruments and recording measurements //! //! ``` -//! # use opentelemetry::attributes::AttributeSet; +//! # use opentelemetry::AttributeSet; //! #[cfg(feature = "metrics")] //! # { -//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; +//! use opentelemetry::{AttributeSet, global, KeyValue}; //! //! // get a meter from a provider //! let meter = global::meter("my_service"); diff --git a/opentelemetry-sdk/src/metrics/mod.rs b/opentelemetry-sdk/src/metrics/mod.rs index 25b1f07c3c..622133aa70 100644 --- a/opentelemetry-sdk/src/metrics/mod.rs +++ b/opentelemetry-sdk/src/metrics/mod.rs @@ -13,7 +13,7 @@ //! metrics::{MeterProvider, Unit}, //! KeyValue, //! }; -//! use opentelemetry::attributes::AttributeSet; +//! use opentelemetry::AttributeSet; //! use opentelemetry_sdk::{metrics::SdkMeterProvider, Resource}; //! //! // Generate SDK configuration, resource, views, etc diff --git a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs index 86b41d6c83..3edff3d2dd 100644 --- a/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs +++ b/opentelemetry-sdk/src/testing/metrics/in_memory_exporter.rs @@ -29,7 +29,7 @@ use std::sync::{Arc, Mutex}; /// ``` ///# use opentelemetry_sdk::{metrics, runtime}; ///# use opentelemetry::{KeyValue}; -///# use opentelemetry::attributes::AttributeSet; +///# use opentelemetry::AttributeSet; ///# use opentelemetry::metrics::MeterProvider; ///# use opentelemetry_sdk::testing::metrics::InMemoryMetricsExporter; ///# use opentelemetry_sdk::metrics::PeriodicReader; diff --git a/opentelemetry/src/global/mod.rs b/opentelemetry/src/global/mod.rs index 0efff241c1..3af9145dc5 100644 --- a/opentelemetry/src/global/mod.rs +++ b/opentelemetry/src/global/mod.rs @@ -92,7 +92,7 @@ //! # #[cfg(feature="metrics")] //! # { //! use opentelemetry::metrics::{Meter, noop::NoopMeterProvider}; -//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; +//! use opentelemetry::{AttributeSet, global, KeyValue}; //! //! fn init_meter() { //! let provider = NoopMeterProvider::new(); @@ -123,7 +123,7 @@ //! ``` //! # #[cfg(feature="metrics")] //! # { -//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; +//! use opentelemetry::{AttributeSet, global, KeyValue}; //! //! pub fn my_traced_library_function() { //! // End users of your library will configure their global meter provider diff --git a/opentelemetry/src/lib.rs b/opentelemetry/src/lib.rs index dfafa22a1c..c6753174fe 100644 --- a/opentelemetry/src/lib.rs +++ b/opentelemetry/src/lib.rs @@ -72,7 +72,7 @@ //! ``` //! # #[cfg(feature = "metrics")] //! # { -//! use opentelemetry::{attributes::AttributeSet, global, KeyValue}; +//! use opentelemetry::{AttributeSet, global, KeyValue}; //! //! // get a meter from a provider //! let meter = global::meter("my_service"); diff --git a/opentelemetry/src/metrics/meter.rs b/opentelemetry/src/metrics/meter.rs index 94e6797a61..999c0e9b1f 100644 --- a/opentelemetry/src/metrics/meter.rs +++ b/opentelemetry/src/metrics/meter.rs @@ -72,7 +72,7 @@ pub trait MeterProvider { /// Provides access to instrument instances for recording measurements. /// /// ``` -/// use opentelemetry::{attributes::AttributeSet, global, KeyValue}; +/// use opentelemetry::{AttributeSet, global, KeyValue}; /// /// let meter = global::meter("my-meter"); /// From 4d5dcddd27fe767e6e172fa53fc2829decba4d41 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Tue, 23 Jan 2024 10:14:28 -0500 Subject: [PATCH 27/31] Add changelog entry --- opentelemetry/CHANGELOG.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index b57647e5ab..8b7962c8c3 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -17,6 +17,16 @@ gains, and avoids `IndexMap` dependency. This affects `body` and `attributes` of `LogRecord`. [#1353](https://github.com/open-telemetry/opentelemetry-rust/pull/1353) - Add `TextMapCompositePropagator` [#1373](https://github.com/open-telemetry/opentelemetry-rust/pull/1373) +- `Counters`, `UpDownCounters`, `Observables`, and `Histograms` now take an + `Into` as the parameter type for recording metric values. This + allows passing in a precreated `AttributeSet` for better performance when the + same set of attributes are used across instruments. This is backward + compatible with previous calls passing in `&[KeyValue]`. + [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) +- `Histograms` and `Gauges` no longer accept `&[KeyValue]` parameters for + `observe()` or `record()` calls, and only accept a precreated `AttributeSet` + value. + [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) ### Removed From 892b6f1b00b09ee1d3b900824d60bdde73d65787 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Tue, 23 Jan 2024 10:24:39 -0500 Subject: [PATCH 28/31] Minor nits --- opentelemetry-otlp/examples/basic-otlp/src/main.rs | 2 +- opentelemetry-prometheus/tests/integration_test.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/opentelemetry-otlp/examples/basic-otlp/src/main.rs b/opentelemetry-otlp/examples/basic-otlp/src/main.rs index 55ae98b030..1c252906f9 100644 --- a/opentelemetry-otlp/examples/basic-otlp/src/main.rs +++ b/opentelemetry-otlp/examples/basic-otlp/src/main.rs @@ -132,7 +132,7 @@ async fn main() -> Result<(), Box> { span.add_event("Sub span event", vec![]); - histogram.record(1.3, AttributeSet::default()); + histogram.record(1.3, &[]); }); }); diff --git a/opentelemetry-prometheus/tests/integration_test.rs b/opentelemetry-prometheus/tests/integration_test.rs index dec40b0edb..b81e4ec241 100644 --- a/opentelemetry-prometheus/tests/integration_test.rs +++ b/opentelemetry-prometheus/tests/integration_test.rs @@ -59,7 +59,7 @@ fn prometheus_exporter_integration() { .init(); counter.add(5.0, attrs.clone()); counter.add(10.3, attrs.clone()); - counter.add(9.0, attrs.clone()); + counter.add(9.0, attrs); let attrs2 = AttributeSet::from(&[ Key::new("A").string("D"), @@ -90,7 +90,7 @@ fn prometheus_exporter_integration() { .init(); counter.add(5.0, attrs.clone()); counter.add(10.3, attrs.clone()); - counter.add(9.0, attrs.clone()); + counter.add(9.0, attrs); let attrs2 = AttributeSet::from(&[ Key::new("A").string("D"), Key::new("C").string("B"), From d2f7ad024d886d6dda17a3a17131922232d3e78f Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 24 Jan 2024 14:18:22 -0500 Subject: [PATCH 29/31] Histogram is backward compatible --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index 8b7962c8c3..cad688c645 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -23,7 +23,7 @@ gains, and avoids `IndexMap` dependency. This affects `body` and `attributes` of same set of attributes are used across instruments. This is backward compatible with previous calls passing in `&[KeyValue]`. [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) -- `Histograms` and `Gauges` no longer accept `&[KeyValue]` parameters for +- `Gauges` no longer accept `&[KeyValue]` parameters for `observe()` or `record()` calls, and only accept a precreated `AttributeSet` value. [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) From a3b1cf4e9bca0abc0344bc9ca79058e4b9ea3d61 Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 24 Jan 2024 14:39:18 -0500 Subject: [PATCH 30/31] Gauges are compat, observables are not --- opentelemetry/CHANGELOG.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index cad688c645..c9aa24c272 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -17,13 +17,13 @@ gains, and avoids `IndexMap` dependency. This affects `body` and `attributes` of `LogRecord`. [#1353](https://github.com/open-telemetry/opentelemetry-rust/pull/1353) - Add `TextMapCompositePropagator` [#1373](https://github.com/open-telemetry/opentelemetry-rust/pull/1373) -- `Counters`, `UpDownCounters`, `Observables`, and `Histograms` now take an +- `Counters`, `UpDownCounters`, `Gauges`, and `Histograms` now take an `Into` as the parameter type for recording metric values. This allows passing in a precreated `AttributeSet` for better performance when the same set of attributes are used across instruments. This is backward compatible with previous calls passing in `&[KeyValue]`. [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) -- `Gauges` no longer accept `&[KeyValue]` parameters for +- Observable instruments no longer accept `&[KeyValue]` parameters for `observe()` or `record()` calls, and only accept a precreated `AttributeSet` value. [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) From ef330e130af51d179cfb7860084837c9f51c43ca Mon Sep 17 00:00:00 2001 From: Matthew Shapiro Date: Wed, 24 Jan 2024 14:48:44 -0500 Subject: [PATCH 31/31] Update opentelemetry/CHANGELOG.md Co-authored-by: Cijo Thomas --- opentelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/opentelemetry/CHANGELOG.md b/opentelemetry/CHANGELOG.md index c9aa24c272..db83c515ae 100644 --- a/opentelemetry/CHANGELOG.md +++ b/opentelemetry/CHANGELOG.md @@ -24,7 +24,7 @@ gains, and avoids `IndexMap` dependency. This affects `body` and `attributes` of compatible with previous calls passing in `&[KeyValue]`. [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421) - Observable instruments no longer accept `&[KeyValue]` parameters for - `observe()` or `record()` calls, and only accept a precreated `AttributeSet` + `observe()` calls, and only accept a precreated `AttributeSet` value. [#1421](https://github.com/open-telemetry/opentelemetry-rust/pull/1421)