Log Handlers
Inspired by the python logging module, this library implements a handler interface with the following handler implementations:
- Console Handler: Log to
stdout
orstderr
. - File Handler: Log to a file on the filesystem.
- Rotating File Handler: Log to a file and rotate logfiles when a maximum size is reached.
Multiple handlers can be used in parallel and each log will be sent to all registered handlers. See Using multiple handlers for more information.
Notes:
- By default, if no handlers has been registered when calling
logger__init()
, a defaultconsole
handler is created and initialised. Subsequent calls tologger__init()
will reinitialise all registered handlers.- On embedded systems, the file handlers will most likely not work unless a filesystem implementation exists. This library is designed to have several options for customisation. See Customising Handlers.
Console Handler
Handler to log to stdout
or stderr
.
// Get a default logger_handler_t struct
// by passing a name and the stream to log to (stdout|stderr)
logger_handler_t handler = logger__handler_get_console("name", stdout);
// Register handler
logger__add_handler(handler);
// Init library and handlers
logger__init();
File Handler
Handler to log to filesystem.
// Requires a name and a filename
logger_handler_t handler = logger__handler_get_file("name", "out.log");
// Register handler
logger__add_handler(handler);
// Init library and handlers
logger__init();
Rotating File Handler
Handler to log to filesystem and rotate files.
// Requires a name, a filename, the maximum file size in bytes and the maximum number of backup files.
logger_handler_t handler = logger__handler_get_rotating_file("name", "out.log", 1000000, 10);
// Register handler
logger__add_handler(handler);
// Init library and handlers
logger__init();
This handler uses the rename and append rotation strategy. When the log file has reached the configured maximum size, all backups files are renamed from the oldest to the newest:
- "out.log.2" renamed to "out.log.3"
- "out.log.1" renamed to "out.log.2"
- "out.log" renamed to "out.log.1"
Subsequent logs will be added to "out.log` until the next rotation.
If the maximum backup count is reached, the oldest index file will be removed before the renaming takes place.
Using multiple handlers
You can register multiple handlers at runtime and logs will be forwarded to all handlers.
// Adding a console handler
logger_handler_t console = logger__handler_get_console("console", stdout);
logger__add_handler(console);
// Adding a file handler
logger_handler_t file = logger__handler_get_file("file", "out.log");
logger__add_handler(file);
// Init library and handlers
logger__init();
// Start logging ...
log_i("main", "Hello World!");
You can also remove a handler at runtime:
Customisation
Several options exist for customisation of the handler system.
Customising existing handlers
Overriding printf
All exisiting handlers support overriding the "print" function called internally. By default, vfprintf
from <stdio.h>
is used.
// Custom implementation of a print function having the same signature as 'vfprintf'.
int custom_vfprintf(FILE *file, const char *format, va_list args) {
// ...
return 0;
}
// Overide vfprintf function used by handler
logger__handler_set_print_function("console", custom_vfprintf);
See the examples or tests directories for more concrete examples.
Custom Handler
TODO