Skip to main content

hotshot/
helpers.rs

1use tracing_subscriber::{
2    EnvFilter, Layer, Registry, fmt::format::FmtSpan, layer::SubscriberExt, util::SubscriberInitExt,
3};
4
5/// A type-erased fmt layer attached over a `Registry`. The OTel bridge layer
6/// wraps a subscriber of type `Layered<ErasedFmtLayer, Registry>`.
7pub type ErasedFmtLayer = Box<dyn Layer<Registry> + Send + Sync + 'static>;
8
9/// Composed subscriber type after the fmt layer is applied. Callers building
10/// an OTel layer for `initialize_logging_with` should target this subscriber.
11pub type FmtSubscriber = tracing_subscriber::layer::Layered<ErasedFmtLayer, Registry>;
12
13/// Initializes logging
14pub fn initialize_logging() {
15    let stderr = stderr_layer();
16    Registry::default().with(stderr).init();
17}
18
19/// Initializes logging with an optional extra `Layer` (e.g. an OTel bridge).
20///
21/// The extra layer must implement `Layer<FmtSubscriber>`. A polymorphic layer
22/// like `OpenTelemetryTracingBridge` satisfies this naturally.
23pub fn initialize_logging_with<L>(extra: Option<L>)
24where
25    L: Layer<FmtSubscriber> + Send + Sync + 'static,
26{
27    let stderr = stderr_layer();
28    Registry::default().with(stderr).with(extra).init();
29}
30
31fn stderr_layer() -> ErasedFmtLayer {
32    let span_event_filter = parse_span_filter();
33    let json_mode = std::env::var("RUST_LOG_FORMAT") == Ok("json".to_string());
34    if json_mode {
35        tracing_subscriber::fmt::layer()
36            .json()
37            .with_span_events(span_event_filter)
38            .with_filter(EnvFilter::from_default_env())
39            .boxed()
40    } else {
41        tracing_subscriber::fmt::layer()
42            .with_span_events(span_event_filter)
43            .with_filter(EnvFilter::from_default_env())
44            .boxed()
45    }
46}
47
48fn parse_span_filter() -> FmtSpan {
49    match std::env::var("RUST_LOG_SPAN_EVENTS") {
50        Ok(val) => val
51            .split(',')
52            .map(|s| match s.trim() {
53                "new" => FmtSpan::NEW,
54                "enter" => FmtSpan::ENTER,
55                "exit" => FmtSpan::EXIT,
56                "close" => FmtSpan::CLOSE,
57                "active" => FmtSpan::ACTIVE,
58                "full" => FmtSpan::FULL,
59                _ => FmtSpan::NONE,
60            })
61            .fold(FmtSpan::NONE, |acc, x| acc | x),
62        Err(_) => FmtSpan::NONE,
63    }
64}