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
|
* And the resulting log line will include the short_name
|
||||||
* modules[DB].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
|
#ifdef __cplusplus
|
||||||
@@ -93,7 +100,11 @@ enum UC_LOG_DESTINATION {
|
|||||||
struct uc_log_module {
|
struct uc_log_module {
|
||||||
/** The id of the log module.
|
/** The id of the log module.
|
||||||
* This is the id one specifies in the various log
|
* 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;
|
int id;
|
||||||
|
|
||||||
/** A short name for the module.
|
/** A short name for the module.
|
||||||
@@ -103,7 +114,8 @@ struct uc_log_module {
|
|||||||
const char *long_name;
|
const char *long_name;
|
||||||
/** The log level of this module. Only
|
/** The log level of this module. Only
|
||||||
* log statements with a level >= the log_level
|
* 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;
|
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);
|
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.
|
/** Closes and re-opens all the UC_LDEST_FILE log destinations.
|
||||||
* Intended for use when a log file is rotated externally.
|
* 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 SLIST_HEAD(, uc_log_destination) g_destinations;
|
||||||
static int uc_log_reopen_file(struct uc_log_destination *dest);
|
static int uc_log_reopen_file(struct uc_log_destination *dest);
|
||||||
//Uses enum UC_LOG_LEVEL as index
|
//Uses enum UC_LOG_LEVEL as index
|
||||||
static const char *const g_debug_levels[] = {
|
static const char *const g_log_levels[] = {
|
||||||
"NONE",
|
"NONE",
|
||||||
"DEBUG",
|
"DEBUG",
|
||||||
"UNKNOWN_2",
|
"UNKNOWN_2",
|
||||||
"INFO",
|
"INFO",
|
||||||
"UNKNOWN_4"
|
"UNKNOWN_4",
|
||||||
"WARNING",
|
"WARNING",
|
||||||
"UNKNOWN_6",
|
"UNKNOWN_6",
|
||||||
"ERROR"
|
"ERROR"
|
||||||
@@ -80,20 +80,20 @@ static const char *const g_debug_levels[] = {
|
|||||||
|
|
||||||
inline const char *uc_ll_2_str(enum UC_LOG_LEVEL l)
|
inline const char *uc_ll_2_str(enum UC_LOG_LEVEL l)
|
||||||
{
|
{
|
||||||
if (l < ARRAY_SIZE(g_debug_levels)) {
|
if (l < ARRAY_SIZE(g_log_levels)) {
|
||||||
return g_debug_levels[l];
|
return g_log_levels[l];
|
||||||
} else {
|
} else {
|
||||||
return "???";
|
return "???";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//returns if the string is not a known log level
|
//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;
|
size_t i;
|
||||||
|
|
||||||
for (i = 0; i < ARRAY_SIZE(g_debug_levels); i++) {
|
for (i = 0; i < ARRAY_SIZE(g_log_levels); i++) {
|
||||||
if (strcmp(str, g_debug_levels[i]) == 0) {
|
if (strncasecmp(str, g_log_levels[i], len) == 0) {
|
||||||
return (int)i;
|
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;
|
time_buf[sizeof time_buf -1] = 0;
|
||||||
|
|
||||||
|
|
||||||
if (dest->log_location) {
|
if (dest->log_location) {
|
||||||
fprintf(dest->type.file.file, "[%-7s] %s %s:%d [%s] : ",
|
fprintf(dest->type.file.file, "[%-7s] %s %s:%d [%s] : ",
|
||||||
uc_ll_2_str(args->log_level), time_buf, args->file,
|
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,
|
void uc_logf(int log_level, int module, int raw,
|
||||||
const char *file, int line, const char *fmt, ...)
|
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;
|
struct uc_log_destination *dest;
|
||||||
uc_log_init(&modules);
|
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);
|
dest = uc_log_new_file("test.log", UC_LL_INFO, 1);
|
||||||
uc_log_add_destination(dest);
|
uc_log_add_destination(dest);
|
||||||
dest = uc_log_new_syslog("log.test", LOG_DAEMON, UC_LL_INFO, 0);
|
dest = uc_log_new_syslog("log.test", LOG_DAEMON, UC_LL_INFO, 0);
|
||||||
uc_log_add_destination(dest);
|
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_INFO, CC, "Test cc info %d\n", 2);
|
||||||
UC_LOGF( UC_LL_WARNING, HO, "Test HO warning%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_INFO, MAIN, "Test MAIN info \n" );
|
||||||
UC_LOGF( UC_LL_WARNING, MAIN, "Test MAIN warning\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_LOGF( UC_LL_INFO, MAIN, "Test MAIN INFO 2\n" );
|
||||||
|
|
||||||
UC_LOGFR(UC_LL_INFO, MAIN, "Test RAW logging 1\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_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);
|
uc_log_delete_destination(dest);
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+51
-1
@@ -53,10 +53,13 @@ START_TEST (test_logfile_location)
|
|||||||
|
|
||||||
UC_LOGF(UC_LL_DEBUG, 0, "Lorum ipson %d\n", 1);
|
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 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);
|
rc = stat(FILE_NAME, &st);
|
||||||
fail_if(rc != 0, "stat failed: %s\n", strerror(errno));
|
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
|
END_TEST
|
||||||
|
|
||||||
START_TEST (test_logfile_no_location)
|
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);
|
fail_if(st.st_size != 14*2, "was %ld\n", (long)st.st_size);
|
||||||
END_TEST
|
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)
|
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_loglevel_surpressed_module);
|
||||||
tcase_add_test(tc1, test_logfile_reopen_files);
|
tcase_add_test(tc1, test_logfile_reopen_files);
|
||||||
tcase_add_test(tc1, test_logfile_remove_dest);
|
tcase_add_test(tc1, test_logfile_remove_dest);
|
||||||
|
tcase_add_test(tc1, test_logfile_dest_mask);
|
||||||
|
|
||||||
if (access("/dev/full", R_OK) == 0) {
|
if (access("/dev/full", R_OK) == 0) {
|
||||||
tcase_add_test(tc1, test_logfile_full_filesystem);
|
tcase_add_test(tc1, test_logfile_full_filesystem);
|
||||||
|
|||||||
Reference in New Issue
Block a user