1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
use tracing::span::{Attributes, Record};
use tracing::{Event, Id, Metadata};

pub struct SharedLogger {
    dispatch: tracing::Dispatch,
    tracing_level: tracing::level_filters::LevelFilter,
    #[cfg(feature = "log")]
    logger: &'static dyn log::Log,
    #[cfg(feature = "log")]
    level: log::LevelFilter,
}

pub fn build_shared_logger() -> SharedLogger {
    SharedLogger {
        dispatch: tracing::dispatcher::get_default(|dispatch| dispatch.clone()),
        tracing_level: tracing::level_filters::LevelFilter::current(),
        #[cfg(feature = "log")]
        logger: log::logger(),
        #[cfg(feature = "log")]
        level: log::max_level(),
    }
}
// required to set level hint
// see below
struct FakeSubscriber {
    level: tracing::level_filters::LevelFilter,
}
impl tracing::Subscriber for FakeSubscriber {
    fn max_level_hint(&self) -> Option<tracing::level_filters::LevelFilter> {
        Some(self.level)
    }
    fn enabled(&self, _metadata: &Metadata<'_>) -> bool {
        true
    }

    fn new_span(&self, _span: &Attributes<'_>) -> Id {
        unreachable!()
    }

    fn record(&self, _span: &Id, _values: &Record<'_>) {
        unreachable!()
    }

    fn record_follows_from(&self, _span: &Id, _follows: &Id) {
        unreachable!()
    }

    fn event(&self, _event: &Event<'_>) {
        unreachable!()
    }

    fn enter(&self, _span: &Id) {
        unreachable!()
    }

    fn exit(&self, _span: &Id) {
        todo!()
    }
}

pub fn setup_shared_logger(logger: SharedLogger) {
    // https://github.com/tokio-rs/tracing/issues/2976
    // we want to set the max level hint of the subscriber
    tracing::Dispatch::new(FakeSubscriber {
        level: logger.tracing_level,
    });
    tracing::dispatcher::set_global_default(logger.dispatch).unwrap();
    #[cfg(feature = "log")]
    log::set_logger(logger.logger).unwrap();
    #[cfg(feature = "log")]
    log::set_max_level(logger.level);
}