From de6dd72dbbbcc7facf25c4a2521c71f653c7b1b2 Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Tue, 17 Nov 2015 11:52:24 +0100 Subject: log: Add log_check_level function This commit adds this predicate function which can be used to avoid the execution of code if a certain log level is not enabled. The function will only return 0 (false), if it is sure that a logging call for the same facility and level will not produce any output. This safety criterion shall ensure, that no logging output is lost due to the use of this predicate as a guard. On the other hand, even if the predicate returns != 0 (true), no logging output might get generated by a similar logging command. Note that the current implementation is not focussed on performance, which could be improved by using a lookup table instead of iterating through every target. Sponsored-by: On-Waves ehf --- src/logging.c | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) (limited to 'src') diff --git a/src/logging.c b/src/logging.c index 876964ae..c7b19999 100644 --- a/src/logging.c +++ b/src/logging.c @@ -865,4 +865,43 @@ int log_init(const struct log_info *inf, void *ctx) return 0; } +/*! \brief Check whether a log entry will be generated. + * \returns != 0 if a log entry might get generated by at least one target */ +int log_check_level(int subsys, unsigned int level) +{ + struct log_target *tar; + + if (subsys < 0) + subsys = subsys_lib2index(subsys); + + if (subsys > osmo_log_info->num_cat) + subsys = DLGLOBAL; + + /* TODO: The following could/should be cached (update on config) */ + + llist_for_each_entry(tar, &osmo_log_target_list, entry) { + struct log_category *category; + + category = &tar->categories[subsys]; + /* subsystem is not supposed to be logged */ + if (!category->enabled) + continue; + + /* Check the global log level */ + if (tar->loglevel != 0 && level < tar->loglevel) + continue; + + /* Check the category log level */ + if (tar->loglevel == 0 && category->loglevel != 0 && + level < category->loglevel) + continue; + + /* This might get logged (ignoring filters) */ + return 1; + } + + /* We are sure, that this will not be logged. */ + return 0; +} + /*! @} */ -- cgit v1.2.3 From e0dc6a1c7cd49433bdf592624ff484576a7ce4e4 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Mon, 21 Dec 2015 14:45:16 +0100 Subject: logging: Remove some code duplication Extract the mapping of the subsystem number and the checking for the loglevel to a inline method that is shared between the new and old. --- src/logging.c | 74 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 37 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/logging.c b/src/logging.c index c7b19999..7db7101e 100644 --- a/src/logging.c +++ b/src/logging.c @@ -310,35 +310,52 @@ err: target->output(target, level, buf); } -/*! \brief vararg version of logging function */ -void osmo_vlogp(int subsys, int level, const char *file, int line, - int cont, const char *format, va_list ap) +static inline int map_subsys(int subsys) { - struct log_target *tar; - if (subsys < 0) subsys = subsys_lib2index(subsys); if (subsys > osmo_log_info->num_cat) subsys = DLGLOBAL; + return subsys; +} + +static inline int check_log_to_target(struct log_target *tar, int subsys, int level) +{ + struct log_category *category; + + category = &tar->categories[subsys]; + + /* subsystem is not supposed to be logged */ + if (!category->enabled) + return 0; + + /* Check the global log level */ + if (tar->loglevel != 0 && level < tar->loglevel) + return 0; + + /* Check the category log level */ + if (tar->loglevel == 0 && category->loglevel != 0 && + level < category->loglevel) + return 0; + + /* TODO: Check the filter/selector too? */ + return 1; +} + +/*! \brief vararg version of logging function */ +void osmo_vlogp(int subsys, int level, const char *file, int line, + int cont, const char *format, va_list ap) +{ + struct log_target *tar; + + subsys = map_subsys(subsys); llist_for_each_entry(tar, &osmo_log_target_list, entry) { - struct log_category *category; int output = 0; va_list bp; - category = &tar->categories[subsys]; - /* subsystem is not supposed to be logged */ - if (!category->enabled) - continue; - - /* Check the global log level */ - if (tar->loglevel != 0 && level < tar->loglevel) - continue; - - /* Check the category log level */ - if (tar->loglevel == 0 && category->loglevel != 0 && - level < category->loglevel) + if (!check_log_to_target(tar, subsys, level)) continue; /* Apply filters here... if that becomes messy we will @@ -871,29 +888,12 @@ int log_check_level(int subsys, unsigned int level) { struct log_target *tar; - if (subsys < 0) - subsys = subsys_lib2index(subsys); - - if (subsys > osmo_log_info->num_cat) - subsys = DLGLOBAL; + subsys = map_subsys(subsys); /* TODO: The following could/should be cached (update on config) */ llist_for_each_entry(tar, &osmo_log_target_list, entry) { - struct log_category *category; - - category = &tar->categories[subsys]; - /* subsystem is not supposed to be logged */ - if (!category->enabled) - continue; - - /* Check the global log level */ - if (tar->loglevel != 0 && level < tar->loglevel) - continue; - - /* Check the category log level */ - if (tar->loglevel == 0 && category->loglevel != 0 && - level < category->loglevel) + if (!check_log_to_target(tar, subsys, level)) continue; /* This might get logged (ignoring filters) */ -- cgit v1.2.3 From 79599acd663f7c488560d72d63f4e29587fc63a2 Mon Sep 17 00:00:00 2001 From: Holger Hans Peter Freyther Date: Fri, 15 Jan 2016 16:49:06 +0100 Subject: logging: Move the filter check up as well There doesn't seem to be a reason not to check the filter. Update and extend the test. Currently the filter function will be called once for the log check and once for the output of it. --- src/logging.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/logging.c b/src/logging.c index 7db7101e..1c9c6634 100644 --- a/src/logging.c +++ b/src/logging.c @@ -339,6 +339,15 @@ static inline int check_log_to_target(struct log_target *tar, int subsys, int le level < category->loglevel) return 0; + /* Apply filters here... if that becomes messy we will + * need to put filters in a list and each filter will + * say stop, continue, output */ + if ((tar->filter_map & LOG_FILTER_ALL) != 0) + return 1; + + if (osmo_log_info->filter_fn) + return osmo_log_info->filter_fn(&log_context, tar); + /* TODO: Check the filter/selector too? */ return 1; } @@ -358,17 +367,6 @@ void osmo_vlogp(int subsys, int level, const char *file, int line, if (!check_log_to_target(tar, subsys, level)) continue; - /* Apply filters here... if that becomes messy we will - * need to put filters in a list and each filter will - * say stop, continue, output */ - if ((tar->filter_map & LOG_FILTER_ALL) != 0) - output = 1; - else if (osmo_log_info->filter_fn) - output = osmo_log_info->filter_fn(&log_context, - tar); - if (!output) - continue; - /* According to the manpage, vsnprintf leaves the value of ap * in undefined state. Since _output uses vsnprintf and it may * be called several times, we have to pass a copy of ap. */ -- cgit v1.2.3