feat: Allow event name to be provided to IsEnabled check in Logger (#2756)
This commit is contained in:
parent
c5a4b7f436
commit
ff33638d1e
|
@ -136,9 +136,11 @@ where
|
||||||
{
|
{
|
||||||
fn enabled(&self, _metadata: &Metadata) -> bool {
|
fn enabled(&self, _metadata: &Metadata) -> bool {
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
return self
|
return self.logger.event_enabled(
|
||||||
.logger
|
severity_of_level(_metadata.level()),
|
||||||
.event_enabled(severity_of_level(_metadata.level()), _metadata.target());
|
_metadata.target(),
|
||||||
|
None,
|
||||||
|
);
|
||||||
#[cfg(not(feature = "spec_unstable_logs_enabled"))]
|
#[cfg(not(feature = "spec_unstable_logs_enabled"))]
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,10 @@ Receivers (processors, exporters) are expected to use `LogRecord.target()` as
|
||||||
scope name. This is already done in OTLP Exporters, so this change should be
|
scope name. This is already done in OTLP Exporters, so this change should be
|
||||||
transparent to most users.
|
transparent to most users.
|
||||||
|
|
||||||
|
- Passes event name to the `event_enabled` method on the `Logger`. This allows
|
||||||
|
implementations (SDK, processor, exporters) to leverage this additional
|
||||||
|
information to determine if an event is enabled.
|
||||||
|
|
||||||
## 0.28.1
|
## 0.28.1
|
||||||
|
|
||||||
Released 2025-Feb-12
|
Released 2025-Feb-12
|
||||||
|
|
|
@ -52,7 +52,7 @@ impl LogProcessor for NoopProcessor {
|
||||||
&self,
|
&self,
|
||||||
_level: opentelemetry::logs::Severity,
|
_level: opentelemetry::logs::Severity,
|
||||||
_target: &str,
|
_target: &str,
|
||||||
_name: &str,
|
_name: Option<&str>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
self.enabled
|
self.enabled
|
||||||
}
|
}
|
||||||
|
|
|
@ -155,10 +155,12 @@ where
|
||||||
event: &tracing::Event<'_>,
|
event: &tracing::Event<'_>,
|
||||||
_ctx: tracing_subscriber::layer::Context<'_, S>,
|
_ctx: tracing_subscriber::layer::Context<'_, S>,
|
||||||
) {
|
) {
|
||||||
let severity = severity_of_level(event.metadata().level());
|
let metadata = event.metadata();
|
||||||
let target = event.metadata().target();
|
let severity = severity_of_level(metadata.level());
|
||||||
|
let target = metadata.target();
|
||||||
|
let name = metadata.name();
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
if !self.logger.event_enabled(severity, target) {
|
if !self.logger.event_enabled(severity, target, Some(name)) {
|
||||||
// TODO: See if we need internal logs or track the count.
|
// TODO: See if we need internal logs or track the count.
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -169,16 +171,13 @@ where
|
||||||
#[cfg(feature = "experimental_metadata_attributes")]
|
#[cfg(feature = "experimental_metadata_attributes")]
|
||||||
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
|
let meta = normalized_meta.as_ref().unwrap_or_else(|| event.metadata());
|
||||||
|
|
||||||
#[cfg(not(feature = "experimental_metadata_attributes"))]
|
|
||||||
let meta = event.metadata();
|
|
||||||
|
|
||||||
let mut log_record = self.logger.create_log_record();
|
let mut log_record = self.logger.create_log_record();
|
||||||
|
|
||||||
// TODO: Fix heap allocation
|
// TODO: Fix heap allocation
|
||||||
log_record.set_target(target.to_string());
|
log_record.set_target(target.to_string());
|
||||||
log_record.set_event_name(meta.name());
|
log_record.set_event_name(name);
|
||||||
log_record.set_severity_number(severity);
|
log_record.set_severity_number(severity);
|
||||||
log_record.set_severity_text(meta.level().as_str());
|
log_record.set_severity_text(metadata.level().as_str());
|
||||||
let mut visitor = EventVisitor::new(&mut log_record);
|
let mut visitor = EventVisitor::new(&mut log_record);
|
||||||
#[cfg(feature = "experimental_metadata_attributes")]
|
#[cfg(feature = "experimental_metadata_attributes")]
|
||||||
visitor.visit_experimental_metadata(meta);
|
visitor.visit_experimental_metadata(meta);
|
||||||
|
@ -226,9 +225,10 @@ mod tests {
|
||||||
use opentelemetry::logs::Severity;
|
use opentelemetry::logs::Severity;
|
||||||
use opentelemetry::trace::TracerProvider;
|
use opentelemetry::trace::TracerProvider;
|
||||||
use opentelemetry::trace::{TraceContextExt, TraceFlags, Tracer};
|
use opentelemetry::trace::{TraceContextExt, TraceFlags, Tracer};
|
||||||
|
use opentelemetry::InstrumentationScope;
|
||||||
use opentelemetry::{logs::AnyValue, Key};
|
use opentelemetry::{logs::AnyValue, Key};
|
||||||
use opentelemetry_sdk::error::OTelSdkResult;
|
use opentelemetry_sdk::error::OTelSdkResult;
|
||||||
use opentelemetry_sdk::logs::InMemoryLogExporter;
|
use opentelemetry_sdk::logs::{InMemoryLogExporter, LogProcessor};
|
||||||
use opentelemetry_sdk::logs::{LogBatch, LogExporter};
|
use opentelemetry_sdk::logs::{LogBatch, LogExporter};
|
||||||
use opentelemetry_sdk::logs::{SdkLogRecord, SdkLoggerProvider};
|
use opentelemetry_sdk::logs::{SdkLogRecord, SdkLoggerProvider};
|
||||||
use opentelemetry_sdk::trace::{Sampler, SdkTracerProvider};
|
use opentelemetry_sdk::trace::{Sampler, SdkTracerProvider};
|
||||||
|
@ -244,10 +244,7 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(impl_trait_overcaptures)] // can only be fixed with Rust 1.82+
|
#[allow(impl_trait_overcaptures)] // can only be fixed with Rust 1.82+
|
||||||
fn create_tracing_subscriber(
|
fn create_tracing_subscriber(logger_provider: &SdkLoggerProvider) -> impl tracing::Subscriber {
|
||||||
_exporter: InMemoryLogExporter,
|
|
||||||
logger_provider: &SdkLoggerProvider,
|
|
||||||
) -> impl tracing::Subscriber {
|
|
||||||
let level_filter = tracing_subscriber::filter::LevelFilter::WARN; // Capture WARN and ERROR levels
|
let level_filter = tracing_subscriber::filter::LevelFilter::WARN; // Capture WARN and ERROR levels
|
||||||
let layer =
|
let layer =
|
||||||
layer::OpenTelemetryTracingBridge::new(logger_provider).with_filter(level_filter); // No filter based on target, only based on log level
|
layer::OpenTelemetryTracingBridge::new(logger_provider).with_filter(level_filter); // No filter based on target, only based on log level
|
||||||
|
@ -327,7 +324,7 @@ mod tests {
|
||||||
.with_simple_exporter(exporter.clone())
|
.with_simple_exporter(exporter.clone())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let subscriber = create_tracing_subscriber(exporter.clone(), &logger_provider);
|
let subscriber = create_tracing_subscriber(&logger_provider);
|
||||||
|
|
||||||
// avoiding setting tracing subscriber as global as that does not
|
// avoiding setting tracing subscriber as global as that does not
|
||||||
// play well with unit tests.
|
// play well with unit tests.
|
||||||
|
@ -450,7 +447,7 @@ mod tests {
|
||||||
.with_simple_exporter(exporter.clone())
|
.with_simple_exporter(exporter.clone())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let subscriber = create_tracing_subscriber(exporter.clone(), &logger_provider);
|
let subscriber = create_tracing_subscriber(&logger_provider);
|
||||||
|
|
||||||
// avoiding setting tracing subscriber as global as that does not
|
// avoiding setting tracing subscriber as global as that does not
|
||||||
// play well with unit tests.
|
// play well with unit tests.
|
||||||
|
@ -627,7 +624,7 @@ mod tests {
|
||||||
.with_simple_exporter(exporter.clone())
|
.with_simple_exporter(exporter.clone())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let subscriber = create_tracing_subscriber(exporter.clone(), &logger_provider);
|
let subscriber = create_tracing_subscriber(&logger_provider);
|
||||||
|
|
||||||
// avoiding setting tracing subscriber as global as that does not
|
// avoiding setting tracing subscriber as global as that does not
|
||||||
// play well with unit tests.
|
// play well with unit tests.
|
||||||
|
@ -703,7 +700,7 @@ mod tests {
|
||||||
.with_simple_exporter(exporter.clone())
|
.with_simple_exporter(exporter.clone())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
let subscriber = create_tracing_subscriber(exporter.clone(), &logger_provider);
|
let subscriber = create_tracing_subscriber(&logger_provider);
|
||||||
|
|
||||||
// avoiding setting tracing subscriber as global as that does not
|
// avoiding setting tracing subscriber as global as that does not
|
||||||
// play well with unit tests.
|
// play well with unit tests.
|
||||||
|
@ -785,4 +782,70 @@ mod tests {
|
||||||
assert!(!attributes_key.contains(&Key::new("log.target")));
|
assert!(!attributes_key.contains(&Key::new("log.target")));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
struct LogProcessorWithIsEnabled {
|
||||||
|
severity_level: Severity,
|
||||||
|
name: String,
|
||||||
|
target: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogProcessorWithIsEnabled {
|
||||||
|
fn new(severity_level: Severity, name: String, target: String) -> Self {
|
||||||
|
LogProcessorWithIsEnabled {
|
||||||
|
severity_level,
|
||||||
|
name,
|
||||||
|
target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LogProcessor for LogProcessorWithIsEnabled {
|
||||||
|
fn emit(&self, _record: &mut SdkLogRecord, _scope: &InstrumentationScope) {
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
|
fn event_enabled(&self, level: Severity, target: &str, name: Option<&str>) -> bool {
|
||||||
|
// assert that passed in arguments are same as the ones set in the test.
|
||||||
|
assert_eq!(self.severity_level, level);
|
||||||
|
assert_eq!(self.target, target);
|
||||||
|
assert_eq!(
|
||||||
|
self.name,
|
||||||
|
name.expect("name is expected from tracing appender")
|
||||||
|
);
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn force_flush(&self) -> OTelSdkResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn shutdown(&self) -> OTelSdkResult {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
|
#[test]
|
||||||
|
fn is_enabled() {
|
||||||
|
// Arrange
|
||||||
|
let logger_provider = SdkLoggerProvider::builder()
|
||||||
|
.with_log_processor(LogProcessorWithIsEnabled::new(
|
||||||
|
Severity::Error,
|
||||||
|
"my-event-name".to_string(),
|
||||||
|
"my-system".to_string(),
|
||||||
|
))
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let subscriber = create_tracing_subscriber(&logger_provider);
|
||||||
|
|
||||||
|
// avoiding setting tracing subscriber as global as that does not
|
||||||
|
// play well with unit tests.
|
||||||
|
let _guard = tracing::subscriber::set_default(subscriber);
|
||||||
|
|
||||||
|
// Name, Target and Severity are expected to be passed to the IsEnabled check
|
||||||
|
// The validation is done in the LogProcessorWithIsEnabled struct.
|
||||||
|
error!(name: "my-event-name", target: "my-system", event_id = 20, user_name = "otel", user_email = "otel@opentelemetry.io");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,10 +38,13 @@
|
||||||
|
|
||||||
- **Breaking** The SpanExporter::export() method no longer requires a mutable reference to self.
|
- **Breaking** The SpanExporter::export() method no longer requires a mutable reference to self.
|
||||||
Before:
|
Before:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult
|
async fn export(&mut self, batch: Vec<SpanData>) -> OTelSdkResult
|
||||||
```
|
```
|
||||||
|
|
||||||
After:
|
After:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult
|
async fn export(&self, batch: Vec<SpanData>) -> OTelSdkResult
|
||||||
```
|
```
|
||||||
|
@ -52,6 +55,11 @@
|
||||||
when its `shutdown` is invoked.
|
when its `shutdown` is invoked.
|
||||||
|
|
||||||
- Reduced some info level logs to debug
|
- Reduced some info level logs to debug
|
||||||
|
- **Breaking** for custom LogProcessor/Exporter authors: Changed `name`
|
||||||
|
parameter from `&str` to `Option<&str>` in `event_enabled` method on the
|
||||||
|
`LogProcessor` and `LogExporter` traits. `SdkLogger` no longer passes its
|
||||||
|
`scope` name but instead passes the incoming `name` when invoking
|
||||||
|
`event_enabled` on processors.
|
||||||
|
|
||||||
## 0.28.0
|
## 0.28.0
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ pub trait LogExporter: Send + Sync + Debug {
|
||||||
}
|
}
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
/// Check if logs are enabled.
|
/// Check if logs are enabled.
|
||||||
fn event_enabled(&self, _level: Severity, _target: &str, _name: &str) -> bool {
|
fn event_enabled(&self, _level: Severity, _target: &str, _name: Option<&str>) -> bool {
|
||||||
// By default, all logs are enabled
|
// By default, all logs are enabled
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ pub trait LogProcessor: Send + Sync + Debug {
|
||||||
fn shutdown(&self) -> OTelSdkResult;
|
fn shutdown(&self) -> OTelSdkResult;
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
/// Check if logging is enabled
|
/// Check if logging is enabled
|
||||||
fn event_enabled(&self, _level: Severity, _target: &str, _name: &str) -> bool {
|
fn event_enabled(&self, _level: Severity, _target: &str, _name: Option<&str>) -> bool {
|
||||||
// By default, all logs are enabled
|
// By default, all logs are enabled
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,10 @@ impl opentelemetry::logs::Logger for SdkLogger {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
fn event_enabled(&self, level: Severity, target: &str) -> bool {
|
fn event_enabled(&self, level: Severity, target: &str, name: Option<&str>) -> bool {
|
||||||
self.provider
|
self.provider
|
||||||
.log_processors()
|
.log_processors()
|
||||||
.iter()
|
.iter()
|
||||||
.any(|processor| processor.event_enabled(level, target, self.scope.name().as_ref()))
|
.any(|processor| processor.event_enabled(level, target, name))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,10 @@
|
||||||
- Updated `Baggage` constants to reflect latest standard (`MAX_KEY_VALUE_PAIRS` - 180 -> 64, `MAX_BYTES_FOR_ONE_PAIR` - removed) and increased insert performance see #[2284](https://github.com/open-telemetry/opentelemetry-rust/pull/2284).
|
- Updated `Baggage` constants to reflect latest standard (`MAX_KEY_VALUE_PAIRS` - 180 -> 64, `MAX_BYTES_FOR_ONE_PAIR` - removed) and increased insert performance see #[2284](https://github.com/open-telemetry/opentelemetry-rust/pull/2284).
|
||||||
- *Breaking* Align `Baggage.remove()` signature with `.get()` to take the key as a reference
|
- *Breaking* Align `Baggage.remove()` signature with `.get()` to take the key as a reference
|
||||||
|
|
||||||
|
- Added additional `name: Option<&str>` parameter to the `event_enabled` method
|
||||||
|
on the `Logger` trait. This allows implementations (SDK, processor, exporters)
|
||||||
|
to leverage this additional information to determine if an event is enabled.
|
||||||
|
|
||||||
## 0.28.0
|
## 0.28.0
|
||||||
|
|
||||||
Released 2025-Feb-10
|
Released 2025-Feb-10
|
||||||
|
|
|
@ -21,7 +21,7 @@ pub trait Logger {
|
||||||
|
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
/// Check if the given log level is enabled.
|
/// Check if the given log level is enabled.
|
||||||
fn event_enabled(&self, level: Severity, target: &str) -> bool;
|
fn event_enabled(&self, level: Severity, target: &str, name: Option<&str>) -> bool;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Interfaces that can create [`Logger`] instances.
|
/// Interfaces that can create [`Logger`] instances.
|
||||||
|
|
|
@ -79,7 +79,7 @@ impl Logger for NoopLogger {
|
||||||
}
|
}
|
||||||
fn emit(&self, _record: Self::LogRecord) {}
|
fn emit(&self, _record: Self::LogRecord) {}
|
||||||
#[cfg(feature = "spec_unstable_logs_enabled")]
|
#[cfg(feature = "spec_unstable_logs_enabled")]
|
||||||
fn event_enabled(&self, _level: super::Severity, _target: &str) -> bool {
|
fn event_enabled(&self, _level: super::Severity, _target: &str, _name: Option<&str>) -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue