From 2ce3523cd91426310d4bd1e2563cb7af09d0d5bd Mon Sep 17 00:00:00 2001 From: Martin Mares Date: Thu, 19 Feb 2009 19:35:04 +0100 Subject: [PATCH] Logging: Implemented message types. --- ucw/doc/log.txt | 9 +++++++++ ucw/log-internal.h | 2 ++ ucw/log-stream.c | 33 +++++++++++++++++++++++++++++++++ ucw/log.c | 43 +++++++++++++++++++++++++++++++++++++------ ucw/log.h | 13 ++++++++++++- 5 files changed, 93 insertions(+), 7 deletions(-) diff --git a/ucw/doc/log.txt b/ucw/doc/log.txt index a24a50dd..94e1e82a 100644 --- a/ucw/doc/log.txt +++ b/ucw/doc/log.txt @@ -89,6 +89,15 @@ Example return 0; } +Message types +------------- +Messages can also have types, which can be used for further filtering inside streams. +By default, there is only the default message type. To obtain an identifier of a new +type (again to be OR'ed to the log level when calling <>), use <>. +The number of types is currently limited to 32. + +If you want non-default types to be visible, enable the `LSFMT_TYPE` format flag. + Processes, threads and signals ------------------------------ When you fork a new process, it automatically inherits all currently configured log diff --git a/ucw/log-internal.h b/ucw/log-internal.h index 9651d033..5d21ce77 100644 --- a/ucw/log-internal.h +++ b/ucw/log-internal.h @@ -29,4 +29,6 @@ extern int log_streams_after; extern struct log_stream log_stream_default; +extern char **log_type_names; + #endif diff --git a/ucw/log-stream.c b/ucw/log-stream.c index 3e94d748..8b697f8b 100644 --- a/ucw/log-stream.c +++ b/ucw/log-stream.c @@ -136,6 +136,7 @@ log_new_stream(size_t size) /* Initialize the stream */ bzero(l, sizeof(*l)); l->levels = ~0U; + l->types = ~0U; l->regnum = LS_SET_STRNUM(index); clist_init(&l->substreams); return log_ref_stream(l); @@ -168,3 +169,35 @@ log_set_format(struct log_stream *ls, uns mask, uns data) CLIST_FOR_EACH(simp_node *, i, ls->substreams) log_set_format(i->p, mask, data); } + +/*** Registry of type names ***/ + +int log_register_type(const char *name) +{ + if (!log_type_names) + { + log_type_names = xmalloc_zero(LS_GET_TYPE(~0U) * sizeof(char *)); + log_type_names[0] = "default"; + } + uns id; + for (id=0; id < LS_GET_TYPE(~0U) && log_type_names[id]; id++) + if (!strcmp(log_type_names[id], name)) + return LS_SET_TYPE(id); + ASSERT(id < LS_GET_TYPE(~0U)); + log_type_names[id] = xstrdup(name); + return LS_SET_TYPE(id); +} + +/** Find a message type by name and return its ID encoded by `LS_SET_TYPE`. Returns -1 if no such type found. **/ +int log_find_type(const char *name) +{ + if (!strcmp(name, "default")) + return 0; + if (!log_type_names) + return -1; + + for (uns id=0; id < LS_GET_TYPE(~0U) && log_type_names[id]; id++) + if (!strcmp(log_type_names[id], name)) + return LS_SET_TYPE(id); + return -1; +} diff --git a/ucw/log.c b/ucw/log.c index 0810451b..35a0cc83 100644 --- a/ucw/log.c +++ b/ucw/log.c @@ -42,6 +42,7 @@ struct log_stream log_stream_default = { .use_count = 1000000, .handler = default_log_handler, .levels = ~0U, + .types = ~0U, .msgfmt = LSFMT_DEFAULT, // an empty clist .substreams.head.next = (cnode *) &log_stream_default.substreams.head, @@ -71,6 +72,21 @@ log_stream_by_flags(uns flags) return log_streams.ptr[n]; } +/*** Known message types ***/ + +char **log_type_names; + +char * +log_type_name(uns flags) +{ + uns type = LS_GET_TYPE(flags); + + if (!log_type_names || !log_type_names[type]) + return "default"; + else + return log_type_names[type]; +} + /*** Logging ***/ void @@ -193,10 +209,10 @@ log_pass_msg(int depth, struct log_stream *ls, struct log_msg *m) return 1; } - /* Filter by level and hook function */ - if (!((1 << LS_GET_LEVEL(m->flags)) & ls->levels)) - return 0; - if (ls->filter && ls->filter(ls, m)) + /* Filter by level, type and hook function */ + if (!((1 << LS_GET_LEVEL(m->flags)) & ls->levels) || + !((1 << LS_GET_TYPE(m->flags)) & ls->types) || + ls->filter && ls->filter(ls, m)) return 0; /* Pass the message to substreams */ @@ -208,12 +224,19 @@ log_pass_msg(int depth, struct log_stream *ls, struct log_msg *m) if (!ls->handler) return 0; + /* Will print a message type? */ + char *type = NULL; + if ((ls->msgfmt & LSFMT_TYPE) && LS_GET_TYPE(m->flags)) + type = log_type_name(m->flags); + /* Upper bound on message length */ int len = strlen(m->raw_msg) + strlen(m->stime) + strlen(m->sutime) + 32; if (log_title) len += strlen(log_title); if (ls->name) len += strlen(ls->name); + if (type) + len += strlen(type) + 3; /* Get a buffer and format the message */ char *free_buf = NULL; @@ -268,6 +291,10 @@ log_pass_msg(int depth, struct log_stream *ls, struct log_msg *m) p += sprintf(p, " "); } + /* Message type ( |type| + 3 chars ) */ + if (ls->msgfmt & LSFMT_TYPE) + p += sprintf(p, "{%s} ", type); + /* The message itself ( |m| + 1 chars ) */ { const char *q = m->raw_msg; @@ -369,14 +396,18 @@ log_fork(void) int main(void) { + int type = log_find_type("foo"); + ASSERT(type < 0); + type = log_register_type("foo"); + struct log_stream *ls = log_new_syslog("local3", 0); #if 0 log_add_substream(ls, ls); ls->stream_flags |= LSFLAG_ERR_IS_FATAL; #endif msg(L_INFO | ls->regnum, "Brum <%300s>", ":-)"); - log_set_format(log_default_stream(), ~0U, LSFMT_USEC); - msg(L_INFO, "Brum <%300s>", ":-)"); + log_set_format(log_default_stream(), ~0U, LSFMT_USEC | LSFMT_TYPE); + msg(L_INFO | type, "Brum <%300s>", ":-)"); log_close_all(); return 0; } diff --git a/ucw/log.h b/ucw/log.h index 3c7264a6..d0f1a9f8 100644 --- a/ucw/log.h +++ b/ucw/log.h @@ -35,6 +35,7 @@ struct log_stream { char *name; // Optional name, allocated by the user (or constructor) int regnum; // Stream number, already encoded by LS_SET_STRNUM(); -1 if closed uns levels; // Bitmask of accepted severity levels (default: all) + uns types; // Bitmask of accepted message types (default: all) uns msgfmt; // Formatting flags (LSFMT_xxx) uns use_count; // Number of references to the stream uns stream_flags; // Various other flags (LSFLAG_xxx) @@ -55,6 +56,7 @@ enum ls_fmt { LSFMT_TITLE = 8, // program title (log_title) */ LSFMT_PID = 16, // program PID (log_pid) */ LSFMT_LOGNAME = 32, // name of the log_stream */ + LSFMT_TYPE = 64, // message type }; #define LSFMT_DEFAULT (LSFMT_LEVEL | LSFMT_TIME | LSFMT_TITLE | LSFMT_PID) /** Default format **/ @@ -71,7 +73,7 @@ enum ls_flag { * === Message flags * * The @flags parameter of msg() is divided to several groups of bits (from the LSB): - * message severity level (`L_xxx`), destination stream, message type [currently unused] + * message severity level (`L_xxx`), destination stream, message type * and control bits (e.g., `L_SIGHANDLER`). ***/ @@ -108,6 +110,15 @@ enum ls_flagmasks { // Bit masks of groups #define LS_SET_TYPE(type) ((type) << LS_TYPE_POS) /** Convert message type to flags **/ #define LS_SET_CTRL(ctrl) ((ctrl) << LS_CTRL_POS) /** Convert control bits to flags **/ +/** Register a new message type and return the corresponding flag set (encoded by `LS_SET_TYPE`). **/ +int log_register_type(const char *name); + +/** Find a message type by name and return the corresponding flag set. Returns -1 if no such type found. **/ +int log_find_type(const char *name); + +/** Given a flag set, extract the message type ID and return its name. **/ +char *log_type_name(uns flags); + /*** === Operations on streams ***/ /** -- 2.39.2