Introduces ExcludeRegexp to the tail plugin
authorPeter Warasin <peter@endian.com>
Tue, 23 Mar 2010 20:55:54 +0000 (21:55 +0100)
committerFlorian Forster <octo@huhu.verplant.org>
Wed, 24 Mar 2010 16:00:09 +0000 (17:00 +0100)
Hi Florian

Florian Forster wrote:
> On Fri, Mar 19, 2010 at 06:13:14PM +0100, Peter Warasin wrote:
>> I'm searching for something like "ExcludeRegExp".
>
> no, something like that doesn't exist yet. I like the idea though, so
> I've added it to the [[Roadmap]] wiki page.

Attached is a patch which implements this.
The patch is against 4.9.1

Please tell me if you want me to rebase it to current svn

kind regards,
peter

--
:: e n d i a n
:: open source - open minds

:: peter warasin
:: http://www.endian.com   :: peter@endian.com

Adds ExcludeRegex to the tail-match plugin

With this keyword it is possible to exclude a line from a match.

Signed-off-by: Florian Forster <octo@huhu.verplant.org>
src/collectd.conf.in
src/collectd.conf.pod
src/curl.c
src/memcachec.c
src/tail.c
src/utils_match.c
src/utils_match.h
src/utils_tail_match.c
src/utils_tail_match.h

index 888875c..cd7839d 100644 (file)
@@ -784,6 +784,7 @@ FQDNLookup   true
 #    </Match>
 #    <Match>
 #      Regex "\\<R=local_user\\>"
+#      ExcludeRegex "\\<R=local_user\\>.*mail_spool defer"
 #      DSType "CounterInc"
 #      Type "counter"
 #      Instance "local_user"
index facb058..583e30c 100644 (file)
@@ -3872,6 +3872,7 @@ user using (extended) regular expressions, as described in L<regex(7)>.
       </Match>
       <Match>
         Regex "\\<R=local_user\\>"
+        ExcludeRegex "\\<R=local_user\\>.*mail_spool defer"
         DSType "CounterInc"
         Type "counter"
         Instance "local_user"
@@ -3906,6 +3907,13 @@ want to match literal parentheses you need to do the following:
 
   Regex "SPAM \\(Score: (-?[0-9]+\\.[0-9]+)\\)"
 
+=item B<ExcludeRegex> I<regex>
+
+Sets an optional regular expression to use for excluding lines from the match.
+An example which excludes all connections from localhost from the match:
+
+  ExcludeRegex "127\\.0\\.0\\.1"
+
 =item B<DSType> I<Type>
 
 Sets how the values are cumulated. I<Type> is one of:
