1use lazy_static::lazy_static;
4use std::cmp::Ord;
5use std::collections::VecDeque;
6use std::str::FromStr;
7use std::sync::{Mutex, RwLock};
8
9pub struct CursiveLogger;
34
35lazy_static! {
36 pub static ref LOGS: Mutex<VecDeque<Record>> =
40 Mutex::new(VecDeque::with_capacity(1_000));
41
42 static ref INT_FILTER_LEVEL: RwLock<log::LevelFilter> = RwLock::new(log::LevelFilter::Trace);
44 static ref EXT_FILTER_LEVEL: RwLock<log::LevelFilter> = RwLock::new(log::LevelFilter::Trace);
46}
47
48pub fn set_internal_filter_level(level: log::LevelFilter) {
50 *INT_FILTER_LEVEL.write().unwrap() = level;
51}
52
53pub fn set_external_filter_level(level: log::LevelFilter) {
55 *EXT_FILTER_LEVEL.write().unwrap() = level;
56}
57
58pub fn set_filter_levels_from_env() {
63 if let Ok(rust_log) = std::env::var("RUST_LOG") {
64 match log::LevelFilter::from_str(&rust_log) {
65 Ok(filter_level) => {
66 set_internal_filter_level(filter_level);
67 set_external_filter_level(filter_level);
68 }
69 Err(e) => log::warn!("Could not parse RUST_LOG: {}", e),
70 }
71 }
72 if let Ok(cursive_log) = std::env::var("CURSIVE_LOG") {
73 match log::LevelFilter::from_str(&cursive_log) {
74 Ok(filter_level) => {
75 set_internal_filter_level(filter_level);
76 }
77 Err(e) => log::warn!("Could not parse CURSIVE_LOG: {}", e),
78 }
79 }
80}
81
82pub struct Record {
84 pub level: log::Level,
86 pub time: time::OffsetDateTime,
88 pub message: String,
90}
91
92pub fn log(record: &log::Record) {
94 let mut logs = LOGS.lock().unwrap();
95 if logs.len() == logs.capacity() {
97 logs.pop_front();
98 }
99 logs.push_back(Record {
100 level: record.level(),
101 message: format!("{}", record.args()),
102 time: time::OffsetDateTime::now_local().unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
103 });
104}
105
106impl log::Log for CursiveLogger {
107 fn enabled(&self, metadata: &log::Metadata) -> bool {
108 if metadata.target().starts_with("cursive_core::") {
109 metadata.level() <= *INT_FILTER_LEVEL.read().unwrap()
110 } else {
111 metadata.level() <= *EXT_FILTER_LEVEL.read().unwrap()
112 }
113 }
114
115 fn log(&self, record: &log::Record) {
116 if self.enabled(record.metadata()) {
117 log(record);
118 }
119 }
120
121 fn flush(&self) {}
122}
123
124pub fn init() {
131 log::set_max_level((*INT_FILTER_LEVEL.read().unwrap()).max(*EXT_FILTER_LEVEL.read().unwrap()));
132 log::set_logger(&CursiveLogger).unwrap();
134}
135
136pub fn get_logger() -> CursiveLogger {
142 CursiveLogger
143}
144
145pub fn reserve_logs(n: usize) {
149 LOGS.lock().unwrap().reserve(n);
150}