A lightweight, flexible logger library for the C language, inspired by log4.c project and Python's logging package. This library provides a simple yet powerful way to log messages with different levels, handlers, and formatting options. It supports both stream and file handlers, and customizable log formats.
- Default root handler (a stream handler) for immediate use, you don't need to create it.
- More file and stream handlers can be added.
- Multiple log levels:
TRACE
,DEBUG
,INFO
,WARN
,ERROR
,FATAL
. - Customizable log formatting with color support for terminals.
- Flexible date/time formatting.
- Clone or download the repository:
git clone https://github.com/JeepWay/logger-c.git
- Include the header file logger.h and source file logger.c in your project. The following is an example (main.c):
#include <stdio.h> #include <stdlib.h> #include "logger/logger.h" int main(void) { log_trace("Trace message %d", 1); log_debug("Debug message %d", 2); log_info("Info message %d", 3); log_warn("Warn message %d", 4); log_error("Error message %d", 5); log_fatal("Fatal message %d", 6); return 0; }
- Compile your program with a C compiler (e.g., gcc), and execute it.
gcc -o main logger/logger.c main.c ./main
- You will see the result in the console like the top picture.
The following DEFAULT
values are defined in logger.h. You can use them to set the default values for convenience, or you can specify your own values.
The default log level of root handler is TRACE
. You can change the log level by using log_set_level(char* name, size_t value)
, where name
is the handler name and value
is the log level.
log_set_level(DEFAULT, LOG_INFO);
// Equal to the following line
log_set_level("root", LOG_INFO);
The default setting only contains a stream handler (root handler). You can add a file handler to log messages to a file by using log_add_file_handler(char *filename, char *filemode, size_t level, char *name)
, where filename
is the name of the file, filemode
is the mode to open the file, level
is the log level, and name
(can't be NULL
) is the handler name.
log_add_file_handler(DEFAULT, DEFAULT, DEFAULT_LEVEL, "file1");
// Equal to the following line
log_add_file_handler("logger/program.log", "a", LOG_INFO, "file1");
And then you can see the log messages in the file logger/program.log
.
You can add a stream handler to log messages to the console by using log_add_stream_handler(FILE *fp, size_t level, char *name)
, where fp
is the file pointer, level
is the log level, and name
(can't be NULL
) is the handler name.
log_add_stream_handler(DEFAULT, DEFAULT_LEVEL, "bash2");
// Equal to the following line
log_add_stream_handler(stderr, LOG_INFO, "bash2");
You will see the log messages in the console. Since the log level of bash2
is INFO
and the log level of root
is TRACE
, only log messages with level INFO
and above will appear twice in the console (once from each handler).
Every handler is not quiet by default. You can make a handler quiet by using log_set_quiet(char* name, bool value)
, where name
is the handler name and value
is a boolean value.
log_set_quiet("root", true);
log_add_stream_handler(DEFAULT, DEFAULT_LEVEL, "bash2");
The console will only show the log messages from the bash2
handler, as the root
handler is quiet.
You can change the date and time format by using log_set_date_fmt(char* name, char* date_fmt)
, where name
is the handler name and date_fmt
is the date and time format.
log_set_date_fmt("root", DEFAULT_DATE_FORMAT3);
// Equal to the following line
log_set_date_fmt("root", "%Y/%m/%d %H:%M:%S");
The default text format for stream is color_fmt1 function, for file is no_color_fmt1 function.
The avaliable text format function are color_fmt1
, color_fmt2
, no_color_fmt1
, no_color_fmt2
.
You can change the text format by using log_set_fmt_fn(char* name, log_fmt_t fmt)
, where name
is the handler name and fmt
is the function pointer to the text format function.
log_set_fmt_fn("root", color_fmt2);
You will see the name of the handler in the log messages.
You can also change the text from colorful to plain. Note that the colorful format only works in the terminal and doesn't work in the text file.
log_set_fmt_fn("root", no_color_fmt2);
If you don't like the default text format, you can define your own text format function and use it. Below is an example of a custom text format function.
void custom_fmt(record_t *rec, const char *time_buf)
{
static const char *fmt = "%s\x1b[0m \x1b[90m[%s:%d] %s%-5s:\x1b[0m ";
fprintf(rec->hd_fp, fmt, time_buf, rec->file, rec->line,
level_colors[rec->level], level_strings[rec->level]);
}
log_set_fmt_fn("root", custom_fmt);
The default dump log function is dump_log function.
void dump_log(record_t *rec)
{
char time_buf[32];
time_buf[strftime(time_buf, sizeof(time_buf), rec->hd_date_fmt,
rec->time)] = '\0';
rec->hd_fmt_fn(rec, time_buf);
vfprintf(rec->hd_fp, rec->msg_fmt, rec->ap);
fprintf(rec->hd_fp, "\n");
fflush(rec->hd_fp);
}
You can change the dump log function by using log_set_dump_fn(char* name, log_dump_fn dump_fn)
, where name
is the handler name and dump_fn
is the function pointer to the dump log function.
#include <stdio.h>
#include <stdlib.h>
#include "logger/logger.h"
int main(void)
{
char *f1 = "file1";
log_add_file_handler("logger/program.log", "w", LOG_WARN, f1);
log_set_fmt_fn(f1, no_color_fmt2);
log_set_quiet("root", true);
log_trace("Trace message %d", 1);
log_debug("Debug message %d", 2);
log_info("Info message %d", 3);
log_warn("Warn message %d", 4);
log_error("Error message %d", 5);
log_fatal("Fatal message %d", 6);
return 0;
}
You will only see the log messages in the file logger/program.log
with the log level WARN
and above. Nothing will appear in the console.
Contributions are welcome! Please submit a pull request or open an issue on the repository. Here are some ways you can contribute:
- Implement a filter function, like the filter class in Python's logging package, to filter log messages based on the maximum log level and handler name.
- Make the sequential search of handlers more efficient, for example, hashing the handler names into id.
- Prevent adding handlers with the same name.
- Add more safety checks in logger.c to ensure robustness and prevent potential issues.
- log4.c
- Python logging module - Comprehensive guide on Python's logging package.
- Logging in Python - An article to introduce the logging package.
This library is free. You can redistribute and modify it under the MIT License. See the LICENSE for details.