mirror of https://gerrit.osmocom.org/libosmocore
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:
parent
ea19c97816
commit
b43bc048eb
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
112
src/logging.c
112
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 */
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue