oak - a modern logger 1.0
|
Welcome to the official Oak documentation. This guide provides comprehensive information and practical examples to help you get started with the Oak logging library.
Oak is a lightweight and robust logging library for C++23, designed to simplify logging in modern C++ applications.
Built with modern C++ practices, Oak leverages advanced language features to offer high performance and flexibility. Key features include:
In the following sections, we'll explore Oak's functionality in greater detail and demonstrate its capabilities through practical examples.
To start logging with Oak, simply include the oak.hpp
header file in your project and oak.cpp
in your source files.
That's about it for basic usage.
The library uses the oak
namespace, so you can access its functionality by prefixing it with oak::
. All names are in snake_case.
If you want to log to a socket (which will be covered more deeply later) you must compile your program with OAK_USE_SOCKET
, this is done because you might not want to include the socket libraries in your project if you don't need them.
The logger uses a writer thread to write the logs to the desired output. When a new message is created, the message is first evaluated into a std::string
either synchronously or asynchronously, depending on which method you use. It is then safely added to a queue, which is read by the writer thread. As soon as you add the message, the writer thread will be woken up and It will start writing the messages to the output until the queue is empty, without blocking the main thread.
To start and stop the writer thread, you can use the oak::init_writer()
and oak::stop_writer()
functions.
To log a message, you can use the oak::log()
function. This function takes a log level, a format message and any number of arguments to format the message.
The messages are formatted using std::format
, so you can use the same syntax: every "{}" in the message will be replaced by the next argument.
The log levels are the following:
oak::level::debug
oak::level::info
oak::level::warn
oak::level::error
oak::level::output
oak::level::disabled
You can also use the following shorter functions to log messages:
Or use macros:
You can set the global log level with the oak::set_level()
function. Only messages with a level equal or higher than the global log level will be logged.
The default log level is oak::level::debug
.
The library supports logging to multiple outputs, in particular:
To log to a file, you can use oak::set_file()
. This function takes the path to the file and the log level to log to the file, It will return a std::expected<int, std::string>
with either the file descriptor or an error message.
All the next logs will be sent also to the file.
To log to a socket, you can use oak::set_socket()
. This function takes either a unix socket path for unix sockets or host, port and protocol for network sockets. For example:
Similarly to the file, all the next logs will be sent to the socket.
The library offers a range of customization options to tailor the logging experience to your specific requirements. More customization ideas are always welcome, so feel free to open an issue or a pull request.
You can add automatic metadata to the log messages by enabling any number of flags with oak::set_flags()
. The flags are the following:
oak::flags::level
: Adds the log level to the log message.oak::flags::date
: Adds the current date to the log message.oak::flags::time
: Adds the current time to the log message.oak::flags::pid
: Adds the process id to the log message.oak::flags::tid
: Adds the thread id to the log message.oak::flags::json
: Serializes the log message to json.Example:
You can serialize the logs to json by enabling the oak::flags::json
flag.
You can also set the settings from a file, this is useful if you want to change the settings without recompiling the program. The setting file contains lines with the format key=value1,value2...
. The allowed keys are:
level
: The global log level.flags
: The flags to enable, separated by commas.file
: The file to log to. All spaces are ignored.Example:
By default, the library logs synchronously, meaning that the log message is formatted immediatly and sent to the writer's queue. You can format the message asynchronously by using the oak::async()
function.