Skip to content

Commit bee56bc

Browse files
authored
Merge branch 'main' into feature/update-prometheus-to-otel-27
2 parents 3ed3455 + 129ca03 commit bee56bc

File tree

15 files changed

+211
-79
lines changed

15 files changed

+211
-79
lines changed

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ on:
88
- main
99
paths-ignore:
1010
- '**.md'
11+
concurrency:
12+
group: ${{ github.workflow }}-${{ github.ref }}
13+
cancel-in-progress: true
1114
jobs:
1215
test:
1316
strategy:

.github/workflows/semver.yml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ env:
44
on:
55
pull_request:
66
types: [ labeled, synchronize, opened, reopened ]
7-
87
jobs:
98
semver-compliance: # This job uses the latest published crate as baseline for comparison.
109
runs-on: ubuntu-latest

examples/self-diagnostics/src/main.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
2626
// OpenTelemetry uses `tracing` crate for its internal logging. Unless a
2727
// tracing subscriber is set, the logs will be discarded. In this example,
2828
// we configure a `tracing` subscriber to:
29-
// 1. Print logs of level INFO or higher to stdout.
29+
// 1. Print logs of level INFO or higher to stdout using tracing's fmt layer.
3030
// 2. Filter logs from OpenTelemetry's dependencies (like tonic, hyper,
3131
// reqwest etc. which are commonly used by the OTLP exporter) to only print
3232
// ERROR-level logs. This filtering helps reduce repetitive log messages
@@ -35,7 +35,7 @@ async fn main() -> Result<(), Box<dyn Error + Send + Sync + 'static>> {
3535
// https://github.com/open-telemetry/opentelemetry-rust/issues/761 is
3636
// resolved.
3737

38-
// Target name used by OpenTelemetry always start with "opentelemetry".
38+
// Target names used by all OpenTelemetry official crates always start with "opentelemetry".
3939
// Hence, one may use "add_directive("opentelemetry=off".parse().unwrap())"
4040
// to turn off all logs from OpenTelemetry.
4141

