Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
6 changes: 6 additions & 0 deletions crates/stackable-telemetry/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file.

## [Unreleased]

### Changed

- Add support for setting the environment variable for each configured tracing subscriber ([#801]).

[#801]: https://github.com/stackabletech/operator-rs/pull/801

## [0.1.0] - 2024-05-08

### Changed
Expand Down
103 changes: 65 additions & 38 deletions crates/stackable-telemetry/src/tracing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use opentelemetry_sdk::{
use opentelemetry_semantic_conventions::resource;
use snafu::{ResultExt as _, Snafu};
use tracing::{level_filters::LevelFilter, subscriber::SetGlobalDefaultError};
use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Layer, Registry};
use tracing_subscriber::{filter::Directive, layer::SubscriberExt, EnvFilter, Layer, Registry};

type Result<T, E = Error> = std::result::Result<T, E>;

Expand Down Expand Up @@ -48,9 +48,9 @@ pub enum Error {
/// async fn main() -> Result<(), Error> {
/// let _tracing_guard = Tracing::builder()
/// .service_name("test")
/// .with_console_output(LevelFilter::INFO)
/// .with_otlp_log_exporter(LevelFilter::DEBUG)
/// .with_otlp_trace_exporter(LevelFilter::TRACE)
/// .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)
/// .build()
/// .init()?;
///
Expand Down Expand Up @@ -138,20 +138,22 @@ impl Tracing {
let mut layers: Vec<Box<dyn Layer<Registry> + Sync + Send>> = Vec::new();

if self.console_log_config.enabled {
let env_filter_layer = EnvFilter::builder()
.with_default_directive(self.console_log_config.level_filter.into()) // TODO (@NickLarsenNZ): support Directives
.from_env_lossy();
let env_filter_layer = env_filter_builder(
self.console_log_config.env_var,
self.console_log_config.default_level_filter,
);
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 {
let env_filter_layer = EnvFilter::builder()
.with_default_directive(self.otlp_log_config.level_filter.into()) // TODO (@NickLarsenNZ): support Directives
.from_env_lossy()
// 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"));
let env_filter_layer = env_filter_builder(
self.otlp_log_config.env_var,
self.otlp_log_config.default_level_filter,
)
// 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"));

let log_exporter = opentelemetry_otlp::new_exporter().tonic();
let otel_log =
Expand All @@ -173,11 +175,12 @@ impl Tracing {
}

if self.otlp_trace_config.enabled {
let env_filter_layer = EnvFilter::builder()
.with_default_directive(self.otlp_trace_config.level_filter.into()) // TODO (@NickLarsenNZ): support Directives
.from_env_lossy()
// 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"));
let env_filter_layer = env_filter_builder(
self.otlp_trace_config.env_var,
self.otlp_trace_config.default_level_filter,
)
// 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"));

let trace_exporter = opentelemetry_otlp::new_exporter().tonic();
let otel_tracer = opentelemetry_otlp::new_pipeline()
Expand All @@ -186,7 +189,7 @@ impl Tracing {
.with_trace_config(
trace::config()
.with_sampler(Sampler::AlwaysOn) // TODO (@NickLarsenNZ): Make this configurable. See also Sampler::ParentBased
.with_id_generator(RandomIdGenerator::default()) // TODO (@NickLarsenNZ): Is there a more appropriate ID generator?
.with_id_generator(RandomIdGenerator::default())
.with_resource(Resource::new(vec![KeyValue::new(
resource::SERVICE_NAME,
self.service_name,
Expand Down Expand Up @@ -308,14 +311,16 @@ pub struct TracingBuilder<S: BuilderState> {
#[derive(Clone, Debug, PartialEq)]
struct SubscriberConfig {
enabled: bool,
level_filter: LevelFilter,
env_var: &'static str,
default_level_filter: LevelFilter,
}

impl Default for SubscriberConfig {
fn default() -> Self {
Self {
enabled: false,
level_filter: LevelFilter::OFF,
env_var: EnvFilter::DEFAULT_ENV,
default_level_filter: LevelFilter::OFF,
}
}
}
Expand All @@ -333,58 +338,68 @@ impl TracingBuilder<builder_state::PreServiceName> {
}

impl TracingBuilder<builder_state::Config> {
/// Enable the console output tracing subscriber, and filter the log level.
/// Enable the console output tracing subscriber and set the default
/// [`LevelFilter`] which is overridable through the given environment
/// variable.
pub fn with_console_output(
self,
level_filter: LevelFilter,
env_var: &'static str,
default_level_filter: LevelFilter,
) -> TracingBuilder<builder_state::Config> {
TracingBuilder {
service_name: self.service_name,
console_log_config: SubscriberConfig {
enabled: true,
level_filter,
env_var,
default_level_filter,
},
otlp_log_config: self.otlp_log_config,
otlp_trace_config: self.otlp_trace_config,
_marker: self._marker,
}
}

/// Enable the OTLP logging subscriber, and filter the log level.
/// Enable the OTLP logging subscriber and set the default [`LevelFilter`]
/// 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`].
pub fn with_otlp_log_exporter(
self,
level_filter: LevelFilter,
env_var: &'static str,
default_level_filter: LevelFilter,
) -> TracingBuilder<builder_state::Config> {
TracingBuilder {
service_name: self.service_name,
console_log_config: self.console_log_config,
otlp_log_config: SubscriberConfig {
enabled: true,
level_filter,
env_var,
default_level_filter,
},
otlp_trace_config: self.otlp_trace_config,
_marker: self._marker,
}
}

/// Enable the OTLP tracing subscriber, and filter the log level.
/// Enable the OTLP tracing subscriber and set the default [`LevelFilter`]
/// 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`].
pub fn with_otlp_trace_exporter(
self,
level_filter: LevelFilter,
env_var: &'static str,
default_level_filter: LevelFilter,
) -> TracingBuilder<builder_state::Config> {
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,
level_filter,
env_var,
default_level_filter,
},
_marker: self._marker,
}
Expand All @@ -406,6 +421,14 @@ impl TracingBuilder<builder_state::Config> {
}
}

/// Create an [`EnvFilter`] configured with the given environment variable and default [`Directive`].
fn env_filter_builder(env_var: &str, default_directive: impl Into<Directive>) -> EnvFilter {
EnvFilter::builder()
.with_env_var(env_var)
.with_default_directive(default_directive.into())
.from_env_lossy()
}

#[cfg(test)]
mod test {
use super::*;
Expand All @@ -421,15 +444,16 @@ mod test {
fn builder_with_console_output() {
let trace_guard = Tracing::builder()
.service_name("test")
.with_console_output(LevelFilter::TRACE)
.with_console_output(LevelFilter::DEBUG)
.with_console_output("ABC_A", LevelFilter::TRACE)
.with_console_output("ABC_B", LevelFilter::DEBUG)
.build();

assert_eq!(
trace_guard.console_log_config,
SubscriberConfig {
enabled: true,
level_filter: LevelFilter::DEBUG
env_var: "ABC_B",
default_level_filter: LevelFilter::DEBUG
}
);
assert!(!trace_guard.otlp_log_config.enabled);
Expand All @@ -440,30 +464,33 @@ mod test {
fn builder_with_all() {
let trace_guard = Tracing::builder()
.service_name("test")
.with_console_output(LevelFilter::INFO)
.with_otlp_log_exporter(LevelFilter::DEBUG)
.with_otlp_trace_exporter(LevelFilter::TRACE)
.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)
.build();

assert_eq!(
trace_guard.console_log_config,
SubscriberConfig {
enabled: true,
level_filter: LevelFilter::INFO
env_var: "ABC_CONSOLE",
default_level_filter: LevelFilter::INFO
}
);
assert_eq!(
trace_guard.otlp_log_config,
SubscriberConfig {
enabled: true,
level_filter: LevelFilter::DEBUG
env_var: "ABC_OTLP_LOG",
default_level_filter: LevelFilter::DEBUG
}
);
assert_eq!(
trace_guard.otlp_trace_config,
SubscriberConfig {
enabled: true,
level_filter: LevelFilter::TRACE
env_var: "ABC_OTLP_TRACE",
default_level_filter: LevelFilter::TRACE
}
);
}
Expand Down