OAuth2Lib/log.c

177 lines
4.3 KiB
C

#include "log.h"
#include <assert.h>
#include <stdarg.h>
#include <time.h>
#include <openssl/err.h>
#include "util/sorted_str_set.h"
static const char* LOG_LEVEL_STRING_TABLE[] = {
"ERROR",
"WARN",
"INFO",
"DEBUG",
"TRACE"
};
// Maybe add __attribute__((constructor)) in the future if available to skip _config_initialized
static bool _user_default_config_initialized = false;
static struct log_config_s _user_default_config;
static sorted_str_set* _module_configs = NULL;
static inline struct log_config_s _default_config() {
if (_user_default_config_initialized) {
return _user_default_config;
}
return (struct log_config_s) {
.loc_error = LOG_LOC_STDS(stderr),
.loc_warn = LOG_LOC_STDS(stderr),
.loc_info = LOG_LOC_STDS(stdout),
.loc_debug = LOG_LOC_NONE(),
.loc_trace = LOG_LOC_NONE(),
.timestamp = true,
};
}
void log_set_default_config(struct log_config_s config) {
_user_default_config = config;
_user_default_config_initialized = true;
}
struct log_config_s* log_get_config(const char* module_name) {
assert(module_name != NULL);
if (!_module_configs) {
if (!(_module_configs = sorted_str_set_new(sizeof(struct log_config_s)))) {
return NULL;
}
}
struct log_config_s default_conf = _default_config();
return sorted_str_set_insert(_module_configs, module_name, &default_conf);
}
void log_log(const char* module, enum LOG_LEVEL log_level, const char* fmt, ...) {
assert(module != NULL);
struct log_config_s* config = log_get_config(module);
assert(config);
struct log_loc* dest_loc;
switch (log_level) {
case LOG_ERR: dest_loc = &config->loc_error; break;
case LOG_WARN: dest_loc = &config->loc_warn; break;
case LOG_INFO: dest_loc = &config->loc_info; break;
case LOG_DEBUG: dest_loc = &config->loc_debug; break;
case LOG_TRACE: dest_loc = &config->loc_trace; break;
default: return;
}
if (dest_loc->type == LOG_LOC_TYPE_DISABLED) {
return;
} else if (dest_loc->type == LOG_LOC_TYPE_FS) {
if (!dest_loc->location) {
if (!(dest_loc->location = fopen(dest_loc->file_name, "a"))) {
return;
}
}
} else if (dest_loc->type != LOG_LOC_TYPE_STDS) {
return;
}
FILE* dest = dest_loc->location;
va_list varargs;
va_start(varargs, fmt);
if (config->timestamp) {
struct timespec utc_time;
struct tm local_time;
char time_str_buf[10+1+8+1];
timespec_get(&utc_time, TIME_UTC);
localtime_r(&(utc_time.tv_sec), &local_time);
if(strftime(time_str_buf, sizeof(time_str_buf), "%F %T", &local_time)) {
fprintf(dest, "[%s.%9lu] ", time_str_buf, utc_time.tv_nsec);
}
}
fprintf(dest, "[%s] %s: ", LOG_LEVEL_STRING_TABLE[log_level], module);
vfprintf(dest, fmt, varargs);
fprintf(dest, "\n");
if (dest_loc->type == LOG_LOC_TYPE_FS && !dest_loc->keep_file_open) {
fclose(dest_loc->location);
dest_loc->location = NULL;
}
}
void log_log_ssl_err(const char* module, enum LOG_LEVEL log_level, const char* fmt, ...) {
assert(module != NULL);
struct log_config_s* config = log_get_config(module);
assert(config);
struct log_loc* dest_loc;
switch (log_level) {
case LOG_ERR: dest_loc = &config->loc_error; break;
case LOG_WARN: dest_loc = &config->loc_warn; break;
case LOG_INFO: dest_loc = &config->loc_info; break;
case LOG_DEBUG: dest_loc = &config->loc_debug; break;
case LOG_TRACE: dest_loc = &config->loc_trace; break;
default: return;
}
if (dest_loc->type == LOG_LOC_TYPE_DISABLED) {
return;
} else if (dest_loc->type == LOG_LOC_TYPE_FS) {
if (!dest_loc->location) {
if (!(dest_loc->location = fopen(dest_loc->file_name, "a"))) {
return;
}
}
} else if (dest_loc->type != LOG_LOC_TYPE_STDS) {
return;
}
FILE* dest = dest_loc->location;
va_list varargs;
va_start(varargs, fmt);
if (config->timestamp) {
struct timespec utc_time;
struct tm local_time;
char time_str_buf[10+1+8+1];
timespec_get(&utc_time, TIME_UTC);
localtime_r(&(utc_time.tv_sec), &local_time);
if(strftime(time_str_buf, sizeof(time_str_buf), "%F %T", &local_time)) {
fprintf(dest, "[%s.%9lu] ", time_str_buf, utc_time.tv_nsec);
}
}
fprintf(dest, "[%s] %s: ", LOG_LEVEL_STRING_TABLE[log_level], module);
vfprintf(dest, fmt, varargs);
fprintf(dest, "\n");
ERR_print_errors_fp(dest);
if (dest_loc->type == LOG_LOC_TYPE_FS && !dest_loc->keep_file_open) {
fclose(dest_loc->location);
dest_loc->location = NULL;
}
}