diff --git a/crates/stackable-telemetry/CHANGELOG.md b/crates/stackable-telemetry/CHANGELOG.md index 8ba94c69b..889682a5a 100644 --- a/crates/stackable-telemetry/CHANGELOG.md +++ b/crates/stackable-telemetry/CHANGELOG.md @@ -4,6 +4,17 @@ All notable changes to this project will be documented in this file. ## [Unreleased] +### Added + +- Introduce common `Settings` and subscriber specific settings ([#901]). + +### Changed + +- BREAKING: Renamed `TracingBuilder` methods with long names, and prefix with `with_` ([#901]). +- BREAKING: Use the new subscriber settings in the `TracingBuilder` ([#901]). + +[#901]: https://github.com/stackabletech/operator-rs/pull/901 + ## [0.2.0] - 2024-07-10 ### Changed diff --git a/crates/stackable-telemetry/src/tracing.rs b/crates/stackable-telemetry/src/tracing/mod.rs similarity index 69% rename from crates/stackable-telemetry/src/tracing.rs rename to crates/stackable-telemetry/src/tracing/mod.rs index 2f61e9ac3..43c943599 100644 --- a/crates/stackable-telemetry/src/tracing.rs +++ b/crates/stackable-telemetry/src/tracing/mod.rs @@ -15,9 +15,13 @@ use opentelemetry_sdk::{ }; use opentelemetry_semantic_conventions::resource; use snafu::{ResultExt as _, Snafu}; -use tracing::{level_filters::LevelFilter, subscriber::SetGlobalDefaultError}; +use tracing::subscriber::SetGlobalDefaultError; use tracing_subscriber::{filter::Directive, layer::SubscriberExt, EnvFilter, Layer, Registry}; +use settings::{ConsoleLogSettings, OtlpLogSettings, OtlpTraceSettings}; + +pub mod settings; + type Result = std::result::Result; #[derive(Debug, Snafu)] @@ -40,18 +44,41 @@ pub enum Error { /// /// # Usage: /// ``` -/// use stackable_telemetry::tracing::{Tracing, Error}; +/// use stackable_telemetry::tracing::{Tracing, Error, settings::{Build as _, Settings}}; /// use tracing_subscriber::filter::LevelFilter; /// /// #[tokio::main] /// async fn main() -> Result<(), Error> { +/// // This can come from a Clap argument for example. The enabled builder +/// // function below allows enabling/disabling certain subscribers during +/// // runtime. +/// let otlp_log_flag = false; +/// /// // IMPORTANT: Name the guard variable appropriately, do not just use /// // `let _ =`, as that will drop immediately. /// let _tracing_guard = Tracing::builder() /// .service_name("test") -/// .with_console_output("TEST_CONSOLE", LevelFilter::INFO) -/// .with_otlp_log_exporter("TEST_OTLP_LOG", LevelFilter::DEBUG) -/// .with_otlp_trace_exporter("TEST_OTLP_TRACE", LevelFilter::TRACE) +/// .with_console_output( +/// Settings::builder() +/// .with_environment_variable("TEST_CONSOLE") +/// .with_default_level(LevelFilter::INFO) +/// .enabled(true) +/// .build() +/// ) +/// .with_otlp_log_exporter( +/// Settings::builder() +/// .with_environment_variable("TEST_OTLP_LOG") +/// .with_default_level(LevelFilter::DEBUG) +/// .enabled(otlp_log_flag) +/// .build() +/// ) +/// .with_otlp_trace_exporter( +/// Settings::builder() +/// .with_environment_variable("TEST_OTLP_TRACE") +/// .with_default_level(LevelFilter::TRACE) +/// .enabled(true) +/// .build() +/// ) /// .build() /// .init()?; /// @@ -123,9 +150,9 @@ pub enum Error { /// [5]: https://docs.rs/opentelemetry_sdk/latest/src/opentelemetry_sdk/logs/log_processor.rs.html pub struct Tracing { service_name: &'static str, - console_log_config: SubscriberConfig, - otlp_log_config: SubscriberConfig, - otlp_trace_config: SubscriberConfig, + console_log_settings: ConsoleLogSettings, + otlp_log_settings: OtlpLogSettings, + otlp_trace_settings: OtlpTraceSettings, logger_provider: Option, } @@ -142,20 +169,22 @@ impl Tracing { pub fn init(mut self) -> Result { let mut layers: Vec + Sync + Send>> = Vec::new(); - if self.console_log_config.enabled { + if self.console_log_settings.enabled { let env_filter_layer = env_filter_builder( - self.console_log_config.env_var, - self.console_log_config.default_level_filter, + self.console_log_settings + .common_settings + .environment_variable, + self.console_log_settings.default_level, ); let console_output_layer = tracing_subscriber::fmt::layer().with_filter(env_filter_layer); layers.push(console_output_layer.boxed()); } - if self.otlp_log_config.enabled { + if self.otlp_log_settings.enabled { let env_filter_layer = env_filter_builder( - self.otlp_log_config.env_var, - self.otlp_log_config.default_level_filter, + self.otlp_log_settings.environment_variable, + self.otlp_log_settings.default_level, ) // TODO (@NickLarsenNZ): Remove this directive once https://github.com/open-telemetry/opentelemetry-rust/issues/761 is resolved .add_directive("h2=off".parse().expect("invalid directive")); @@ -180,10 +209,12 @@ impl Tracing { self.logger_provider = Some(otel_log); } - if self.otlp_trace_config.enabled { + if self.otlp_trace_settings.enabled { let env_filter_layer = env_filter_builder( - self.otlp_trace_config.env_var, - self.otlp_trace_config.default_level_filter, + self.otlp_trace_settings + .common_settings + .environment_variable, + self.otlp_trace_settings.default_level, ) // TODO (@NickLarsenNZ): Remove this directive once https://github.com/open-telemetry/opentelemetry-rust/issues/761 is resolved .add_directive("h2=off".parse().expect("invalid directive")); @@ -231,12 +262,12 @@ impl Tracing { impl Drop for Tracing { fn drop(&mut self) { tracing::debug!( - opentelemetry.tracing.enabled = self.otlp_trace_config.enabled, - opentelemetry.logger.enabled = self.otlp_log_config.enabled, + opentelemetry.tracing.enabled = self.otlp_trace_settings.enabled, + opentelemetry.logger.enabled = self.otlp_log_settings.enabled, "shutting down opentelemetry OTLP providers" ); - if self.otlp_trace_config.enabled { + if self.otlp_trace_settings.enabled { // NOTE (@NickLarsenNZ): This might eventually be replaced with something like SdkMeterProvider::shutdown(&self) // as has been done with the LoggerProvider (further below) // see: https://github.com/open-telemetry/opentelemetry-rust/pull/1412/files#r1409608679 @@ -315,31 +346,14 @@ impl BuilderState for builder_state::Config {} #[derive(Default)] pub struct TracingBuilder { service_name: Option<&'static str>, - console_log_config: SubscriberConfig, - otlp_log_config: SubscriberConfig, - otlp_trace_config: SubscriberConfig, + console_log_settings: ConsoleLogSettings, + otlp_log_settings: OtlpLogSettings, + otlp_trace_settings: OtlpTraceSettings, /// Allow the generic to be used (needed for impls). _marker: std::marker::PhantomData, } -#[derive(Clone, Debug, PartialEq)] -struct SubscriberConfig { - enabled: bool, - env_var: &'static str, - default_level_filter: LevelFilter, -} - -impl Default for SubscriberConfig { - fn default() -> Self { - Self { - enabled: false, - env_var: EnvFilter::DEFAULT_ENV, - default_level_filter: LevelFilter::OFF, - } - } -} - impl TracingBuilder { /// Set the service name used in OTLP exports, and console output. /// @@ -354,68 +368,59 @@ impl TracingBuilder { impl TracingBuilder { /// Enable the console output tracing subscriber and set the default - /// [`LevelFilter`] which is overridable through the given environment + /// [`LevelFilter`][1] which is overridable through the given environment /// variable. + /// + /// [1]: tracing_subscriber::filter::LevelFilter pub fn with_console_output( self, - env_var: &'static str, - default_level_filter: LevelFilter, + console_log_settings: ConsoleLogSettings, ) -> TracingBuilder { TracingBuilder { service_name: self.service_name, - console_log_config: SubscriberConfig { - enabled: true, - env_var, - default_level_filter, - }, - otlp_log_config: self.otlp_log_config, - otlp_trace_config: self.otlp_trace_config, + console_log_settings, + otlp_log_settings: self.otlp_log_settings, + otlp_trace_settings: self.otlp_trace_settings, _marker: self._marker, } } - /// Enable the OTLP logging subscriber and set the default [`LevelFilter`] + /// Enable the OTLP logging subscriber and set the default [`LevelFilter`][1] /// which is overridable through the given environment variable. /// /// You can configure the OTLP log exports through the variables defined /// in the opentelemetry crates. See [`Tracing`]. + /// + /// [1]: tracing_subscriber::filter::LevelFilter pub fn with_otlp_log_exporter( self, - env_var: &'static str, - default_level_filter: LevelFilter, + otlp_log_settings: OtlpLogSettings, ) -> TracingBuilder { TracingBuilder { service_name: self.service_name, - console_log_config: self.console_log_config, - otlp_log_config: SubscriberConfig { - enabled: true, - env_var, - default_level_filter, - }, - otlp_trace_config: self.otlp_trace_config, + console_log_settings: self.console_log_settings, + otlp_log_settings, + otlp_trace_settings: self.otlp_trace_settings, _marker: self._marker, } } - /// Enable the OTLP tracing subscriber and set the default [`LevelFilter`] + /// Enable the OTLP tracing subscriber and set the default [`LevelFilter`][1] /// which is overridable through the given environment variable. /// /// You can configure the OTLP trace exports through the variables defined /// in the opentelemetry crates. See [`Tracing`]. + /// + /// [1]: tracing_subscriber::filter::LevelFilter pub fn with_otlp_trace_exporter( self, - env_var: &'static str, - default_level_filter: LevelFilter, + otlp_trace_settings: OtlpTraceSettings, ) -> TracingBuilder { TracingBuilder { service_name: self.service_name, - console_log_config: self.console_log_config, - otlp_log_config: self.otlp_log_config, - otlp_trace_config: SubscriberConfig { - enabled: true, - env_var, - default_level_filter, - }, + console_log_settings: self.console_log_settings, + otlp_log_settings: self.otlp_log_settings, + otlp_trace_settings, _marker: self._marker, } } @@ -429,9 +434,9 @@ impl TracingBuilder { service_name: self .service_name .expect("service_name must be configured at this point"), - console_log_config: self.console_log_config, - otlp_log_config: self.otlp_log_config, - otlp_trace_config: self.otlp_trace_config, + console_log_settings: self.console_log_settings, + otlp_log_settings: self.otlp_log_settings, + otlp_trace_settings: self.otlp_trace_settings, logger_provider: None, } } @@ -447,6 +452,9 @@ fn env_filter_builder(env_var: &str, default_directive: impl Into) -> #[cfg(test)] mod test { + use settings::{Build as _, Settings}; + use tracing::level_filters::LevelFilter; + use super::*; #[test] @@ -460,53 +468,93 @@ mod test { fn builder_with_console_output() { let trace_guard = Tracing::builder() .service_name("test") - .with_console_output("ABC_A", LevelFilter::TRACE) - .with_console_output("ABC_B", LevelFilter::DEBUG) + .with_console_output( + Settings::builder() + .with_environment_variable("ABC_A") + .with_default_level(LevelFilter::TRACE) + .enabled(true) + .build(), + ) + .with_console_output( + Settings::builder() + .with_environment_variable("ABC_B") + .with_default_level(LevelFilter::DEBUG) + .enabled(true) + .build(), + ) .build(); assert_eq!( - trace_guard.console_log_config, - SubscriberConfig { - enabled: true, - env_var: "ABC_B", - default_level_filter: LevelFilter::DEBUG + trace_guard.console_log_settings, + ConsoleLogSettings { + common_settings: Settings { + enabled: true, + environment_variable: "ABC_B", + default_level: LevelFilter::DEBUG + }, + log_format: Default::default() } ); - assert!(!trace_guard.otlp_log_config.enabled); - assert!(!trace_guard.otlp_trace_config.enabled); + assert!(!trace_guard.otlp_log_settings.enabled); + assert!(!trace_guard.otlp_trace_settings.enabled); } #[test] fn builder_with_all() { let trace_guard = Tracing::builder() .service_name("test") - .with_console_output("ABC_CONSOLE", LevelFilter::INFO) - .with_otlp_log_exporter("ABC_OTLP_LOG", LevelFilter::DEBUG) - .with_otlp_trace_exporter("ABC_OTLP_TRACE", LevelFilter::TRACE) + .with_console_output( + Settings::builder() + .with_environment_variable("ABC_CONSOLE") + .with_default_level(LevelFilter::INFO) + .enabled(true) + .build(), + ) + .with_otlp_log_exporter( + Settings::builder() + .with_environment_variable("ABC_OTLP_LOG") + .with_default_level(LevelFilter::DEBUG) + .enabled(true) + .build(), + ) + .with_otlp_trace_exporter( + Settings::builder() + .with_environment_variable("ABC_OTLP_TRACE") + .with_default_level(LevelFilter::TRACE) + .enabled(true) + .build(), + ) .build(); assert_eq!( - trace_guard.console_log_config, - SubscriberConfig { - enabled: true, - env_var: "ABC_CONSOLE", - default_level_filter: LevelFilter::INFO + trace_guard.console_log_settings, + ConsoleLogSettings { + common_settings: Settings { + enabled: true, + environment_variable: "ABC_CONSOLE", + default_level: LevelFilter::INFO + }, + log_format: Default::default() } ); assert_eq!( - trace_guard.otlp_log_config, - SubscriberConfig { - enabled: true, - env_var: "ABC_OTLP_LOG", - default_level_filter: LevelFilter::DEBUG + trace_guard.otlp_log_settings, + OtlpLogSettings { + common_settings: Settings { + enabled: true, + environment_variable: "ABC_OTLP_LOG", + default_level: LevelFilter::DEBUG + }, } ); assert_eq!( - trace_guard.otlp_trace_config, - SubscriberConfig { - enabled: true, - env_var: "ABC_OTLP_TRACE", - default_level_filter: LevelFilter::TRACE + trace_guard.otlp_trace_settings, + OtlpTraceSettings { + common_settings: Settings { + enabled: true, + environment_variable: "ABC_OTLP_TRACE", + default_level: LevelFilter::TRACE + } } ); } diff --git a/crates/stackable-telemetry/src/tracing/settings/console_log.rs b/crates/stackable-telemetry/src/tracing/settings/console_log.rs new file mode 100644 index 000000000..0ba059592 --- /dev/null +++ b/crates/stackable-telemetry/src/tracing/settings/console_log.rs @@ -0,0 +1,115 @@ +//! Console Log Subscriber Settings. + +use std::ops::Deref; + +use super::{Build, Settings, SettingsBuilder}; + +/// Configure specific settings for the Console Log subscriber. +#[derive(Debug, Default, PartialEq)] +pub struct ConsoleLogSettings { + /// Common subscriber settings that apply to the Console Log Subscriber. + pub common_settings: Settings, + + /// Console Subscriber log event output format. + pub log_format: Format, +} + +impl Deref for ConsoleLogSettings { + type Target = Settings; + + fn deref(&self) -> &Self::Target { + &self.common_settings + } +} + +/// Console Subscriber log event output formats. +/// +/// Currently, only [Plain][Format::Plain] is supported. +#[derive(Debug, Default, PartialEq)] +pub enum Format { + /// Use the plain unstructured log output. + /// + /// ANSI color output is enabled by default, but can be disabled at runtime by + /// setting `NO_COLOR` to a non-empty value. + /// + /// See: [`Layer::with_ansi`][tracing_subscriber::fmt::Layer::with_ansi]. + #[default] + Plain, + // Json { pretty: bool }, + // LogFmt, +} + +/// For building [`ConsoleLogSettings`]. +/// +///
+/// Do not use directly, instead use the [`Settings::builder`] associated function. +///
+pub struct ConsoleLogSettingsBuilder { + pub(crate) common_settings: Settings, + pub(crate) log_format: Format, +} + +impl ConsoleLogSettingsBuilder { + pub fn with_log_format(mut self, format: Format) -> Self { + self.log_format = format; + self + } + + pub fn build(self) -> ConsoleLogSettings { + ConsoleLogSettings { + common_settings: self.common_settings, + log_format: self.log_format, + } + } +} + +/// This implementation is used to turn the common settings builder into the console log specific +/// settings builder via the [`SettingsBuilder::console_log_settings_builder`] function. +impl From for ConsoleLogSettingsBuilder { + fn from(value: SettingsBuilder) -> Self { + Self { + common_settings: value.build(), + log_format: Format::default(), + } + } +} + +/// This implementation is used to build console log settings from common settings without +/// specifying console log specific settings. +impl Build for SettingsBuilder { + fn build(self) -> ConsoleLogSettings { + ConsoleLogSettings { + common_settings: self.build(), + ..Default::default() + } + } +} + +#[cfg(test)] +mod test { + use tracing::level_filters::LevelFilter; + + use super::*; + + #[test] + fn builds_settings() { + let expected = ConsoleLogSettings { + common_settings: Settings { + environment_variable: "hello", + default_level: LevelFilter::DEBUG, + enabled: true, + }, + log_format: Format::Plain, + }; + let result = Settings::builder() + .with_environment_variable("hello") + .with_default_level(LevelFilter::DEBUG) + .enabled(true) + .console_log_settings_builder() + .with_log_format(Format::Plain) + // color + .build(); + + assert_eq!(expected, result); + } +} diff --git a/crates/stackable-telemetry/src/tracing/settings/mod.rs b/crates/stackable-telemetry/src/tracing/settings/mod.rs new file mode 100644 index 000000000..aaf71c6bb --- /dev/null +++ b/crates/stackable-telemetry/src/tracing/settings/mod.rs @@ -0,0 +1,148 @@ +//! Subscriber settings. + +use tracing::level_filters::LevelFilter; + +pub mod console_log; +pub use console_log::*; + +pub mod otlp_log; +pub use otlp_log::*; + +pub mod otlp_trace; +pub use otlp_trace::*; + +/// General settings that apply to any subscriber. +#[derive(Debug, PartialEq)] +pub struct Settings { + /// The environment variable used to set the [`LevelFilter`]. + /// + /// When the environment variable is set, it will override what is set by + /// [`Self::default_level`]. + pub environment_variable: &'static str, + + /// The [`LevelFilter`] to fallback to if [`Self::environment_variable`] has + /// not been set. + pub default_level: LevelFilter, + + /// Whether or not the subscriber is enabled. + /// + /// When set to `true`, the [`tracing::Subscriber`] will be added to the + /// [`tracing_subscriber::Layer`] list. + pub enabled: bool, +} + +impl Settings { + /// Builder methods to override defaults. + pub fn builder() -> SettingsBuilder { + SettingsBuilder::default() + } +} + +impl Default for Settings { + fn default() -> Self { + SettingsBuilder::default().build() + } +} + +/// For building [`Settings`]. +pub struct SettingsBuilder { + environment_variable: &'static str, + enabled: bool, + default_level: LevelFilter, +} + +/// Finalizer to be implemented on builders. +pub trait Build { + /// Finalize settings. + fn build(self) -> T; +} + +impl Build for SettingsBuilder { + fn build(self) -> Settings { + Settings { + environment_variable: self.environment_variable, + default_level: self.default_level, + enabled: self.enabled, + } + } +} + +impl SettingsBuilder { + /// Set the environment variable used for overriding the [`Settings::default_level`]. + /// + /// Defaults to `RUST_LOG`. + // TODO (@NickLarsenNZ): set a constant for the default environment variable. + pub fn with_environment_variable(mut self, name: &'static str) -> Self { + self.environment_variable = name; + self + } + + /// Set the default [`LevelFilter`]. + /// + /// Defaults to [`LevelFilter::OFF`]. + // TODO (@NickLarsenNZ): set a constant for the default level. + pub fn with_default_level(mut self, level: impl Into) -> Self { + self.default_level = level.into(); + self + } + + /// Enable or disable the [`tracing::Subscriber`]. + /// + /// Defaults to `false`. + // TODO (@NickLarsenNZ): Currently this has to be called to enable the + // subscriber. Eventually it should become optional, and default to on (if + // settings are supplied). Therefore, the fields in TracingBuilder to hold + // the subscriber settings should become Option so that the subscriber is + // disabled when not configured, is enabled when configured, while still + // controllable through this function. Then this can be renamed to `with_enabled` + pub fn enabled(mut self, enabled: bool) -> Self { + self.enabled = enabled; + self + } + + /// Set specific [`ConsoleLogSettings`]. + pub fn console_log_settings_builder(self) -> ConsoleLogSettingsBuilder { + self.into() + } + + /// Set specific [`OtlpLogSettings`]. + pub fn otlp_log_settings_builder(self) -> OtlpLogSettingsBuilder { + self.into() + } + + /// Set specific [`OtlpTraceSettings`]. + pub fn otlp_trace_settings_builder(self) -> OtlpTraceSettingsBuilder { + self.into() + } +} + +impl Default for SettingsBuilder { + fn default() -> Self { + Self { + environment_variable: "RUST_LOG", + default_level: LevelFilter::OFF, + enabled: false, + } + } +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn builds_settings() { + let expected = Settings { + environment_variable: "hello", + default_level: LevelFilter::DEBUG, + enabled: true, + }; + let result = Settings::builder() + .with_environment_variable("hello") + .with_default_level(LevelFilter::DEBUG) + .enabled(true) + .build(); + + assert_eq!(expected, result); + } +} diff --git a/crates/stackable-telemetry/src/tracing/settings/otlp_log.rs b/crates/stackable-telemetry/src/tracing/settings/otlp_log.rs new file mode 100644 index 000000000..6015e0564 --- /dev/null +++ b/crates/stackable-telemetry/src/tracing/settings/otlp_log.rs @@ -0,0 +1,77 @@ +//! OTLP Log Subscriber Settings. + +use std::ops::Deref; + +use super::{Build, Settings, SettingsBuilder}; + +#[derive(Debug, Default, PartialEq)] +pub struct OtlpLogSettings { + pub common_settings: Settings, +} + +impl Deref for OtlpLogSettings { + type Target = Settings; + + fn deref(&self) -> &Self::Target { + &self.common_settings + } +} + +pub struct OtlpLogSettingsBuilder { + pub(crate) common_settings: Settings, +} + +impl OtlpLogSettingsBuilder { + pub fn build(self) -> OtlpLogSettings { + OtlpLogSettings { + common_settings: self.common_settings, + } + } +} + +/// This implementation is used to turn the common settings builder into the OTLP log specific +/// settings builder via the [`SettingsBuilder::otlp_log_settings_builder`] function. +impl From for OtlpLogSettingsBuilder { + fn from(value: SettingsBuilder) -> Self { + Self { + common_settings: value.build(), + } + } +} + +/// This implementation is used to build OTLP log settings from common settings without +/// specifying OTLP log specific settings. +impl Build for SettingsBuilder { + fn build(self) -> OtlpLogSettings { + OtlpLogSettings { + common_settings: self.build(), + // ..Default::default() + } + } +} + +#[cfg(test)] +mod test { + use tracing::level_filters::LevelFilter; + + use super::*; + + #[test] + fn builds_settings() { + let expected = OtlpLogSettings { + common_settings: Settings { + environment_variable: "hello", + default_level: LevelFilter::DEBUG, + enabled: true, + }, + }; + let result = Settings::builder() + .with_environment_variable("hello") + .with_default_level(LevelFilter::DEBUG) + .enabled(true) + .otlp_log_settings_builder() + .build(); + + assert_eq!(expected, result); + } +} diff --git a/crates/stackable-telemetry/src/tracing/settings/otlp_trace.rs b/crates/stackable-telemetry/src/tracing/settings/otlp_trace.rs new file mode 100644 index 000000000..df13a9e2b --- /dev/null +++ b/crates/stackable-telemetry/src/tracing/settings/otlp_trace.rs @@ -0,0 +1,77 @@ +//! OTLP Trace Subscriber Settings. + +use std::ops::Deref; + +use super::{Build, Settings, SettingsBuilder}; + +#[derive(Debug, Default, PartialEq)] +pub struct OtlpTraceSettings { + pub common_settings: Settings, +} + +impl Deref for OtlpTraceSettings { + type Target = Settings; + + fn deref(&self) -> &Self::Target { + &self.common_settings + } +} + +pub struct OtlpTraceSettingsBuilder { + pub(crate) common_settings: Settings, +} + +impl OtlpTraceSettingsBuilder { + pub fn build(self) -> OtlpTraceSettings { + OtlpTraceSettings { + common_settings: self.common_settings, + } + } +} + +/// This implementation is used to turn the common settings builder into the OTLP trace specific +/// settings builder via the [`SettingsBuilder::otlp_trace_settings_builder`] function. +impl From for OtlpTraceSettingsBuilder { + fn from(value: SettingsBuilder) -> Self { + Self { + common_settings: value.build(), + } + } +} + +/// This implementation is used to build OTLP trace settings from common settings without +/// specifying OTLP trace specific settings. +impl Build for SettingsBuilder { + fn build(self) -> OtlpTraceSettings { + OtlpTraceSettings { + common_settings: self.build(), + // ..Default::default() + } + } +} + +#[cfg(test)] +mod test { + use tracing::level_filters::LevelFilter; + + use super::*; + + #[test] + fn builds_settings() { + let expected = OtlpTraceSettings { + common_settings: Settings { + environment_variable: "hello", + default_level: LevelFilter::DEBUG, + enabled: true, + }, + }; + let result = Settings::builder() + .with_environment_variable("hello") + .with_default_level(LevelFilter::DEBUG) + .enabled(true) + .otlp_trace_settings_builder() + .build(); + + assert_eq!(expected, result); + } +}