#include "collectd.h"
#include "filter_chain.h"
+#include "meta_data.h"
+#include "utils_llist.h"
#include <sys/types.h>
#include <regex.h>
mr_regex_t *plugin_instance;
mr_regex_t *type;
mr_regex_t *type_instance;
+ llist_t *meta; /* Maps each meta key into mr_regex_t* */
_Bool invert;
};
mr_free_regex (m->plugin_instance);
mr_free_regex (m->type);
mr_free_regex (m->type_instance);
+ for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next)
+ {
+ free (e->key);
+ mr_free_regex ((mr_regex_t *) e->value);
+ }
+ llist_destroy (m->meta);
free (m);
} /* }}} void mr_free_match */
return (FC_MATCH_MATCHES);
} /* }}} int mr_match_regexen */
-static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
- oconfig_item_t *ci)
+static int mr_add_regex (mr_regex_t **re_head, const char *re_str, /* {{{ */
+ const char *option)
{
mr_regex_t *re;
int status;
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- log_warn ("`%s' needs exactly one string argument.", ci->key);
- return (-1);
- }
-
re = calloc (1, sizeof (*re));
if (re == NULL)
{
- log_err ("mr_config_add_regex: calloc failed.");
+ log_err ("mr_add_regex: calloc failed.");
return (-1);
}
re->next = NULL;
- re->re_str = strdup (ci->values[0].value.string);
+ re->re_str = strdup (re_str);
if (re->re_str == NULL)
{
free (re);
- log_err ("mr_config_add_regex: strdup failed.");
+ log_err ("mr_add_regex: strdup failed.");
return (-1);
}
regerror (status, &re->re, errmsg, sizeof (errmsg));
errmsg[sizeof (errmsg) - 1] = 0;
log_err ("Compiling regex `%s' for `%s' failed: %s.",
- re->re_str, ci->key, errmsg);
+ re->re_str, option, errmsg);
free (re->re_str);
free (re);
return (-1);
}
return (0);
+} /* }}} int mr_add_regex */
+
+static int mr_config_add_regex (mr_regex_t **re_head, /* {{{ */
+ oconfig_item_t *ci)
+{
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
+ {
+ log_warn ("`%s' needs exactly one string argument.", ci->key);
+ return (-1);
+ }
+
+ return mr_add_regex (re_head, ci->values[0].value.string, ci->key);
} /* }}} int mr_config_add_regex */
+static int mr_config_add_meta_regex (llist_t **meta, /* {{{ */
+ oconfig_item_t *ci)
+{
+ char *key;
+ llentry_t *entry;
+ mr_regex_t *re_head;
+ int status;
+ char buffer[1024];
+
+ if ((ci->values_num != 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || (ci->values[1].type != OCONFIG_TYPE_STRING))
+ {
+ log_warn ("`%s' needs exactly two string arguments.", ci->key);
+ return (-1);
+ }
+
+ if (*meta == NULL)
+ {
+ *meta = llist_create();
+ if (*meta == NULL)
+ {
+ log_err ("mr_config_add_meta_regex: llist_create failed.");
+ return (-1);
+ }
+ }
+
+ key = ci->values[0].value.string;
+ entry = llist_search (*meta, key);
+ if (entry == NULL)
+ {
+ key = strdup (key);
+ if (key == NULL)
+ {
+ log_err ("mr_config_add_meta_regex: strdup failed.");
+ return (-1);
+ }
+ entry = llentry_create (key, NULL);
+ if (entry == NULL)
+ {
+ log_err ("mr_config_add_meta_regex: llentry_create failed.");
+ free (key);
+ return (-1);
+ }
+ /* key and entry will now be freed by mr_free_match(). */
+ llist_append (*meta, entry);
+ }
+
+ snprintf (buffer, sizeof (buffer), "%s `%s'", ci->key, key);
+ /* Can't pass &entry->value into mr_add_regex, so copy in/out. */
+ re_head = entry->value;
+ status = mr_add_regex (&re_head, ci->values[1].value.string, buffer);
+ if (status == 0) {
+ entry->value = re_head;
+ }
+ return status;
+} /* }}} int mr_config_add_meta_regex */
+
static int mr_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
{
mr_match_t *m;
status = mr_config_add_regex (&m->type, child);
else if (strcasecmp ("TypeInstance", child->key) == 0)
status = mr_config_add_regex (&m->type_instance, child);
+ else if (strcasecmp ("MetaData", child->key) == 0)
+ status = mr_config_add_meta_regex (&m->meta, child);
else if (strcasecmp ("Invert", child->key) == 0)
status = cf_util_get_boolean(child, &m->invert);
else
&& (m->plugin == NULL)
&& (m->plugin_instance == NULL)
&& (m->type == NULL)
- && (m->type_instance == NULL))
+ && (m->type_instance == NULL)
+ && (m->meta == NULL))
{
log_err ("No (valid) regular expressions have been configured. "
"This match will be ignored.");
if (mr_match_regexen (m->type_instance,
vl->type_instance) == FC_MATCH_NO_MATCH)
return (nomatch_value);
+ if (vl->meta != NULL)
+ {
+ for (llentry_t *e = llist_head(m->meta); e != NULL; e = e->next)
+ {
+ mr_regex_t *meta_re = (mr_regex_t *) e->value;
+ char *value;
+ int status = meta_data_get_string (vl->meta, e->key, &value);
+ if (status == 0) /* key is present */
+ {
+ if (mr_match_regexen (meta_re, value) == FC_MATCH_NO_MATCH)
+ {
+ free (value);
+ return (nomatch_value);
+ }
+ free (value);
+ }
+ }
+ }
return (match_value);
} /* }}} int mr_match */