C-libs 0.1.0
Some C utils libraries
 
Loading...
Searching...
No Matches
logger.h File Reference

Thread-safe logger library for debugging purposes in C99. More...

#include <ayaztub/utils/util_attributes.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

Macros

#define SOURCE_PATH_SIZE   0
 Macro to truncate the root file path.
 
#define __FILENAME__   ((__FILE__) + (SOURCE_PATH_SIZE))
 Macro to adjust the file path based on SOURCE_PATH_SIZE.
 
#define LOG(lvl, ...)
 Logs a message using the default log macro.
 
#define LOG_FATAL(...)
 Logs a fatal message and exits the program.
 

Typedefs

typedef void(* logger_cb_t) (enum log_level lvl, const char *const colored_message, const char *const raw_message)
 Logger callback type.
 

Enumerations

enum  log_level {
  LOG_QUITE , LOG_FATAL , LOG_ERROR , LOG_TIMEOUT ,
  LOG_WARN , LOG_INFO , LOG_TRACE , LOG_DEBUG ,
  LOG_FULL
}
 Log levels supported by the logger. More...
 

Functions

CONSTRUCTOR void logger_init (void)
 Initializes the logger.
 
DESTRUCTOR void logger_deinit (void)
 Deinitializes the logger.
 
void logger_set_format_options (bool show_date, bool show_thread, bool log_trace_on_fatal)
 Configures log formatting options.
 
void logger_set_log_level (enum log_level level)
 Sets the current log level.
 
void logger_set_log_level_from_string (const char *const log_level) NONNULL NULL_TERMINATED_STRING_ARG(1)
 Sets the log level based on a string.
 
void logger_set_log_level_from_env (void)
 Sets the log level based on an environment variable.
 
bool logger_set_log_file (const char *const filename) NONNULL NULL_TERMINATED_STRING_ARG(1)
 Sets the output file for log messages.
 
bool logger_set_log_file_from_env (const char *const default_filename)
 Sets the output file for log messages based on an environment variable.
 
bool logger_set_log_fileno (FILE *file) NONNULL FD_ARG_WRITE(1)
 Sets the file descriptor for log output.
 
void logger_close_file (void)
 Closes the current log file, if any.
 
void logger_set_callback (logger_cb_t callback)
 Sets a callback function to handle log messages.
 
void log_message (enum log_level level, const char *const file, size_t line, const char *const func, const char *const fmt,...) NONNULL NULL_TERMINATED_STRING_ARG(2) NULL_TERMINATED_STRING_ARG(4)
 Logs a message with a specified log level.
 
void log_on_stdout (enum log_level, const char *const, const char *const) NONNULL NULL_TERMINATED_STRING_ARG(2) NULL_TERMINATED_STRING_ARG(3)
 Logs a message to stdout using the logger callback.
 
void log_on_stderr (enum log_level, const char *const, const char *const) NONNULL NULL_TERMINATED_STRING_ARG(2) NULL_TERMINATED_STRING_ARG(3)
 Logs a message to stderr using the logger callback.
 

Detailed Description

Thread-safe logger library for debugging purposes in C99.

This library provides logging functionality with various log levels, support for callbacks, and options to log to files or standard output. It is designed for debugging and includes features like backtrace logging on fatal errors.

Note
define NOLOG to remove all LOG() calls
Warning
As you can remove all LOG() calls using NOLOG, you MUST NEVER call a function in the LOG() macro argument as this function call will also be removed.
Note
define NOLOG will not remove backtrace logs on fatal signals (SIGSEGV, SIGILL, SIGABRT, ...)
Warning
This logger is optimized for debugging and may not be suitable for high-performance logging in production. For release builds, use restrictive log levels or disable logging using NOLOG.
This library is thread-safe but the logger callback registered by the user is called IN the critical section (to ensure logs order consitancy between with the logger core). To avoid deadlocks, the user MUST NEVER do recursive logging and thus MUST NEVER call any logger core functions/macros in the callback provided.
Note
On fatal error (or signal SIGSEGV, SIGABRT, SIGILL, SIGFPE, SIGBUS), the backtrace may be logged as FATAL. For example, the backtrace log ./a.out(+0x21ae) [0x5620024571ae] can be retrieved using addr2line: addr2line -Cfspe ./a.out +0x21ae gives us the function, file and line (with debug flags -g)
Todo
Integrate the addr2line tool in the log_backtrace() function, without any allocation (fatal error may be due to corrupted memory...).

Usage example:

