libprettylogger
A highly customizable logger library written in Rust.
Table of Contents
TL;DR
Install the library:
cargo add libprettylogger
Include the library in your project:
// Include stuff from the library:
use Logger;
use Verbosity;
// A `Logger` struct with default configuration
let mut logger = default;
// Configure `Logger` to your liking
logger.set_verbosity; // Don't suppress any log messages
// Print logs:
logger.debug;
logger.info;
logger.warning;
logger.error;
logger.fatal;
Installation
To install the library with cargo, run:
cargo add libprettylogger
Or add this to your Cargo.toml:
[]
= "1.0.0"
The Logger
The Logger struct is the core of the entire project.
This is what you are going to use when you want to print a log, set filtering
rules or modify log formatting.
All of it's fields are private, only allowing for modification via setters.
Creating a Logger struct with default configuration:
let mut logger = default;
Constructors:
default()→Loggerwith default configuration.from_template(path: &str)→ DeserializesLoggerfrom a JSON template file (see this).
Logging Methods:
debug(message: &str)→ Prints a debug message.info(message: &str)→ Prints info message.warning(message: &str)→ Prints a warning.error(message: &str)→ Prints an error.fatal(message: &str)→ Prints a fatal error.
BTW, debug, info and warning methods have their variants that bypass
filtering:
debug_no_filtering(message: &str)→ Prints a debug message, bypasses filtering.info_no_filtering(message: &str)→ Prints info message, bypasses filtering.warning_no_filtering(message: &str)→ Prints a warning, bypasses filtering.
Note that error and fatal methods don't have _no_filtering variants.
This is because errors can't be suppressed.
Setters:
Log filtering (see this):
set_verbosity(verbosity: Verbosity)→ Sets theLoggerverbosity.toggle_log_filtering(enabled: bool)→ Toggles log filtering.
Log formatting (see this):
toggle_log_header_color(enabled: bool)→ Toggles log type header color, same as setting all the log type header colors toColor::None.set_debug/info/warning/error/fatal_header(header: &str)→ Sets the log type header for different log types (debug, info, warning, error, fatal).set_debug/info/warning/error/fatal_color(color: Color)→ Sets the log type header color for different log types. TheColorenum is declared inprettylogger::colors.set_datetime_format(format: &str)→ Sets the timestamp format.set_log_format(format: &str)→ Sets the log format.
File logging (see this):
set_log_file_path(path: &str)→ Sets the log file path.toggle_file_logging(enabled: bool)→ Toggles file logging.set_max_log_buffer_size(size: usize)→ Sets the maximum size of the log buffer. When log buffer exceeds this limit, it gets flushed.toggle_log_file_lock(enabled: bool)→ Toggles log file lock used to avoid race conditions.
Other Methods:
format_log(log: &LogStruct)→ Returns a formatted log based on theLogStructandLoggerconfiguration. TheLogStructis declared inprettylogger::logging.flush()→ Flushes the log buffer.save_template(path: &str)→ SerializesLoggerinto a JSON template file. (see this)
Log Format and Log Headers
A log consists of several headers:
- Log Type → The type of the log (debug, info, warning etc.)
- Timestamp → Contains the date and time the log was created
- Message → The actual log message
Here is a log message with all it's parts marked:
[ DEBUG 21:52:37 An example debug message ]
^^^^^ ^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^
| | |
| | the message
| timestamp
log type
This specific effect was achieved by setting the datetime format to %H:%M:%S,
log format to [ %h %d %m ] and the debug log type header to DEBUG.
You can use this method to set the datetime format of a Logger:
logger.set_datetime_format;
Log format can be customized using:
logger.set_log_format;
Note: The %m placeholder is mandatory and you will get an error unless you
include it in your format string.
And log type headers can be customized with their corresponding methods:
logger.set_debug_header;
logger.set_info_header;
logger.set_warning_header;
logger.set_error_header;
logger.set_fatal_header;
Log type headers can be further customized by changing their colors:
logger.set_debug_color;
logger.set_info_color;
logger.set_warning_color;
logger.set_error_color;
logger.set_fatal_color;
The Color enum is declared in prettylogger::colors. It can hold one of the
following values:
None→ Represents no color. When a log type header color is set to this value, it will appear as regular text.Black→ Black color.Blue→ The default color for debug header.CyanGreen→ The default color for info header.GrayMagenta→ The default color for fatal header.Red→ The default color for error header.WhiteYellow→ The default color for warning header.
Log Filtering
Logs are filtered based on the current LogLevel and the Logger's Verbosity
setting.
The Verbosity level determines which logs are filtered out:
All→ Disables log filtering, allowing all logs to pass through.Standard(default) → Filters out debug logs.Quiet→ Only allows errors and warnings to be displayed.ErrorsOnly→ Only allows errors to be shown.
The Verbosity enum is defined in prettylogger::filtering.
To modify the Verbosity of the Logger, use:
logger.set_verbosity;
To toggle log filtering, use:
logger.toggle_log_filtering;
File Logging
File logging is a feature that allows you to automatically save log output to a file.
Enabling file logging:
// Set the log file path first:
logger.set_log_file_path;
// Then enable file logging:
logger.toggle_file_logging;
logger.info; // Yay!
logger.flush; // Flush the log buffer to a file
It is CRUCIAL to set the log file path FIRST. This is because when
you attempt to enable file logging, Logger will check if the log file path is
correct and since the default log file path is an empty string, you will get an
error.
Locking the Log File
The log file can be locked to prevent race conditions when there are multiple
threads accessing it at the same time. The lock prevents Logger from writing to
the log file until the lock has been released. Logger only ignores the log file
lock when it's being dropped and the OnDropPolicy is set to IgnoreLogFileLock
(off by default).
Note: Log file lock is not persistent (it's not saved when calling
logger.save_template("path")).
To toggle log file lock, use:
logger.toggle_lock_file_lock;
// Do some I/O operations on the log file here
logger.toggle_lock_file_lock;
To set the on drop log file policy, use:
// Ignore the log file lock and write to the log file anyway.
logger.set_on_drop_file_policy;
OnDropPolicy is declared in the logging module, and all it's possible values
are:
IgnoreLogFileLock→ Ignore the log file lock and write to the log file anyway.DiscardLogBuffer(default) → Don't write to the log file on drop (discard all logs from log buffer).
Automatic Log Buffer Flushing
You can either flush the log buffer automatically or set up automatic flushing based on the log buffer size:
logger.set_log_file_path;
logger.toggle_file_logging;
// This will make `Logger` to flush the log buffer every 16 logs:
logger.set_max_log_buffer_size;
let mut i = 0;
loop
Logger Templates
A Logger Template is a JSON file that defines the configuration of a
Logger struct. This allows you to easily manage and store logging settings in a
file.
Here’s an example of what a Logger struct looks like in JSON format:
Deserializing Logger from a template file:
let mut logger = from_template;
Serializing Logger to a template file:
let mut logger = default; // Create a default `Logger`
logger.save_template;