index bc11c28..6e2811c 100644 (file)
@@ -333,7 +333,7 @@ static int cc_config_add_match (web_page_t *page, /* {{{ */
   if (status != 0)
     return (status);
 
-  match->match = match_create_simple (match->regex, match->dstype);
+  match->match = match_create_simple (match->regex, NULL, match->dstype);
   if (match->match == NULL)
   {
     ERROR ("curl plugin: tail_match_add_match_simple failed.");
index 451a853..75e6427 100644 (file)
@@ -262,7 +262,7 @@ static int cmc_config_add_match (web_page_t *page, /* {{{ */
   if (status != 0)
     return (status);
 
-  match->match = match_create_simple (match->regex, match->dstype);
+  match->match = match_create_simple (match->regex, NULL, match->dstype);
   if (match->match == NULL)
   {
     ERROR ("memcachec plugin: tail_match_add_match_simple failed.");
index 8becc05..25cbcd4 100644 (file)
@@ -30,6 +30,7 @@
  *     Instance "exim"
  *     <Match>
  *       Regex "S=([1-9][0-9]*)"
+ *       ExcludeRegex "U=root.*S="
  *       DSType "CounterAdd"
  *       Type "ipt_bytes"
  *       Instance "total"
@@ -41,6 +42,7 @@
 struct ctail_config_match_s
 {
   char *regex;
+  char *excluderegex;
   int flags;
   char *type;
   char *type_instance;
@@ -157,6 +159,9 @@ static int ctail_config_add_match (cu_tail_match_t *tm,
 
     if (strcasecmp ("Regex", option->key) == 0)
       status = ctail_config_add_string ("Regex", &cm.regex, option);
+    else if (strcasecmp ("ExcludeRegex", option->key) == 0)
+      status = ctail_config_add_string ("ExcludeRegex", &cm.excluderegex,
+                                       option);
     else if (strcasecmp ("DSType", option->key) == 0)
       status = ctail_config_add_match_dstype (&cm, option);
     else if (strcasecmp ("Type", option->key) == 0)
@@ -201,8 +206,8 @@ static int ctail_config_add_match (cu_tail_match_t *tm,
 
   if (status == 0)
   {
-    status = tail_match_add_match_simple (tm, cm.regex, cm.flags,
-       "tail", plugin_instance, cm.type, cm.type_instance);
+    status = tail_match_add_match_simple (tm, cm.regex, cm.excluderegex,
+       cm.flags, "tail", plugin_instance, cm.type, cm.type_instance);
 
     if (status != 0)
     {
@@ -211,6 +216,7 @@ static int ctail_config_add_match (cu_tail_match_t *tm,
   }
 
   sfree (cm.regex);
+  sfree (cm.excluderegex);
   sfree (cm.type);
   sfree (cm.type_instance);
 
index bdbad3f..0f87bc0 100644 (file)
 #include <regex.h>
 
 #define UTILS_MATCH_FLAGS_FREE_USER_DATA 0x01
+#define UTILS_MATCH_FLAGS_EXCLUDE_REGEX 0x02
 
 struct cu_match_s
 {
   regex_t regex;
+  regex_t excluderegex;
   int flags;
 
   int (*callback) (const char *str, char * const *matches, size_t matches_num,
@@ -210,7 +212,7 @@ static int default_callback (const char __attribute__((unused)) *str,
 /*
  * Public functions
  */
-cu_match_t *match_create_callback (const char *regex,
+cu_match_t *match_create_callback (const char *regex, const char *excluderegex,
                int (*callback) (const char *str,
                  char * const *matches, size_t matches_num, void *user_data),
                void *user_data)
@@ -218,7 +220,8 @@ cu_match_t *match_create_callback (const char *regex,
   cu_match_t *obj;
   int status;
 
-  DEBUG ("utils_match: match_create_callback: regex = %s", regex);
+  DEBUG ("utils_match: match_create_callback: regex = %s, excluderegex = %s",
+        regex, excluderegex);
 
   obj = (cu_match_t *) malloc (sizeof (cu_match_t));
   if (obj == NULL)
@@ -233,13 +236,26 @@ cu_match_t *match_create_callback (const char *regex,
     return (NULL);
   }
 
+  if (excluderegex && strcmp(excluderegex, "") != 0) {
+    status = regcomp (&obj->excluderegex, excluderegex, REG_EXTENDED);
+    if (status != 0)
+    {
+       ERROR ("Compiling the excluding regular expression \"%s\" failed.",
+              excluderegex);
+       sfree (obj);
+       return (NULL);
+    }
+    obj->flags |= UTILS_MATCH_FLAGS_EXCLUDE_REGEX;
+  }
+
   obj->callback = callback;
   obj->user_data = user_data;
 
   return (obj);
 } /* cu_match_t *match_create_callback */
 
-cu_match_t *match_create_simple (const char *regex, int match_ds_type)
+cu_match_t *match_create_simple (const char *regex,
+                                const char *excluderegex, int match_ds_type)
 {
   cu_match_value_t *user_data;
   cu_match_t *obj;
@@ -250,7 +266,8 @@ cu_match_t *match_create_simple (const char *regex, int match_ds_type)
   memset (user_data, '\0', sizeof (cu_match_value_t));
   user_data->ds_type = match_ds_type;
 
-  obj = match_create_callback (regex, default_callback, user_data);
+  obj = match_create_callback (regex, excluderegex,
+                              default_callback, user_data);
   if (obj == NULL)
   {
     sfree (user_data);
@@ -286,6 +303,17 @@ int match_apply (cu_match_t *obj, const char *str)
   if ((obj == NULL) || (str == NULL))
     return (-1);
 
+  if (obj->flags & UTILS_MATCH_FLAGS_EXCLUDE_REGEX) {
+    status = regexec (&obj->excluderegex, str,
+                     STATIC_ARRAY_SIZE (re_match), re_match,
+                     /* eflags = */ 0);
+    /* Regex did match, so exclude this line */
+    if (status == 0) {
+      DEBUG("ExludeRegex matched, don't count that line\n");
+      return (0);
+    }
+  }
+
   status = regexec (&obj->regex, str,
       STATIC_ARRAY_SIZE (re_match), re_match,
       /* eflags = */ 0);
index 5a0c033..9e47d5c 100644 (file)
@@ -82,8 +82,10 @@ typedef struct cu_match_value_s cu_match_value_t;
  *  then only the submatch (the part in the parenthesis) will be passed to the
  *  callback. If there is no submatch, then the entire string is passed to the
  *  callback.
+ *  The optional `excluderegex' allows to exclude the line from the match, if
+ *  the excluderegex matches.
  */
-cu_match_t *match_create_callback (const char *regex,
+cu_match_t *match_create_callback (const char *regex, const char *excluderegex,
                int (*callback) (const char *str,
                  char * const *matches, size_t matches_num, void *user_data),
                void *user_data);
@@ -112,7 +114,8 @@ cu_match_t *match_create_callback (const char *regex,
  *    The function will not search for anything in the string and increase
  *    value.counter by one.
  */
-cu_match_t *match_create_simple (const char *regex, int ds_type);
+cu_match_t *match_create_simple (const char *regex,
+                                const char *excluderegex, int ds_type);
 
 /*
  * NAME
index 22c7917..8ae2208 100644 (file)
@@ -191,7 +191,7 @@ int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match,
 } /* int tail_match_add_match */
 
 int tail_match_add_match_simple (cu_tail_match_t *obj,
-    const char *regex, int ds_type,
+    const char *regex, const char *excluderegex, int ds_type,
     const char *plugin, const char *plugin_instance,
     const char *type, const char *type_instance)
 {
@@ -199,7 +199,7 @@ int tail_match_add_match_simple (cu_tail_match_t *obj,
   cu_tail_match_simple_t *user_data;
   int status;
 
-  match = match_create_simple (regex, ds_type);
+  match = match_create_simple (regex, excluderegex, ds_type);
   if (match == NULL)
     return (-1);
 
index d08c728..7659745 100644 (file)
@@ -97,12 +97,13 @@ int tail_match_add_match (cu_tail_match_t *obj, cu_match_t *match,
  *  The values gathered are dispatched by the tail_match module in this case. The
  *  passed `plugin', `plugin_instance', `type', and `type_instance' are
  *  directly used when submitting these values.
+ *  With excluderegex it is possible to exlude lines from the match.
  *
  * RETURN VALUE
  *   Zero upon success, non-zero otherwise.
  */
 int tail_match_add_match_simple (cu_tail_match_t *obj,
-    const char *regex, int ds_type,
+    const char *regex, const char *excluderegex, int ds_type,
     const char *plugin, const char *plugin_instance,
     const char *type, const char *type_instance);