A simple C logging library featuring
- multiple, completely independent instances,
- multiple output streams, either for narrow or wide characters and with the option to disable the formatting, and
- customizable output styles, allowing users to choose which elements to include in the log messages, adjust text color and attributes, and define a callback function to be called whenever a log message is sent.
This project is the successor to my bad, purely macro-based logging.
- Ensure you have
- a working C compiler
- CMake
- a build system
- Create a "build" directory in the repository root and
cd
into it - Run
cmake
- Build the library using your build system
- Add
build/libbeeper.a
to your project source - Include
build/beeper.h
in your source code
Although it supports multiple instances, Beeper is primarily designed for single-instance applications. For this reason, instead of explicitly providing an instance alongside each operation, users define a global active beeper to receive all requests.
Start by creating a beeper, providing a short identifier to indicate what the instance represents:
bp_beeper beeper = bp_beeper_new(/* identifier: */ "id");
If you're only going to use a single instance, you can discard the return value of this function – it's only used to switch between instances.
Newly created beepers are automatically selected as active beeper. You can select a different instance like this:
bp_beeper_select(/* handle: */ beeper);
Once you're done logging, destroy the active beeper to release the memory it occupied:
bp_destroy();
Before we can start logging, we need to add some recipients to our beeper. Recipients consist of a FILE*
alongside some options.
Let's add stdout
as a recipient:
bp_recipient_add(/* stream: */ stdout, /* wide: */ false, /* formatted: */ true);
If you need to remove a recipient, you can do so as follows:
bp_recipient_remove(/* stream: */ stdout);
Recipients are cleaned up as part of
bp_destroy()
, so there's no need to remove them manually.
Now we can start logging messages. For example, we can log a warning as follows:
beep(/* style: */ warn, "Problematic integer: %d", 45)
The beep
macro accepts a message style (see Styles), followed by a (literal!) format string and the values to go alongside it (Beeper wraps around the printf
family of functions).
For more control, there are also the beep_with
(to explicitly select an instance for this specific message), beep_at
(to supply a custom origin file and line), and beep_with_at
(both) macros.
The header also declares some macros useful for quick debugging. For example, you can quickly log the value of an integer as follows:
int integer = 46;
beep_i(integer);
Refer to the header to find the other types you can log in this manner.
Beeper offers the following built-in message styles: success
, info
, warn
, fail
, and debug
.
However, we can also add our own or overwrite the existing ones:
bp_style_set(/* name: */ "custom", /* style: */ (bp_style){
.foreground_color = BP_COLOR_DARK_PURPLE,
.italic = true,
.show_style = true,
.hide_origin = true
});
Refer to the header to discover all the stylization options.
This style produces the following output:
To unset a style, use the following function:
bp_style_unset(/* name: */ "custom");
If your style overwrote a built-in style, unsetting it restores the built-in one. Also, like the recipients, custom styles are cleaned up as part of
bp_destroy()
, so it's not required to manually unset them.