diff --git a/src/logging.c b/src/logging.c index 2ace73e..d6de280 100644 --- a/src/logging.c +++ b/src/logging.c @@ -9,6 +9,11 @@ #include "ucore/logging.h" +//used to realise per destination settings +struct uc_log_module_setting { + int log_level; +}; + struct uc_log_destination { SLIST_ENTRY(uc_log_destination) entry; enum UC_LOG_DESTINATION dest_type; @@ -16,6 +21,7 @@ struct uc_log_destination { int log_level; //Whether to log the source file name and line number int log_location; + struct uc_log_module_setting *module_settings; union { //for syslog openlog() struct { @@ -95,6 +101,22 @@ static inline int uc_ll_2_syslog(enum UC_LOG_LEVEL l) return LOG_INFO; } +static int uc_log_init_settings(struct uc_log_destination *dest) +{ + int i; + + dest->module_settings = calloc(g_modules.cnt, sizeof *dest->module_settings); + if (dest->module_settings == NULL) { + return -1; + } + + for (i = 0; i < g_modules.cnt; i++) { + dest->module_settings[i].log_level = g_modules.mods[i].log_level; + } + + return 0; +} + struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location) { struct uc_log_destination *dest = calloc(1, sizeof *dest); @@ -102,6 +124,11 @@ struct uc_log_destination *uc_log_new_stderr(int log_level, int log_location) if(dest == NULL) return NULL; + if (uc_log_init_settings(dest) != 0) { + free(dest); + return NULL; + } + dest->dest_type = UC_LDEST_STDERR; dest->type.file.file = stderr; dest->log_level = log_level;; @@ -118,9 +145,15 @@ struct uc_log_destination *uc_log_new_syslog(const char *ident, int facility, in if (dest == NULL) return NULL; + if (uc_log_init_settings(dest) != 0) { + free(dest); + return NULL; + } + //copy the ident - though it's unused inside the struct for now id = strdup(ident); if (id == NULL) { + free(dest->module_settings); free(dest); return NULL; } @@ -145,14 +178,21 @@ struct uc_log_destination *uc_log_new_file(const char *filename, int log_level, if (dest == NULL) return NULL; + if (uc_log_init_settings(dest) != 0) { + free(dest); + return NULL; + } + name = strdup(filename); if (name == NULL) { + free(dest->module_settings); free(dest); return NULL; } f = fopen(filename, "a"); if (f == NULL) { + free(dest->module_settings); free(name); free(dest); return NULL; @@ -245,6 +285,7 @@ void uc_log_delete_destination(struct uc_log_destination *dest) free(dest->type.file.file_name); break; } + free(dest->module_settings); free(dest); @@ -412,43 +453,51 @@ void uc_logf(int log_level, int module, int raw, else log_module = &g_unknown_module; - //Check if the module should not be logged - if (log_level < log_module->log_level) - goto out; - //do logging for each destination SLIST_FOREACH(dest, &g_destinations, entry) { va_list apc; + int module_log_level; - if (log_level >= dest->log_level) { - const struct uc_log_args args = { - .dest = dest, - .module = log_module, - .log_level = log_level, - .file = file, - .line = line, - .raw = raw - }; - //log func will mess with the va_list, - //so make a copy - va_copy(apc, ap); + //destnation level + if (log_level < dest->log_level) + continue; - switch (dest->dest_type) { - case UC_LDEST_SYSLOG: - uc_vlog_syslog(&args, fmt, apc); - break; - case UC_LDEST_STDERR: - case UC_LDEST_FILE: - uc_vlog_file(&args, fmt, apc); - break; - } + //individual module level + if (module >= 0 && module < g_modules.cnt) + module_log_level = dest->module_settings[module].log_level; + else //application bug. use global/unknown module + module_log_level = log_module->log_level; - va_end(apc); + if (log_level < module_log_level) + continue; + + const struct uc_log_args args = { + .dest = dest, + .module = log_module, + .log_level = log_level, + .file = file, + .line = line, + .raw = raw + }; + + //log func will mess with the va_list, + //so make a copy + va_copy(apc, ap); + + switch (dest->dest_type) { + case UC_LDEST_SYSLOG: + uc_vlog_syslog(&args, fmt, apc); + break; + case UC_LDEST_STDERR: + case UC_LDEST_FILE: + uc_vlog_file(&args, fmt, apc); + break; } + + va_end(apc); } -out: pthread_mutex_unlock(&g_log_lock); va_end(ap); }