diff --git a/lib/pinelog/Makefile.am b/lib/pinelog/Makefile.am index 2eea553..5521812 100644 --- a/lib/pinelog/Makefile.am +++ b/lib/pinelog/Makefile.am @@ -34,101 +34,198 @@ test_CFLAGS = \ LOG_DRIVER = env AM_TAP_AWK='$(AWK)' $(SHELL) $(top_srcdir)/tap-driver.sh TESTS = \ - test_ts_lvl_tr \ - test_ts_lvl_notr \ - test_ts_nolvl_tr \ - test_ts_nolvl_notr \ - test_nots_lvl_tr \ - test_nots_lvl_notr \ - test_nots_nolvl_tr \ - test_nots_nolvl_notr \ - bench_ts_lvl_tr \ - bench_ts_lvl_notr \ - bench_ts_nolvl_tr \ - bench_ts_nolvl_notr \ - bench_nots_lvl_tr \ - bench_nots_lvl_notr \ - bench_nots_nolvl_tr \ - bench_nots_nolvl_notr + fp_test_ts_lvl_tr \ + fp_test_ts_lvl_notr \ + fp_test_ts_nolvl_tr \ + fp_test_ts_nolvl_notr \ + fp_test_nots_lvl_tr \ + fp_test_nots_lvl_notr \ + fp_test_nots_nolvl_tr \ + fp_test_nots_nolvl_notr \ + fp_bench_ts_lvl_tr \ + fp_bench_ts_lvl_notr \ + fp_bench_ts_nolvl_tr \ + fp_bench_ts_nolvl_notr \ + fp_bench_nots_lvl_tr \ + fp_bench_nots_lvl_notr \ + fp_bench_nots_nolvl_tr \ + fp_bench_nots_nolvl_notr \ + str_test_ts_lvl_tr \ + str_test_ts_lvl_notr \ + str_test_ts_nolvl_tr \ + str_test_ts_nolvl_notr \ + str_test_nots_lvl_tr \ + str_test_nots_lvl_notr \ + str_test_nots_nolvl_tr \ + str_test_nots_nolvl_notr \ + str_bench_ts_lvl_tr \ + str_bench_ts_lvl_notr \ + str_bench_ts_nolvl_tr \ + str_bench_ts_nolvl_notr \ + str_bench_nots_lvl_tr \ + str_bench_nots_lvl_notr \ + str_bench_nots_nolvl_tr \ + str_bench_nots_nolvl_notr check_PROGRAMS = $(TESTS) -test_ts_lvl_tr_SOURCES = $(test_SRCFILES) -test_ts_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_ts_lvl_tr_SOURCES = $(test_SRCFILES) +fp_test_ts_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 -test_ts_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_ts_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) -test_ts_lvl_notr_SOURCES = $(test_SRCFILES) -test_ts_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_ts_lvl_notr_SOURCES = $(test_SRCFILES) +fp_test_ts_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 -test_ts_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_ts_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) -test_ts_nolvl_tr_SOURCES = $(test_SRCFILES) -test_ts_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_ts_nolvl_tr_SOURCES = $(test_SRCFILES) +fp_test_ts_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 -test_ts_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_ts_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) -test_ts_nolvl_notr_SOURCES = $(test_SRCFILES) -test_ts_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_ts_nolvl_notr_SOURCES = $(test_SRCFILES) +fp_test_ts_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 -test_ts_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_ts_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) -test_nots_lvl_tr_SOURCES = $(test_SRCFILES) -test_nots_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_nots_lvl_tr_SOURCES = $(test_SRCFILES) +fp_test_nots_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 -test_nots_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_nots_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) -test_nots_lvl_notr_SOURCES = $(test_SRCFILES) -test_nots_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_nots_lvl_notr_SOURCES = $(test_SRCFILES) +fp_test_nots_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 -test_nots_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_nots_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) -test_nots_nolvl_tr_SOURCES = $(test_SRCFILES) -test_nots_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_nots_nolvl_tr_SOURCES = $(test_SRCFILES) +fp_test_nots_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 -test_nots_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_nots_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) -test_nots_nolvl_notr_SOURCES = $(test_SRCFILES) -test_nots_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_test_nots_nolvl_notr_SOURCES = $(test_SRCFILES) +fp_test_nots_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 -test_nots_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_test_nots_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) -bench_ts_lvl_tr_SOURCES = $(bench_SRCFILES) -bench_ts_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_ts_lvl_tr_SOURCES = $(bench_SRCFILES) +fp_bench_ts_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 -bench_ts_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_ts_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) -bench_ts_lvl_notr_SOURCES = $(bench_SRCFILES) -bench_ts_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_ts_lvl_notr_SOURCES = $(bench_SRCFILES) +fp_bench_ts_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 -bench_ts_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_ts_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) -bench_ts_nolvl_tr_SOURCES = $(bench_SRCFILES) -bench_ts_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_ts_nolvl_tr_SOURCES = $(bench_SRCFILES) +fp_bench_ts_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 -bench_ts_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_ts_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) -bench_ts_nolvl_notr_SOURCES = $(bench_SRCFILES) -bench_ts_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_ts_nolvl_notr_SOURCES = $(bench_SRCFILES) +fp_bench_ts_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 -bench_ts_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_ts_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) -bench_nots_lvl_tr_SOURCES = $(bench_SRCFILES) -bench_nots_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_nots_lvl_tr_SOURCES = $(bench_SRCFILES) +fp_bench_nots_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 -bench_nots_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_nots_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) -bench_nots_lvl_notr_SOURCES = $(bench_SRCFILES) -bench_nots_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_nots_lvl_notr_SOURCES = $(bench_SRCFILES) +fp_bench_nots_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 -bench_nots_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_nots_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) -bench_nots_nolvl_tr_SOURCES = $(bench_SRCFILES) -bench_nots_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_nots_nolvl_tr_SOURCES = $(bench_SRCFILES) +fp_bench_nots_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 -bench_nots_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_nots_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) -bench_nots_nolvl_notr_SOURCES = $(bench_SRCFILES) -bench_nots_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ +fp_bench_nots_nolvl_notr_SOURCES = $(bench_SRCFILES) +fp_bench_nots_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 -bench_nots_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) +fp_bench_nots_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +test_CFLAGS += -DPINELOG_BUFFER_SZ=4096 +str_test_ts_lvl_tr_SOURCES = $(test_SRCFILES) +str_test_ts_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 +str_test_ts_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_ts_lvl_notr_SOURCES = $(test_SRCFILES) +str_test_ts_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 +str_test_ts_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_ts_nolvl_tr_SOURCES = $(test_SRCFILES) +str_test_ts_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 +str_test_ts_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_ts_nolvl_notr_SOURCES = $(test_SRCFILES) +str_test_ts_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 +str_test_ts_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_nots_lvl_tr_SOURCES = $(test_SRCFILES) +str_test_nots_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 +str_test_nots_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_nots_lvl_notr_SOURCES = $(test_SRCFILES) +str_test_nots_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 +str_test_nots_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_nots_nolvl_tr_SOURCES = $(test_SRCFILES) +str_test_nots_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 +str_test_nots_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_test_nots_nolvl_notr_SOURCES = $(test_SRCFILES) +str_test_nots_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 +str_test_nots_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_ts_lvl_tr_SOURCES = $(bench_SRCFILES) +str_bench_ts_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 +str_bench_ts_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_ts_lvl_notr_SOURCES = $(bench_SRCFILES) +str_bench_ts_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 +str_bench_ts_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_ts_nolvl_tr_SOURCES = $(bench_SRCFILES) +str_bench_ts_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 +str_bench_ts_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_ts_nolvl_notr_SOURCES = $(bench_SRCFILES) +str_bench_ts_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=1 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 +str_bench_ts_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_nots_lvl_tr_SOURCES = $(bench_SRCFILES) +str_bench_nots_lvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=1 +str_bench_nots_lvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_nots_lvl_notr_SOURCES = $(bench_SRCFILES) +str_bench_nots_lvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=1 -DPINELOG_SHOW_BACKTRACE=0 +str_bench_nots_lvl_notr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_nots_nolvl_tr_SOURCES = $(bench_SRCFILES) +str_bench_nots_nolvl_tr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=1 +str_bench_nots_nolvl_tr_LDFLAGS = $(WARN_LDFLAGS) + +str_bench_nots_nolvl_notr_SOURCES = $(bench_SRCFILES) +str_bench_nots_nolvl_notr_CFLAGS = $(WARN_CFLAGS) $(test_CFLAGS) \ + -DPINELOG_SHOW_DATE=0 -DPINELOG_SHOW_LEVEL=0 -DPINELOG_SHOW_BACKTRACE=0 +str_bench_nots_nolvl_notr_LDFLAGS = $(WARN_LDFLAGS) diff --git a/lib/pinelog/pinelog.c b/lib/pinelog/pinelog.c index c5b2e22..558d2f1 100644 --- a/lib/pinelog/pinelog.c +++ b/lib/pinelog/pinelog.c @@ -8,6 +8,8 @@ #include #include +#include +#include #include #include @@ -24,6 +26,15 @@ #define PINELOG_DEFAULT_LEVEL PINELOG_LVL_ERROR #endif +/* + * Buffer size is used to create an automatic buffer. Set to 0 to disable, + * and write directly to the output stream. The drawback is that log messages + * from multiple threads may be interleaved without a buffer. + */ +#ifndef PINELOG_BUFFER_SZ +#define PINELOG_BUFFER_SZ 0 +#endif + /********************************************************************** * Configure logging parameters *********************************************************************/ @@ -76,6 +87,15 @@ static FILE *output_stream = NULL; /** Default logging level */ static int log_level = PINELOG_DEFAULT_LEVEL; +/** Number of modules */ +static int num_modules = 0; + +/** Per module logging levels */ +static int *module_level = NULL; + +/** Module names */ +static const char **module_name = NULL; + /* Initialize defaults */ #if defined __has_attribute # if __has_attribute(constructor) @@ -88,6 +108,42 @@ void pinelog_set_defaults(void) log_level = PINELOG_DEFAULT_LEVEL; } +int pinelog_init(int count) { + int rc = 0; + int i; + + if (count <= 0) { + return EINVAL; + } + + num_modules = count; + free(module_level); + free(module_name); + + module_level = calloc(sizeof(*module_level), count); + if (module_level == NULL) { + rc = errno; + goto cleanup; + } + + module_name = calloc(sizeof(*module_name), count); + if (module_name == NULL) { + rc = errno; + goto cleanup; + } + + for (i = 0; i < count; i++) { + module_level[i] = PINELOG_LVL_NOTSET; + } + + return 0; + +cleanup: + num_modules = 0; + free(module_level); + free(module_name); + return rc; +} #if defined __has_attribute # if __has_attribute(destructor) __attribute__((destructor)) @@ -153,15 +209,73 @@ int pinelog_set_level(int level) return 0; } +int pinelog_get_module_level(int module) +{ + int global_level = pinelog_get_level(); + int level = global_level; + + if (module >= 0 && module < num_modules) { + level = module_level[module]; + if (level == PINELOG_LVL_NOTSET) { + level = global_level; + } + } + + return level; +} + +int pinelog_set_module_level(int module, int level) +{ + if (module < 0 || module > num_modules) { + if (module == PINELOG_MODULE_GLOBAL) { + return pinelog_set_level(level); + } + + return ERANGE; + } + + if (level < PINELOG_LVL_NOTSET || level > PINELOG_LVL_TRACE) { + return EINVAL; + } + + module_level[module] = level; + return 0; +} + +int pinelog_setup_module(int module, const char *name) +{ + if (module < 0 || module > num_modules) { + return ERANGE; + } + + if (name == NULL) { + return EINVAL; + } + + module_name[module] = name; + return 0; +} + /********************************************************************** * Log the message to the output stream *********************************************************************/ -void pinelog_log_message(int level, const char *file, int line, const char *fmt, ...) +void pinelog_log_message(int module, int level, const char *file, int line, const char *fmt, ...) { + #if PINELOG_BUFFER_SZ + char output_buffer[PINELOG_BUFFER_SZ]; + size_t buf_pos = 0; + #endif + va_list ap; + /* Break out if the module is not in the acceptable range */ + if ((module < 0 || module >= num_modules ) && module != PINELOG_MODULE_GLOBAL) { + return; + } + + /* Reset the level if we are in a module and the level is NOTSET */ /* Don't log anything if the level is not severe enough */ - if (level > log_level || level < 0) { + if (level > pinelog_get_module_level(module) || level < 0) { return; } @@ -187,12 +301,17 @@ void pinelog_log_message(int level, const char *file, int line, const char *fmt, time_t t; struct tm tm1; struct tm *tmp; - char date_string[30]; t = time(NULL); tmp = localtime_r(&t, &tm1); if (tmp != NULL) { + #if PINELOG_BUFFER_SZ + buf_pos += strftime(output_buffer + buf_pos, sizeof(output_buffer) - buf_pos, + "%F %T ", tmp); + #else + char date_string[30]; strftime(date_string, sizeof(date_string), "%F %T ", tmp); fputs(date_string, output_stream); + #endif } } while (0); #endif @@ -208,18 +327,46 @@ void pinelog_log_message(int level, const char *file, int line, const char *fmt, PINELOG_TRACE_STR, }; + #if PINELOG_BUFFER_SZ + buf_pos += snprintf(output_buffer + buf_pos, sizeof(output_buffer) - buf_pos, + "%s: ", level_strings[level]); + #else fputs(level_strings[level], output_stream); fputs(": ", output_stream); + #endif } while (0); #endif #if PINELOG_SHOW_BACKTRACE + #if PINELOG_BUFFER_SZ + buf_pos += snprintf(output_buffer + buf_pos, sizeof(output_buffer) - buf_pos, + "%s:%d ", file, line); + #else fprintf(output_stream, "%s:%d ", file, line); + #endif #endif + /* Set the module name if it is not the root */ + if (module != PINELOG_MODULE_GLOBAL) { + #if PINELOG_BUFFER_SZ + buf_pos += snprintf(output_buffer + buf_pos, sizeof(output_buffer) - buf_pos, + "%s: ", module_name[module]); + #else + fprintf(output_stream, "%s: ", module_name[module]); + #endif + } + va_start(ap, fmt); + #if PINELOG_BUFFER_SZ + buf_pos += vsnprintf(output_buffer + buf_pos, sizeof(output_buffer) - buf_pos, + fmt, ap); + // Append a trailing newline to flush the log message + buf_pos += snprintf(output_buffer + buf_pos, sizeof(output_buffer) - buf_pos, "\n"); + fputs(output_buffer, output_stream); + #else vfprintf(output_stream, fmt, ap); - va_end(ap); // Append a trailing newline to flush the log message fputs("\n", output_stream); + #endif + va_end(ap); } diff --git a/lib/pinelog/pinelog.h b/lib/pinelog/pinelog.h index 6f090df..61de8e0 100644 --- a/lib/pinelog/pinelog.h +++ b/lib/pinelog/pinelog.h @@ -34,6 +34,12 @@ extern "C" { * logged to the logging framework. */ enum { + /** + * In modules, it will defer to the global level. + * Equivalent to \ref PINELOG_LVL_NONE for the global level + */ + PINELOG_LVL_NOTSET = -2, + /** No messages will be logged */ PINELOG_LVL_NONE = -1, @@ -61,6 +67,25 @@ enum { */ void pinelog_set_defaults(void); +/** + * @brief Initialize pinelog to have these many modules + * + * @param[in] num_modules Maximum number of modules + * + * @returns 0 on success, errno on failure. + */ +int pinelog_init(int num_modules); + +/** + * @brief Save the current module name + * + * @param[in] module Module identifier + * @param[in] name Module name - displayed in logs + * + * @returns 0 on success, errno on failure. + */ +int pinelog_setup_module(int module, const char *name); + /** * @brief Close the output stream and terminate the logs */ @@ -95,7 +120,7 @@ int pinelog_set_output_stream(FILE *stream); int pinelog_set_output_file(const char *file); /** - * @brief Set the logging level + * @brief Set the global logging level * * @param[in] level Level to filter * @@ -104,12 +129,32 @@ int pinelog_set_output_file(const char *file); int pinelog_set_level(int level); /** - * @brief Get the logging level + * @brief Get the global logging level * - * @returns the configured logging level + * @returns the configured global logging level */ int pinelog_get_level(void); +/** + * @brief Set the per-module logging level + * + * @param[in] module Module identifier + * @param[in] level Level to filter + * + * @returns 0 on success, EINVAL if the level or module identifier is not valid + */ +int pinelog_set_module_level(int module, int level); + +/** + * @brief Get the per-module logging level + * + * @param[in] module Module identifier + * + * @returns the configured per-module logging level, or the global logging level + * if the module identifier is outside the configured range. + */ +int pinelog_get_module_level(int module); + /** * @brief Log a message to the logger * @@ -117,6 +162,7 @@ int pinelog_get_level(void); * never need to call this directly, but instead, should always use the * \code PINELOG_* macros. * + * @param[in] module Module identifier * @param[in] level Level to log the message at * @param[in] fmt Format string * @@ -124,10 +170,10 @@ int pinelog_get_level(void); */ #if defined __has_attribute # if __has_attribute(format) - __attribute__((format(printf, 4, 5))) + __attribute__((format(printf, 5, 6))) # endif #endif -void pinelog_log_message(int level, const char *file, int line, const char *fmt, ...); +void pinelog_log_message(int module, int level, const char *file, int line, const char *fmt, ...); // Test harness will redefine pinelog_exit #ifndef PINELOG_TEST @@ -144,42 +190,49 @@ void pinelog_log_message(int level, const char *file, int line, const char *fmt, # define PINELOG_FILE __FILE__ #endif +// Global module - used for generic logging +#define PINELOG_MODULE_GLOBAL -1 + +#ifndef PINELOG_MODULE +#define PINELOG_MODULE PINELOG_MODULE_GLOBAL +#endif + #define PINELOG_FATAL(fmt, ...) do { \ - if (PINELOG_LVL_FATAL <= pinelog_get_level()) { \ - pinelog_log_message(PINELOG_LVL_FATAL, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ + if (PINELOG_LVL_FATAL <= pinelog_get_module_level(PINELOG_MODULE)) { \ + pinelog_log_message(PINELOG_MODULE, PINELOG_LVL_FATAL, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ } \ pinelog_exit(1); \ } while (0) #define PINELOG_ERROR(fmt, ...) do { \ - if (PINELOG_LVL_ERROR <= pinelog_get_level()) { \ - pinelog_log_message(PINELOG_LVL_ERROR, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ + if (PINELOG_LVL_ERROR <= pinelog_get_module_level(PINELOG_MODULE)) { \ + pinelog_log_message(PINELOG_MODULE, PINELOG_LVL_ERROR, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ } \ } while (0) #define PINELOG_WARN(fmt, ...) do { \ - if (PINELOG_LVL_WARNING <= pinelog_get_level()) { \ - pinelog_log_message(PINELOG_LVL_WARNING, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ + if (PINELOG_LVL_WARNING <= pinelog_get_module_level(PINELOG_MODULE)) { \ + pinelog_log_message(PINELOG_MODULE, PINELOG_LVL_WARNING, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ } \ } while(0) #define PINELOG_INFO(fmt, ...) do { \ - if (PINELOG_LVL_INFO <= pinelog_get_level()) { \ - pinelog_log_message(PINELOG_LVL_INFO, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ + if (PINELOG_LVL_INFO <= pinelog_get_module_level(PINELOG_MODULE)) { \ + pinelog_log_message(PINELOG_MODULE, PINELOG_LVL_INFO, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ } \ } while(0) #define PINELOG_DEBUG(fmt, ...) do { \ - if (PINELOG_LVL_DEBUG <= pinelog_get_level()) { \ - pinelog_log_message(PINELOG_LVL_DEBUG, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ + if (PINELOG_LVL_DEBUG <= pinelog_get_module_level(PINELOG_MODULE)) { \ + pinelog_log_message(PINELOG_MODULE, PINELOG_LVL_DEBUG, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ } \ } while(0) /* PINELOG_DISABLE_TRACE allows all traces to be compiled out */ #ifndef PINELOG_DISABLE_TRACE #define PINELOG_TRACE(fmt, ...) do { \ - if (PINELOG_LVL_TRACE <= pinelog_get_level()) { \ - pinelog_log_message(PINELOG_LVL_TRACE, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ + if (PINELOG_LVL_TRACE <= pinelog_get_module_level(PINELOG_MODULE)) { \ + pinelog_log_message(PINELOG_MODULE, PINELOG_LVL_TRACE, PINELOG_FILE, __LINE__, fmt, ##__VA_ARGS__); \ } \ } while(0) #else diff --git a/lib/pinelog/test_pinelog.c b/lib/pinelog/test_pinelog.c index def0234..bb2ec46 100644 --- a/lib/pinelog/test_pinelog.c +++ b/lib/pinelog/test_pinelog.c @@ -64,7 +64,7 @@ static void dump_data(const char *type, size_t len, char *data) printf("\n"); } -static int test_setup(int level, int filter, const char *file, int line) +static int test_setup(int module, int level, int filter, const char *file, int line) { expected_len = 0; memset(expected_output, 0, sizeof(expected_output)); @@ -114,6 +114,12 @@ static int test_setup(int level, int filter, const char *file, int line) "%s:%d ", basename, line); } + if (module >= 0) { + static const char * modules[] = {"foo", "bar"}; + expected_len += snprintf(&expected_output[expected_len], + sizeof(expected_output) - expected_len, + "%s: ", modules[module]); + } return 1; } @@ -148,24 +154,29 @@ static void verify_defaults(void) #define PINELOG_WARNING PINELOG_WARN -#define TEST_LOG(lvl, filter, fmt, ...) do { \ - if (test_setup(PINELOG_LVL_ ## lvl, PINELOG_LVL_ ## filter, \ +#define TEST_LOG(module, lvl, filter, fmt, ...) do { \ + if (test_setup(module, PINELOG_LVL_ ## lvl, PINELOG_LVL_ ## filter, \ __FILE__, __LINE__)) \ expected_len += snprintf(&expected_output[expected_len], \ sizeof(expected_output) - expected_len, \ fmt "\n", ##__VA_ARGS__); \ PINELOG_ ## lvl (fmt, ##__VA_ARGS__); \ - test_teardown("Log " #lvl " filter " #filter); \ + switch (module) { \ + case -1: test_teardown("Global Log " #lvl " filter " #filter); break; \ + case 0: test_teardown("Module foo Log " #lvl " filter " #filter); break; \ + case 1: test_teardown("Module bar Log " #lvl " filter " #filter); break; \ + default: test_teardown("Module ??? Log " #lvl " filter " #filter); break; \ + } \ } while(0) -#define TEST(filter, fmt, ...) do { \ +#define TEST(module, filter, fmt, ...) do { \ pinelog_set_level(PINELOG_LVL_ ## filter); \ - TEST_LOG(TRACE, filter, fmt, ##__VA_ARGS__); \ - TEST_LOG(DEBUG, filter, fmt, ##__VA_ARGS__); \ - TEST_LOG(INFO, filter, fmt, ##__VA_ARGS__); \ - TEST_LOG(WARNING, filter, fmt, ##__VA_ARGS__); \ - TEST_LOG(ERROR, filter, fmt, ##__VA_ARGS__); \ - TEST_LOG(FATAL, filter, fmt, ##__VA_ARGS__); \ + TEST_LOG(module, TRACE, filter, fmt, ##__VA_ARGS__); \ + TEST_LOG(module, DEBUG, filter, fmt, ##__VA_ARGS__); \ + TEST_LOG(module, INFO, filter, fmt, ##__VA_ARGS__); \ + TEST_LOG(module, WARNING, filter, fmt, ##__VA_ARGS__); \ + TEST_LOG(module, ERROR, filter, fmt, ##__VA_ARGS__); \ + TEST_LOG(module, FATAL, filter, fmt, ##__VA_ARGS__); \ } while (0) #if defined __has_attribute @@ -210,14 +221,24 @@ int main(int argc, char **argv) verify_defaults(); + pinelog_init(2); + pinelog_setup_module(0, "foo"); + pinelog_setup_module(1, "bar"); + pinelog_set_output_stream(observed_stream_w); - TEST(TRACE, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); - TEST(DEBUG, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); - TEST(INFO, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); - TEST(WARNING, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); - TEST(ERROR, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); - TEST(FATAL, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); - TEST(NONE, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + for (int i = -1; i < 2; i++) { + #ifdef PINELOG_MODULE + #undef PINELOG_MODULE + #define PINELOG_MODULE i + #endif + TEST(i, TRACE, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + TEST(i, DEBUG, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + TEST(i, INFO, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + TEST(i, WARNING, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + TEST(i, ERROR, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + TEST(i, FATAL, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + TEST(i, NONE, "testing %s... %d, %f, %u", "testing", -1, 0.0, 1); + } printf("1..%u\n", test_id);