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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
//! # Logger with smart widget for the `tui` and `ratatui` crate
//!
//! [](https://deps.rs/repo/github/gin66/tui-logger)
//! 
//!
//!
//! ## Demo of the widget
//!
//! 
//!
//! ## Documentation
//!
//! [Documentation](https://docs.rs/tui-logger/latest/tui_logger/)
//!
//! I have stumbled over an excellent AI-generated description of `tui-logger`, which provides surprisingly deep and (mostly) correct implementation details.
//! It would have costed me many days to write an equally good description with so many details and diagrams.
//! This docu can be found [here](https://deepwiki.com/gin66/tui-logger).
//!
//! ## Important note for `tui`
//!
//! The `tui` crate has been archived and `ratatui` has taken over.
//! In order to avoid supporting compatibility for an inactive crate,
//! the v0.9.x releases are the last to support `tui`. In case future bug fixes
//! are needed, the branch `tui_legacy` has been created to track changes to 0.9.x releases.
//!
//! Starting with v0.10 `tui-logger` is `ratatui` only.
//!
//! ## Features
//!
//! - [X] Logger implementation for the `log` crate
//! - [X] Logger enable/disable detection via hash table (avoid string compare)
//! - [X] Hot logger code only copies enabled log messages with timestamp into a circular buffer
//! - [X] Widgets/move_message() retrieve captured log messages from hot circular buffer
//! - [X] Lost message detection due to circular buffer
//! - [X] Log filtering performed on log record target
//! - [X] Simple Widgets to view logs and configure debuglevel per target
//! - [X] Logging of enabled logs to file
//! - [X] Scrollback in log history
//! - [x] Title of target and log pane can be configured
//! - [X] `slog` support, providing a Drain to integrate into your `slog` infrastructure
//! - [X] `tracing` support
//! - [X] Support to use custom formatter for log events
//! - [X] Configurable by environment variables
//! - [ ] Allow configuration of target dependent loglevel specifically for file logging
//! - [X] Avoid duplicating of module_path and filename in every log record
//! - [ ] Simultaneous modification of all targets' display/hot logging loglevel by key command
//!
//! ## Smart Widget
//!
//! Smart widget consists of two widgets. Left is the target selector widget and
//! on the right side the logging messages view scrolling up. The target selector widget
//! can be hidden/shown during runtime via key command.
//! The key command to be provided to the TuiLoggerWidget via transition() function.
//!
//! The target selector widget looks like this:
//!
//! 
//!
//! It controls:
//!
//! - Capturing of log messages by the logger
//! - Selection of levels for display in the logging message view
//!
//! The two columns have the following meaning:
//!
//! - Code EWIDT: E stands for Error, W for Warn, Info, Debug and Trace.
//! + Inverted characters (EWIDT) are enabled log levels in the view
//! + Normal characters show enabled capturing of a log level per target
//! + If any of EWIDT are not shown, then the respective log level is not captured
//! - Target of the log events can be defined in the log e.g. `warn!(target: "demo", "Log message");`
//!
//! ## Smart Widget Key Commands
//! ```ignore
//! | KEY | ACTION
//! |----------|-----------------------------------------------------------|
//! | h | Toggles target selector widget hidden/visible
//! | f | Toggle focus on the selected target only
//! | UP | Select previous target in target selector widget
//! | DOWN | Select next target in target selector widget
//! | LEFT | Reduce SHOWN (!) log messages by one level
//! | RIGHT | Increase SHOWN (!) log messages by one level
//! | - | Reduce CAPTURED (!) log messages by one level
//! | + | Increase CAPTURED (!) log messages by one level
//! | PAGEUP | Enter Page Mode and scroll approx. half page up in log history.
//! | PAGEDOWN | Only in page mode: scroll 10 events down in log history.
//! | ESCAPE | Exit page mode and go back to scrolling mode
//! | SPACE | Toggles hiding of targets, which have logfilter set to off
//! ```
//!
//! The mapping of key to action has to be done in the application. The respective TuiWidgetEvent
//! has to be provided to TuiWidgetState::transition().
//!
//! Remark to the page mode: The timestamp of the event at event history's bottom line is used as
//! reference. This means, changing the filters in the EWIDT/focus from the target selector window
//! should work as expected without jumps in the history. The page next/forward advances as
//! per visibility of the events.
//!
//! ## Basic usage to initialize logger-system:
//! ```rust
//! #[macro_use]
//! extern crate log;
//! //use tui_logger;
//!
//! fn main() {
//! // Early initialization of the logger
//!
//! // Set max_log_level to Trace
//! tui_logger::init_logger(log::LevelFilter::Trace).unwrap();
//!
//! // Set default level for unknown targets to Trace
//! tui_logger::set_default_level(log::LevelFilter::Trace);
//!
//! // code....
//! }
//! ```
//!
//! For use of the widget please check examples/demo.rs
//!
//! ## Demo
//!
//! Run demo using termion:
//!
//! ```ignore
//! cargo run --example demo --features termion
//! ```
//!
//! Run demo with crossterm:
//!
//! ```ignore
//! cargo run --example demo --features crossterm
//! ```
//!
//! Run demo using termion and simple custom formatter in bottom right log widget:
//!
//! ```ignore
//! cargo run --example demo --features termion,formatter
//! ```
//!
//! ## Configuration by environment variables
//!
//! `tui.logger` uses `env-filter` crate to support configuration by a string or an environment variable.
//! This is an opt-in by call to one of these two functions.
//! ```rust
//! pub fn set_env_filter_from_string(filterstring: &str) {}
//! pub fn set_env_filter_from_env(env_name: Option<&str>) {}
//! ```
//! Default environment variable name is `RUST_LOG`.
//!
//! ## `slog` support
//!
//! `tui-logger` provides a [`TuiSlogDrain`] which implements `slog::Drain` and will route all records
//! it receives to the `tui-logger` widget.
//!
//! Enabled by feature "slog-support"
//!
//! ## `tracing-subscriber` support
//!
//! `tui-logger` provides a [`TuiTracingSubscriberLayer`] which implements
//! `tracing_subscriber::Layer` and will collect all events
//! it receives to the `tui-logger` widget
//!
//! Enabled by feature "tracing-support"
//!
//! ## Custom filtering
//! ```rust
//! #[macro_use]
//! extern crate log;
//! //use tui_logger;
//! use env_logger;
//!
//! fn main() {
//! // Early initialization of the logger
//! let drain = tui_logger::Drain::new();
//! // instead of tui_logger::init_logger, we use `env_logger`
//! env_logger::Builder::default()
//! .format(move |buf, record|
//! // patch the env-logger entry through our drain to the tui-logger
//! Ok(drain.log(record))
//! ).init(); // make this the global logger
//! // code....
//! }
//! ```
//!
//! ## Custom formatting
//!
//! For experts only ! Configure along the lines:
//! ```ignore
//! use tui_logger::LogFormatter;
//!
//! let formatter = MyLogFormatter();
//!
//! TuiLoggerWidget::default()
//! .block(Block::bordered().title("Filtered TuiLoggerWidget"))
//! .formatter(formatter)
//! .state(&filter_state)
//! .render(left, buf);
//! ```
//! The example demo can be invoked to use a custom formatter as example for the bottom right widget.
//!
// Enable docsrs doc_cfg - to display non-default feature documentation.
extern crate lazy_static;
pub use env_filter;
pub use crateCircularBuffer;
pub use crateTuiSlogDrain;
pub use crateTuiTracingSubscriberLayer;
pub use LevelFilter;
pub use TuiWidgetEvent;
pub use TuiWidgetState;
pub use LogFormatter;
pub use TuiLoggerSmartWidget;
pub use TuiLoggerWidget;
pub use TuiLoggerTargetWidget;
pub use LevelConfig;
pub use TuiLoggerFile;
pub use crate*;
pub use crateExtLogRecord;
pub use crateTuiLoggerLevelOutput;
use crate*;