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
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
//
// File Name: lib.rs
// Project Name: flogger_macros
//
// Copyright (C) 2025 Bradley Willcott
//
// SPDX-License-Identifier: GPL-3.0-or-later
//
// This library (crate) is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This library (crate) is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this library (crate). If not, see <https://www.gnu.org/licenses/>.
//
//!
//! # Flogging Macros
//!
//! This is a **supporting crate** for the `flogging` crate.
//!
//! It is _not_ meant to be used on its own. In fact, it would not work without the
//! other crate. Further, it should not be separately added to your project. Add
//! `flogging` instead, and this will be included as a dependent to that crate.
//!
//! ```text
//! $ cargo add flogging
//! ```
//! Alternatively, add the following to your project's `Cargo.toml` file:
//! ```text
//! [dependencies]
//! flogging = "0.6.0"
//! ```
//!
//! ## Special Note
//!
//! For the macros that accept the parameter: `msg`, the following is true:
//!
//! - They accept parameters the same as for [`std::format!`](https://doc.rust-lang.org/std/macro.format.html)
//! - plain text `&str`: `("It's your time.")`
//! - format `&str` with interpolated variables: `("Var: {var}")`
//! - format `&str` with supporting parameters: `("Var: {}", var)`
//! - Combination of the last two: `("Vars {var1} - {}:{}", var2, var3)`
//! - Additional Feature
//! - Just one or more variables: `(var1, var2, var3)`
//! - In this case, a default format string will be used: `"{}, {}, {}"`
//! - The number of `"{}"` will depend on the number of parameters.
//! - Ideal for logging concrete instances that have very good `Display` implementations,
//! or you just need their data without further explanation.
//! - Special Cases
//! - [entering!] and [exiting!]
//! - These two macros have the same features as the others,
//! but they may also be used _without_ any parameters. In such
//! a case, their defaults will be used.
//!
extern crate dyn_fmt;
extern crate proc_macro;
extern crate proc_macro_error;
use crate::;
use TokenStream;
// use proc_macro_error::proc_macro_error;
///
/// Log a CONFIG message.
///
/// CONFIG is a message level for static configuration messages.
///
/// CONFIG messages are intended to provide a variety of static
/// configuration information, to assist in debugging problems
/// that may be associated with particular configurations.
///
/// For example, a CONFIG message might include the CPU type, the
/// graphics depth, the GUI look-and-feel, etc.
///
/// If the logger is currently enabled for the CONFIG message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// ```no_run
/// use flogging::*;
/// use chrono::Local;
///
/// const_logger!({
/// Logger::console_logger(module_path!())
/// });
///
/// #[logger]
/// pub fn my_func(data: &str) {
/// config!("Some text to store.");
///
/// let time = Local::now();
///
/// config!(time);
/// config!(time, data);
/// config!("The configuration as at: {}", time);
/// config!("The configuration as at: {time}: {}", data);
/// config!("The configuration as at: {time:?}: {data}");
/// }
///
/// fn main(){
/// let data = "Some data";
/// my_func(data);
/// }
/// ```
/// Output:
/// ```text
/// |flogging->my_func| [CONFIG ] Some text to store.
/// |flogging->my_func| [CONFIG ] 2025-07-18 19:52:06.927418853 +08:00
/// |flogging->my_func| [CONFIG ] 2025-07-18 19:52:06.927418853 +08:00, Some data
/// |flogging->my_func| [CONFIG ] The configuration as at: 2025-07-18 19:52:06.927418853 +08:00
/// |flogging->my_func| [CONFIG ] The configuration as at: 2025-07-18 19:52:06.927418853 +08:00: Some data
/// |flogging->my_func| [CONFIG ] The configuration as at: 2025-07-18T19:52:06.927418853+08:00: Some data
/// ```
/// [format]: https://doc.rust-lang.org/std/macro.format.html
///
// #[proc_macro_error]
///
/// Log entry into a function/method.
///
/// This is a convenience macro that can be used to log entry into to a function/method. It can be used
/// without an alternative message. A possible use is to provide the function/method's parameters
/// to track what is being passed-in.
///
/// If no alternative message is provided, then the default message, "Entry", is used.
///
/// A `LogEntry` is created with a log level of FINER, that is then logged.
///
/// ## Parameters
/// - `msg` - (Optional) See [Special Note](index.html#special-note)
///
/// ## Examples
///```no_run
/// #[logger]
/// pub fn add_student(name: String, age: u8) {
/// entering!("name: {name}, age: {age}");
/// }
///
/// fn main(){
/// let name = "Mary Jane Thompson".to_string();
/// let age = 18;
///
/// add_student(name, age);
/// }
/// ```
/// Output:
/// ```text
/// |flogging->add_student| [FINER ] Entry: (name: Mary Jane Thompson, age: 18)
/// ```
///
///
/// Log return from a function/method.
///
/// This is a convenience macro that can be used to log exiting from a function/method. It can be used
/// without an alternative message. A possible use is to provide the function/method's return value
/// to track what is being passed-out.
///
/// If no alternative message is provided, then the default message, "Return", is used.
///
/// A `LogEntry` is created with a log level of FINER, that is then logged.
///
/// ## Parameters
/// - `msg` - (Optional) See [Special Note](index.html#special-note)
///
/// ## Examples
///```no_run
/// #[logger]
/// pub fn add_student(name: String, age: u8) -> bool {
/// let mut rtn = false;
///
/// entering!("name: {name}, age: {age}");
///
/// /* Some processing that provides a result (rtn) */
/// rtn = true;
///
/// exiting!("rtn: {rtn}");
/// rtn
/// }
///
/// fn main(){
/// let name = "Mary Jane Thompson".to_string();
/// let age = 18;
///
/// if add_student(name, age) {
/// println!("Success");
/// } else {
/// println!("Failure!");
/// }
/// }
/// ```
/// Output:
/// ```text
/// |flogging->add_student| [FINER ] Entry: (name: Mary Jane Thompson, age: 18)
/// |flogging->add_student| [FINER ] Return: (rtn: true)
/// Success
/// ```
///
///
/// Log a FINE message.
///
/// FINE is a message level providing tracing information.
///
/// All of FINE, FINER, and FINEST are intended for relatively
/// detailed tracing. The exact meaning of the three levels will
/// vary between subsystems, but in general, FINEST should be
/// used for the most voluminous detailed output, FINER for somewhat
/// less detailed output, and FINE for the lowest volume (and most
/// important) messages.
///
/// In general the FINE level should be used for information that
/// will be broadly interesting to developers who do not have a
/// specialized interest in the specific subsystem.
///
/// FINE messages might include things like minor (recoverable)
/// failures. Issues indicating potential performance problems are
/// also worth logging as FINE.
///
/// If the logger is currently enabled for the FINE message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// See [config](macro.config.html#examples). The syntax/usage is the same.
/// Just substitute `fine!` for `config!`.
///
///
/// Log a FINER message.
///
/// FINER indicates a fairly detailed tracing message.
/// Suggest logging calls for entering, returning,
/// or `Error`s, such as returned via `Result`, are traced at
/// this level.
///
/// If the logger is currently enabled for the FINER message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// See [config](macro.config.html#examples). The syntax/usage is the same.
/// Just substitute `finer!` for `config!`.
///
///
/// Log a FINEST message.
///
/// FINEST indicates a highly detailed tracing message.
///
/// If the logger is currently enabled for the FINEST message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// See [config](macro.config.html#examples). The syntax/usage is the same.
/// Just substitute `finest!` for `config!`.
///
///
/// Get the required `Handler`.
///
/// ## Examples
/// ```no_run
/// extern crate flogging;
/// use flogging::*;
///
/// // Setting up the module level logger.
/// const_logger!({
/// Logger::builder(module_path!())
/// .add_string_handler()
/// .set_level(Level::ALL)
/// .build()
/// });
///
/// #[logger]
/// fn my_func(){
/// info!("Some text to store.");
/// warning!("Rain is wet!");
/// severe!("Hurricanes are windy!");
///
/// if let Some(h) = get_handler!(Handler::String) {
/// println!(
/// "\n(h.get_log())\n======v======\n{}\n======^======",
/// h.get_log()
/// );
/// } else {
/// println!("Sorry. Not there!");
/// }
/// }
/// ```
/// Output:
/// ```text
/// (h.get_log())
/// ======v======
/// |flogging->my_func| [INFO ] Some text to store.
/// |flogging->my_func| [WARNING] Rain is wet!
/// |flogging->my_func| [SEVERE ] Hurricanes are windy!
///
/// ======^======
/// ```
///
///
/// Log an INFO message.
///
/// INFO is a message level for informational messages.
///
/// Typically INFO messages will be written to the console or its
/// equivalent. So the INFO level should only be used for reasonably
/// significant messages that will make sense to end users and system
/// administrators.
///
/// **\[default level]** : This is the default level used when a logger is created.
/// See [set_level!] for changing this.
///
/// If the logger is currently enabled for the INFO message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// See [config](macro.config.html#examples). The syntax/usage is the same.
/// Just substitute `info!` for `config!`.
///
///
/// Checks whether or not this logger is processing log requests.
///
/// Returns `true` if it is, `false` if not.
///
/// ## Examples
/// ```no_run
/// extern crate flogging;
/// use flogging::*;
///
/// // Setting up the module level logger.
/// const_logger!({
/// Logger::builder(module_path!())
/// .add_console_handler()
/// .add_file_handler("test_logs/debug.log")
/// .set_level(Level::FINEST)
/// .build()
/// });
///
/// #[logger]
/// fn main() {
/// set_level!(Level::OFF);
///
/// let msg = "The program might become unstable.";
/// warning!(msg);
///
/// if !is_logging!() {
/// eprintln! {"{msg}"};
/// }
/// }
///
/// ```
/// Output to [`std::io::stderr`]:
/// ```text
/// The program might become unstable.
/// ```
///
///
/// Provides for logging within the attributed function/method.
///
/// This is required to be able to use the [macros](index.html#macros-1).
/// It sets up the local variable used by the other macros, and it also registers the function/method
/// name used by the log entries (if included in the formatter's `fmt_string`).
///
/// ```no_run
/// #[logger]
/// pub fn my_func(msg: &str){
/// entering!();
/// fine!("msg: {msg}");
///
/// ...
/// }
/// ```
///
///
/// Set the logging level for this `Logger` instance.
///
/// The default level is INFO.
///
/// ## Parameters
/// - `level` - The required logging level.
///
/// ## Examples
/// ```
/// #[logger]
/// pub fn my_func(msg: &str){
/// entering!("msg: {msg}");
/// fine!("Everything is just fine!");
///
/// // ...
/// }
///
/// fn main(){
/// set_level!(Level::FINER);
///
/// let msg = "Just some text to work with.";
///
/// my_func(msg);
/// }
///
/// ```
/// Output:
/// ```text
/// |flogging->my_func| [FINER ] Entry: (msg: Just some text to work with.)
/// |flogging->my_func| [FINE ] Everything is just fine!
/// ```
///
///
/// Log a SEVERE message.
///
/// SEVERE is a message level indicating a serious failure.
///
/// In general SEVERE messages should describe events that are of
/// considerable importance and which will prevent normal program
/// execution. They should be reasonably intelligible to end users
/// and to system administrators.
///
/// If the logger is currently enabled for the SEVERE message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// See [config](macro.config.html#examples). The syntax/usage is the same.
/// Just substitute `severe!` for `config!`.
///
///
/// Log a WARNING message.
///
/// WARNING is a message level indicating a potential problem.
///
/// In general WARNING messages should describe events that will be
/// of interest to end users or system managers, or which indicate
/// potential problems.
///
/// If the logger is currently enabled for the WARNING message level
/// then the given message is forwarded to all the registered output
/// Handler objects.
///
/// ## Parameters
/// - `msg` - See [Special Note](index.html#special-note)
///
/// ## Examples
///
/// See [config](macro.config.html#examples). The syntax/usage is the same.
/// Just substitute `warning!` for `config!`.
///