aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2011-06-27 10:29:17 +0200
committerHarald Welte <laforge@gnumonks.org>2011-06-27 10:40:25 +0200
commitb43bc048eb4c2c0855d4d7c4ad6b0b3c14e50eb2 (patch)
treebd413e31f3b84238287a01d19128809433b93b2c
parentea19c978160af32e4fee8001f5308518bcf4fd4c (diff)
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.
-rw-r--r--include/osmocom/core/logging.h17
-rw-r--r--src/application.c2
-rw-r--r--src/logging.c112
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 <stdint.h>
#include <osmocom/core/linuxlist.h>
-#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 <osmocom/vty/logging.h> /* 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 */
}