Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Replace once_cell::Lazy with std::sync::OnceLock for global Initialization in otel-sdk crate #2342

Merged
merged 10 commits into from
Nov 27, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion opentelemetry-sdk/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ async-trait = { workspace = true, optional = true }
futures-channel = "0.3"
futures-executor = { workspace = true }
futures-util = { workspace = true, features = ["std", "sink", "async-await-macro"] }
once_cell = { workspace = true }
percent-encoding = { version = "2.0", optional = true }
rand = { workspace = true, features = ["std", "std_rng","small_rng"], optional = true }
glob = { version = "0.3.1", optional =true}
Expand Down
26 changes: 15 additions & 11 deletions opentelemetry-sdk/src/logs/log_emitter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,24 @@ use std::{
borrow::Cow,
sync::{
atomic::{AtomicBool, Ordering},
Arc,
Arc, OnceLock,
},
};

use once_cell::sync::Lazy;

// a no nop logger provider used as placeholder when the provider is shutdown
static NOOP_LOGGER_PROVIDER: Lazy<LoggerProvider> = Lazy::new(|| LoggerProvider {
inner: Arc::new(LoggerProviderInner {
processors: Vec::new(),
resource: Resource::empty(),
is_shutdown: AtomicBool::new(true),
}),
});
// TODO - replace it with LazyLock once it is stable
static NOOP_LOGGER_PROVIDER: OnceLock<LoggerProvider> = OnceLock::new();

#[inline]
fn noop_logger_provider() -> &'static LoggerProvider {
NOOP_LOGGER_PROVIDER.get_or_init(|| LoggerProvider {
inner: Arc::new(LoggerProviderInner {
processors: Vec::new(),
resource: Resource::empty(),
is_shutdown: AtomicBool::new(true),
}),
})
}

#[derive(Debug, Clone)]
/// Handles the creation and coordination of [`Logger`]s.
Expand Down Expand Up @@ -55,7 +59,7 @@ impl opentelemetry::logs::LoggerProvider for LoggerProvider {
fn logger_with_scope(&self, scope: InstrumentationScope) -> Self::Logger {
// If the provider is shutdown, new logger will refer a no-op logger provider.
if self.inner.is_shutdown.load(Ordering::Relaxed) {
return Logger::new(scope, NOOP_LOGGER_PROVIDER.clone());
return Logger::new(scope, noop_logger_provider().clone());
}
if scope.name().is_empty() {
otel_info!(name: "LoggerNameEmpty", message = "Logger name is empty; consider providing a meaningful name. Logger will function normally and the provided name will be used as-is.");
Expand Down
62 changes: 34 additions & 28 deletions opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{f64::consts::LOG2_E, mem::replace, ops::DerefMut, sync::Mutex, time::SystemTime};

use once_cell::sync::Lazy;
use opentelemetry::{otel_debug, KeyValue};
use std::sync::OnceLock;

use crate::metrics::{
data::{self, Aggregation},
Expand Down Expand Up @@ -131,7 +131,7 @@ impl<T: Number> ExpoHistogramDataPoint<T> {
}
return (exp - correction) >> -self.scale;
}
(exp << self.scale) + (frac.ln() * SCALE_FACTORS[self.scale as usize]) as i32 - 1
(exp << self.scale) + (frac.ln() * scale_factors()[self.scale as usize]) as i32 - 1
}
}

Expand Down Expand Up @@ -165,32 +165,38 @@ fn scale_change(max_size: i32, bin: i32, start_bin: i32, length: i32) -> u32 {
count
}

/// Constants used in calculating the logarithm index.
static SCALE_FACTORS: Lazy<[f64; 21]> = Lazy::new(|| {
[
LOG2_E * 2f64.powi(0),
LOG2_E * 2f64.powi(1),
LOG2_E * 2f64.powi(2),
LOG2_E * 2f64.powi(3),
LOG2_E * 2f64.powi(4),
LOG2_E * 2f64.powi(5),
LOG2_E * 2f64.powi(6),
LOG2_E * 2f64.powi(7),
LOG2_E * 2f64.powi(8),
LOG2_E * 2f64.powi(9),
LOG2_E * 2f64.powi(10),
LOG2_E * 2f64.powi(11),
LOG2_E * 2f64.powi(12),
LOG2_E * 2f64.powi(13),
LOG2_E * 2f64.powi(14),
LOG2_E * 2f64.powi(15),
LOG2_E * 2f64.powi(16),
LOG2_E * 2f64.powi(17),
LOG2_E * 2f64.powi(18),
LOG2_E * 2f64.powi(19),
LOG2_E * 2f64.powi(20),
]
});
// TODO - replace it with LazyLock once it is stable
static SCALE_FACTORS: OnceLock<[f64; 21]> = OnceLock::new();

/// returns constants used in calculating the logarithm index.
#[inline]
fn scale_factors() -> &'static [f64; 21] {
SCALE_FACTORS.get_or_init(|| {
[
LOG2_E * 2f64.powi(0),
LOG2_E * 2f64.powi(1),
LOG2_E * 2f64.powi(2),
LOG2_E * 2f64.powi(3),
LOG2_E * 2f64.powi(4),
LOG2_E * 2f64.powi(5),
LOG2_E * 2f64.powi(6),
LOG2_E * 2f64.powi(7),
LOG2_E * 2f64.powi(8),
LOG2_E * 2f64.powi(9),
LOG2_E * 2f64.powi(10),
LOG2_E * 2f64.powi(11),
LOG2_E * 2f64.powi(12),
LOG2_E * 2f64.powi(13),
LOG2_E * 2f64.powi(14),
LOG2_E * 2f64.powi(15),
LOG2_E * 2f64.powi(16),
LOG2_E * 2f64.powi(17),
LOG2_E * 2f64.powi(18),
LOG2_E * 2f64.powi(19),
LOG2_E * 2f64.powi(20),
]
})
}

