1use std::thread;
2#[cfg(feature = "waiter")]
3use std::time::Duration;
4
5use crate::logger::fast_hash::fast_str_hash;
6use crate::CircularBuffer;
7use crate::TuiLoggerFile;
8use log::LevelFilter;
9use log::Record;
10use log::SetLoggerError;
11
12use crate::TUI_LOGGER;
13
14#[derive(Debug)]
16pub enum TuiLoggerError {
17 SetLoggerError(SetLoggerError),
18 ThreadError(std::io::Error),
19}
20impl std::error::Error for TuiLoggerError {
21 fn description(&self) -> &str {
22 match self {
23 TuiLoggerError::SetLoggerError(_) => "SetLoggerError",
24 TuiLoggerError::ThreadError(_) => "ThreadError",
25 }
26 }
27 fn cause(&self) -> Option<&dyn std::error::Error> {
28 match self {
29 TuiLoggerError::SetLoggerError(_) => None,
30 TuiLoggerError::ThreadError(err) => Some(err),
31 }
32 }
33}
34impl std::fmt::Display for TuiLoggerError {
35 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
36 match self {
37 TuiLoggerError::SetLoggerError(err) => write!(f, "SetLoggerError({})", err),
38 TuiLoggerError::ThreadError(err) => write!(f, "ThreadError({})", err),
39 }
40 }
41}
42
43pub fn init_logger(max_level: LevelFilter) -> Result<(), TuiLoggerError> {
45 let join_handle = thread::Builder::new()
46 .name("tui-logger::move_events".into())
47 .spawn(|| {
48 let duration = std::time::Duration::from_millis(10);
49 loop {
50 thread::park_timeout(duration);
51 TUI_LOGGER.move_events();
52 }
53 })
54 .map_err(TuiLoggerError::ThreadError)?;
55 TUI_LOGGER.hot_log.lock().mover_thread = Some(join_handle);
56 if cfg!(feature = "tracing-support") {
57 set_default_level(max_level);
58 Ok(())
59 } else {
60 log::set_max_level(max_level);
61 log::set_logger(&*TUI_LOGGER).map_err(TuiLoggerError::SetLoggerError)
62 }
63}
64
65pub fn set_hot_buffer_depth(depth: usize) {
68 TUI_LOGGER.inner.lock().hot_depth = depth;
69}
70
71pub fn set_buffer_depth(depth: usize) {
74 TUI_LOGGER.inner.lock().events = CircularBuffer::new(depth);
75}
76
77pub fn set_log_file(file_options: TuiLoggerFile) {
79 TUI_LOGGER.inner.lock().dump = Some(file_options);
80}
81
82pub fn set_default_level(levelfilter: LevelFilter) {
84 TUI_LOGGER.hot_select.lock().default = levelfilter;
85 TUI_LOGGER.inner.lock().default = levelfilter;
86}
87
88pub fn remove_env_filter() {
90 TUI_LOGGER.hot_select.lock().filter = None;
91 TUI_LOGGER.inner.lock().filter = None;
92}
93
94fn set_env_filter(filter1: env_filter::Filter, filter2: env_filter::Filter) {
95 TUI_LOGGER.hot_select.lock().filter = Some(filter1);
98 TUI_LOGGER.inner.lock().filter = Some(filter2);
99}
100
101pub fn set_env_filter_from_string(filterstring: &str) {
103 let mut builder1 = env_filter::Builder::new();
104 let mut builder2 = env_filter::Builder::new();
105
106 builder1.parse(filterstring);
107 builder2.parse(filterstring);
108
109 set_env_filter(builder1.build(), builder2.build());
110}
111
112pub fn set_env_filter_from_env(env_name: Option<&str>) {
114 let mut builder1 = env_filter::Builder::new();
115 let mut builder2 = env_filter::Builder::new();
116
117 if let Ok(ref filter) = std::env::var(env_name.unwrap_or("RUST_LOG")) {
119 builder1.parse(filter);
120 builder2.parse(filter);
121
122 set_env_filter(builder1.build(), builder2.build());
123 }
124}
125
126pub fn set_level_for_target(target: &str, levelfilter: LevelFilter) {
128 let h = fast_str_hash(target);
129 TUI_LOGGER.inner.lock().targets.set(target, levelfilter);
130 let mut hs = TUI_LOGGER.hot_select.lock();
131 hs.hashtable.insert(h, levelfilter);
132}
133
134pub fn move_events() {
136 TUI_LOGGER.move_events();
137}
138
139#[cfg(feature = "waiter")]
144#[cfg_attr(docsrs, doc(cfg(feature = "waiter")))]
145pub fn wait() -> u64 {
146 TUI_LOGGER.waiter.wait()
147}
148
149#[cfg(feature = "waiter")]
156#[cfg_attr(docsrs, doc(cfg(feature = "waiter")))]
157pub fn wait_timeout(timeout: Duration) -> Option<u64> {
158 TUI_LOGGER.waiter.wait_timeout(timeout)
159}
160
161#[derive(Default)]
163pub struct Drain;
164
165impl Drain {
166 pub fn new() -> Self {
168 Drain
169 }
170 pub fn log(&self, record: &Record) {
172 TUI_LOGGER.raw_log(record)
173 }
174}