ethstat plugin: Implement the "Map" option.
authorFlorian Forster <octo@collectd.org>
Mon, 12 Mar 2012 12:35:38 +0000 (13:35 +0100)
committerFlorian Forster <octo@collectd.org>
Mon, 12 Mar 2012 12:35:38 +0000 (13:35 +0100)
src/collectd.conf.in
src/collectd.conf.pod
src/ethstat.c

index 01f024d..befb7ab 100644 (file)
 
 #<Plugin ethstat>
 #      Interface "eth0"
+#      Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+#      Map "multicast" "if_multicast"
 #</Plugin>
 
 #<Plugin exec>
index 765d2ac..bd14d0e 100644 (file)
@@ -1281,6 +1281,8 @@ B<Synopsis:>
 
  <Plugin "ethstat">
    Interface "eth0"
+   Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+   Map "multicast" "if_multicast"
  </Plugin>
 
 B<Options:>
@@ -1291,6 +1293,13 @@ B<Options:>
 
 Collect statistical information about interface I<Name>.
 
+=item B<Map> I<Name> I<Type> [I<TypeInstance>]
+
+By default, the plugin will submit values as type C<derive> and I<type
+instance> set to I<Name>, the name of the metric as reported by the driver. If
+an appropriate B<Map> option exists, the given I<Type> and, optionally,
+I<TypeInstance> will be used.
+
 =back
 
 =head2 Plugin C<exec>
index b280a58..490a9bf 100644 (file)
@@ -24,6 +24,7 @@
 #include "common.h"
 #include "plugin.h"
 #include "configfile.h"
+#include "utils_avltree.h"
 
 #if HAVE_SYS_IOCTL_H
 # include <sys/ioctl.h>
 # include <linux/ethtool.h>
 #endif
 
-static const char *config_keys[] =
+struct value_map_s
 {
-       "Interface"
+  char type[DATA_MAX_NAME_LEN];
+  char type_instance[DATA_MAX_NAME_LEN];
 };
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+typedef struct value_map_s value_map_t;
 
 static char **interfaces = NULL;
 static size_t interfaces_num = 0;
 
-static int ethstat_config (const char *key, const char *value)
+static c_avl_tree_t *value_map = NULL;
+
+static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
 {
-       if (strcasecmp ("Interface", key) == 0)
-       {
-               char **tmp;
-
-               tmp = realloc (interfaces,
-                               sizeof (*interfaces) * (interfaces_num + 1));
-               if (tmp == NULL)
-                       return (-1);
-               interfaces = tmp;
-
-               interfaces[interfaces_num] = strdup (value);
-               if (interfaces[interfaces_num] == NULL)
-               {
-                       ERROR ("ethstat plugin: strdup() failed.");
-                       return (-1);
-               }
-
-               interfaces_num++;
-               INFO("ethstat plugin: Registred interface %s", value);
-       }
-       return (0);
-}
+  char **tmp;
+  int status;
+
+  tmp = realloc (interfaces,
+      sizeof (*interfaces) * (interfaces_num + 1));
+  if (tmp == NULL)
+    return (-1);
+  interfaces = tmp;
+
+  status = cf_util_get_string (ci, interfaces + interfaces_num);
+  if (status != 0)
+    return (status);
+
+  interfaces_num++;
+  INFO("ethstat plugin: Registred interface %s",
+      interfaces[interfaces_num - 1]);
+
+  return (0);
+} /* }}} int ethstat_add_interface */
+
+static int ethstat_add_map (const oconfig_item_t *ci) /* {{{ */
+{
+  value_map_t *map;
+  int status;
+
+  if ((ci->values_num < 2)
+      || (ci->values_num > 3)
+      || (ci->values[0].type != OCONFIG_TYPE_STRING)
+      || (ci->values[1].type != OCONFIG_TYPE_STRING)
+      || ((ci->values_num == 3)
+        && (ci->values[2].type != OCONFIG_TYPE_STRING)))
+  {
+    ERROR ("ethstat plugin: The %s option requires "
+        "two or three string arguments.", ci->key);
+    return (-1);
+  }
+
+  map = malloc (sizeof (*map));
+  if (map == NULL)
+  {
+    ERROR ("ethstat plugin: malloc(3) failed.");
+    return (ENOMEM);
+  }
+  memset (map, 0, sizeof (*map));
+
+  sstrncpy (map->type, ci->values[1].value.string, sizeof (map->type));
+  if (ci->values_num == 2)
+    sstrncpy (map->type_instance, ci->values[2].value.string,
+        sizeof (map->type_instance));
+
+  if (value_map == NULL)
+  {
+    value_map = c_avl_create ((void *) strcmp);
+    if (value_map == NULL)
+    {
+      sfree (map);
+      ERROR ("ethstat plugin: c_avl_create() failed.");
+      return (-1);
+    }
+  }
+
+  status = c_avl_insert (value_map,
+      /* key = */ ci->values[0].value.string,
+      /* value = */ map);
+  if (status != 0)
+  {
+    sfree (map);
+    if (status > 0)
+      ERROR ("ethstat plugin: Multiple mappings for \"%s\".",
+          ci->values[0].value.string);
+    else
+      ERROR ("ethstat plugin: c_avl_insert(\"%s\") failed.",
+          ci->values[0].value.string);
+    return (-1);
+  }
+
+  return (0);
+} /* }}} int ethstat_add_map */
+
+static int ethstat_config (oconfig_item_t *ci) /* {{{ */
+{
+  int i;
+
+  for (i = 0; i < ci->children_num; i++)
+  {
+    oconfig_item_t *child = ci->children + i;
+
+    if (strcasecmp ("Interface", child->key) == 0)
+      ethstat_add_interface (child);
+    else if (strcasecmp ("Map", child->key) == 0)
+      ethstat_add_map (child);
+    else
+      WARNING ("ethstat plugin: The config option \"%s\" is unknown.",
+          child->key);
+  }
+
+  return (0);
+} /* }}} */
 
 static void ethstat_submit_value (const char *device,
                const char *type_instance, derive_t value)
 {
        value_t values[1];
        value_list_t vl = VALUE_LIST_INIT;
+        value_map_t *map = NULL;
+
+        if (value_map != NULL)
+          c_avl_get (value_map, type_instance, (void *) &map);
 
        values[0].derive = value;
        vl.values = values;
@@ -85,8 +169,17 @@ static void ethstat_submit_value (const char *device,
        sstrncpy (vl.host, hostname_g, sizeof (vl.host));
        sstrncpy (vl.plugin, "ethstat", sizeof (vl.plugin));
        sstrncpy (vl.plugin_instance, device, sizeof (vl.plugin_instance));
-       sstrncpy (vl.type, "derive", sizeof (vl.type));
-       sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+        if (map != NULL)
+        {
+          sstrncpy (vl.type, map->type, sizeof (vl.type));
+          sstrncpy (vl.type_instance, map->type_instance,
+              sizeof (vl.type_instance));
+        }
+        else
+        {
+          sstrncpy (vl.type, "derive", sizeof (vl.type));
+          sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+        }
 
        plugin_dispatch_values (&vl);
 }
@@ -218,7 +311,8 @@ static int ethstat_read(void)
 
 void module_register (void)
 {
-       plugin_register_config ("ethstat", ethstat_config,
-                       config_keys, config_keys_num);
+       plugin_register_complex_config ("ethstat", ethstat_config);
        plugin_register_read ("ethstat", ethstat_read);
 }
+
+/* vim: set sw=2 sts=2 et fdm=marker : */