From b43bc048eb4c2c0855d4d7c4ad6b0b3c14e50eb2 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Mon, 27 Jun 2011 10:29:17 +0200 Subject: logging: introduce library-internal logging categories We do this by using a trick: library-internal log categories use negative subsystem numbers, which are converted into positive array indexes at the time of logging. library-internal log categories need to be knwo at compile-time, while application-specified categories now are of unlimited number, as they are dynamically allocated. --- include/osmocom/core/logging.h | 17 ++++--- src/application.c | 2 +- src/logging.c | 112 +++++++++++++++++++++++++++++++++-------- 3 files changed, 104 insertions(+), 27 deletions(-) diff --git a/include/osmocom/core/logging.h b/include/osmocom/core/logging.h index db029402..b477a668 100644 --- a/include/osmocom/core/logging.h +++ b/include/osmocom/core/logging.h @@ -5,7 +5,6 @@ #include #include -#define LOG_MAX_CATEGORY 32 #define LOG_MAX_CTX 8 #define LOG_MAX_FILTERS 8 @@ -20,7 +19,7 @@ #endif -void logp(unsigned int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); +void logp(int subsys, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 5, 6))); /* new logging interface */ #define LOGP(ss, level, fmt, args...) \ @@ -37,6 +36,10 @@ void logp(unsigned int subsys, char *file, int line, int cont, const char *forma #define LOG_FILTER_ALL 0x0001 +/* logging levels defined by the library itself */ +#define DLGLOBAL -1 +#define OSMO_NUM_DLIB 1 + struct log_category { uint8_t loglevel; uint8_t enabled; @@ -65,8 +68,9 @@ struct log_info { log_filter *filter_fn; /* per-category information */ - const struct log_info_cat *cat; + struct log_info_cat *cat; unsigned int num_cat; + unsigned int num_cat_user; }; enum log_target_type { @@ -82,7 +86,8 @@ struct log_target { int filter_map; void *filter_data[LOG_MAX_FILTERS+1]; - struct log_category categories[LOG_MAX_CATEGORY+1]; + struct log_category *categories; + uint8_t loglevel; int use_color:1; int print_timestamp:1; @@ -110,10 +115,10 @@ struct log_target { }; /* use the above macros */ -void logp2(unsigned int subsys, unsigned int level, char *file, +void logp2(int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) __attribute__ ((format (printf, 6, 7))); -void log_init(const struct log_info *cat); +int log_init(const struct log_info *inf, void *talloc_ctx); /* context management */ void log_reset_context(void); diff --git a/src/application.c b/src/application.c index 5f8f4471..b7e943d7 100644 --- a/src/application.c +++ b/src/application.c @@ -44,7 +44,7 @@ void osmo_init_ignore_signals(void) int osmo_init_logging(const struct log_info *log_info) { - log_init(log_info); + log_init(log_info, NULL); osmo_stderr_target = log_target_create_stderr(); if (!osmo_stderr_target) return -1; diff --git a/src/logging.c b/src/logging.c index 3c9dc03f..def13b3b 100644 --- a/src/logging.c +++ b/src/logging.c @@ -40,7 +40,7 @@ #include /* for LOGGING_STR. */ -const struct log_info *osmo_log_info; +struct log_info *osmo_log_info; static struct log_context log_context; static void *tall_log_ctx = NULL; @@ -58,6 +58,16 @@ static const struct value_string loglevel_strs[LOGLEVEL_DEFS+1] = { { 0, NULL }, }; +#define INT2IDX(x) (-1*(x)-1) +static const struct log_info_cat internal_cat[OSMO_NUM_DLIB] = { + [INT2IDX(DLGLOBAL)] = { /* -1 becomes 0 */ + .name = "DLGLOBAL", + .description = "Library-internal global log family", + .loglevel = LOGL_NOTICE, + .enabled = 1, + }, +}; + /* You have to keep this in sync with the structure loglevel_strs. */ const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { "Log simply everything", @@ -69,6 +79,12 @@ const char *loglevel_descriptions[LOGLEVEL_DEFS+1] = { NULL, }; +/* special magic for negative (library-internal) log subsystem numbers */ +static int subsys_lib2index(int subsys) +{ + return (subsys * -1) + (osmo_log_info->num_cat_user-1); +} + int log_parse_level(const char *lvl) { return get_string_value(loglevel_strs, lvl); @@ -84,6 +100,8 @@ int log_parse_category(const char *category) int i; for (i = 0; i < osmo_log_info->num_cat; ++i) { + if (osmo_log_info->cat[i].name == NULL) + continue; if (!strcasecmp(osmo_log_info->cat[i].name+1, category)) return i; } @@ -103,7 +121,7 @@ void log_parse_category_mask(struct log_target* target, const char *_mask) char *category_token = NULL; /* Disable everything to enable it afterwards */ - for (i = 0; i < ARRAY_SIZE(target->categories); ++i) + for (i = 0; i < osmo_log_info->num_cat; ++i) target->categories[i].enabled = 0; category_token = strtok(mask, ":"); @@ -112,6 +130,9 @@ void log_parse_category_mask(struct log_target* target, const char *_mask) char* colon = strstr(category_token, ","); int length = strlen(category_token); + if (!osmo_log_info->cat[i].name) + continue; + if (colon) length = colon - category_token; @@ -189,12 +210,17 @@ err: target->output(target, level, buf); } - -static void _logp(unsigned int subsys, int level, char *file, int line, +static void _logp(int subsys, int level, char *file, int line, int cont, const char *format, va_list ap) { struct log_target *tar; + if (subsys < 0) + subsys = subsys_lib2index(subsys); + + if (subsys > osmo_log_info->num_cat) + subsys = DLGLOBAL; + llist_for_each_entry(tar, &osmo_log_target_list, entry) { struct log_category *category; int output = 0; @@ -234,7 +260,7 @@ static void _logp(unsigned int subsys, int level, char *file, int line, } } -void logp(unsigned int subsys, char *file, int line, int cont, +void logp(int subsys, char *file, int line, int cont, const char *format, ...) { va_list ap; @@ -244,7 +270,7 @@ void logp(unsigned int subsys, char *file, int line, int cont, va_end(ap); } -void logp2(unsigned int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) +void logp2(int subsys, unsigned int level, char *file, int line, int cont, const char *format, ...) { va_list ap; @@ -326,6 +352,14 @@ struct log_target *log_target_create(void) if (!target) return NULL; + target->categories = talloc_zero_array(target, + struct log_category, + osmo_log_info->num_cat); + if (!target->categories) { + talloc_free(target); + return NULL; + } + INIT_LLIST_HEAD(&target->entry); /* initialize the per-category enabled/loglevel from defaults */ @@ -441,8 +475,11 @@ const char *log_vty_command_string(const struct log_info *info) int size = strlen("logging level () ()") + 1; char *str; - for (i = 0; i < info->num_cat; i++) + for (i = 0; i < info->num_cat; i++) { + if (info->cat[i].name == NULL) + continue; size += strlen(info->cat[i].name) + 1; + } for (i = 0; i < LOGLEVEL_DEFS; i++) size += strlen(loglevel_strs[i].str) + 1; @@ -458,17 +495,19 @@ const char *log_vty_command_string(const struct log_info *info) OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < info->num_cat; i++) { - int j, name_len = strlen(info->cat[i].name)+1; - char name[name_len]; + if (info->cat[i].name) { + int j, name_len = strlen(info->cat[i].name)+1; + char name[name_len]; - for (j = 0; j < name_len; j++) - name[j] = tolower(info->cat[i].name[j]); + for (j = 0; j < name_len; j++) + name[j] = tolower(info->cat[i].name[j]); - name[name_len-1] = '\0'; - ret = snprintf(str + offset, rem, "%s|", name+1); - if (ret < 0) - goto err; - OSMO_SNPRINTF_RET(ret, rem, offset, len); + name[name_len-1] = '\0'; + ret = snprintf(str + offset, rem, "%s|", name+1); + if (ret < 0) + goto err; + OSMO_SNPRINTF_RET(ret, rem, offset, len); + } } offset--; /* to remove the trailing | */ rem++; @@ -512,8 +551,11 @@ const char *log_vty_command_description(const struct log_info *info) strlen(LOGGING_STR "Set the log level for a specified category\n") + 1; - for (i = 0; i < info->num_cat; i++) + for (i = 0; i < info->num_cat; i++) { + if (info->cat[i].name == NULL) + continue; size += strlen(info->cat[i].description) + 1; + } for (i = 0; i < LOGLEVEL_DEFS; i++) size += strlen(loglevel_descriptions[i]) + 1; @@ -537,6 +579,8 @@ const char *log_vty_command_description(const struct log_info *info) OSMO_SNPRINTF_RET(ret, rem, offset, len); for (i = 0; i < info->num_cat; i++) { + if (info->cat[i].name == NULL) + continue; ret = snprintf(str + offset, rem, "%s\n", info->cat[i].description); if (ret < 0) @@ -555,8 +599,36 @@ err: return str; } -void log_init(const struct log_info *cat) +int log_init(const struct log_info *inf, void *ctx) { - tall_log_ctx = talloc_named_const(NULL, 1, "logging"); - osmo_log_info = cat; + int i; + + tall_log_ctx = talloc_named_const(ctx, 1, "logging"); + if (!tall_log_ctx) + return -ENOMEM; + + osmo_log_info = talloc_zero(tall_log_ctx, struct log_info); + if (!osmo_log_info) + return -ENOMEM; + + osmo_log_info->num_cat_user = inf->num_cat; + /* total number = number of user cat + library cat */ + osmo_log_info->num_cat = inf->num_cat + OSMO_NUM_DLIB; + + osmo_log_info->cat = talloc_zero_array(osmo_log_info, + struct log_info_cat, + osmo_log_info->num_cat); + if (!osmo_log_info->cat) { + talloc_free(osmo_log_info); + osmo_log_info = NULL; + return -ENOMEM; + } + + /* copy over the user part */ + for (i = 0; i < inf->num_cat; i++) { + memcpy(&osmo_log_info->cat[i], &inf->cat[i], + sizeof(struct log_info_cat)); + } + + /* copy over the library part */ } -- cgit v1.2.3