opentelemetry-sdk/CHANGELOG.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,13 @@
1818
.build();
1919
```
2020
- `logs::LogData` struct is deprecated, and scheduled to be removed from public API in `v0.28.0`.
21+
- Bug fix: Empty Meter names are retained as-is instead of replacing with
22+
"rust.opentelemetry.io/sdk/meter"
23+
[#2334](https://github.com/open-telemetry/opentelemetry-rust/pull/2334)
24+
25+
- Bug fix: Empty Logger names are retained as-is instead of replacing with
26+
"rust.opentelemetry.io/sdk/logger"
27+
[#2316](https://github.com/open-telemetry/opentelemetry-rust/pull/2316)
2128

2229
## 0.27.0
2330

opentelemetry-sdk/src/logs/log_emitter.rs

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{BatchLogProcessor, LogProcessor, LogRecord, SimpleLogProcessor, TraceContext};
22
use crate::{export::logs::LogExporter, runtime::RuntimeChannel, Resource};
33
use crate::{logs::LogError, logs::LogResult};
4-
use opentelemetry::{otel_debug, trace::TraceContextExt, Context, InstrumentationScope};
4+
use opentelemetry::{otel_debug, otel_info, trace::TraceContextExt, Context, InstrumentationScope};
55

66
#[cfg(feature = "spec_unstable_logs_enabled")]
77
use opentelemetry::logs::Severity;
@@ -44,19 +44,10 @@ pub struct LoggerProvider {
4444
inner: Arc<LoggerProviderInner>,
4545
}
4646

47-
/// Default logger name if empty string is provided.
48-
const DEFAULT_COMPONENT_NAME: &str = "rust.opentelemetry.io/sdk/logger";
49-
5047
impl opentelemetry::logs::LoggerProvider for LoggerProvider {
5148
type Logger = Logger;
5249

5350
fn logger(&self, name: impl Into<Cow<'static, str>>) -> Self::Logger {
54-
let mut name = name.into();
55-
56-
if name.is_empty() {
57-
name = Cow::Borrowed(DEFAULT_COMPONENT_NAME)
58-
};
59-
6051
let scope = InstrumentationScope::builder(name).build();
6152
self.logger_with_scope(scope)
6253
}
@@ -66,6 +57,9 @@ impl opentelemetry::logs::LoggerProvider for LoggerProvider {
6657
if self.inner.is_shutdown.load(Ordering::Relaxed) {
6758
return Logger::new(scope, NOOP_LOGGER_PROVIDER.clone());
6859
}
60+
if scope.name().is_empty() {
61+
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.");
62+
};
6963
Logger::new(scope, self.clone())
7064
}
7165
}
@@ -154,10 +148,15 @@ impl LoggerProviderInner {
154148
impl Drop for LoggerProviderInner {
155149
fn drop(&mut self) {
156150
if !self.is_shutdown.load(Ordering::Relaxed) {
151+
otel_info!(
152+
name: "LoggerProvider.Drop",
153+
message = "Last reference of LoggerProvider dropped, initiating shutdown."
154+
);
157155
let _ = self.shutdown(); // errors are handled within shutdown
158156
} else {
159157
otel_debug!(
160-
name: "LoggerProvider.Drop.AlreadyShutdown"
158+
name: "LoggerProvider.Drop.AlreadyShutdown",
159+
message = "LoggerProvider was already shut down; drop will not attempt shutdown again."
161160
);
162161
}
163162
}
@@ -700,6 +699,42 @@ mod tests {
700699
assert_eq!(*shutdown_called.lock().unwrap(), 1);
701700
}
702701

702+
#[test]
703+
fn test_empty_logger_name() {
704+
let exporter = InMemoryLogExporter::default();
705+
let logger_provider = LoggerProvider::builder()
706+
.with_simple_exporter(exporter.clone())
707+
.build();
708+
let logger = logger_provider.logger("");
709+
let mut record = logger.create_log_record();
710+
record.set_body("Testing empty logger name".into());
711+
logger.emit(record);
712+
713+
// Create a logger using a scope with an empty name
714+
let scope = InstrumentationScope::builder("").build();
715+
let scoped_logger = logger_provider.logger_with_scope(scope);
716+
let mut scoped_record = scoped_logger.create_log_record();
717+
scoped_record.set_body("Testing empty logger scope name".into());
718+
scoped_logger.emit(scoped_record);
719+
720+
// Assert: Verify that the emitted logs are processed correctly
721+
let emitted_logs = exporter.get_emitted_logs().unwrap();
722+
assert_eq!(emitted_logs.len(), 2);
723+
// Assert the first log
724+
assert_eq!(
725+
emitted_logs[0].clone().record.body,
726+
Some(AnyValue::String("Testing empty logger name".into()))
727+
);
728+
assert_eq!(logger.instrumentation_scope().name(), "");
729+
730+
// Assert the second log created through the scope
731+
assert_eq!(
732+
emitted_logs[1].clone().record.body,
733+
Some(AnyValue::String("Testing empty logger scope name".into()))
734+
);
735+
assert_eq!(scoped_logger.instrumentation_scope().name(), "");
736+
}
737+
703738
#[derive(Debug)]
704739
pub(crate) struct LazyLogProcessor {
705740
shutdown_called: Arc<Mutex<bool>>,

opentelemetry-sdk/src/metrics/meter_provider.rs

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use std::{
99

1010
use opentelemetry::{
1111
metrics::{Meter, MeterProvider},
12-
otel_debug, otel_error, InstrumentationScope,
12+
otel_debug, otel_error, otel_info, InstrumentationScope,
1313
};
1414

1515
use crate::metrics::{MetricError, MetricResult};
@@ -109,6 +109,10 @@ impl SdkMeterProvider {
109109
/// There is no guaranteed that all telemetry be flushed or all resources have
110110
/// been released on error.
111111
pub fn shutdown(&self) -> MetricResult<()> {
112+
otel_info!(
113+
name: "MeterProvider.Shutdown",
114+
message = "User initiated shutdown of MeterProvider."
115+
);
112116
self.inner.shutdown()
113117
}
114118
}
@@ -139,28 +143,31 @@ impl Drop for SdkMeterProviderInner {
139143
// shutdown(), then we don't need to call shutdown again.
140144
if self.is_shutdown.load(Ordering::Relaxed) {
141145
otel_debug!(
142-
name: "MeterProvider.AlreadyShutdown",
143-
message = "Meter provider was already shut down; drop will not attempt shutdown again."
146+
name: "MeterProvider.Drop.AlreadyShutdown",
147+
message = "MeterProvider was already shut down; drop will not attempt shutdown again."
144148
);
145-
} else if let Err(err) = self.shutdown() {
146-
otel_error!(
147-
name: "MeterProvider.ShutdownFailed",
148-
message = "Shutdown attempt failed during drop of MeterProvider.",
149-
reason = format!("{}", err)
149+
} else {
150+
otel_info!(
151+
name: "MeterProvider.Drop",
152+
message = "Last reference of MeterProvider dropped, initiating shutdown."
150153
);
154+
if let Err(err) = self.shutdown() {
155+
otel_error!(
156+
name: "MeterProvider.Drop.ShutdownFailed",
157+
message = "Shutdown attempt failed during drop of MeterProvider.",
158+
reason = format!("{}", err)
159+
);
160+
} else {
161+
otel_info!(
162+
name: "MeterProvider.Drop.ShutdownCompleted",
163+
);
164+
}
151165
}
152166
}
153167
}
154168

155-
/// Default meter name if empty string is provided.
156-
const DEFAULT_COMPONENT_NAME: &str = "rust.opentelemetry.io/sdk/meter";
157-
158169
impl MeterProvider for SdkMeterProvider {
159-
fn meter(&self, mut name: &'static str) -> Meter {
160-
if name.is_empty() {
161-
name = DEFAULT_COMPONENT_NAME
162-
};
163-
170+
fn meter(&self, name: &'static str) -> Meter {
164171
let scope = InstrumentationScope::builder(name).build();
165172
self.meter_with_scope(scope)
166173
}
@@ -170,6 +177,10 @@ impl MeterProvider for SdkMeterProvider {
170177
return Meter::new(Arc::new(NoopMeter::new()));
171178
}
172179

180+
if scope.name().is_empty() {
181+
otel_info!(name: "MeterNameEmpty", message = "Meter name is empty; consider providing a meaningful name. Meter will function normally and the provided name will be used as-is.");
182+
};
183+
173184
if let Ok(mut meters) = self.inner.meters.lock() {
174185
let meter = meters
175186
.entry(scope)
@@ -231,7 +242,7 @@ impl MeterProviderBuilder {
231242
/// Construct a new [MeterProvider] with this configuration.
232243
233244
pub fn build(self) -> SdkMeterProvider {
234-
SdkMeterProvider {
245+
let meter_provider = SdkMeterProvider {
235246
inner: Arc::new(SdkMeterProviderInner {
236247
pipes: Arc::new(Pipelines::new(
237248
self.resource.unwrap_or_default(),
@@ -241,7 +252,12 @@ impl MeterProviderBuilder {
241252
meters: Default::default(),
242253
is_shutdown: AtomicBool::new(false),
243254
}),
244-
}
255+
};
256+
257+
otel_info!(
258+
name: "MeterProvider.Built",
259+
);
260+
meter_provider
245261
}
246262
}
247263

opentelemetry-sdk/src/metrics/mod.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,44 @@ mod tests {
463463
}
464464
}
465465

466+
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
467+
async fn empty_meter_name_retained() {
468+
async fn meter_name_retained_helper(
469+
meter: Meter,
470+
provider: SdkMeterProvider,
471+
exporter: InMemoryMetricExporter,
472+
) {
473+
// Act
474+
let counter = meter.u64_counter("my_counter").build();
475+
476+
counter.add(10, &[]);
477+
provider.force_flush().unwrap();
478+
479+
// Assert
480+
let resource_metrics = exporter
481+
.get_finished_metrics()
482+
.expect("metrics are expected to be exported.");
483+
assert!(
484+
resource_metrics[0].scope_metrics[0].metrics.len() == 1,
485+
"There should be a single metric"
486+
);
487+
let meter_name = resource_metrics[0].scope_metrics[0].scope.name();
488+
assert_eq!(meter_name, "");
489+
}
490+
491+
let exporter = InMemoryMetricExporter::default();
492+
let reader = PeriodicReader::builder(exporter.clone(), runtime::Tokio).build();
493+
let meter_provider = SdkMeterProvider::builder().with_reader(reader).build();
494+
495+
// Test Meter creation in 2 ways, both with empty string as meter name
496+
let meter1 = meter_provider.meter("");
497+
meter_name_retained_helper(meter1, meter_provider.clone(), exporter.clone()).await;
498+
499+
let meter_scope = InstrumentationScope::builder("").build();
500+
let meter2 = meter_provider.meter_with_scope(meter_scope);
501+
meter_name_retained_helper(meter2, meter_provider, exporter).await;
502+
}
503+
466504
#[tokio::test(flavor = "multi_thread", worker_threads = 1)]
467505
async fn counter_duplicate_instrument_merge() {
468506
// Arrange

opentelemetry-sdk/src/metrics/periodic_reader.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,10 +234,18 @@ impl<RT: Runtime> PeriodicReaderWorker<RT> {
234234
async fn collect_and_export(&mut self) -> MetricResult<()> {
235235
self.reader.collect(&mut self.rm)?;
236236
if self.rm.scope_metrics.is_empty() {
237+
otel_debug!(
238+
name: "PeriodicReaderWorker.NoMetricsToExport",
239+
);
237240
// No metrics to export.
238241
return Ok(());
239242
}
240243

244+
otel_debug!(
245+
name: "PeriodicReaderWorker.InvokeExporter",
246+
message = "Calling exporter's export method with collected metrics.",
247+
count = self.rm.scope_metrics.len(),
248+
);
241249
let export = self.reader.exporter.export(&mut self.rm);
242250
let timeout = self.runtime.delay(self.timeout);
243251
pin_mut!(export);

opentelemetry/Cargo.toml

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,19 +21,18 @@ all-features = true
2121
rustdoc-args = ["--cfg", "docsrs"]
2222

2323
[dependencies]
24-
futures-core = { workspace = true }
25-
futures-sink = "0.3"
26-
once_cell = { workspace = true }
24+
futures-core = { workspace = true, optional = true }
25+
futures-sink = { version = "0.3", optional = true }
2726
pin-project-lite = { workspace = true, optional = true }
28-
thiserror = { workspace = true }
27+
thiserror = { workspace = true, optional = true}
2928
tracing = {workspace = true, optional = true} # optional for opentelemetry internal logging
3029

3130
[target.'cfg(all(target_arch = "wasm32", not(target_os = "wasi")))'.dependencies]
3231
js-sys = "0.3.63"
3332

3433
[features]
35-
default = ["trace", "metrics", "logs"]
36-
trace = ["pin-project-lite"]
34+
default = ["trace", "metrics", "logs", "internal-logs"]
35+
trace = ["pin-project-lite", "futures-sink", "futures-core", "thiserror"]
3736
metrics = []
3837
testing = ["trace", "metrics"]
3938
logs = []

opentelemetry/src/baggage.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,22 @@
1515
//!
1616
//! [W3C Baggage]: https://w3c.github.io/baggage
1717
use crate::{Context, Key, KeyValue, Value};
18-
use once_cell::sync::Lazy;
1918
use std::collections::{hash_map, HashMap};
2019
use std::fmt;
20+
use std::sync::OnceLock;
2121

22-
static DEFAULT_BAGGAGE: Lazy<Baggage> = Lazy::new(Baggage::default);
22+
static DEFAULT_BAGGAGE: OnceLock<Baggage> = OnceLock::new();
2323

2424
const MAX_KEY_VALUE_PAIRS: usize = 180;
2525
const MAX_BYTES_FOR_ONE_PAIR: usize = 4096;
2626
const MAX_LEN_OF_ALL_PAIRS: usize = 8192;
2727

28+
/// Returns the default baggage, ensuring it is initialized only once.
29+
#[inline]
30+
fn get_default_baggage() -> &'static Baggage {
31+
DEFAULT_BAGGAGE.get_or_init(Baggage::default)
32+
}
33+
2834
/// A set of name/value pairs describing user-defined properties.
2935
///
3036
/// ### Baggage Names
@@ -399,7 +405,7 @@ impl BaggageExt for Context {
399405
}
400406

401407
fn baggage(&self) -> &Baggage {
402-
self.get::<Baggage>().unwrap_or(&DEFAULT_BAGGAGE)
408+
self.get::<Baggage>().unwrap_or(get_default_baggage())
403409
}
404410
}
405411

0 commit comments

Comments
 (0)