#include <ayaztub/logger.h>
int main(int argc, char **argv) {
#ifndef __GNUC__
#endif // __GNUC__
logger_set_format_options(true, true, true);
if (!logger_set_log_file("logfile.txt")) {
// error on logger setup...
fprintf(stderr, "Failed to setup logger:"
" open logfile.txt failed !\n");
exit(1);
}
// Log messages of various levels
LOG(LOG_INFO, "This is and informational message.");
LOG(LOG_WARN, "This is a warning message.");
LOG(LOG_ERROR, "This is an error message.");
LOG(LOG_DEBUG, "Debugging details: x = %d, y = %d", 69, 96);
// Demonstarte callback usage (log to stdout)
LOG(LOG_TRACE, "Trace message with callback active"
" (logged on both stdout and logfile.txt).");
// cleanup: logger_close_file() autonatically called by
// logger_deinit() destructor
#ifndef __GNUC__
#endif // __GNUC__
return 0;
}
Thread-safe logger library for debugging purposes in C99.
void logger_set_format_options(bool show_date, bool show_thread, bool log_trace_on_fatal)
Configures log formatting options.
bool logger_set_log_file(const char *const filename) NONNULL NULL_TERMINATED_STRING_ARG(1)
Sets the output file for log messages.
void logger_set_log_level(enum log_level level)
Sets the current log level.
CONSTRUCTOR void logger_init(void)
Initializes the logger.
DESTRUCTOR void logger_deinit(void)
Deinitializes the logger.
#define LOG(lvl,...)
Logs a message using the default log macro.
Definition logger.h:306
void logger_set_callback(logger_cb_t callback)
Sets a callback function to handle log messages.
@ LOG_ERROR
Definition logger.h:120
@ LOG_TRACE
Definition logger.h:124
@ LOG_INFO
Definition logger.h:123
@ LOG_DEBUG
Definition logger.h:125
@ LOG_WARN
Definition logger.h:122
void log_on_stdout(enum log_level, const char *const, const char *const) NONNULL NULL_TERMINATED_STRING_ARG(2) NULL_TERMINATED_STRING_ARG(3)
Logs a message to stdout using the logger callback.

Macro Definition Documentation

◆ __FILENAME__

#define __FILENAME__   ((__FILE__) + (SOURCE_PATH_SIZE))

Macro to adjust the file path based on SOURCE_PATH_SIZE.

This macro modifies the __FILE__ macro to remove a specified number of characters from the beginning, making the logged file paths more readable.

◆ LOG

#define LOG ( lvl,
... )
Value:
log_message((lvl), __FILENAME__, __LINE__, __func__, __VA_ARGS__)
#define __FILENAME__
Macro to adjust the file path based on SOURCE_PATH_SIZE.
Definition logger.h:110
void log_message(enum log_level level, const char *const file, size_t line, const char *const func, const char *const fmt,...) NONNULL NULL_TERMINATED_STRING_ARG(2) NULL_TERMINATED_STRING_ARG(4)
Logs a message with a specified log level.

Logs a message using the default log macro.

Usage:

LOG(LOG_INFO, "This is an info message with value: %d", value);
Parameters
lvlLog level.
...Format string and arguments.
Examples
example_logger.c.

◆ LOG_FATAL

#define LOG_FATAL ( ...)
Value:
do { \
LOG(LOG_FATAL, __VA_ARGS__); \
exit(1); \
} while (0)
#define LOG_FATAL(...)
Logs a fatal message and exits the program.
Definition logger.h:318

Logs a fatal message and exits the program.

This macro is intended to exit the program even if logging is disabled (with NOLOG defined).

Parameters
...Format string and arguments.
Examples
example_logger.c.

◆ SOURCE_PATH_SIZE

#define SOURCE_PATH_SIZE   0

Macro to truncate the root file path.

This macro is useful when the project is compiled with CMake, allowing for a cleaner file path in logs by removing a fixed number of characters from the start of the __FILE__ macro. The default value if the macro wasn't defined earlier is 0.

Typedef Documentation

◆ logger_cb_t

typedef void(* logger_cb_t) (enum log_level lvl, const char *const colored_message, const char *const raw_message)

Logger callback type.

This function is called whenever a log message is generated. It must not call logger functions/macros directly to avoid recursion.

Parameters
lvlLog level of the message.
colored_messageLog message with formatting (for TTY outputs like stdout).
raw_messageLog message without formatting (for file outputs).

Enumeration Type Documentation

◆ log_level

enum log_level

Log levels supported by the logger.

Enumerator
LOG_QUITE 

No output

LOG_FATAL 

Fatal errors (program will terminate)

