rcx

miscellaneous C library
git clone git://git.rr3.xyz/rcx
Log | Files | Refs | README | LICENSE

log.h (3244B)


      1 #pragma once
      2 
      3 #include <stdarg.h>
      4 #include <stdbool.h>
      5 
      6 /* This module provides formatted logging to stderr. All logging functions are
      7  * thread-safe and preserve errno.
      8  *
      9  * The r_{,v}logf_generic functions accept an arbitrary integer log level to
     10  * filter by (see r_log_init) and an associated name (e.g., "info" or "error"),
     11  * color (for when terminal color is enabled via r_log_init), and exit code (to
     12  * terminate the process with if nonzero). This allows users to create their
     13  * own log levels.
     14  *
     15  * The r_{,v}log_basic functions have four fixed log levels (info, warn, error,
     16  * and fatal), with corresponding helper macros. Consult the implementation of
     17  * these macros to see how the main logging functions work. */
     18 
     19 /* TODO: Support optionally logging __func__ */
     20 
     21 #define R_LOG_LEVEL_INFO  0
     22 #define R_LOG_LEVEL_WARN  1
     23 #define R_LOG_LEVEL_ERROR 2
     24 #define R_LOG_LEVEL_FATAL 3
     25 
     26 #define r_logf(level, ...) r_logf_basic(__FILE__, __LINE__, level, __VA_ARGS__)
     27 #define r_infof(...)  r_logf(R_LOG_LEVEL_INFO, __VA_ARGS__)
     28 #define r_warnf(...)  r_logf(R_LOG_LEVEL_WARN, __VA_ARGS__)
     29 #define r_errorf(...) r_logf(R_LOG_LEVEL_ERROR, __VA_ARGS__)
     30 #define r_fatalf(...) r_logf(R_LOG_LEVEL_FATAL, __VA_ARGS__)
     31 
     32 /* Set global logging settings.
     33  *   color:     <0 force disables color, 0 detects if color should be used,
     34  *              and >0 force enables color
     35  *   log_time:  enable/disable timestamps in log messages
     36  *   log_loc:   enable/disable source location in log messages
     37  *   min_level: output log messages iff their level is at least this value
     38  * The color detection happens when r_log_init is called, not on each
     39  * subsequent invocation of a logging function.
     40  *
     41  * r_log_init can be called multiple times, but it is not thread-safe.
     42  * Typically, you should call r_log_init just once and before starting
     43  * multiple threads.
     44  *
     45  * Calling r_log_init is optional. By default, color is off, time and source
     46  * location are not logged, and the minimum log level is set to 0 (so all basic
     47  * logs are printed). */
     48 void r_log_init(int color, bool log_time, bool log_loc, int min_level);
     49 
     50 void r_vlogf_generic(char *file, int line, int level, char *name, char *color, int code, char *fmt, va_list args);
     51 
     52 static inline void
     53 r_logf_generic(char *file, int line, int level, char *name, char *color, int code, char *fmt, ...) {
     54 	va_list args;
     55 	va_start(args, fmt);
     56 	r_vlogf_generic(file, line, level, name, color, code, fmt, args);
     57 	va_end(args);
     58 }
     59 
     60 static inline void
     61 r_vlogf_basic(char *file, int line, int level, char *fmt, va_list args) {
     62 	static char *names[] = { "INFO", "WARN", "ERROR", "FATAL" };
     63 
     64 #define RED    "\x1b[31m"
     65 #define GREEN  "\x1b[32m"
     66 #define YELLOW "\x1b[33m"
     67 	static char *colors[] = { GREEN, YELLOW, RED, RED };
     68 #undef YELLOW
     69 #undef GREEN
     70 #undef RED
     71 
     72 	static int codes[] = { 0, 0, 0, 1 };
     73 
     74 	/* Clamp level */
     75 	if (level < R_LOG_LEVEL_INFO)  level = R_LOG_LEVEL_INFO;
     76 	if (level > R_LOG_LEVEL_FATAL) level = R_LOG_LEVEL_FATAL;
     77 
     78 	r_vlogf_generic(file, line, level, names[level], colors[level], codes[level], fmt, args);
     79 }
     80 
     81 static inline void
     82 r_logf_basic(char *file, int line, int level, char *fmt, ...) {
     83 	va_list args;
     84 	va_start(args, fmt);
     85 	r_vlogf_basic(file, line, level, fmt, args);
     86 	va_end(args);
     87 }