Skip to content

Commit fa6e6cd

Browse files
authored
Replace once_cell::Lazy with std::sync::OnceLock for global Initialization in otel-sdk crate (#2342)
1 parent 8e6b479 commit fa6e6cd

File tree

7 files changed

+105
-78
lines changed

7 files changed

+105
-78
lines changed

opentelemetry-sdk/Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ async-trait = { workspace = true, optional = true }
1717
futures-channel = "0.3"
1818
futures-executor = { workspace = true }
1919
futures-util = { workspace = true, features = ["std", "sink", "async-await-macro"] }
20-
once_cell = { workspace = true }
2120
percent-encoding = { version = "2.0", optional = true }
2221
rand = { workspace = true, features = ["std", "std_rng","small_rng"], optional = true }
2322
glob = { version = "0.3.1", optional =true}

opentelemetry-sdk/src/logs/log_emitter.rs

+15-11
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,24 @@ use std::{
1111
borrow::Cow,
1212
sync::{
1313
atomic::{AtomicBool, Ordering},
14-
Arc,
14+
Arc, OnceLock,
1515
},
1616
};
1717

18-
use once_cell::sync::Lazy;
19-
2018
// a no nop logger provider used as placeholder when the provider is shutdown
21-
static NOOP_LOGGER_PROVIDER: Lazy<LoggerProvider> = Lazy::new(|| LoggerProvider {
22-
inner: Arc::new(LoggerProviderInner {
23-
processors: Vec::new(),
24-
resource: Resource::empty(),
25-
is_shutdown: AtomicBool::new(true),
26-
}),
27-
});
19+
// TODO - replace it with LazyLock once it is stable
20+
static NOOP_LOGGER_PROVIDER: OnceLock<LoggerProvider> = OnceLock::new();
21+
22+
#[inline]
23+
fn noop_logger_provider() -> &'static LoggerProvider {
24+
NOOP_LOGGER_PROVIDER.get_or_init(|| LoggerProvider {
25+
inner: Arc::new(LoggerProviderInner {
26+
processors: Vec::new(),
27+
resource: Resource::empty(),
28+
is_shutdown: AtomicBool::new(true),
29+
}),
30+
})
31+
}
2832

