synthphonia/
log.rs

1use std::cell::RefCell;
2use std::cell::Cell;
3
4
5thread_local! {
6    pub static LOGLEVEL: Cell<u8>  = const { Cell::new(2) };
7}
8thread_local! {
9    pub static INDENT: RefCell<String> = RefCell::new(String::from(""));
10}
11
12/// Sets the logging level for the application. 
13/// 
14/// This adjusts the verbosity of the log output by setting the specified logging level within a thread-local variable. 
15/// The function modifies the global logging behavior based on the provided level, influencing which log messages are output according to their priority.
16/// 
17pub fn set_log_level(level: u8) {
18    LOGLEVEL.set(level);
19}
20/// Returns the current logging level as an unsigned 8-bit integer. 
21/// 
22/// This function retrieves the logging level by accessing a globally maintained `LOGLEVEL` value using its `get` method. 
23/// The logging level is likely set elsewhere in the program, potentially allowing different components to conditionally alter their logging verbosity based on this value.
24/// 
25pub fn log_level() -> u8 {
26    LOGLEVEL.get()
27}
28
29/// Increases the current indentation level by adding two spaces. 
30/// This function accesses a thread-local string variable to modify its content by appending two spaces, effectively augmenting the indentation for subsequent operations that rely on this thread-local state.
31pub fn indent() {
32    INDENT.with_borrow_mut(|s| {
33        s.push_str("  ");
34    })
35}
36
37/// Reduces the indentation level by two steps. 
38/// 
39/// This function modifies a thread-local mutable state, specifically adjusting a global `INDENT` string to reflect a reduction in indentation by removing the last two characters. 
40/// This is likely used in contexts where indentation levels are dynamically adjusted, such as generating or formatting text outputs where the indentation signifies scope or hierarchy.
41/// 
42pub fn dedent() {
43    INDENT.with_borrow_mut(|s| { s.pop(); s.pop() } );
44}
45
46
47#[macro_export]
48/// Expands a logging macro for outputting informational messages. 
49/// 
50/// It checks the current log level, and if it's set to 3 or higher, it processes the provided format arguments to display a message prefixed with "INFO". 
51/// This message includes the current indentation level, styled with specific ANSI escape codes for color formatting, and appends the file name and line number from where the log was called. 
52/// The macro ensures that informational messages are logged consistently across the module whenever the appropriate log level is set.
53/// 
54macro_rules! info {
55    ($($fmt:expr),+) => {
56        if $crate::log::LOGLEVEL.get() >= 3 {
57            $crate::log::INDENT.with_borrow(|s| {
58                eprintln!("{}\u{001b}[34;1m\u{001b}[1mINFO\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($($fmt),+), file!(), line!())
59            })
60        }
61    };
62}
63
64#[macro_export]
65/// A macro for custom debug logging. 
66/// 
67/// This macro checks if the current logging level is set to 4 or higher, indicating that debug-level messages should be printed. 
68/// If the condition is met, it formats the provided arguments using `format_args!`, and then prints them with a specific format including colored annotations for better readability in the terminal. 
69/// The output includes an indentation prefix, a "DEBG" tag in green, the formatted message in cyan, and the originating file and line number. 
70/// The macro utilizes thread-local storage for the indentation level, ensuring that debugging messages are neatly organized according to the current execution context.
71/// 
72macro_rules! debg {
73    ($($fmt:expr),+) => {
74        if $crate::log::LOGLEVEL.get() >= 4 {
75            $crate::log::INDENT.with_borrow(|s| {
76                eprintln!("{}\u{001b}[32mDEBG\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($($fmt),+), file!(), line!())
77            })
78        }
79    };
80}
81
82#[macro_export]
83/// Expands to produce a debug logging statement for high verbosity levels. 
84/// 
85/// 
86/// The macro is designed to output formatted debug messages to the standard error stream when a global logging level set within the crate is 5 or higher. 
87/// It formats the message using provided expressions, marks the message with "DEBG" using ANSI color coding for enhanced terminal visibility, and appends the current file and line number for precise location tracking. 
88/// This enables developers to efficiently trace and debug program execution, especially when dealing with complex synthesis algorithms in the Synthphonia module. 
89/// The macro relies on a thread-local storage for consistent formatting in multi-threaded scenarios.
90macro_rules! debg2 {
91    ($($fmt:expr),+) => {
92        if $crate::log::LOGLEVEL.get() >= 5 {
93            $crate::log::INDENT.with_borrow(|s| {
94                eprintln!("{}\u{001b}[32mDEBG\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($($fmt),+), file!(), line!())
95            })
96        }
97    };
98}
99
100#[macro_export]
101/// Logs critical messages based on the defined logging level. 
102/// 
103/// This macro evaluates whether the current logging level is at least 1 and, if so, prints a formatted critical log message to standard error. 
104/// The message is prefixed with an indentation from a thread-local storage followed by the formatted critical prefix in bold red. 
105/// The message content is then followed by the related source file and line number of the log statement for easier debugging and tracing. 
106/// The formatting allows developers to have an immediate visual indication of a critical logging event in their output.
107/// 
108macro_rules! crit {
109    ($($fmt:expr),+) => {
110        if $crate::log::LOGLEVEL.get() >= 1 {
111        $crate::log::INDENT.with_borrow(|s| {
112            eprintln!("{}\u{001b}[31;1m\u{001b}[1mCRIT\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($($fmt),+), file!(), line!())
113        })
114    }
115    };
116}
117
118#[macro_export]
119/// This macro generates a warning message. 
120/// 
121/// It formats and prints a warning when the global log level is set to 2 or higher. 
122/// It leverages a thread-local storage for indentation to structure the output appropriately, highlighting the word "WARN" and the formatted message with ANSI escape codes to apply color and style. 
123/// The macro uses `eprintln!` to output the warning to the standard error stream, including the file name and line number where the macro is invoked, enhancing debugging and log tracing capabilities.
124/// 
125macro_rules! warn {
126    ($($fmt:expr),+) => {
127        if $crate::log::LOGLEVEL.get() >= 2 {
128            $crate::log::INDENT.with_borrow(|s| {
129                eprintln!("{}\u{001b}[33;1m\u{001b}[1mWARN\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($($fmt),+), file!(), line!())
130            })
131        }
132    };
133}
134
135#[macro_export]
136/// Evaluates a given expression with conditional logging of informational messages based on the current log level. 
137/// 
138/// This macro checks if the logging level is set to 3 or higher, indicating verbose output. 
139/// If the condition is met, it formats a log message with a custom indentation and colored "INFO" prefix, appending the source file name and line number. 
140/// The macro uses thread-local storage to manage log indentation, ensuring that nested logging maintains a consistent structure. 
141/// It then executes the provided expression while temporarily adjusting the indentation, allowing for nested operations to be clearly delineated in the log output. 
142/// If the log level is below 3, the expression is evaluated without additional logging.
143/// 
144macro_rules! infob {
145    ($fmt:literal, $e:expr) => {
146        if $crate::log::LOGLEVEL.get() >= 3 {
147            $crate::log::INDENT.with_borrow(|s| {
148                eprintln!("{}\u{001b}[36m\u{001b}[1mINFO\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($fmt), file!(), line!())
149            });
150            $crate::log::indent();
151            let _result_ = $e;
152            $crate::log::dedent();
153            _result_
154        } else {
155            $e
156        }
157    };
158}
159
160#[macro_export]
161/// Expands into a conditional logging block for debugging expressions. 
162/// 
163/// It evaluates whether the log level is sufficiently high (4 or above) to output detailed debug information. 
164/// If the condition is met, it inserts an entry into the log with a specific format that highlights the debug message and includes the file and line number where the macro is used. 
165/// The macro adjusts the indentation context before and after the expression is evaluated to maintain a coherent log structure. 
166/// Regardless of the log level, the expression is always executed, and its result is returned. 
167/// This macro is useful for temporarily inserting detailed logging around specific sections of code, especially during development and debugging sessions.
168/// 
169macro_rules! debgb {
170    ($fmt:literal, $e:expr) => {
171        if $crate::log::LOGLEVEL.get() >= 4 {
172            $crate::log::INDENT.with_borrow(|s| {
173                eprintln!("{}\u{001b}[32mDEBG\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($fmt), file!(), line!())
174            });
175            $crate::log::indent();
176            let _result_ = $e;
177            $crate::log::dedent();
178            _result_
179        } else {
180            $e
181        }
182    };
183}
184
185#[macro_export]
186/// Expands to a logging and evaluation mechanism. 
187/// 
188/// This macro evaluates an expression, logging detailed debug information if the current logging level is set to 5 or higher. 
189/// It leverages the project's logging infrastructure to output a well-formatted message showing the provided format string and its evaluated result, along with the file and line number where the macro is invoked. 
190/// The macro manipulates an indent level to ensure the logs maintain structured readability through related log invocations. 
191/// In case the log level condition is not met, it simply evaluates the expression without any additional logging.
192/// 
193macro_rules! debgb2 {
194    ($fmt:literal, $e:expr) => {
195        if $crate::log::LOGLEVEL.get() >= 5 {
196            $crate::log::INDENT.with_borrow(|s| {
197                eprintln!("{}\u{001b}[32mDEBG\u{001b}[0m \u{001b}[36m{:?}\u{001b}[0m {}:{}", s, format_args!($fmt), file!(), line!())
198            });
199            $crate::log::indent();
200            let _result_ = $e;
201            $crate::log::dedent();
202            _result_
203        } else {
204            $e
205        }
206    };
207}