BLogger
BLogger copied to clipboard
An easy to use modern C++14/17 async cross-platform logger which supports custom formatting/patterns, colored output, Unicode, file logging, log rotation & more!
BLogger |
|
|
An easy to use modern C++14/17 async cross-platform logger which supports custom formatting/patterns, colored output, Unicode, file logging, log rotation & more!
Performance
BlockingLogger
- Debug: 90μs/message (~11,111/sec).
- Release: 77μs/message (~12,987/sec).
AsyncLogger
- Debug: 8μs/message (~125,000/sec).
- Release: 0.35μs/message (~2,857,142/sec).
The tests were done with a single-argument message, and a full pattern, as well as a colored StdoutSink.
RAM usage peakes at about 6MB with a full queue (10,000 log messages by default). This can obviously be different for you depending on how long your log message is.
Building the Example project
- Clone the repository
git clone https://github.com/8infy/BLogger
- Build the project
cd BLogger && mkdir build && cd build && cmake .. && cmake --build .
In order to use BLogger in your own project simply add BLogger's include folder into your project's include directories.
Using the logger
// 1. Create a logger using one of the factory functions
// You can use one of the common preconfigured loggers
auto async_logger = bl::logger::make_async_console();
// Or maybe you want a fully customizable one
auto custom_logger = bl::logger::make_custom(
"SomeTag", // logger tag
bl::level::crit, // log level filter
bl::logger::default_pattern, // logger pattern
false, // is asynchronous
bl::sink::make_stderr(), // any number of sinks at the end
bl::sink::make_file(
"/logs", // path to a directory where you want the log files to be stored
bl::infinite, // bytes per file
bl::infinite, // maximum log files
true // should rotate logs?
)
);
// 2. Start logging
async_logger->warning("{0}, {}!", "Hello", "World");
// Even after a logger is created it's still highly customizable:
// You can set a new tag
async_logger->set_tag("NewTag");
// Add a new sink
async_logger->add_sink(bl::sink::make_stdout());
// And even set a new pattern
async_logger->set_pattern("[{ts}][{tag}]\n[{lvl}] -> {msg}\n");
- Available factory functions
// A basic console logger
bl::logger::make_console(string tag, level lvl, string pattern, bool colored);
// An asychronous console logger
bl::logger::make_async_console(string tag, level lvl, string pattern, bool colored);
// A basic file logger
bl::logger::make_file(string tag,
level lvl,
string pattern,
string directory_path,
size_t byte_per_file,
size_t max_log_files,
bool rotate_logs);
// An asynchronous file logger
bl::logger::make_async_file(string tag,
level lvl,
string pattern,
string directory_path,
size_t byte_per_file,
size_t max_log_files,
bool rotate_logs);
// Or a fully customizable logger with
// any number of sinks at the end
bl::logger::make_custom(string tag,
level lvl,
string pattern,
bool asynchronous,
Sinks... sinks);
- Setting the pattern
Arguments you can use for creating a custom pattern:
-
{ts}
-> timestamp. -
{lvl}
-> logging level of the current message. -
{tag}
-> logger tag(name). -
{msg}
-> the message itself.
After you've decided on your pattern you can set it by calling set_pattern(string pattern)
.
Here's an example of an interesting pattern "[{ts}][{tag}]\n[{lvl}] -> {msg}\n"
, which looks like this:
- Logging your messages
-
log(level lvl, string message)
-> Logs the message with a given level. -
log(level lvl, string formattedMsg, Args ... args)
-> Logs the formatted message with a given level.
- The following redundant member functions are also available with the same overloads as log()
, however, don't require a level argument
-
trace(...)
-> Logs the given message with logging leveltrace
. -
debug(...)
-> Logs the given message with logging leveldebug
. -
info(...)
-> Logs the given message with logging levelinfo
. -
warning(...)
-> Logs the given message with logging levelwarn
. -
error(...)
-> Logs the given message with logging levelerror
. -
critical(...)
-> Logs the given message with logging levelcrit
.
- BLogger log message formatting
BLogger accepts the following formats:
-
{}
a normal argument. Usage example:logger->critical("Something went wrong {}", error.message());
. -
{n}
a positional argument. Usage example:logger->info("{1}, {0}!", "World", "Hello")
-> printsHello, World!
. - You can also mix the two types like so
logger->info("{}, {1}{0}", '!', "World", "Hello")
-> printsHello, World!
Note: if you are passing a user defined data type make sure it has the <<
operator overloads for std::ostream
.
- Unicode logging
- In order to enable Unicode mode type
#define BLOGGER_UNICODE_MODE
before including BLogger.h in any translation unit (aka .cpp). - When Unicode mode is enabled, all functions expect wide strings and
const wchar_t*
for literals, wide string literal is defined by typingL
before the opening quotes. Same waystd::ostream
is replaced withstd::wostream
for passing a user defined data type.
- Misc member functions
-
set_filter(level lvl)
- > Sets the logging filter to the level specified. -
set_tag(string tag)
-> Sets the logger name to the name specified. -
flush()
-> Flushes the logger. -
add_sink(sink::ptr sink)
-> Adds a sink to the logger. -
global_console_write_lock()
-> returns the global mutex BLogger uses to write to a global sink. Use this mutex if you want to combine using BLogger with raw calls tostd::cout
. If you lock the mutex before writing to a global sink your message is guaranteed to be properly printed and be the default color. -
formatter::cut_if_exceeds(size_t size, string postfix)
-> Sets the maximum size of a log message. If the message exceeeds the set size it will be cut and the postfix will be inserted after. The postfix is set to"..."
by default. Size can also be set tobl::infinite
, which is the default setting. -
formatter::set_timestamp_format(string new_format)
-> Sets the timestamp format. Should be formatted according to thestrftime
specifications. -
formatter::set_ending(string ending)
-> Sets the global log message ending. Defaults to\n
. The length is not included into message size calculations.
- Logging sinks
BLogger offers a list or predefined sinks, which you can extend with ease.
-
sink::make_stdout(bool colored)
-> a sink associated withstdout
. -
sink::make_stderr(bool colored)
-> a sink associated withstderr
. -
sink::make_stdlog(bool colored)
-> a wrapper aroundstd::clog
(usesstderr
). -
sink::make_console(bool colored)
-> same assink::make_stdlog
. -
sink::make_file(string directory_path, size_t bytes_per_file, size_t max_log_files, bool rotate_logs)
-> a file sink. -
sink::make_syslog()
-> a syslog sink. (Will compile on any platform but only works on linux)