]> mj.ucw.cz Git - libucw.git/commitdiff
Logging: Implemented message types.
authorMartin Mares <mj@ucw.cz>
Thu, 19 Feb 2009 18:35:04 +0000 (19:35 +0100)
committerMartin Mares <mj@ucw.cz>
Thu, 19 Feb 2009 18:35:04 +0000 (19:35 +0100)
ucw/doc/log.txt
ucw/log-internal.h
ucw/log-stream.c
ucw/log.c
ucw/log.h

index a24a50ddddfea3549f1df2fed874fe855f6c9fbd..94e1e82a87bd10d58c84932fcc0c66faab367dc9 100644 (file)
@@ -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 <<msg()>>), use <<log_register_type()>>.
+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
index 9651d033a8f007eca667ba012cee675cf13f55cb..5d21ce7773702b5a494d1a7e1e3c54ec69330baf 100644 (file)
@@ -29,4 +29,6 @@ extern int log_streams_after;
 
 extern struct log_stream log_stream_default;
 
+extern char **log_type_names;
+
 #endif
index 3e94d74832ab678e1de24d4708c126e956facb1b..8b697f8bf9816bad3ac05f1b5f4147b7f2033557 100644 (file)
@@ -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;
+}
index 0810451b0c3ca5d5cb48e818486778b0934492d2..35a0cc8392d8a62e2400f89ec1ef1986cba3ccbf 100644 (file)
--- 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;
 }
index 3c7264a6deaa1880faf053d5bc0f4a30bb9cfa9f..d0f1a9f8192f166a346eccc82e43b539de6a4353 100644 (file)
--- 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 ***/
 
 /**