1use log::LevelFilter as LogLevelFilter;
2use std::io;
3use std::io::Stdout;
4use tracing::info;
5use tracing_subscriber::filter::LevelFilter as TracingLevelFilter;
6use tracing_subscriber::fmt::format::{DefaultFields, Format};
7use tracing_subscriber::layer::SubscriberExt;
8use tracing_subscriber::reload::Handle;
9use tracing_subscriber::{Layer, Registry, fmt};
10use tui_logger::TuiTracingSubscriberLayer;
11
12#[derive(Debug)]
14pub struct LogSwitcher {
15 level: TracingLevelFilter,
16 handle: Handle<
17 tracing_subscriber::filter::Filtered<
18 tracing_subscriber::fmt::Layer<Registry, DefaultFields, Format, fn() -> Stdout>,
19 TracingLevelFilter,
20 Registry,
21 >,
22 Registry,
23 >,
24}
25impl LogSwitcher {
26 pub(crate) fn initialize(tracing_level_filter: TracingLevelFilter) -> Self {
33 let log_level_filter = Self::convert_level(tracing_level_filter);
34
35 let stdout_layer = fmt::layer()
37 .with_writer(io::stdout as fn() -> Stdout)
38 .with_target(true)
39 .with_filter(tracing_level_filter);
40 let (reload_layer, reload_handle) = tracing_subscriber::reload::Layer::new(stdout_layer);
41
42 let subscriber = Registry::default()
43 .with(reload_layer)
44 .with(TuiTracingSubscriberLayer.with_filter(tracing_level_filter));
45
46 tracing::subscriber::set_global_default(subscriber)
47 .expect("Failed to set global subscriber");
48
49 tui_logger::init_logger(log_level_filter).expect("Fails to init TUI logger");
50 tui_logger::set_default_level(log_level_filter);
51 tui_logger::set_level_for_target("mio::poll", LogLevelFilter::Warn);
52
53 info!("Logging initialized");
54 Self {
55 level: tracing_level_filter,
56 handle: reload_handle,
57 }
58 }
59 pub(crate) fn toggle_stdout_logging(&self, enable_stdout: bool) {
60 let new_filter = if enable_stdout {
61 self.level
62 } else {
63 TracingLevelFilter::OFF
64 };
65
66 self.handle
67 .modify(|layer| {
68 *layer.filter_mut() = new_filter;
69 })
70 .expect("Failed to modify layer");
71
72 info!(
73 "Env logging {}",
74 if enable_stdout { "enabled" } else { "disabled" }
75 );
76 }
77 fn convert_level(level: TracingLevelFilter) -> LogLevelFilter {
78 match level {
79 TracingLevelFilter::OFF => log::LevelFilter::Off,
80 TracingLevelFilter::ERROR => log::LevelFilter::Error,
81 TracingLevelFilter::WARN => log::LevelFilter::Warn,
82 TracingLevelFilter::INFO => log::LevelFilter::Info,
83 TracingLevelFilter::DEBUG => log::LevelFilter::Debug,
84 TracingLevelFilter::TRACE => log::LevelFilter::Trace,
85 }
86 }
87}