Skip to content

Commit 8493d96

Browse files
authored
refactor: streamline OTLP configuration and remove dead var (#82)
* chore: bump tracing-opentelemetry and otlp deps to compatible version * refactor: streamline tracing and use env filter * fix: ajj to published version * fix: don't double filter * chore: simplify init a bit
1 parent 10bd8b0 commit 8493d96

File tree

3 files changed

+55
-56
lines changed

3 files changed

+55
-56
lines changed

Cargo.toml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ name = "init4-bin-base"
44
description = "Internal utilities for binaries produced by the init4 team"
55
keywords = ["init4", "bin", "base"]
66

7-
version = "0.13.1"
7+
version = "0.14.0"
88
edition = "2021"
99
rust-version = "1.85"
1010
authors = ["init4", "James Prestwich", "evalir"]
@@ -28,11 +28,11 @@ tracing-core = "0.1.33"
2828
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "json", "registry"] }
2929

3030
# OTLP
31-
opentelemetry_sdk = "0.29.0"
32-
opentelemetry = "0.29.0"
33-
opentelemetry-otlp = "0.29.0"
34-
opentelemetry-semantic-conventions = { version = "0.29.0", features = ["semconv_experimental"] }
35-
tracing-opentelemetry = "0.30.0"
31+
opentelemetry_sdk = "0.30.0"
32+
opentelemetry = "0.30.0"
33+
opentelemetry-otlp = "0.30.0"
34+
opentelemetry-semantic-conventions = { version = "0.30.0", features = ["semconv_experimental"] }
35+
tracing-opentelemetry = "0.31.0"
3636
url = "2.5.4"
3737

3838
# Metrics
@@ -61,7 +61,7 @@ reqwest = { version = "0.12.15", optional = true }
6161
rustls = { version = "0.23.31", optional = true }
6262

6363
[dev-dependencies]
64-
ajj = "0.3.1"
64+
ajj = { version = "0.4.1", features = ["axum", "ws", "ipc"] }
6565
axum = "0.8.1"
6666
eyre = "0.6.12"
6767
serial_test = "3.2.0"

src/utils/otlp.rs

Lines changed: 40 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,15 @@
11
use crate::utils::from_env::{EnvItemInfo, FromEnv, FromEnvErr, FromEnvVar};
22
use opentelemetry::{trace::TracerProvider, KeyValue};
3-
use opentelemetry_sdk::trace::SdkTracerProvider;
4-
use opentelemetry_sdk::Resource;
3+
use opentelemetry_sdk::{trace::SdkTracerProvider, Resource};
54
use opentelemetry_semantic_conventions::{
65
attribute::{DEPLOYMENT_ENVIRONMENT_NAME, SERVICE_NAME, SERVICE_VERSION},
76
SCHEMA_URL,
87
};
9-
use std::time::Duration;
10-
use tracing::level_filters::LevelFilter;
11-
use tracing_subscriber::Layer;
8+
use tracing_subscriber::{EnvFilter, Layer};
129
use url::Url;
1310

1411
const OTEL_ENDPOINT: &str = "OTEL_EXPORTER_OTLP_ENDPOINT";
1512
const OTEL_LEVEL: &str = "OTEL_LEVEL";
16-
const OTEL_TIMEOUT: &str = "OTEL_TIMEOUT";
1713
const OTEL_ENVIRONMENT: &str = "OTEL_ENVIRONMENT_NAME";
1814

1915
/// Drop guard for the Otel provider. This will shutdown the provider when
@@ -33,7 +29,7 @@ const OTEL_ENVIRONMENT: &str = "OTEL_ENVIRONMENT_NAME";
3329
/// # }
3430
/// ```
3531
#[derive(Debug)]
36-
pub struct OtelGuard(SdkTracerProvider, tracing::Level);
32+
pub struct OtelGuard(SdkTracerProvider, EnvFilter);
3733