2933
#[derive(Debug, Clone)]
3034
/// Handles the creation and coordination of [`Logger`]s.
@@ -55,7 +59,7 @@ impl opentelemetry::logs::LoggerProvider for LoggerProvider {
5559
fn logger_with_scope(&self, scope: InstrumentationScope) -> Self::Logger {
5660
// If the provider is shutdown, new logger will refer a no-op logger provider.
5761
if self.inner.is_shutdown.load(Ordering::Relaxed) {
58-
return Logger::new(scope, NOOP_LOGGER_PROVIDER.clone());
62+
return Logger::new(scope, noop_logger_provider().clone());
5963
}
6064
if scope.name().is_empty() {
6165
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.");

opentelemetry-sdk/src/metrics/internal/exponential_histogram.rs

+34-28
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::{f64::consts::LOG2_E, mem::replace, ops::DerefMut, sync::Mutex, time::SystemTime};
22

3-
use once_cell::sync::Lazy;
43
use opentelemetry::{otel_debug, KeyValue};
4+
use std::sync::OnceLock;
55

66
use crate::metrics::{
77
data::{self, Aggregation},
@@ -131,7 +131,7 @@ impl<T: Number> ExpoHistogramDataPoint<T> {
131131
}
132132
return (exp - correction) >> -self.scale;
133133
}
134-
(exp << self.scale) + (frac.ln() * SCALE_FACTORS[self.scale as usize]) as i32 - 1
134+
(exp << self.scale) + (frac.ln() * scale_factors()[self.scale as usize]) as i32 - 1
135135
}
136136
}
137137

@@ -165,32 +165,38 @@ fn scale_change(max_size: i32, bin: i32, start_bin: i32, length: i32) -> u32 {
165165
count
166166
}
167167

168-
/// Constants used in calculating the logarithm index.
169-
static SCALE_FACTORS: Lazy<[f64; 21]> = Lazy::new(|| {
170-
[
171-
LOG2_E * 2f64.powi(0),
172-
LOG2_E * 2f64.powi(1),
173-
LOG2_E * 2f64.powi(2),
174-
LOG2_E * 2f64.powi(3),
175-
LOG2_E * 2f64.powi(4),
176-
LOG2_E * 2f64.powi(5),
177-
LOG2_E * 2f64.powi(6),
178-
LOG2_E * 2f64.powi(7),
179-
LOG2_E * 2f64.powi(8),
180-
LOG2_E * 2f64.powi(9),
181-
LOG2_E * 2f64.powi(10),
182-
LOG2_E * 2f64.powi(11),
183-
LOG2_E * 2f64.powi(12),
184-
LOG2_E * 2f64.powi(13),
185-
LOG2_E * 2f64.powi(14),
186-
LOG2_E * 2f64.powi(15),
187-
LOG2_E * 2f64.powi(16),
188-
LOG2_E * 2f64.powi(17),
189-
LOG2_E * 2f64.powi(18),
190-
LOG2_E * 2f64.powi(19),
191-
LOG2_E * 2f64.powi(20),
192-
]
193-
});
168+
// TODO - replace it with LazyLock once it is stable
169+
static SCALE_FACTORS: OnceLock<[f64; 21]> = OnceLock::new();
170+
171+
/// returns constants used in calculating the logarithm index.
172+
#[inline]
173+
fn scale_factors() -> &'static [f64; 21] {
174+
SCALE_FACTORS.get_or_init(|| {
175+
[
176+
LOG2_E * 2f64.powi(0),
177+
LOG2_E * 2f64.powi(1),
178+
LOG2_E * 2f64.powi(2),
179+
LOG2_E * 2f64.powi(3),
180+
LOG2_E * 2f64.powi(4),
181+
LOG2_E * 2f64.powi(5),
182+
LOG2_E * 2f64.powi(6),
183+
LOG2_E * 2f64.powi(7),
184+
LOG2_E * 2f64.powi(8),
185+
LOG2_E * 2f64.powi(9),
186+
LOG2_E * 2f64.powi(10),
187+
LOG2_E * 2f64.powi(11),
188+
LOG2_E * 2f64.powi(12),
189+
LOG2_E * 2f64.powi(13),
190+
LOG2_E * 2f64.powi(14),
191+
LOG2_E * 2f64.powi(15),
192+
LOG2_E * 2f64.powi(16),
193+
LOG2_E * 2f64.powi(17),
194+
LOG2_E * 2f64.powi(18),
195+
LOG2_E * 2f64.powi(19),
196+
LOG2_E * 2f64.powi(20),
197+
]
198+
})
199+
}
194200

195201
/// Breaks the number into a normalized fraction and a base-2 exponent.
196202
///

opentelemetry-sdk/src/metrics/internal/mod.rs

+9-5
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,15 @@ use std::sync::{Arc, OnceLock, RwLock};
1515
use aggregate::{is_under_cardinality_limit, STREAM_CARDINALITY_LIMIT};
1616
pub(crate) use aggregate::{AggregateBuilder, ComputeAggregation, Measure};
1717
pub(crate) use exponential_histogram::{EXPO_MAX_SCALE, EXPO_MIN_SCALE};
18-
use once_cell::sync::Lazy;
1918
use opentelemetry::{otel_warn, KeyValue};
2019

21-
pub(crate) static STREAM_OVERFLOW_ATTRIBUTES: Lazy<Vec<KeyValue>> =
22-
Lazy::new(|| vec![KeyValue::new("otel.metric.overflow", "true")]);
20+
// TODO Replace it with LazyLock once it is stable
21+
pub(crate) static STREAM_OVERFLOW_ATTRIBUTES: OnceLock<Vec<KeyValue>> = OnceLock::new();
22+
23+
#[inline]
24+
fn stream_overflow_attributes() -> &'static Vec<KeyValue> {
25+
STREAM_OVERFLOW_ATTRIBUTES.get_or_init(|| vec![KeyValue::new("otel.metric.overflow", "true")])
26+
}
2327

