From df571818f156df6262a6d41eae6cbeb0e8d237c6 Mon Sep 17 00:00:00 2001 From: Lambda Date: Fri, 7 Jun 2024 10:14:05 +0000 Subject: [PATCH] Make tracing filters configurable per backend --- src/config.rs | 30 ++++++++++++--- src/observability.rs | 91 +++++++++++++++++++++++++------------------- 2 files changed, 77 insertions(+), 44 deletions(-) diff --git a/src/config.rs b/src/config.rs index d0eb50d7..9cef6383 100644 --- a/src/config.rs +++ b/src/config.rs @@ -14,7 +14,7 @@ use crate::error; mod env_filter_clone; mod proxy; -use env_filter_clone::EnvFilterClone; +pub(crate) use env_filter_clone::EnvFilterClone; use proxy::ProxyConfig; /// The default configuration file path @@ -180,16 +180,36 @@ pub(crate) struct MetricsConfig { pub(crate) enable: bool, } -#[derive(Clone, Debug, Default, Deserialize)] +#[derive(Debug, Deserialize)] #[serde(default)] pub(crate) struct OtelTraceConfig { pub(crate) enable: bool, + pub(crate) filter: EnvFilterClone, } -#[derive(Clone, Debug, Default, Deserialize)] +impl Default for OtelTraceConfig { + fn default() -> Self { + Self { + enable: false, + filter: default_tracing_filter(), + } + } +} + +#[derive(Debug, Deserialize)] #[serde(default)] pub(crate) struct FlameConfig { pub(crate) enable: bool, + pub(crate) filter: EnvFilterClone, +} + +impl Default for FlameConfig { + fn default() -> Self { + Self { + enable: false, + filter: default_tracing_filter(), + } + } } #[derive(Debug, Deserialize)] @@ -203,7 +223,7 @@ pub(crate) struct LogConfig { impl Default for LogConfig { fn default() -> Self { Self { - filter: default_log(), + filter: default_tracing_filter(), colors: true, format: LogFormat::default(), } @@ -286,7 +306,7 @@ fn default_trusted_servers() -> Vec { vec![OwnedServerName::try_from("matrix.org").unwrap()] } -fn default_log() -> EnvFilterClone { +fn default_tracing_filter() -> EnvFilterClone { "info,ruma_state_res=warn" .parse() .expect("hardcoded env filter should be valid") diff --git a/src/observability.rs b/src/observability.rs index 3b3b1764..ff1a68fc 100644 --- a/src/observability.rs +++ b/src/observability.rs @@ -24,7 +24,7 @@ use tracing_flame::{FlameLayer, FlushGuard}; use tracing_subscriber::{layer::SubscriberExt, EnvFilter, Layer, Registry}; use crate::{ - config::{Config, LogFormat}, + config::{Config, EnvFilterClone, LogFormat}, error, utils::error::Result, }; @@ -84,13 +84,37 @@ pub(crate) enum FoundIn { Nothing, } +/// Wrapper for the creation of a `tracing` [`Layer`] and any associated opaque +/// data. +/// +/// Returns a no-op `None` layer if `enable` is `false`, otherwise calls the +/// given closure to construct the layer and associated data, then applies the +/// filter to the layer. +fn make_backend( + enable: bool, + filter: &EnvFilterClone, + init: impl FnOnce() -> Result<(L, T), error::Observability>, +) -> Result<(impl Layer, Option), error::Observability> +where + L: Layer, + S: tracing::Subscriber + + for<'span> tracing_subscriber::registry::LookupSpan<'span>, +{ + enable + .then(|| { + let (layer, data) = init()?; + Ok((layer.with_filter(EnvFilter::from(filter)), data)) + }) + .transpose() + .map(Option::unzip) +} + /// Initialize observability pub(crate) fn init(config: &Config) -> Result { - let jaeger_layer = config - .observability - .traces - .enable - .then(|| { + let (jaeger_layer, _) = make_backend( + config.observability.traces.enable, + &config.observability.traces.filter, + || { opentelemetry::global::set_text_map_propagator( opentelemetry_jaeger_propagator::Propagator::new(), ); @@ -102,43 +126,32 @@ pub(crate) fn init(config: &Config) -> Result { ) .with_exporter(opentelemetry_otlp::new_exporter().tonic()) .install_batch(opentelemetry_sdk::runtime::Tokio)?; - let telemetry = tracing_opentelemetry::layer().with_tracer(tracer); + Ok((tracing_opentelemetry::layer().with_tracer(tracer), ())) + }, + )?; - Ok::<_, error::Observability>(telemetry.with_filter( - EnvFilter::from(&config.observability.logs.filter), - )) - }) - .transpose()?; - - let (flame_layer, flame_guard) = config - .observability - .flame - .enable - .then(|| { + let (flame_layer, flame_guard) = make_backend( + config.observability.flame.enable, + &config.observability.flame.filter, + || { let (flame_layer, guard) = FlameLayer::with_file("./tracing.folded")?; - let flame_layer = flame_layer.with_empty_samples(false); + Ok((flame_layer.with_empty_samples(false), guard)) + }, + )?; - Ok::<_, error::Observability>(( - flame_layer.with_filter(EnvFilter::from( - &config.observability.logs.filter, - )), - guard, - )) - }) - .transpose()? - .unzip(); - - let fmt_layer = tracing_subscriber::fmt::Layer::new() - .with_ansi(config.observability.logs.colors); - let fmt_layer = match config.observability.logs.format { - LogFormat::Pretty => fmt_layer.pretty().boxed(), - LogFormat::Full => fmt_layer.boxed(), - LogFormat::Compact => fmt_layer.compact().boxed(), - LogFormat::Json => fmt_layer.json().boxed(), - }; - let fmt_layer = fmt_layer - .with_filter(EnvFilter::from(&config.observability.logs.filter)); + let (fmt_layer, _) = + make_backend(true, &config.observability.logs.filter, || { + let fmt_layer = tracing_subscriber::fmt::Layer::new() + .with_ansi(config.observability.logs.colors); + let fmt_layer = match config.observability.logs.format { + LogFormat::Pretty => fmt_layer.pretty().boxed(), + LogFormat::Full => fmt_layer.boxed(), + LogFormat::Compact => fmt_layer.compact().boxed(), + LogFormat::Json => fmt_layer.json().boxed(), + }; + Ok((fmt_layer, ())) + })?; let subscriber = Registry::default() .with(jaeger_layer)