3834
impl OtelGuard {
3935
/// Get a tracer from the provider.
@@ -49,7 +45,7 @@ impl OtelGuard {
4945
let tracer = self.tracer("tracing-otel-subscriber");
5046
tracing_opentelemetry::layer()
5147
.with_tracer(tracer)
52-
.with_filter(LevelFilter::from_level(self.1))
48+
.with_filter(self.1.clone())
5349
}
5450
}
5551

@@ -68,7 +64,7 @@ impl Drop for OtelGuard {
6864
/// should be some valid URL. If not specified, then [`OtelConfig::load`]
6965
/// will return [`None`].
7066
/// - OTEL_LEVEL - optional. Specifies the minimum [`tracing::Level`] to
71-
/// export. Defaults to [`tracing::Level::DEBUG`].
67+
/// export in the [`EnvFilter`] format. Defaults to [`tracing::Level::DEBUG`].
7268
/// - OTEL_TIMEOUT - optional. Specifies the timeout for the exporter in
7369
/// **milliseconds**. Defaults to 1000ms, which is equivalent to 1 second.
7470
/// - OTEL_ENVIRONMENT_NAME - optional. Value for the `deployment.environment.
@@ -81,10 +77,7 @@ pub struct OtelConfig {
8177
pub endpoint: Url,
8278

8379
/// Defaults to DEBUG.
84-
pub level: tracing::Level,
85-
86-
/// Defaults to 1 second. Specified in Milliseconds.
87-
pub timeout: Duration,
80+
pub level: EnvFilter,
8881

8982
/// OTEL convenition `deployment.environment.name`
9083
pub environment: String,
@@ -103,12 +96,7 @@ impl FromEnv for OtelConfig {
10396
},
10497
&EnvItemInfo {
10598
var: OTEL_LEVEL,
106-
description: "OTLP level to export, defaults to DEBUG. Permissible values are: TRACE, DEBUG, INFO, WARN, ERROR, OFF",
107-
optional: true,
108-
},
109-
&EnvItemInfo {
110-
var: OTEL_TIMEOUT,
111-
description: "OTLP timeout in milliseconds",
99+
description: "OTLP level to export. Follows the RUST_LOG env filter format. e.g. `OTEL_LEVEL=warn,my_crate=info`. Defaults to the value of `RUST_LOG` if not present.",
112100
optional: true,
113101
},
114102
&EnvItemInfo {
@@ -123,16 +111,22 @@ impl FromEnv for OtelConfig {
123111
// load endpoint from env. ignore empty values (shortcut return None), parse, and print the error if any using inspect_err
124112
let endpoint = Url::from_env_var(OTEL_ENDPOINT)?;
125113

126-
let level = tracing::Level::from_env_var(OTEL_LEVEL).unwrap_or(tracing::Level::DEBUG);
127-
128-
let timeout = Duration::from_env_var(OTEL_TIMEOUT).unwrap_or(Duration::from_millis(1000));
114+
let level = if std::env::var(OTEL_LEVEL)
115+
.as_ref()
116+
.map(String::len)
117+
.unwrap_or_default()
118+
> 0
119+
{
120+
EnvFilter::from_env(OTEL_LEVEL)
121+
} else {
122+
EnvFilter::from_default_env()
123+
};
129124

130125
let environment = String::from_env_var(OTEL_ENVIRONMENT).unwrap_or("unknown".into());
131126

132127
Ok(Self {
133128
endpoint,
134129
level,
135-
timeout,
136130
environment,
137131
})
138132
}
@@ -184,7 +178,19 @@ impl OtelConfig {
184178
.with_batch_exporter(exporter)
185179
.build();
186180

187-
OtelGuard(provider, self.level)
181+
OtelGuard(provider, self.level.clone())
182+
}
183+
184+
/// Create a new Otel provider, returning both the guard and a tracing
185+
/// layer that can be added to a subscriber.
186+
///
187+
pub fn into_guard_and_layer<S>(self) -> (OtelGuard, impl Layer<S>)
188+
where
189+
S: tracing::Subscriber + for<'span> tracing_subscriber::registry::LookupSpan<'span>,
190+
{
191+
let guard = self.provider();
192+
let layer = guard.layer();
193+
(guard, layer)
188194
}
189195
}
190196

@@ -197,7 +203,6 @@ mod test {
197203
fn clear_env() {
198204
std::env::remove_var(OTEL_ENDPOINT);
199205
std::env::remove_var(OTEL_LEVEL);
200-
std::env::remove_var(OTEL_TIMEOUT);
201206
std::env::remove_var(OTEL_ENVIRONMENT);
202207
}
203208

@@ -215,11 +220,14 @@ mod test {
215220
fn test_env_read() {
216221
run_clear_env(|| {
217222
std::env::set_var(OTEL_ENDPOINT, URL);
223+
std::env::set_var(OTEL_LEVEL, "debug");
218224

219225
let cfg = OtelConfig::load().unwrap();
220226
assert_eq!(cfg.endpoint, URL.parse().unwrap());
221-
assert_eq!(cfg.level, tracing::Level::DEBUG);
222-
assert_eq!(cfg.timeout, std::time::Duration::from_millis(1000));
227+
assert_eq!(
228+
cfg.level.max_level_hint(),
229+
Some(tracing::Level::DEBUG.into())
230+
);
223231
assert_eq!(cfg.environment, "unknown");
224232
})
225233
}
@@ -229,22 +237,13 @@ mod test {
229237
fn test_env_read_level() {
230238
run_clear_env(|| {
231239
std::env::set_var(OTEL_ENDPOINT, URL);
232-
std::env::set_var(OTEL_LEVEL, "WARN");
233-
234-
let cfg = OtelConfig::load().unwrap();
235-
assert_eq!(cfg.level, tracing::Level::WARN);
236-
})
237-
}
238-
239-
#[test]
240-
#[serial_test::serial]
241-
fn test_env_read_timeout() {
242-
run_clear_env(|| {
243-
std::env::set_var(OTEL_ENDPOINT, URL);
244-
std::env::set_var(OTEL_TIMEOUT, "500");
240+
std::env::set_var(OTEL_LEVEL, "warn,my_app=info");
245241

246242
let cfg = OtelConfig::load().unwrap();
247-
assert_eq!(cfg.timeout, std::time::Duration::from_millis(500));
243+
let s = cfg.level.to_string();
244+
let iter = s.split(",");
245+
assert!(iter.clone().any(|x| x == "warn"));
246+
assert!(iter.clone().any(|x| x == "my_app=info"));
248247
})
249248
}
250249

src/utils/tracing.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,12 @@ macro_rules! install_fmt {
1818
let fmt = tracing_subscriber::fmt::layer().with_filter($filter);
1919
$registry.with(fmt).init();
2020
}};
21-
($registry:ident) => {{
21+
($registry:ident, $filter:ident) => {{
2222
let json = bool::from_env_var(TRACING_LOG_JSON).unwrap_or(false);
23-
let filter = EnvFilter::from_default_env();
2423
if json {
25-
install_fmt!(json @ $registry, filter);
24+
install_fmt!(json @ $registry, $filter);
2625
} else {
27-
install_fmt!(log @ $registry, filter);
26+
install_fmt!(log @ $registry, $filter);
2827
}
2928
}};
3029
}
@@ -48,14 +47,15 @@ macro_rules! install_fmt {
4847
/// [`OtelConfig`]: crate::utils::otlp::OtelConfig
4948
pub fn init_tracing() -> Option<OtelGuard> {
5049
let registry = tracing_subscriber::registry();
50+
let filter = EnvFilter::from_default_env();
5151

5252
if let Some(cfg) = OtelConfig::load() {
53-
let guard = cfg.provider();
54-
let registry = registry.with(guard.layer());
55-
install_fmt!(registry);
53+
let (guard, layer) = cfg.into_guard_and_layer();
54+
let registry = registry.with(layer);
55+
install_fmt!(registry, filter);
5656
Some(guard)
5757
} else {
58-
install_fmt!(registry);
58+
install_fmt!(registry, filter);
5959
tracing::debug!(
6060
"No OTEL config found or error while loading otel config, using default tracing"
6161
);

0 commit comments

Comments
 (0)