2428
pub(crate) trait Aggregator {
2529
/// A static configuration that is needed in order to initialize aggregator.
@@ -134,12 +138,12 @@ where
134138
trackers.insert(sorted_attrs, new_tracker);
135139

136140
self.count.fetch_add(1, Ordering::SeqCst);
137-
} else if let Some(overflow_value) = trackers.get(STREAM_OVERFLOW_ATTRIBUTES.as_slice()) {
141+
} else if let Some(overflow_value) = trackers.get(stream_overflow_attributes().as_slice()) {
138142
overflow_value.update(value);
139143
} else {
140144
let new_tracker = A::create(&self.config);
141145
new_tracker.update(value);
142-
trackers.insert(STREAM_OVERFLOW_ATTRIBUTES.clone(), Arc::new(new_tracker));
146+
trackers.insert(stream_overflow_attributes().clone(), Arc::new(new_tracker));
143147
otel_warn!( name: "ValueMap.measure",
144148
message = "Maximum data points for metric stream exceeded. Entry added to overflow. Subsequent overflows to same metric until next collect will not be logged."
145149
);

opentelemetry-sdk/src/propagation/baggage.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
use once_cell::sync::Lazy;
21
use opentelemetry::{
32
baggage::{BaggageExt, KeyValueMetadata},
43
otel_warn,
@@ -7,10 +6,17 @@ use opentelemetry::{
76
};
87
use percent_encoding::{percent_decode_str, utf8_percent_encode, AsciiSet, CONTROLS};
98
use std::iter;
9+
use std::sync::OnceLock;
1010

1111
static BAGGAGE_HEADER: &str = "baggage";
1212
const FRAGMENT: &AsciiSet = &CONTROLS.add(b' ').add(b'"').add(b';').add(b',').add(b'=');
13-
static BAGGAGE_FIELDS: Lazy<[String; 1]> = Lazy::new(|| [BAGGAGE_HEADER.to_owned()]);
13+
14+
// TODO Replace this with LazyLock once it is stable.
15+
static BAGGAGE_FIELDS: OnceLock<[String; 1]> = OnceLock::new();
16+
#[inline]
17+
fn baggage_fields() -> &'static [String; 1] {
18+
BAGGAGE_FIELDS.get_or_init(|| [BAGGAGE_HEADER.to_owned()])
19+
}
1420

1521
/// Propagates name-value pairs in [W3C Baggage] format.
1622
///
@@ -149,7 +155,7 @@ impl TextMapPropagator for BaggagePropagator {
149155
}
150156

151157
fn fields(&self) -> FieldIter<'_> {
152-
FieldIter::new(BAGGAGE_FIELDS.as_ref())
158+
FieldIter::new(baggage_fields())
153159
}
154160
}
155161

opentelemetry-sdk/src/propagation/trace_context.rs

+9-4
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,26 @@
11
//! # W3C Trace Context Propagator
22
//!
33
4-
use once_cell::sync::Lazy;
54
use opentelemetry::{
65
propagation::{text_map_propagator::FieldIter, Extractor, Injector, TextMapPropagator},
76
trace::{SpanContext, SpanId, TraceContextExt, TraceFlags, TraceId, TraceState},
87
Context,
98
};
109
use std::str::FromStr;
10+
use std::sync::OnceLock;
1111

1212
const SUPPORTED_VERSION: u8 = 0;
1313
const MAX_VERSION: u8 = 254;
1414
const TRACEPARENT_HEADER: &str = "traceparent";
1515
const TRACESTATE_HEADER: &str = "tracestate";
1616

17-
static TRACE_CONTEXT_HEADER_FIELDS: Lazy<[String; 2]> =
18-
Lazy::new(|| [TRACEPARENT_HEADER.to_owned(), TRACESTATE_HEADER.to_owned()]);
17+
// TODO Replace this with LazyLock once it is stable.
18+
static TRACE_CONTEXT_HEADER_FIELDS: OnceLock<[String; 2]> = OnceLock::new();
19+
20+
fn trace_context_header_fields() -> &'static [String; 2] {
21+
TRACE_CONTEXT_HEADER_FIELDS
22+
.get_or_init(|| [TRACEPARENT_HEADER.to_owned(), TRACESTATE_HEADER.to_owned()])
23+
}
1924

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

148153
fn fields(&self) -> FieldIter<'_> {
149-
FieldIter::new(TRACE_CONTEXT_HEADER_FIELDS.as_ref())
154+
FieldIter::new(trace_context_header_fields())
150155
}
151156
}
152157