/// Breaks the number into a normalized fraction and a base-2 exponent.
///
Expand Down
15 changes: 10 additions & 5 deletions opentelemetry-sdk/src/metrics/internal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,16 @@ use std::sync::{Arc, RwLock};
use aggregate::{is_under_cardinality_limit, STREAM_CARDINALITY_LIMIT};
pub(crate) use aggregate::{AggregateBuilder, ComputeAggregation, Measure};
pub(crate) use exponential_histogram::{EXPO_MAX_SCALE, EXPO_MIN_SCALE};
use once_cell::sync::Lazy;
use opentelemetry::{otel_warn, KeyValue};
use std::sync::OnceLock;

pub(crate) static STREAM_OVERFLOW_ATTRIBUTES: Lazy<Vec<KeyValue>> =
Lazy::new(|| vec![KeyValue::new("otel.metric.overflow", "true")]);
// TODO Replace it with LazyLock once it is stable
pub(crate) static STREAM_OVERFLOW_ATTRIBUTES: OnceLock<Vec<KeyValue>> = OnceLock::new();

#[inline]
fn stream_overflow_attributes() -> &'static Vec<KeyValue> {
STREAM_OVERFLOW_ATTRIBUTES.get_or_init(|| vec![KeyValue::new("otel.metric.overflow", "true")])
}

pub(crate) trait Aggregator {
/// A static configuration that is needed in order to initialize aggregator.
Expand Down Expand Up @@ -129,12 +134,12 @@ where
trackers.insert(sorted_attrs, new_tracker);

self.count.fetch_add(1, Ordering::SeqCst);
} else if let Some(overflow_value) = trackers.get(STREAM_OVERFLOW_ATTRIBUTES.as_slice()) {
} else if let Some(overflow_value) = trackers.get(stream_overflow_attributes().as_slice()) {
overflow_value.update(value);
} else {
let new_tracker = A::create(&self.config);
new_tracker.update(value);
trackers.insert(STREAM_OVERFLOW_ATTRIBUTES.clone(), Arc::new(new_tracker));
trackers.insert(stream_overflow_attributes().clone(), Arc::new(new_tracker));
otel_warn!( name: "ValueMap.measure",
message = "Maximum data points for metric stream exceeded. Entry added to overflow. Subsequent overflows to same metric until next collect will not be logged."
);
Expand Down
12 changes: 9 additions & 3 deletions opentelemetry-sdk/src/propagation/baggage.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
use once_cell::sync::Lazy;
use opentelemetry::{
baggage::{BaggageExt, KeyValueMetadata},
otel_warn,
Expand All @@ -7,10 +6,17 @@ use opentelemetry::{
};
use percent_encoding::{percent_decode_str, utf8_percent_encode, AsciiSet, CONTROLS};
use std::iter;
use std::sync::OnceLock;

static BAGGAGE_HEADER: &str = "baggage";
const FRAGMENT: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b';').add(b',').add(b'=');
static BAGGAGE_FIELDS: Lazy<[String; 1]> = Lazy::new(|| [BAGGAGE_HEADER.to_owned()]);

// TODO Replace this with LazyLock once it is stable.
static BAGGAGE_FIELDS: OnceLock<[String; 1]> = OnceLock::new();
#[inline]
fn baggage_fields() -> &'static [String; 1] {
BAGGAGE_FIELDS.get_or_init(|| [BAGGAGE_HEADER.to_owned()])
}

/// Propagates name-value pairs in [W3C Baggage] format.
///
Expand Down Expand Up @@ -149,7 +155,7 @@ impl TextMapPropagator for BaggagePropagator {
}

fn fields(&self) -> FieldIter<'_> {
FieldIter::new(BAGGAGE_FIELDS.as_ref())
FieldIter::new(baggage_fields())
}
}

Expand Down
13 changes: 9 additions & 4 deletions opentelemetry-sdk/src/propagation/trace_context.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
//! # W3C Trace Context Propagator
//!

