CLog is a simple STB-style header-only logging library for C and C++.
- Flawlessly passes through valgrind
- Powerful overflow protection
- Six logging levels
- DEBUG
- TRACE
- INFO
- WARNING
- ERROR
- FATAL
- Custom log levels
- Colored logging
- Custom formatting
- Printf style formatting for log messages
- Logging to an arbitrary file descriptor
- C99 Compatible
- Logging file info
- Timestamps
- Assertions
CLog is an incredibly powerful and simple logging library. It is not overly bloated with functions, only has whats required. Even with only approximately 350 LoC, it is still able to offer features like customizable log output, customizable timestamps and custom log levels.
CLog work similarly to the stb libraries.
Wherever you define CLOG_IMPLEMENTATION the functions will be defined.
Otherwise, the functions will just be declared
#define CLOG_IMPLEMENTATION
#include <clog.h>
int main(void) {
clog(CLOG_DEBUG, "Hello from CLog!");
clog(CLOG_TRACE, "Hello from CLog!");
clog(CLOG_INFO, "Hello from CLog!");
clog(CLOG_WARNING, "Hello from CLog!");
clog(CLOG_ERROR, "Hello from CLog!");
clog(CLOG_FATAL, "Hello from CLog!");
}If you add this simple line to the demo, any message with the level CLOG_DEBUG or CLOG_TRACE will not show
clog_mute_level(CLOG_INFO);This example will log "Hello, World" into a file called "log.log"
Clog does not handle any kind of files, all it needs is a file descriptor.
#include <stdio.h>
#define CLOG_IMPLEMENTATION
#include <clog.h>
int main(void) {
FILE *f = open("log.log");
clog_set_output(f);
clog(CLOG_INFO, "Hello, World");
fclose(f);
}If you want to disable specific parts of clog, you can define some preprocessor macros to disable those parts
| Macro | Description |
|---|---|
| CLOG_NO_TIME | Disables timestamps for clog |
CLog offers its own assert macro, works just as well as any other.
clog_assert(some_expr);There is also the clog_assert_m(expr, msg) macro, to make an assertion but also enables a customizable fail message.
So the same assertion can look different when it fails:
clog_assert(0 == 1);Outputs
[FATAL] Assertion "0 == 1" failed!However
clog_assert_m(0 == 1, "Zero does not equal one");Outputs
[FATAL] Assertion "0 == 1" failed! Zero does not equal oneJust as some other logging libraries, this one also supports custom formatting of the output
There are two ways for setting the format. You can either set the clog_fmt variable to the format string you want, or, you can let the clog_set_fmt(fmt) macro do that for you.
The logger comes with an example format string already implemented:
"%t: %f:%l (%F) -> %c[%L]%r: %m"| Format prefix | Description |
|---|---|
| %c | The ANSI color escape character for the color of the current level |
| %r | The ANSI color escape character to reset the color |
| %m | The message that you provided |
| %L | The log level string |
| %f | The file from which the log was called |
| %l | The line at which the log was called |
| %t | Timestamp |
| %F | Current function name |
| %% | The character '%' |
Timestamps are specified with the format character 't'.
Timestamps can be formatted with either setting the clog_time_fmt variable, or calling the clog_set_time_fmt macro.
The default format string for timing in CLog is:
"%h:%m:%s.%u"| Format prefix | Description |
|---|---|
| %h | The current hour |
| %m | The current minute |
| %s | The current second |
| %u | The current millisecond |
Clog uses a buffer to construct the log message, the size of this buffer is defined in the macro CLOG_BUF_LIMIT.
It defaults to 1024, but if you want to increase or decrease it, define it with your buffer size before you include.
CLog has a internal function pointer (clog_callback) which is the function that prints the line after it has been constructed.
// The function signature is this
int clog_callback(const char *line);Warning
If the callback returns a non-zero value it reverts to the default callback!
CLog now allows you to add custom Logging levels to your programs, and the best part? It's relatively easy too!
All you have to do is to use the macro CLOG_REGISTER_LEVEL like this:
#include <clog.h>
const clog_level_t MY_CLOG_LEVEL = CLOG_REGISTER_LEVEL("MyClogLevel", CLOG_COLOR_BOLD CLOG_COLOR_GREEN, CLOG_SEVERITY_DEBUG)Now, the parameters might look intimidating, but they are actually pretty simple! The parameters are:
const char *name(The name that appears in the log)const char *color(The color the log gets colored. Use ansi escape characters here, or leave it blank for no color at all)const int severity(The severity of the message, basically decides when its muted and when its not)
There are 5 different severity levels, it is possible to use custom values but it is preferrable to use the predefined macros
| Macro name | Value |
|---|---|
| CLOG_SEVERITY_DEBUG | 0 |
| CLOG_SEVERITY_TRACE | 1 |
| CLOG_SEVERITY_INFO | 2 |
| CLOG_SEVERITY_WARNING | 3 |
| CLOG_SEVERITY_ERROR | 4 |
| CLOG_SEVERITY_FATAL | 5 |
There are a couple colors that clog comes with, these are as follows
| Color name | Description |
|---|---|
| CLOG_COLOR_BLACK | Black color ANSI escape code |
| CLOG_COLOR_RED | Red color ANSI escape code |
| CLOG_COLOR_GREEN | Green color ANSI escape code |
| CLOG_COLOR_YELLOW | Yellow color ANSI escape code |
| CLOG_COLOR_BLUE | Blue color ANSI escape code |
| CLOG_COLOR_MAGENTA | Magenta color ANSI escape code |
| CLOG_COLOR_CYAN | Cyan color ANSI escape code |
| CLOG_COLOR_WHITE | White color ANSI escape code |
| CLOG_COLOR_DEFAULT | Default foreground color escape code |
| CLOG_COLOR_BLACK_BG | Black background color ANSI escape code |
| CLOG_COLOR_RED_BG | Red background color ANSI escape code |
| CLOG_COLOR_GREEN_BG | Green background color ANSI escape code |
| CLOG_COLOR_YELLOW_BG | Yellow background color ANSI escape code |
| CLOG_COLOR_BLUE_BG | Blue background color ANSI escape code |
| CLOG_COLOR_MAGENTA_BG | Magenta background color ANSI escape code |
| CLOG_COLOR_CYAN_BG | Cyan background color ANSI escape code |
| CLOG_COLOR_WHITE_BG | White background color ANSI escape code |
| CLOG_COLOR_DEFAULT_BG | Default background color escape code |
| CLOG_COLOR_BOLD | Bold ANSI escape code |
| CLOG_COLOR_FAINT | Faint ANSI escape code |
| CLOG_COLOR_ITALIC | Italic ANSI escape code |
After this, you can just use it the same as you use any other CLog levels
CLog's internal format, output file descriptor and time format are marked thread local meaning they are individual per-thread variables that can vary between threads.
This means one thread may output to a separate file descriptor than another or may even have a different format than another. (Common uses are a per-thread format with e.g. thread ID)
Otherwise the common rules for dealing with multiple threads writing to the same file apply.