opentelemetry-sdk/src/trace/provider.rs

+29-26
Original file line numberDiff line numberDiff line change
@@ -68,32 +68,38 @@ use crate::trace::{
6868
};
6969
use crate::Resource;
7070
use crate::{export::trace::SpanExporter, trace::SpanProcessor};
71-
use once_cell::sync::{Lazy, OnceCell};
7271
use opentelemetry::trace::TraceError;
7372
use opentelemetry::InstrumentationScope;
7473
use opentelemetry::{otel_debug, trace::TraceResult};
7574
use std::borrow::Cow;
7675
use std::sync::atomic::{AtomicBool, Ordering};
77-
use std::sync::Arc;
76+
use std::sync::{Arc, OnceLock};
7877

7978
use super::IdGenerator;
8079

81-
static PROVIDER_RESOURCE: OnceCell<Resource> = OnceCell::new();
80+
static PROVIDER_RESOURCE: OnceLock<Resource> = OnceLock::new();
8281

8382
// a no nop tracer provider used as placeholder when the provider is shutdown
84-
static NOOP_TRACER_PROVIDER: Lazy<TracerProvider> = Lazy::new(|| TracerProvider {
85-
inner: Arc::new(TracerProviderInner {
86-
processors: Vec::new(),
87-
config: Config {
88-
// cannot use default here as the default resource is not empty
89-
sampler: Box::new(Sampler::ParentBased(Box::new(Sampler::AlwaysOn))),
90-
id_generator: Box::<RandomIdGenerator>::default(),
91-
span_limits: SpanLimits::default(),
92-
resource: Cow::Owned(Resource::empty()),
93-
},
94-
is_shutdown: AtomicBool::new(true),
95-
}),
96-
});
83+
// TODO Replace with LazyLock once it is stable
84+
static NOOP_TRACER_PROVIDER: OnceLock<TracerProvider> = OnceLock::new();
85+
#[inline]
86+
fn noop_tracer_provider() -> &'static TracerProvider {
87+
NOOP_TRACER_PROVIDER.get_or_init(|| {
88+
TracerProvider {
89+
inner: Arc::new(TracerProviderInner {
90+
processors: Vec::new(),
91+
config: Config {
92+
// cannot use default here as the default resource is not empty
93+
sampler: Box::new(Sampler::ParentBased(Box::new(Sampler::AlwaysOn))),
94+
id_generator: Box::<RandomIdGenerator>::default(),
95+
span_limits: SpanLimits::default(),
96+
resource: Cow::Owned(Resource::empty()),
97+
},
98+
is_shutdown: AtomicBool::new(true),
99+
}),
100+
}
101+
})
102+
}
97103

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

270276
fn tracer_with_scope(&self, scope: InstrumentationScope) -> Self::Tracer {
271277
if self.inner.is_shutdown.load(Ordering::Relaxed) {
272-
return Tracer::new(scope, NOOP_TRACER_PROVIDER.clone());
278+
return Tracer::new(scope, noop_tracer_provider().clone());
273279
}
274280
Tracer::new(scope, self.clone())
275281
}
@@ -392,16 +398,13 @@ impl Builder {
392398
// For the uncommon case where there are multiple tracer providers with different resource
393399
// configurations, users can optionally provide their own borrowed static resource.
394400
if matches!(config.resource, Cow::Owned(_)) {
395-
config.resource = match PROVIDER_RESOURCE.try_insert(config.resource.into_owned()) {
396-
Ok(static_resource) => Cow::Borrowed(static_resource),
397-
Err((prev, new)) => {
398-
if prev == &new {
399-
Cow::Borrowed(prev)
400-
} else {
401-
Cow::Owned(new)
401+
config.resource =
402+
match PROVIDER_RESOURCE.get_or_init(|| config.resource.clone().into_owned()) {
403+
static_resource if *static_resource == *config.resource.as_ref() => {
404+
Cow::Borrowed(static_resource)
402405
}
403-
}
404-
}
406+
_ => config.resource, // Use the new resource if different
407+
};
405408
}
406409

407410
// Create a new vector to hold the modified processors

0 commit comments

Comments
 (0)