logging_subscriber/
lib.rs1use std::sync::{Arc, Mutex, MutexGuard, PoisonError};
2
3use console::{Style, StyledObject};
4use lazy_static::lazy_static;
5use tracing_subscriber::filter::LevelFilter;
6
7mod logging_subscriber;
8mod logging_writer;
9mod prelude;
10mod test;
11
12lazy_static! {
13 pub static ref LOGGING_WRITER: Arc<Mutex<LoggingWriter>> = Arc::new(Mutex::new(LoggingWriter::default()));
14}
15
16#[derive(Debug, Clone, Default)]
17pub(crate) struct BlockingWriter {}
18
19#[derive(Debug)]
20#[allow(dead_code)]
21pub struct LoggingWriter {
22 pub(crate) enabled: bool,
23 pub(crate) level: tracing::metadata::LevelFilter,
24
25 default_style: Style,
26
27 date_time_style: Style,
28
29 style_error: Option<Style>,
30 style_warn: Option<Style>,
31 style_debug: Option<Style>,
32 style_trace: Option<Style>,
33 style_info: Option<Style>,
34
35 level_style_error: Style,
36 level_style_warn: Style,
37 level_style_debug: Style,
38 level_style_trace: Style,
39 level_style_info: Style,
40
41 separator: String,
42 timestamp_format: String,
43 format_level: LevelOutput,
44
45 display_line_number: bool,
46 display_level: bool,
47 display_target: bool,
48 display_filename: bool,
49 display_time: bool,
50}
51
52#[derive(Debug, Clone, Copy)]
53#[allow(dead_code)]
54pub enum LevelOutput {
55 Abbreviated,
56 Long,
57 None,
58}
59
60#[derive(Debug, Clone)]
61pub struct LoggingSubscriberLayer;
62
63#[derive(Debug, Clone)]
64pub struct LoggingSubscriberBuilder {
65 pub display_line_number: bool,
66 pub display_level: bool,
67 pub display_time: bool,
68 pub display_target: bool,
69 pub display_filename: bool,
70
71 default_style: Style,
72 date_time_style: Style,
73
74 level_style_error: Style,
75 level_style_warn: Style,
76 level_style_debug: Style,
77 level_style_trace: Style,
78 level_style_info: Style,
79
80 style_error: Option<Style>,
81 style_warn: Option<Style>,
82 style_info: Option<Style>,
83 style_debug: Option<Style>,
84 style_trace: Option<Style>,
85
86 min_level: tracing::metadata::LevelFilter,
87 separator: String,
88 timestamp_format: String,
89 format_level: LevelOutput,
90}
91
92#[derive(Debug, Default, Clone)]
93pub struct AdaptiveStyle {
94 pub(crate) light: console::Style,
95 pub(crate) dark: console::Style,
96}
97
98impl AdaptiveStyle {
99 pub fn new(light: console::Style, dark: console::Style) -> Self {
100 AdaptiveStyle { light, dark }
101 }
102
103 pub fn from(style: console::Style) -> Self {
104 AdaptiveStyle {
105 light: style.clone(),
106 dark: style.clone(),
107 }
108 }
109
110 fn is_dark_background() -> bool {
111 terminal_light::luma().map_or(false, |luma| luma <= 0.5)
112 }
113
114 #[must_use]
115 pub fn paint<D>(&self, val: D) -> StyledObject<D> {
116 if AdaptiveStyle::is_dark_background() {
117 self.dark.apply_to(val)
118 } else {
119 self.dark.apply_to(val)
120 }
121 }
122}
123
124impl From<Style> for AdaptiveStyle {
125 fn from(value: console::Style) -> Self {
126 AdaptiveStyle::from(value)
127 }
128}
129
130impl From<AdaptiveStyle> for console::Style {
131 fn from(value: AdaptiveStyle) -> Self {
132 let dark_theme = terminal_light::luma().map_or(false, |luma| luma <= 0.5);
133 if dark_theme {
134 value.dark
135 } else {
136 value.light
137 }
138 }
139}
140
141#[allow(dead_code)]
142pub fn set_enabled(value: bool) -> Result<(), PoisonError<MutexGuard<'static, LoggingWriter>>> {
143 match LOGGING_WRITER.lock() {
144 Ok(mut item) => {
145 item.enabled = value;
146 Ok(())
147 }
148 Err(err) => Err(err),
149 }
150}
151
152pub fn is_enabled() -> Result<bool, PoisonError<MutexGuard<'static, LoggingWriter>>> {
154 match LOGGING_WRITER.lock() {
155 Ok(item) => Ok(item.enabled),
156 Err(err) => Err(err),
157 }
158}
159
160#[allow(dead_code)]
161pub fn set_level(value: LevelFilter) -> Result<(), PoisonError<MutexGuard<'static, LoggingWriter>>> {
162 match LOGGING_WRITER.lock() {
163 Ok(mut item) => {
164 item.level = value;
165 Ok(())
166 }
167 Err(err) => Err(err),
168 }
169}