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.
This commit is contained in:
Harald Welte 2011-06-27 10:29:17 +02:00
parent ea19c97816
commit b43bc048eb
3 changed files with 104 additions and 27 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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 */
}