LOG_ERROR 

Errors

LOG_TIMEOUT 

Timeout warnings

LOG_WARN 

Warnings

LOG_INFO 

Informational messages

LOG_TRACE 

Trace-level debugging

LOG_DEBUG 

Debug-level messages

LOG_FULL 

All messages

Function Documentation

◆ log_message()

void log_message ( enum log_level level,
const char *const file,
size_t line,
const char *const func,
const char *const fmt,
... )

Logs a message with a specified log level.

Parameters
levelLog level for the message.
fileSource file name (FILE).
lineSource line number (LINE).
funcSource function name (func).
fmtFormat string for the message.
...Additional arguments for the format string.
Note
Please use the user friendly LOG() macro insteed.

◆ log_on_stderr()

void log_on_stderr ( enum log_level,
const char * const ,
const char * const  )

Logs a message to stderr using the logger callback.

◆ log_on_stdout()

void log_on_stdout ( enum log_level,
const char * const ,
const char * const  )

Logs a message to stdout using the logger callback.

◆ logger_close_file()

void logger_close_file ( void )

Closes the current log file, if any.

Note
Automatically called by logger_deinit().

◆ logger_deinit()

DESTRUCTOR void logger_deinit ( void )

Deinitializes the logger.

This function is called automatically at program termination (destructor attribute). It must not be called directly.

Warning
If GNUC is not defined, please refer to the example in logger_init().

◆ logger_init()

CONSTRUCTOR void logger_init ( void )

Initializes the logger.

This function is called automatically at program startup (constructor attribute). It must not be called directly.

Warning
CONSTRUCTOR is not defined without GNUC. If working with a non GNUC complient compiler, please call it directly at main start.
int main(void) {
#ifndef __GNUC__
#endif // __GNUC__
// program code
#ifndef __GNUC__
#endif // __GNUC__
return EXIT_SUCCESS;
}

◆ logger_set_callback()

void logger_set_callback ( logger_cb_t callback)

Sets a callback function to handle log messages.

Parameters
callbackPointer to the callback function.
Examples
example_logger.c.

◆ logger_set_format_options()

void logger_set_format_options ( bool show_date,
bool show_thread,
bool log_trace_on_fatal )

Configures log formatting options.

Parameters
show_dateWhether to include the current date in log messages.
show_threadWhether to include thread identifiers in log messages.
log_trace_on_fatalWhether to log a backtrace on fatal errors or signals.
Note
All options are true by default.
Examples
example_logger.c.

◆ logger_set_log_file()

bool logger_set_log_file ( const char *const filename)

Sets the output file for log messages.

Parameters
filenamePath to the log file.
Returns
true if the file was successfully opened, false otherwise.

◆ logger_set_log_file_from_env()

bool logger_set_log_file_from_env ( const char *const default_filename)

Sets the output file for log messages based on an environment variable.

The logger will look for the environment variable LOG_FILE and configure the output file accordingly.

Parameters
default_filenamePath to the log path if the environment variable was not found. (can be NULL)
Returns
true if environment variable LOG_FILE exists and was successfully opened OR if default_filename is not NULL and was successfully opened, false otherwise (1- LOG_FILE env variable exists but file cannot be opened, 2- LOG_FILE env variable does not exists and default_filename is NULL, 3- LOG_FILE env variable does not exists and default_filename cannot be opened)
Examples
example_logger.c.

◆ logger_set_log_fileno()

bool logger_set_log_fileno ( FILE * file)

Sets the file descriptor for log output.

Parameters
fileA valid file pointer for output.
Returns
true if the file descriptor is valid, false otherwise.
Warning
The file descriptor must not be closed by the user after this function call. If you want to close it, please refer to the logger_close_file() function.

◆ logger_set_log_level()

void logger_set_log_level ( enum log_level level)

Sets the current log level.

Messages below the specified level will not be logged.

Parameters
levelThe desired log level.
Examples
example_logger.c.

◆ logger_set_log_level_from_env()

void logger_set_log_level_from_env ( void )

Sets the log level based on an environment variable.

The logger will look for the environment variable LOG_LEVEL and configure the level accordingly. The environment variable LOG_LEVEL value must follow the same format as the string parameter accepted by logger_set_log_level_from_string().

Examples
example_logger.c.

◆ logger_set_log_level_from_string()

void logger_set_log_level_from_string ( const char *const log_level)

Sets the log level based on a string.

Parameters
log_levelString representation of the log level (e.g., "INFO", "DEBUG", "LOG_INFO", "LOG_DEBUG").