Merge branch 'collectd-4.2'
[collectd.git] / src / utils_threshold.c
index b036f99..1c9ccdd 100644 (file)
@@ -30,7 +30,7 @@
 
 /*
  * Private data structures
- */
+ * {{{ */
 typedef struct threshold_s
 {
   char host[DATA_MAX_NAME_LEN];
@@ -42,19 +42,21 @@ typedef struct threshold_s
   gauge_t max;
   int invert;
 } threshold_t;
+/* }}} */
 
 /*
  * Private (static) variables
- */
+ * {{{ */
 static avl_tree_t     *threshold_tree = NULL;
 static pthread_mutex_t threshold_lock = PTHREAD_MUTEX_INITIALIZER;
+/* }}} */
 
 /*
  * Threshold management
  * ====================
  * The following functions add, delete, search, etc. configured thresholds to
  * the underlying AVL trees.
- */
+ * {{{ */
 static int ut_threshold_add (const threshold_t *th)
 {
   char name[6 * DATA_MAX_NAME_LEN];
@@ -103,14 +105,14 @@ static int ut_threshold_add (const threshold_t *th)
 } /* int ut_threshold_add */
 /*
  * End of the threshold management functions
- */
+ * }}} */
 
 /*
  * Configuration
  * =============
- * The following approximately two hundred functions are used to convert the
- * threshold values..
- */
+ * The following approximately two hundred functions are used to handle the
+ * configuration and fill the threshold list.
+ * {{{ */
 static int ut_config_type_instance (threshold_t *th, oconfig_item_t *ci)
 {
   if ((ci->values_num != 1)
@@ -349,6 +351,16 @@ int ut_config (const oconfig_item_t *ci)
 
   threshold_t th;
 
+  if (threshold_tree == NULL)
+  {
+    threshold_tree = avl_create ((void *) strcmp);
+    if (threshold_tree == NULL)
+    {
+      ERROR ("ut_config: avl_create failed.");
+      return (-1);
+    }
+  }
+
   memset (&th, '\0', sizeof (th));
   th.min = NAN;
   th.max = NAN;
@@ -379,5 +391,153 @@ int ut_config (const oconfig_item_t *ci)
 /*
  * End of the functions used to configure threshold values.
  */
+/* }}} */
+
+static threshold_t *threshold_get (const char *hostname,
+    const char *plugin, const char *plugin_instance,
+    const char *type, const char *type_instance)
+{
+  char name[6 * DATA_MAX_NAME_LEN];
+  threshold_t *th = NULL;
+
+  format_name (name, sizeof (name),
+      (hostname == NULL) ? "" : hostname,
+      (plugin == NULL) ? "" : plugin, plugin_instance,
+      (type == NULL) ? "" : type, type_instance);
+  name[sizeof (name) - 1] = '\0';
+
+  if (avl_get (threshold_tree, name, (void *) &th) == 0)
+    return (th);
+  else
+    return (NULL);
+} /* threshold_t *threshold_get */
+
+static threshold_t *threshold_search (const data_set_t *ds,
+    const value_list_t *vl)
+{
+  threshold_t *th;
+
+  if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance,
+         ds->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, vl->plugin, vl->plugin_instance,
+         ds->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, vl->plugin, NULL,
+         ds->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, vl->plugin, NULL,
+         ds->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, "", NULL,
+         ds->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get (vl->host, "", NULL,
+         ds->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance,
+         ds->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, vl->plugin_instance,
+         ds->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, NULL,
+         ds->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", vl->plugin, NULL,
+         ds->type, NULL)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", "", NULL,
+         ds->type, vl->type_instance)) != NULL)
+    return (th);
+  else if ((th = threshold_get ("", "", NULL,
+         ds->type, NULL)) != NULL)
+    return (th);
+
+  return (NULL);
+} /* threshold_t *threshold_search */
+
+int ut_check_threshold (const data_set_t *ds, const value_list_t *vl)
+{
+  threshold_t *th;
+  gauge_t *values;
+  int i;
+
+  if (threshold_tree == NULL)
+    return (0);
+  pthread_mutex_lock (&threshold_lock);
+  th = threshold_search (ds, vl);
+  pthread_mutex_unlock (&threshold_lock);
+  if (th == NULL)
+    return (0);
+
+  DEBUG ("Found matching threshold");
+
+  values = uc_get_rate (ds, vl);
+  if (values == NULL)
+    return (0);
+
+  for (i = 0; i < ds->ds_num; i++)
+  {
+    if ((th->min > values[i]) || (th->max < values[i]))
+    {
+      notification_t n;
+      char *buf;
+      size_t bufsize;
+      int status;
+
+      WARNING ("ut_check_threshold: ds[%s]: %lf <= !%lf <= %lf",
+         ds->ds[i].name, th->min, values[i], th->max);
+
+      buf = n.message;
+      bufsize = sizeof (n.message);
+
+      status = snprintf (buf, bufsize, "Host %s, plugin %s",
+         vl->host, vl->plugin);
+      buf += status;
+      bufsize -= status;
+
+      if (vl->plugin_instance[0] != '\0')
+      {
+       status = snprintf (buf, bufsize, " (instance %s)",
+           vl->plugin_instance);
+       buf += status;
+       bufsize -= status;
+      }
+
+      status = snprintf (buf, bufsize, " type %s", ds->type);
+      buf += status;
+      bufsize -= status;
+
+      if (vl->type_instance[0] != '\0')
+      {
+       status = snprintf (buf, bufsize, " (instance %s)",
+           vl->type_instance);
+       buf += status;
+       bufsize -= status;
+      }
+
+      status = snprintf (buf, bufsize, ": Data source \"%s\" is currently "
+         "%lf. That is %s the configured threshold of %lf.",
+         ds->ds[i].name, values[i],
+         (values[i] < th->min) ? "below" : "above",
+         (values[i] < th->min) ? th->min : th->max);
+      buf += status;
+      bufsize -= status;
+
+      n.severity = NOTIF_FAILURE;
+      n.time = vl->time;
+
+      strncpy (n.host, vl->host, sizeof (n.host));
+      n.host[sizeof (n.host) - 1] = '\0';
+
+      plugin_dispatch_notification (&n);
+    }
+  } /* for (i = 0; i < ds->ds_num; i++) */
+
+  sfree (values);
+
+  return (0);
+} /* int ut_check_threshold */
 
-/* vim: set sw=2 ts=8 sts=2 tw=78 : */
+/* vim: set sw=2 ts=8 sts=2 tw=78 fdm=marker : */