use once_cell::sync::Lazy;
use opentelemetry::{
propagation::{text_map_propagator::FieldIter, Extractor, Injector, TextMapPropagator},
trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState},
Context,
};
use std::str::FromStr;
use std::sync::OnceLock;

const SUPPORTED_VERSION: u8 = 0;
const MAX_VERSION: u8 = 254;
const TRACEPARENT_HEADER: &str = "traceparent";
const TRACESTATE_HEADER: &str = "tracestate";

static TRACE_CONTEXT_HEADER_FIELDS: Lazy<[String; 2]> =
Lazy::new(|| [TRACEPARENT_HEADER.to_owned(), TRACESTATE_HEADER.to_owned()]);
// TODO Replace this with LazyLock once it is stable.
static TRACE_CONTEXT_HEADER_FIELDS: OnceLock<[String; 2]> = OnceLock::new();

fn trace_context_header_fields() -> &'static [String; 2] {
TRACE_CONTEXT_HEADER_FIELDS
.get_or_init(|| [TRACEPARENT_HEADER.to_owned(), TRACESTATE_HEADER.to_owned()])
}

/// Propagates `SpanContext`s in [W3C TraceContext] format under `traceparent` and `tracestate` header.
///
Expand Down Expand Up @@ -146,7 +151,7 @@ impl TextMapPropagator for TraceContextPropagator {
}

fn fields(&self) -> FieldIter<'_> {
FieldIter::new(TRACE_CONTEXT_HEADER_FIELDS.as_ref())
FieldIter::new(trace_context_header_fields())
}
}

Expand Down
52 changes: 25 additions & 27 deletions opentelemetry-sdk/src/trace/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,32 +68,38 @@ use crate::trace::{
};
use crate::Resource;
use crate::{export::trace::SpanExporter, trace::SpanProcessor};
use once_cell::sync::{Lazy, OnceCell};
use opentelemetry::trace::TraceError;
use opentelemetry::InstrumentationScope;
use opentelemetry::{otel_debug, trace::TraceResult};
use std::borrow::Cow;
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
use std::sync::{Arc, OnceLock};

use super::IdGenerator;

static PROVIDER_RESOURCE: OnceCell<Resource> = OnceCell::new();
static PROVIDER_RESOURCE: OnceLock<Resource> = OnceLock::new();

// a no nop tracer provider used as placeholder when the provider is shutdown
static NOOP_TRACER_PROVIDER: Lazy<TracerProvider> = Lazy::new(|| TracerProvider {
inner: Arc::new(TracerProviderInner {
processors: Vec::new(),
config: Config {
// cannot use default here as the default resource is not empty
sampler: Box::new(Sampler::ParentBased(Box::new(Sampler::AlwaysOn))),
id_generator: Box::<RandomIdGenerator>::default(),
span_limits: SpanLimits::default(),
resource: Cow::Owned(Resource::empty()),
},
is_shutdown: AtomicBool::new(true),
}),
});
// TODO Replace with LazyLock once it is stable
static NOOP_TRACER_PROVIDER: OnceLock<TracerProvider> = OnceLock::new();
#[inline]
fn noop_tracer_provider() -> &'static TracerProvider {
NOOP_TRACER_PROVIDER.get_or_init(|| {
TracerProvider {
inner: Arc::new(TracerProviderInner {
processors: Vec::new(),
config: Config {
// cannot use default here as the default resource is not empty
sampler: Box::new(Sampler::ParentBased(Box::new(Sampler::AlwaysOn))),
id_generator: Box::<RandomIdGenerator>::default(),
span_limits: SpanLimits::default(),
resource: Cow::Owned(Resource::empty()),
},
is_shutdown: AtomicBool::new(true),
}),
}
})
}

/// TracerProvider inner type
#[derive(Debug)]
Expand Down Expand Up @@ -269,7 +275,7 @@ impl opentelemetry::trace::TracerProvider for TracerProvider {

fn tracer_with_scope(&self, scope: InstrumentationScope) -> Self::Tracer {
if self.inner.is_shutdown.load(Ordering::Relaxed) {
return Tracer::new(scope, NOOP_TRACER_PROVIDER.clone());
return Tracer::new(scope, noop_tracer_provider().clone());
}
Tracer::new(scope, self.clone())
}
Expand Down Expand Up @@ -392,16 +398,8 @@ impl Builder {
// For the uncommon case where there are multiple tracer providers with different resource
// configurations, users can optionally provide their own borrowed static resource.
if matches!(config.resource, Cow::Owned(_)) {
config.resource = match PROVIDER_RESOURCE.try_insert(config.resource.into_owned()) {
Ok(static_resource) => Cow::Borrowed(static_resource),
Err((prev, new)) => {
if prev == &new {
Cow::Borrowed(prev)
} else {
Cow::Owned(new)
}
}
}
let owned_resource = config.resource.clone().into_owned();
config.resource = Cow::Borrowed(PROVIDER_RESOURCE.get_or_init(|| owned_resource));
}

// Create a new vector to hold the modified processors
Expand Down
Loading