Implement setting log mask string on a destination.
Improve logging docs
This commit is contained in:
+51
-2
@@ -58,6 +58,13 @@
|
||||
* And the resulting log line will include the short_name
|
||||
* modules[DB].short_name
|
||||
*
|
||||
* Log levels of the messages logged are checked first
|
||||
* by the log_level of the uc_log_destination, and then
|
||||
* by the log_level of the module for that destination.
|
||||
*
|
||||
* Thus for a message to actually be logged the level
|
||||
* must be above the overall log level for the destination and
|
||||
* the log level of the module.
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
@@ -93,7 +100,11 @@ enum UC_LOG_DESTINATION {
|
||||
struct uc_log_module {
|
||||
/** The id of the log module.
|
||||
* This is the id one specifies in the various log
|
||||
* functions/macros*/
|
||||
* functions/macros.
|
||||
* Within the struct uc_log_modules, this id must start
|
||||
* at 0 and be incremented consecutively, being equal
|
||||
* to the index within struct uc_log_modules.mods
|
||||
*/
|
||||
int id;
|
||||
|
||||
/** A short name for the module.
|
||||
@@ -103,7 +114,8 @@ struct uc_log_module {
|
||||
const char *long_name;
|
||||
/** The log level of this module. Only
|
||||
* log statements with a level >= the log_level
|
||||
* are actually logged */
|
||||
* are actually logged, but the log_level of a destination
|
||||
* can restrict the logging further*/
|
||||
int log_level;
|
||||
};
|
||||
|
||||
@@ -202,6 +214,43 @@ void uc_log_destination_set_log_location(struct uc_log_destination *dest, int lo
|
||||
void uc_log_delete_destination(struct uc_log_destination *dest);
|
||||
|
||||
|
||||
/** Set the log level for a particular module on this destination
|
||||
*
|
||||
* @param dest destination to chang
|
||||
* @param moudle the module id to change
|
||||
* @param log_level new log level to set for the module
|
||||
*/
|
||||
void uc_log_destination_set_module_loglevel(
|
||||
struct uc_log_destination *dest,
|
||||
int module,
|
||||
enum UC_LOG_LEVEL log_level
|
||||
);
|
||||
|
||||
/** Set the log mask for the given destination.
|
||||
* The log_mask is a string specifying the log levels for
|
||||
* the modules logged by this destination.
|
||||
* The log_level of the destination itself takes priority
|
||||
* over the log_level of the modules.
|
||||
* The format of the log_mask string is.
|
||||
*
|
||||
* SHORT_NAME_1=LEVEL:SHORT_NAME_2=LEVEL:SHORT_NAME_N=LEVEL
|
||||
*
|
||||
* The SHORT_NAME_N is the .short_name within a struct uc_log_module
|
||||
* LEVEL is one of DEBUG,INFO, WARNING or ERROR
|
||||
* Example:
|
||||
* DB=DEBUG:IO=ERROR:POLLER=INFO
|
||||
*
|
||||
* Modules not mentioned in the string retain their default value.
|
||||
* No whitespaces must be specifed before/after the : or = character
|
||||
*
|
||||
* @param dest destination to set the log mask on
|
||||
* @parama log_mask the log mask as described above to set.
|
||||
*/
|
||||
void uc_log_destination_set_mask(
|
||||
struct uc_log_destination *dest,
|
||||
const char *log_mask
|
||||
);
|
||||
|
||||
/** Closes and re-opens all the UC_LDEST_FILE log destinations.
|
||||
* Intended for use when a log file is rotated externally.
|
||||
*
|
||||
|
||||
+80
-8
@@ -67,12 +67,12 @@ static const struct uc_log_module g_unknown_module = {
|
||||
static SLIST_HEAD(, uc_log_destination) g_destinations;
|
||||
static int uc_log_reopen_file(struct uc_log_destination *dest);
|
||||
//Uses enum UC_LOG_LEVEL as index
|
||||
static const char *const g_debug_levels[] = {
|
||||
static const char *const g_log_levels[] = {
|
||||
"NONE",
|
||||
"DEBUG",
|
||||
"UNKNOWN_2",
|
||||
"INFO",
|
||||
"UNKNOWN_4"
|
||||
"UNKNOWN_4",
|
||||
"WARNING",
|
||||
"UNKNOWN_6",
|
||||
"ERROR"
|
||||
@@ -80,20 +80,20 @@ static const char *const g_debug_levels[] = {
|
||||
|
||||
inline const char *uc_ll_2_str(enum UC_LOG_LEVEL l)
|
||||
{
|
||||
if (l < ARRAY_SIZE(g_debug_levels)) {
|
||||
return g_debug_levels[l];
|
||||
if (l < ARRAY_SIZE(g_log_levels)) {
|
||||
return g_log_levels[l];
|
||||
} else {
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
//returns if the string is not a known log level
|
||||
static int uc_str_2_ll(const char *str)
|
||||
static int uc_str_2_ll(const char *str, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < ARRAY_SIZE(g_debug_levels); i++) {
|
||||
if (strcmp(str, g_debug_levels[i]) == 0) {
|
||||
for (i = 0; i < ARRAY_SIZE(g_log_levels); i++) {
|
||||
if (strncasecmp(str, g_log_levels[i], len) == 0) {
|
||||
return (int)i;
|
||||
}
|
||||
}
|
||||
@@ -411,7 +411,6 @@ static inline void uc_vlog_file(const struct uc_log_args *args, const char *fmt,
|
||||
|
||||
time_buf[sizeof time_buf -1] = 0;
|
||||
|
||||
|
||||
if (dest->log_location) {
|
||||
fprintf(dest->type.file.file, "[%-7s] %s %s:%d [%s] : ",
|
||||
uc_ll_2_str(args->log_level), time_buf, args->file,
|
||||
@@ -467,6 +466,79 @@ log:
|
||||
}
|
||||
}
|
||||
|
||||
void uc_log_destination_set_module_loglevel(
|
||||
struct uc_log_destination *dest,
|
||||
int module,
|
||||
enum UC_LOG_LEVEL log_level
|
||||
)
|
||||
{
|
||||
if (dest == NULL)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&g_log_lock);
|
||||
|
||||
if (module >= 0 && module < g_modules.cnt)
|
||||
dest->module_settings[module].log_level = log_level;
|
||||
|
||||
pthread_mutex_unlock(&g_log_lock);
|
||||
}
|
||||
|
||||
|
||||
void uc_log_destination_set_mask(
|
||||
struct uc_log_destination *dest,
|
||||
const char *log_mask
|
||||
)
|
||||
{
|
||||
size_t module_len;
|
||||
|
||||
if (dest == NULL || log_mask == NULL)
|
||||
return;
|
||||
|
||||
pthread_mutex_lock(&g_log_lock);
|
||||
|
||||
while ((module_len = strcspn(log_mask, "=")) != 0) {
|
||||
int i;
|
||||
int level_len;
|
||||
const char *level_str;
|
||||
int log_level;
|
||||
const char *module_str = log_mask;
|
||||
|
||||
log_mask += module_len;
|
||||
if (log_mask[0] == '=')
|
||||
log_mask++;
|
||||
|
||||
level_len = strcspn(log_mask, ":");
|
||||
if (level_len == 0)
|
||||
continue;
|
||||
|
||||
level_str = log_mask;
|
||||
log_mask += level_len;
|
||||
if (log_mask[0] == ':')
|
||||
log_mask++;
|
||||
|
||||
log_level = uc_str_2_ll(level_str, level_len);
|
||||
if (log_level == -1)
|
||||
continue;
|
||||
|
||||
for (i = 0; i < g_modules.cnt; i++) {
|
||||
size_t short_name_len;;
|
||||
|
||||
if (g_modules.mods[i].short_name == NULL)
|
||||
continue;
|
||||
|
||||
short_name_len = strlen(g_modules.mods[i].short_name);
|
||||
module_len = UC_MAX(module_len, short_name_len);
|
||||
|
||||
if (strncasecmp(g_modules.mods[i].short_name,
|
||||
module_str, module_len) == 0) {
|
||||
dest->module_settings[i].log_level = log_level;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&g_log_lock);
|
||||
}
|
||||
|
||||
void uc_logf(int log_level, int module, int raw,
|
||||
const char *file, int line, const char *fmt, ...)
|
||||
{
|
||||
|
||||
+10
-4
@@ -37,25 +37,31 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
struct uc_log_destination *dest;
|
||||
uc_log_init(&modules);
|
||||
dest = uc_log_new_stderr(UC_LL_INFO, 0);
|
||||
uc_log_add_destination(dest);
|
||||
dest = uc_log_new_file("test.log", UC_LL_INFO, 1);
|
||||
uc_log_add_destination(dest);
|
||||
dest = uc_log_new_syslog("log.test", LOG_DAEMON, UC_LL_INFO, 0);
|
||||
uc_log_add_destination(dest);
|
||||
dest = uc_log_new_stderr(UC_LL_INFO, 0);
|
||||
uc_log_add_destination(dest);
|
||||
UC_LOGF( UC_LL_INFO, CC, "Test cc info %d\n", 2);
|
||||
UC_LOGF( UC_LL_WARNING, HO, "Test HO warning%d\n", 2);
|
||||
UC_LOGF( UC_LL_INFO, MAIN, "Test MAIN info \n" );
|
||||
UC_LOGF( UC_LL_WARNING, MAIN, "Test MAIN warning\n" );
|
||||
|
||||
uc_log_module_set_loglevel(MAIN, UC_LL_INFO);
|
||||
uc_log_destination_set_module_loglevel(dest, MAIN, UC_LL_INFO);
|
||||
UC_LOGF( UC_LL_INFO, MAIN, "Test MAIN INFO 2\n" );
|
||||
|
||||
UC_LOGFR(UC_LL_INFO, MAIN, "Test RAW logging 1\n" );
|
||||
|
||||
uc_log_module_set_loglevel(MAIN, UC_LL_WARNING);
|
||||
uc_log_destination_set_module_loglevel(dest,MAIN, UC_LL_WARNING);
|
||||
UC_LOGF( UC_LL_INFO, MAIN, "Test MAIN INFO 3\n" );
|
||||
|
||||
uc_log_destination_set_loglevel(dest, UC_LL_DEBUG);
|
||||
UC_LOGF( UC_LL_DEBUG, MAIN, "Test MAIN DEBUG SHOULD NOT SHOW\n" );
|
||||
//uc_log_destination_set_module_loglevel(dest, MAIN, UC_LL_INFO);
|
||||
uc_log_destination_set_mask(dest, "HO=ERROR:MAIN=DEBUG:HO=DEBUG");
|
||||
UC_LOGF( UC_LL_DEBUG, MAIN, "Test MAIN DEBUG SHOULD SHOW\n" );
|
||||
|
||||
uc_log_delete_destination(dest);
|
||||
|
||||
|
||||
|
||||
+53
-3
@@ -51,12 +51,15 @@ START_TEST (test_logfile_location)
|
||||
fail_if(dest == NULL);
|
||||
uc_log_add_destination(dest);
|
||||
|
||||
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
|
||||
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson 2\n");
|
||||
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
|
||||
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson 2\n");
|
||||
UC_LOGF(UC_LL_INFO, 0, "Lorum ipson 3\n");
|
||||
UC_LOGF(UC_LL_WARNING, 0, "Lorum ipson 4\n");
|
||||
UC_LOGF(UC_LL_ERROR, 0, "Lorum ipson 5\n");
|
||||
|
||||
rc = stat(FILE_NAME, &st);
|
||||
fail_if(rc != 0, "stat failed: %s\n", strerror(errno));
|
||||
fail_if(st.st_size != 76*2, "was %ld\n", (long)st.st_size);
|
||||
fail_if(st.st_size != 380, "was %ld\n", (long)st.st_size);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_logfile_no_location)
|
||||
@@ -361,6 +364,52 @@ START_TEST (test_logfile_raw)
|
||||
fail_if(st.st_size != 14*2, "was %ld\n", (long)st.st_size);
|
||||
END_TEST
|
||||
|
||||
START_TEST (test_logfile_dest_mask)
|
||||
|
||||
struct uc_log_module m[] = {
|
||||
{
|
||||
.id = 0,
|
||||
.short_name = "MOD1",
|
||||
.long_name = "Module 1",
|
||||
.log_level = UC_LL_WARNING,
|
||||
},
|
||||
{
|
||||
.id = 1,
|
||||
.short_name = "MOD2",
|
||||
.long_name = "Module 2",
|
||||
.log_level = UC_LL_WARNING,
|
||||
}
|
||||
};
|
||||
struct uc_log_modules mods = {
|
||||
.mods = m,
|
||||
.cnt = 2,
|
||||
};
|
||||
struct stat st;
|
||||
struct uc_log_destination *dest;
|
||||
int rc;
|
||||
|
||||
uc_log_init(&mods);
|
||||
|
||||
dest = uc_log_new_file(FILE_NAME, UC_LL_DEBUG, 1);
|
||||
fail_if(dest == NULL);
|
||||
uc_log_add_destination(dest);
|
||||
|
||||
UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
|
||||
UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
|
||||
|
||||
rc = stat(FILE_NAME, &st);
|
||||
fail_if(rc != 0, "stat failed: %s\n", strerror(errno));
|
||||
fail_if(st.st_size != 0, "was %ld\n", (long)st.st_size);
|
||||
|
||||
uc_log_destination_set_mask(dest, "MOD1=DEBUG:mod2=Debug");
|
||||
UC_LOGFR(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
|
||||
UC_LOGFR(UC_LL_DEBUG, 1, "Lorum ipson %d\n", 1);
|
||||
|
||||
rc = stat(FILE_NAME, &st);
|
||||
fail_if(rc != 0, "stat failed: %s\n", strerror(errno));
|
||||
fail_if(st.st_size != 14*2, "was %ld\n", (long)st.st_size);
|
||||
END_TEST
|
||||
|
||||
|
||||
Suite *logging_suite(void)
|
||||
{
|
||||
@@ -374,6 +423,7 @@ Suite *logging_suite(void)
|
||||
tcase_add_test(tc1, test_logfile_loglevel_surpressed_module);
|
||||
tcase_add_test(tc1, test_logfile_reopen_files);
|
||||
tcase_add_test(tc1, test_logfile_remove_dest);
|
||||
tcase_add_test(tc1, test_logfile_dest_mask);
|
||||
|
||||
if (access("/dev/full", R_OK) == 0) {
|
||||
tcase_add_test(tc1, test_logfile_full_filesystem);
|
||||
|
||||
Reference in New Issue
Block a user