Mastering log.c: A Lightweight C99 Logging Library for Embedded Systems
This article introduces log.c, a compact C99 logging library suitable for any platform—including embedded systems—covers its key features, demonstrates usage with code examples, and explains how to configure log levels, file output, callbacks, multithreading, and colored output.
log.c Introduction
GitHub link: https://github.com/rxi/log.c (MIT license)
log.c is a lightweight logging library written in C99, meaning it can be compiled and run on any platform that supports the C99 standard, such as embedded systems.
Features
Uses the C99 standard, suitable for embedded environments.
Supports silent mode.
Allows setting log levels.
Provides ANSI color codes.
Thread‑safe design with configurable lock mechanism.
Usage Example
Add log.c and log.h to your project. log.c defines six macros for different log levels:
#include "log.h"
int main(void) {
// Trace log
log_trace("Trace message: %d", 42);
// Debug log
log_debug("Debug message: %s", "This is a debug message");
// Info log
log_info("Info message: %s", "This is an info message");
// Warn log
log_warn("Warn message: %s", "This is a warning message");
// Error log
log_error("Error message: %s", "This is an error message");
// Fatal log
log_fatal("Fatal message: %s", "This is a fatal message");
return 0;
}Each macro accepts a printf -style format string and additional arguments; the formatted message is written to stderr.
Setting Log Level
Use log_set_level to define the minimum level that will be output to stderr:
log_set_level(LOG_ERROR); // only error and fatal logs are printedOutput to File
Call log_add_fp to direct logs to a file:
#include "log.h"
int main(void) {
FILE* file = fopen("log.txt", "w");
if (file != NULL) {
log_add_fp(file, LOG_INFO); // log INFO and above to file
}
log_trace("Trace message: %d", 42);
log_debug("Debug message: %s", "This is a debug message");
log_info("Info message: %s", "This is an info message");
log_warn("Warn message: %s", "This is a warning message");
log_error("Error message: %s", "This is an error message");
log_fatal("Fatal message: %s", "This is a fatal message");
return 0;
}Using a Callback Function
Register a callback with log_add_callback to customize log formatting, for example to prepend timestamps:
#include "log.h"
static const char *s_level_strings[] = {"TRACE","DEBUG","INFO","WARN","ERROR","FATAL"};
static void my_log_callback(log_Event *ev) {
char buf[64];
buf[strftime(buf, sizeof(buf), "%Y-%m-%d %H:%M:%S", ev->time)] = '\0';
fprintf(ev->udata, "%s %-5s %s:%d: ", buf, s_level_strings[ev->level], ev->file, ev->line);
vfprintf(ev->udata, ev->fmt, ev->ap);
fprintf(ev->udata, "
");
fflush(ev->udata);
}
int main(void) {
log_add_callback(my_log_callback, stderr, LOG_FATAL);
log_trace("Trace message: %d", 42);
log_debug("Debug message: %s", "This is a debug message");
log_info("Info message: %s", "This is an info message");
log_warn("Warn message: %s", "This is a warning message");
log_error("Error message: %s", "This is an error message");
log_fatal("Fatal message: %s", "This is a fatal message");
return 0;
}Multithreaded Use
In a multithreaded environment, set a lock function with log_set_lock:
void lock_function(bool lock, void *udata) {
if (lock) {
// acquire lock
} else {
// release lock
}
}
log_set_lock(lock_function, NULL);Using Colors
Define LOG_USE_COLOR at compile time to enable ANSI color output:
gcc log.c test.c -DLOG_USE_COLOROpen Source Linux
Focused on sharing Linux/Unix content, covering fundamentals, system development, network programming, automation/operations, cloud computing, and related professional knowledge.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
