Merge pull request #56 from octo/ci/nfs
authorFlorian Forster <github@nospam.verplant.org>
Fri, 23 Mar 2012 13:17:00 +0000 (06:17 -0700)
committerFlorian Forster <github@nospam.verplant.org>
Fri, 23 Mar 2012 13:17:00 +0000 (06:17 -0700)
NFS plugin: Add Solaris support.

AUTHORS
README
configure.in
src/Makefile.am
src/collectd.conf.in
src/collectd.conf.pod
src/ethstat.c [new file with mode: 0644]
src/processes.c
src/types.db
src/varnish.c
src/zfs_arc.c

diff --git a/AUTHORS b/AUTHORS
index b7eda46..90560e3 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
@@ -54,6 +54,9 @@ Christophe Kalt <collectd at klb.taranis.org>
  - The version 3 `log' mode.
  - Many Solaris related hints and fixes.
 
+Cyril Feraudet <cyril at feraudet.com>
+ - ethstat plugin.
+
 Dan Berrange <berrange at redhat.com>
  - uuid plugin.
 
diff --git a/README b/README
index e65f46b..67cac04 100644 (file)
--- a/README
+++ b/README
@@ -83,6 +83,9 @@ Features
     - entropy
       Amount of entropy available to the system.
 
+    - ethstat
+      Network interface card statistics.
+
     - exec
       Values gathered by a custom program or script.
       See collectd-exec(5).
index 0ac908d..7ba2260 100644 (file)
@@ -403,6 +403,33 @@ AC_CHECK_HEADERS(linux/netdevice.h, [], [],
 #endif
 ])
 
+# For ethstat module
+AC_CHECK_HEADERS(linux/sockios.h,
+    [have_linux_sockios_h="yes"],
+    [have_linux_sockios_h="no"],
+    [
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+    ])
+AC_CHECK_HEADERS(linux/ethtool.h,
+    [have_linux_ethtool_h="yes"],
+    [have_linux_ethtool_h="no"],
+    [
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_LINUX_SOCKIOS_H
+# include <linux/sockios.h>
+#endif
+    ])
+
 # For ipvs module
 have_linux_ip_vs_h="no"
 have_net_ip_vs_h="no"
@@ -4072,10 +4099,9 @@ then
        CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
        #LDFLAGS="$LDFLAGS $with_libvarnish_libs"
 
-       AC_CHECK_LIB(varnishapi, VSL_OpenStats,
-                    [with_libvarnish="yes"],
-                    [with_libvarnish="no (symbol VSL_OpenStats not found)"],
-                    [$with_libvarnish_libs])
+    AC_CHECK_HEADERS(varnish/vsc.h,
+        [AC_DEFINE([HAVE_VARNISH_V3], [1], [Varnish 3 API support])],
+        [AC_DEFINE([HAVE_VARNISH_V2], [1], [Varnish 2 API support])])
 
        CPPFLAGS="$SAVE_CPPFLAGS"
        #LDFLAGS="$SAVE_LDFLAGS"
@@ -4433,6 +4459,7 @@ plugin_curl_xml="no"
 plugin_df="no"
 plugin_disk="no"
 plugin_entropy="no"
+plugin_ethstat="no"
 plugin_fscache="no"
 plugin_interface="no"
 plugin_ipmi="no"
@@ -4638,6 +4665,11 @@ then
        fi
 fi
 
+if test "x$have_linux_sockios_h$have_linux_ethtool_h" = "xyesyes"
+then
+       plugin_ethstat="yes"
+fi
+
 if test "x$have_getifaddrs" = "xyes"
 then
        plugin_interface="yes"
@@ -4746,6 +4778,7 @@ AC_PLUGIN([disk],        [$plugin_disk],       [Disk usage statistics])
 AC_PLUGIN([dns],         [$with_libpcap],      [DNS traffic analysis])
 AC_PLUGIN([email],       [yes],                [EMail statistics])
 AC_PLUGIN([entropy],     [$plugin_entropy],    [Entropy statistics])
+AC_PLUGIN([ethstat],     [$plugin_ethstat],    [Stats from NIC driver])
 AC_PLUGIN([exec],        [yes],                [Execution of external programs])
 AC_PLUGIN([filecount],   [yes],                [Count files in directories])
 AC_PLUGIN([fscache],     [$plugin_fscache],    [fscache statistics])
@@ -5077,6 +5110,7 @@ Configuration:
     dns . . . . . . . . . $enable_dns
     email . . . . . . . . $enable_email
     entropy . . . . . . . $enable_entropy
+    ethstat . . . . . . . $enable_ethstat
     exec  . . . . . . . . $enable_exec
     filecount . . . . . . $enable_filecount
     fscache . . . . . . . $enable_fscache
index 05f94d9..5c2eb35 100644 (file)
@@ -378,6 +378,14 @@ collectd_LDADD += "-dlopen" exec.la
 collectd_DEPENDENCIES += exec.la
 endif
 
+if BUILD_PLUGIN_ETHSTAT
+pkglib_LTLIBRARIES += ethstat.la
+ethstat_la_SOURCES = ethstat.c
+ethstat_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" ethstat.la
+collectd_DEPENDENCIES += ethstat.la
+endif
+
 if BUILD_PLUGIN_FILECOUNT
 pkglib_LTLIBRARIES += filecount.la
 filecount_la_SOURCES = filecount.c
index 0e1dc2e..f3ef675 100644 (file)
@@ -73,6 +73,7 @@
 #@BUILD_PLUGIN_DNS_TRUE@LoadPlugin dns
 #@BUILD_PLUGIN_EMAIL_TRUE@LoadPlugin email
 #@BUILD_PLUGIN_ENTROPY_TRUE@LoadPlugin entropy
+#@BUILD_PLUGIN_ETHSTAT_TRUE@LoadPlugin ethstat
 #@BUILD_PLUGIN_EXEC_TRUE@LoadPlugin exec
 #@BUILD_PLUGIN_FILECOUNT_TRUE@LoadPlugin filecount
 #@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
 #      MaxConns 5
 #</Plugin>
 
+#<Plugin ethstat>
+#      Interface "eth0"
+#      Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+#      Map "multicast" "if_multicast"
+#      MappedOnly false
+#</Plugin>
+
 #<Plugin exec>
 #      Exec "user:group" "/path/to/exec"
 #      NotificationExec "user:group" "/path/to/exec"
index 139919f..f89af08 100644 (file)
@@ -1272,6 +1272,41 @@ at most B<16384> to prevent typos and dumb mistakes.
 
 =back
 
+=head2 Plugin C<ethstat>
+
+The I<ethstat plugin> collects information about network interface cards (NICs)
+by talking directly with the underlying kernel driver using L<ioctl(2)>.
+
+B<Synopsis:>
+
+ <Plugin "ethstat">
+   Interface "eth0"
+   Map "rx_csum_offload_errors" "if_rx_errors" "checksum_offload"
+   Map "multicast" "if_multicast"
+ </Plugin>
+
+B<Options:>
+
+=over 4
+
+=item B<Interface> I<Name>
+
+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.
+
+=item B<MappedOnly> B<true>|B<false>
+
+When set to B<true>, only metrics that can be mapped to to a I<type> will be
+collected, all other metrics will be ignored. Defaults to B<false>.
+
+=back
+
 =head2 Plugin C<exec>
 
 Please make sure to read L<collectd-exec(5)> before using this plugin. It
diff --git a/src/ethstat.c b/src/ethstat.c
new file mode 100644 (file)
index 0000000..bc02477
--- /dev/null
@@ -0,0 +1,337 @@
+/**
+ * collectd - src/ethstat.c
+ * Copyright (C) 2011       Cyril Feraudet
+ * Copyright (C) 2012       Florian "octo" Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ *
+ * Authors:
+ *   Cyril Feraudet <cyril at feraudet.com>
+ *   Florian "octo" Forster <octo@collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_avltree.h"
+#include "utils_complain.h"
+
+#if HAVE_SYS_IOCTL_H
+# include <sys/ioctl.h>
+#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+#if HAVE_LINUX_SOCKIOS_H
+# include <linux/sockios.h>
+#endif
+#if HAVE_LINUX_ETHTOOL_H
+# include <linux/ethtool.h>
+#endif
+
+struct value_map_s
+{
+  char type[DATA_MAX_NAME_LEN];
+  char type_instance[DATA_MAX_NAME_LEN];
+};
+typedef struct value_map_s value_map_t;
+
+static char **interfaces = NULL;
+static size_t interfaces_num = 0;
+
+static c_avl_tree_t *value_map = NULL;
+
+static _Bool collect_mapped_only = 0;
+
+static int ethstat_add_interface (const oconfig_item_t *ci) /* {{{ */
+{
+  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 if (strcasecmp ("MappedOnly", child->key) == 0)
+      (void) cf_util_get_boolean (child, &collect_mapped_only);
+    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)
+{
+  static c_complain_t complain_no_map = C_COMPLAIN_INIT_STATIC;
+
+  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);
+
+  /* If the "MappedOnly" option is specified, ignore unmapped values. */
+  if (collect_mapped_only && (map == NULL))
+  {
+    if (value_map == NULL)
+      c_complain (LOG_WARNING, &complain_no_map,
+          "ethstat plugin: The \"MappedOnly\" option has been set to true, "
+          "but no mapping has been configured. All values will be ignored!");
+    return;
+  }
+
+  values[0].derive = value;
+  vl.values = values;
+  vl.values_len = 1;
+
+  sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+  sstrncpy (vl.plugin, "ethstat", sizeof (vl.plugin));
+  sstrncpy (vl.plugin_instance, device, sizeof (vl.plugin_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);
+}
+
+static int ethstat_read_interface (char *device)
+{
+  int fd;
+  struct ifreq req;
+  struct ethtool_drvinfo drvinfo;
+  struct ethtool_gstrings *strings;
+  struct ethtool_stats *stats;
+  size_t n_stats;
+  size_t strings_size;
+  size_t stats_size;
+  size_t i;
+  int status;
+
+  memset (&req, 0, sizeof (req));
+  sstrncpy(req.ifr_name, device, sizeof (req.ifr_name));
+
+  fd = socket(AF_INET, SOCK_DGRAM, /* protocol = */ 0);
+  if (fd < 0)
+  {
+    char errbuf[1024];
+    ERROR("ethstat plugin: Failed to open control socket: %s",
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return 1;
+  }
+
+  memset (&drvinfo, 0, sizeof (drvinfo));
+  drvinfo.cmd = ETHTOOL_GDRVINFO;
+  req.ifr_data = (void *) &drvinfo;
+  status = ioctl (fd, SIOCETHTOOL, &req);
+  if (status < 0)
+  {
+    char errbuf[1024];
+    close (fd);
+    ERROR ("ethstat plugin: Failed to get driver information "
+        "from %s: %s", device,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  n_stats = (size_t) drvinfo.n_stats;
+  if (n_stats < 1)
+  {
+    close (fd);
+    ERROR("ethstat plugin: No stats available for %s", device);
+    return (-1);
+  }
+
+  strings_size = sizeof (struct ethtool_gstrings)
+    + (n_stats * ETH_GSTRING_LEN);
+  stats_size = sizeof (struct ethtool_stats)
+    + (n_stats * sizeof (uint64_t));
+
+  strings = malloc (strings_size);
+  stats = malloc (stats_size);
+  if ((strings == NULL) || (stats == NULL))
+  {
+    close (fd);
+    sfree (strings);
+    sfree (stats);
+    ERROR("ethstat plugin: malloc(3) failed.");
+    return (-1);
+  }
+
+  strings->cmd = ETHTOOL_GSTRINGS;
+  strings->string_set = ETH_SS_STATS;
+  strings->len = n_stats;
+  req.ifr_data = (void *) strings;
+  status = ioctl (fd, SIOCETHTOOL, &req);
+  if (status < 0)
+  {
+    char errbuf[1024];
+    close (fd);
+    free (strings);
+    free (stats);
+    ERROR ("ethstat plugin: Cannot get strings from %s: %s",
+        device,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  stats->cmd = ETHTOOL_GSTATS;
+  stats->n_stats = n_stats;
+  req.ifr_data = (void *) stats;
+  status = ioctl (fd, SIOCETHTOOL, &req);
+  if (status < 0)
+  {
+    char errbuf[1024];
+    close (fd);
+    free(strings);
+    free(stats);
+    ERROR("ethstat plugin: Reading statistics from %s failed: %s",
+        device,
+        sstrerror (errno, errbuf, sizeof (errbuf)));
+    return (-1);
+  }
+
+  for (i = 0; i < n_stats; i++)
+  {
+    const char *stat_name;
+
+    stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN],
+              DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
+                  device, stat_name,
+                  (uint64_t) stats->data[i]);
+    ethstat_submit_value (device,
+        stat_name, (derive_t) stats->data[i]);
+  }
+
+  close (fd);
+  sfree (strings);
+  sfree (stats);
+
+  return (0);
+} /* }}} ethstat_read_interface */
+
+static int ethstat_read(void)
+{
+  size_t i;
+
+  for (i = 0; i < interfaces_num; i++)
+    ethstat_read_interface (interfaces[i]);
+
+  return 0;
+}
+
+void module_register (void)
+{
+  plugin_register_complex_config ("ethstat", ethstat_config);
+  plugin_register_read ("ethstat", ethstat_read);
+}
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
index 8f4eb88..518419f 100644 (file)
@@ -200,7 +200,7 @@ static long pagesize_g;
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
-/* no global variables */
+static int pagesize;
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
 
 #elif HAVE_PROCINFO_H
@@ -609,7 +609,7 @@ static int ps_init (void)
 /* #endif KERNEL_LINUX */
 
 #elif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD
-/* no initialization */
+       pagesize = getpagesize();
 /* #endif HAVE_LIBKVM_GETPROCS && HAVE_STRUCT_KINFO_PROC_FREEBSD */
 
 #elif HAVE_PROCINFO_H
@@ -790,7 +790,7 @@ static procstat_t *ps_read_vmem (int pid, procstat_t *ps)
                tmp = strtoll (fields[1], &endptr, /* base = */ 10);
                if ((errno == 0) && (endptr != fields[1]))
                {
-                       if (strncmp (buffer, "VmData", 6) == 0) 
+                       if (strncmp (buffer, "VmData", 6) == 0)
                        {
                                data = tmp;
                        }
@@ -1579,10 +1579,8 @@ static int ps_read (void)
 
        kvm_t *kd;
        char errbuf[1024];
-       char cmdline[ARG_MAX];
-       char *cmdline_ptr;
        struct kinfo_proc *procs;          /* array of processes */
-       char **argv;
+       struct kinfo_proc *proc_ptr = NULL;
        int count;                         /* returns number of processes */
        int i;
 
@@ -1613,64 +1611,80 @@ static int ps_read (void)
        /* Iterate through the processes in kinfo_proc */
        for (i = 0; i < count; i++)
        {
-               /* retrieve the arguments */
-               cmdline[0] = 0;
-               cmdline_ptr = NULL;
-
-               argv = kvm_getargv (kd, (const struct kinfo_proc *) &(procs[i]), 0);
-               if (argv != NULL)
+               /* Create only one process list entry per _process_, i.e.
+                * filter out threads (duplicate PID entries). */
+               if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid))
                {
-                       int status;
-                       int argc;
-
-                       argc = 0;
-                       while (argv[argc] != NULL)
-                               argc++;
+                       char cmdline[ARG_MAX] = "";
+                       _Bool have_cmdline = 0;
 
-                       status = strjoin (cmdline, sizeof (cmdline),
-                                       argv, argc, " ");
-
-                       if (status < 0)
-                       {
-                               WARNING ("processes plugin: Command line did "
-                                               "not fit into buffer.");
-                       }
-                       else
+                       proc_ptr = &(procs[i]);
+                       /* Don't probe system processes and processes without arguments */
+                       if (((procs[i].ki_flag & P_SYSTEM) == 0)
+                                       && (procs[i].ki_args != NULL))
                        {
-                               cmdline_ptr = &cmdline[0];
-                       }
-               }
+                               char **argv;
+                               int argc;
+                               int status;
+
+                               /* retrieve the arguments */
+                               argv = kvm_getargv (kd, proc_ptr, /* nchr = */ 0);
+                               argc = 0;
+                               if ((argv != NULL) && (argv[0] != NULL))
+                               {
+                                       while (argv[argc] != NULL)
+                                               argc++;
+
+                                       status = strjoin (cmdline, sizeof (cmdline), argv, argc, " ");
+                                       if (status < 0)
+                                               WARNING ("processes plugin: Command line did not fit into buffer.");
+                                       else
+                                               have_cmdline = 1;
+                               }
+                       } /* if (process has argument list) */
 
-               pse.id       = procs[i].ki_pid;
-               pse.age      = 0;
+                       pse.id       = procs[i].ki_pid;
+                       pse.age      = 0;
 
-               pse.num_proc = 1;
-               pse.num_lwp  = procs[i].ki_numthreads;
+                       pse.num_proc = 1;
+                       pse.num_lwp  = procs[i].ki_numthreads;
 
-               pse.vmem_size = procs[i].ki_size;
-               pse.vmem_rss = procs[i].ki_rssize * getpagesize();
-               pse.vmem_data = procs[i].ki_dsize * getpagesize();
-               pse.vmem_code = procs[i].ki_tsize * getpagesize();
-               pse.stack_size = procs[i].ki_ssize * getpagesize();
-               pse.vmem_minflt = 0;
-               pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt;
-               pse.vmem_majflt = 0;
-               pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt;
+                       pse.vmem_size = procs[i].ki_size;
+                       pse.vmem_rss = procs[i].ki_rssize * pagesize;
+                       pse.vmem_data = procs[i].ki_dsize * pagesize;
+                       pse.vmem_code = procs[i].ki_tsize * pagesize;
+                       pse.stack_size = procs[i].ki_ssize * pagesize;
+                       pse.vmem_minflt = 0;
+                       pse.vmem_minflt_counter = procs[i].ki_rusage.ru_minflt;
+                       pse.vmem_majflt = 0;
+                       pse.vmem_majflt_counter = procs[i].ki_rusage.ru_majflt;
 
-               pse.cpu_user = 0;
-               pse.cpu_user_counter = procs[i].ki_rusage.ru_utime.tv_sec
-                       * 1000
-                       + procs[i].ki_rusage.ru_utime.tv_usec;
-               pse.cpu_system = 0;
-               pse.cpu_system_counter = procs[i].ki_rusage.ru_stime.tv_sec
-                       * 1000
-                       + procs[i].ki_rusage.ru_stime.tv_usec;
+                       pse.cpu_user = 0;
+                       pse.cpu_system = 0;
+                       pse.cpu_user_counter = 0;
+                       pse.cpu_system_counter = 0;
+                       /*
+                        * The u-area might be swapped out, and we can't get
+                        * at it because we have a crashdump and no swap.
+                        * If it's here fill in these fields, otherwise, just
+                        * leave them 0.
+                        */
+                       if (procs[i].ki_flag & P_INMEM)
+                       {
+                               pse.cpu_user_counter = procs[i].ki_rusage.ru_utime.tv_usec
+                                       + (1000000lu * procs[i].ki_rusage.ru_utime.tv_sec);
+                               pse.cpu_system_counter = procs[i].ki_rusage.ru_stime.tv_usec
+                                       + (1000000lu * procs[i].ki_rusage.ru_stime.tv_sec);
+                       }
 
-               /* no io data */
-               pse.io_rchar = -1;
-               pse.io_wchar = -1;
-               pse.io_syscr = -1;
-               pse.io_syscw = -1;
+                       /* no I/O data */
+                       pse.io_rchar = -1;
+                       pse.io_wchar = -1;
+                       pse.io_syscr = -1;
+                       pse.io_syscw = -1;
+
+                       ps_list_add (procs[i].ki_comm, have_cmdline ? cmdline : NULL, &pse);
+               } /* if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid)) */
 
                switch (procs[i].ki_stat)
                {
@@ -1682,8 +1696,6 @@ static int ps_read (void)
                        case SLOCK:     blocked++;      break;
                        case SZOMB:     zombies++;      break;
                }
-
-               ps_list_add (procs[i].ki_comm, cmdline_ptr, &pse);
        }
 
        kvm_close(kd);
index 8557fe6..ed27b78 100644 (file)
@@ -8,6 +8,7 @@ ath_nodes               value:GAUGE:0:65535
 ath_stat               value:DERIVE:0:U
 bitrate                        value:GAUGE:0:4294967295
 bytes                  value:GAUGE:0:U
+cache_eviction         value:DERIVE:0:U
 cache_operation                value:DERIVE:0:U
 cache_ratio            value:GAUGE:0:100
 cache_result           value:DERIVE:0:U
@@ -63,6 +64,7 @@ frequency             value:GAUGE:0:U
 frequency_offset       value:GAUGE:-1000000:1000000
 fscache_stat           value:DERIVE:0:U
 gauge                  value:GAUGE:U:U
+hash_collisions                value:DERIVE:0:U
 http_request_methods   value:DERIVE:0:U
 http_requests          value:DERIVE:0:U
 http_response_codes    value:DERIVE:0:U
@@ -92,6 +94,7 @@ memcached_octets      rx:DERIVE:0:U, tx:DERIVE:0:U
 memcached_ops          value:DERIVE:0:U
 memory                 value:GAUGE:0:281474976710656
 multimeter             value:GAUGE:U:U
+mutex_operations       value:DERIVE:0:U
 mysql_commands         value:DERIVE:0:U
 mysql_handler          value:DERIVE:0:U
 mysql_locks            value:DERIVE:0:U
index 37fd4bb..d0e6a80 100644 (file)
 
 #include <varnish/varnishapi.h>
 
+#if HAVE_VARNISH_V3
+# include <varnish/vsc.h>
+typedef struct VSC_C_main c_varnish_stats_t;
+#endif
+
+#if HAVE_VARNISH_V2
+typedef struct varnish_stats c_varnish_stats_t;
+#endif
+
 /* {{{ user_config_s */
 struct user_config_s {
        char *instance;
@@ -145,9 +154,11 @@ struct user_config_s {
        _Bool collect_fetch;
        _Bool collect_hcb;
        _Bool collect_shm;
-       _Bool collect_sma;
        _Bool collect_sms;
+#if HAVE_VARNISH_V2
        _Bool collect_sm;
+       _Bool collect_sma;
+#endif
        _Bool collect_totals;
        _Bool collect_workers;
 };
@@ -204,182 +215,222 @@ static int varnish_submit_derive (const char *plugin_instance, /* {{{ */
        return (varnish_submit (plugin_instance, category, type, type_instance, value));
 } /* }}} int varnish_submit_derive */
 
-static void varnish_monitor (const user_config_t *conf, struct varnish_stats *VSL_stats) /* {{{ */
+static void varnish_monitor (const user_config_t *conf, /* {{{ */
+               c_varnish_stats_t *stats)
 {
        if (conf->collect_cache)
        {
                /* Cache hits */
-               varnish_submit_derive (conf->instance, "cache", "cache_result", "hit",     VSL_stats->cache_hit);
+               varnish_submit_derive (conf->instance, "cache", "cache_result", "hit",     stats->cache_hit);
                /* Cache misses */
-               varnish_submit_derive (conf->instance, "cache", "cache_result", "miss",    VSL_stats->cache_miss);
+               varnish_submit_derive (conf->instance, "cache", "cache_result", "miss",    stats->cache_miss);
                /* Cache hits for pass */
-               varnish_submit_derive (conf->instance, "cache", "cache_result", "hitpass", VSL_stats->cache_hitpass);
+               varnish_submit_derive (conf->instance, "cache", "cache_result", "hitpass", stats->cache_hitpass);
        }
 
        if (conf->collect_connections)
        {
                /* Client connections accepted */
-               varnish_submit_derive (conf->instance, "connections", "connections", "accepted", VSL_stats->client_conn);
+               varnish_submit_derive (conf->instance, "connections", "connections", "accepted", stats->client_conn);
                /* Connection dropped, no sess */
-               varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , VSL_stats->client_drop);
+               varnish_submit_derive (conf->instance, "connections", "connections", "dropped" , stats->client_drop);
                /* Client requests received    */
-               varnish_submit_derive (conf->instance, "connections", "connections", "received", VSL_stats->client_req);
+               varnish_submit_derive (conf->instance, "connections", "connections", "received", stats->client_req);
        }
 
        if (conf->collect_esi)
        {
-               /* Objects ESI parsed (unlock) */
-               varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed", VSL_stats->esi_parse);
                /* ESI parse errors (unlock)   */
-               varnish_submit_derive (conf->instance, "esi", "total_operations", "error",  VSL_stats->esi_errors);
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "error",  stats->esi_errors);
+#if HAVE_VARNISH_V2
+               /* Objects ESI parsed (unlock) */
+               varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed", stats->esi_parse);
+#endif
        }
 
        if (conf->collect_backend)
        {
                /* Backend conn. success       */
-               varnish_submit_derive (conf->instance, "backend", "connections", "success"      , VSL_stats->backend_conn);
+               varnish_submit_derive (conf->instance, "backend", "connections", "success"      , stats->backend_conn);
                /* Backend conn. not attempted */
-               varnish_submit_derive (conf->instance, "backend", "connections", "not-attempted", VSL_stats->backend_unhealthy);
+               varnish_submit_derive (conf->instance, "backend", "connections", "not-attempted", stats->backend_unhealthy);
                /* Backend conn. too many      */
-               varnish_submit_derive (conf->instance, "backend", "connections", "too-many"     , VSL_stats->backend_busy);
+               varnish_submit_derive (conf->instance, "backend", "connections", "too-many"     , stats->backend_busy);
                /* Backend conn. failures      */
-               varnish_submit_derive (conf->instance, "backend", "connections", "failures"     , VSL_stats->backend_fail);
+               varnish_submit_derive (conf->instance, "backend", "connections", "failures"     , stats->backend_fail);
                /* Backend conn. reuses        */
-               varnish_submit_derive (conf->instance, "backend", "connections", "reuses"       , VSL_stats->backend_reuse);
+               varnish_submit_derive (conf->instance, "backend", "connections", "reuses"       , stats->backend_reuse);
                /* Backend conn. was closed    */
-               varnish_submit_derive (conf->instance, "backend", "connections", "was-closed"   , VSL_stats->backend_toolate);
+               varnish_submit_derive (conf->instance, "backend", "connections", "was-closed"   , stats->backend_toolate);
                /* Backend conn. recycles      */
-               varnish_submit_derive (conf->instance, "backend", "connections", "recycled"     , VSL_stats->backend_recycle);
+               varnish_submit_derive (conf->instance, "backend", "connections", "recycled"     , stats->backend_recycle);
+#if HAVE_VARNISH_V2
                /* Backend conn. unused        */
-               varnish_submit_derive (conf->instance, "backend", "connections", "unused"       , VSL_stats->backend_unused);
+               varnish_submit_derive (conf->instance, "backend", "connections", "unused"       , stats->backend_unused);
+#endif
        }
 
        if (conf->collect_fetch)
        {
                /* Fetch head                */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "head"       , VSL_stats->fetch_head);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "head"       , stats->fetch_head);
                /* Fetch with length         */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "length"     , VSL_stats->fetch_length);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "length"     , stats->fetch_length);
                /* Fetch chunked             */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "chunked"    , VSL_stats->fetch_chunked);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "chunked"    , stats->fetch_chunked);
                /* Fetch EOF                 */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "eof"        , VSL_stats->fetch_eof);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "eof"        , stats->fetch_eof);
                /* Fetch bad headers         */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "bad_headers", VSL_stats->fetch_bad);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "bad_headers", stats->fetch_bad);
                /* Fetch wanted close        */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "close"      , VSL_stats->fetch_close);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "close"      , stats->fetch_close);
                /* Fetch pre HTTP/1.1 closed */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "oldhttp"    , VSL_stats->fetch_oldhttp);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "oldhttp"    , stats->fetch_oldhttp);
                /* Fetch zero len            */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero"       , VSL_stats->fetch_zero);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero"       , stats->fetch_zero);
                /* Fetch failed              */
-               varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed"     , VSL_stats->fetch_failed);
+               varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed"     , stats->fetch_failed);
        }
 
        if (conf->collect_hcb)
        {
                /* HCB Lookups without lock */
-               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_nolock", VSL_stats->hcb_nolock);
+               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_nolock", stats->hcb_nolock);
                /* HCB Lookups with lock    */
-               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_lock",   VSL_stats->hcb_lock);
+               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "lookup_lock",   stats->hcb_lock);
                /* HCB Inserts              */
-               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert",        VSL_stats->hcb_insert);
+               varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert",        stats->hcb_insert);
        }
 
        if (conf->collect_shm)
        {
                /* SHM records                 */
-               varnish_submit_derive (conf->instance, "shm", "total_operations", "records"   , VSL_stats->shm_records);
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "records"   , stats->shm_records);
                /* SHM writes                  */
-               varnish_submit_derive (conf->instance, "shm", "total_operations", "writes"    , VSL_stats->shm_writes);
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "writes"    , stats->shm_writes);
                /* SHM flushes due to overflow */
-               varnish_submit_derive (conf->instance, "shm", "total_operations", "flushes"   , VSL_stats->shm_flushes);
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "flushes"   , stats->shm_flushes);
                /* SHM MTX contention          */
-               varnish_submit_derive (conf->instance, "shm", "total_operations", "contention", VSL_stats->shm_cont);
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "contention", stats->shm_cont);
                /* SHM cycles through buffer   */
-               varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles"    , VSL_stats->shm_cycles);
+               varnish_submit_derive (conf->instance, "shm", "total_operations", "cycles"    , stats->shm_cycles);
        }
 
+#if HAVE_VARNISH_V2
        if (conf->collect_sm)
        {
                /* allocator requests */
-               varnish_submit_derive (conf->instance, "sm", "total_requests", "nreq",  VSL_stats->sm_nreq);
+               varnish_submit_derive (conf->instance, "sm", "total_requests", "nreq",         stats->sm_nreq);
                /* outstanding allocations */
-               varnish_submit_gauge (conf->instance,  "sm", "requests", "outstanding", VSL_stats->sm_nobj);
+               varnish_submit_gauge (conf->instance,  "sm", "requests", "outstanding",        stats->sm_nobj);
                /* bytes allocated */
-               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "allocated",      VSL_stats->sm_balloc);
+               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "allocated",      stats->sm_balloc);
                /* bytes free */
-               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "free",           VSL_stats->sm_bfree);
+               varnish_submit_derive (conf->instance,  "sm", "total_bytes", "free",           stats->sm_bfree);
        }
 
        if (conf->collect_sma)
        {
                /* SMA allocator requests */
-               varnish_submit_derive (conf->instance, "sma", "total_requests", "nreq",  VSL_stats->sma_nreq);
+               varnish_submit_derive (conf->instance, "sma", "total_requests", "nreq",    stats->sma_nreq);
                /* SMA outstanding allocations */
-               varnish_submit_gauge (conf->instance,  "sma", "requests", "outstanding", VSL_stats->sma_nobj);
+               varnish_submit_gauge (conf->instance,  "sma", "requests", "outstanding",   stats->sma_nobj);
                /* SMA outstanding bytes */
-               varnish_submit_gauge (conf->instance,  "sma", "bytes", "outstanding",    VSL_stats->sma_nbytes);
+               varnish_submit_gauge (conf->instance,  "sma", "bytes", "outstanding",      stats->sma_nbytes);
                /* SMA bytes allocated */
-               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "allocated",      VSL_stats->sma_balloc);
+               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "allocated", stats->sma_balloc);
                /* SMA bytes free */
-               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "free" ,          VSL_stats->sma_bfree);
+               varnish_submit_derive (conf->instance,  "sma", "total_bytes", "free" ,     stats->sma_bfree);
        }
+#endif
 
        if (conf->collect_sms)
        {
                /* SMS allocator requests */
-               varnish_submit_derive (conf->instance, "sms", "total_requests", "allocator", VSL_stats->sms_nreq);
+               varnish_submit_derive (conf->instance, "sms", "total_requests", "allocator", stats->sms_nreq);
                /* SMS outstanding allocations */
-               varnish_submit_gauge (conf->instance,  "sms", "requests", "outstanding",     VSL_stats->sms_nobj);
+               varnish_submit_gauge (conf->instance,  "sms", "requests", "outstanding",     stats->sms_nobj);
                /* SMS outstanding bytes */
-               varnish_submit_gauge (conf->instance,  "sms", "bytes", "outstanding",        VSL_stats->sms_nbytes);
+               varnish_submit_gauge (conf->instance,  "sms", "bytes", "outstanding",        stats->sms_nbytes);
                /* SMS bytes allocated */
-               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "allocated",          VSL_stats->sms_balloc);
+               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "allocated",   stats->sms_balloc);
                /* SMS bytes freed */
-               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",               VSL_stats->sms_bfree);
+               varnish_submit_derive (conf->instance,  "sms", "total_bytes", "free",        stats->sms_bfree);
        }
 
        if (conf->collect_totals)
        {
                /* Total Sessions */
-               varnish_submit_derive (conf->instance, "totals", "total_sessions", "sessions",  VSL_stats->s_sess);
+               varnish_submit_derive (conf->instance, "totals", "total_sessions", "sessions",  stats->s_sess);
                /* Total Requests */
-               varnish_submit_derive (conf->instance, "totals", "total_requests", "requests",  VSL_stats->s_req);
+               varnish_submit_derive (conf->instance, "totals", "total_requests", "requests",  stats->s_req);
                /* Total pipe */
-               varnish_submit_derive (conf->instance, "totals", "total_operations", "pipe",    VSL_stats->s_pipe);
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "pipe",    stats->s_pipe);
                /* Total pass */
-               varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    VSL_stats->s_pass);
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "pass",    stats->s_pass);
                /* Total fetch */
-               varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", VSL_stats->s_fetch);
+               varnish_submit_derive (conf->instance, "totals", "total_operations", "fetches", stats->s_fetch);
                /* Total header bytes */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", VSL_stats->s_hdrbytes);
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "header-bytes", stats->s_hdrbytes);
                /* Total body byte */
-               varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   VSL_stats->s_bodybytes);
+               varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes",   stats->s_bodybytes);
        }
 
        if (conf->collect_workers)
        {
                /* worker threads */
-               varnish_submit_gauge (conf->instance, "workers", "threads", "worker",            VSL_stats->n_wrk);
+               varnish_submit_gauge (conf->instance, "workers", "threads", "worker",             stats->n_wrk);
                /* worker threads created */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     VSL_stats->n_wrk_create);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "created",     stats->n_wrk_create);
                /* worker threads not created */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      VSL_stats->n_wrk_failed);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "failed",      stats->n_wrk_failed);
                /* worker threads limited */
-               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     VSL_stats->n_wrk_max);
+               varnish_submit_derive (conf->instance, "workers", "total_threads", "limited",     stats->n_wrk_max);
+               /* dropped work requests */
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "dropped",    stats->n_wrk_drop);
+#ifdef HAVE_VARNISH_V2
                /* queued work requests */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     VSL_stats->n_wrk_queue);
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "queued",     stats->n_wrk_queue);
                /* overflowed work requests */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", VSL_stats->n_wrk_overflow);
-               /* dropped work requests */
-               varnish_submit_derive (conf->instance, "workers", "total_requests", "dropped",    VSL_stats->n_wrk_drop);
+               varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", stats->n_wrk_overflow);
+#endif
        }
 } /* }}} void varnish_monitor */
 
+#if HAVE_VARNISH_V3
+static int varnish_read (user_data_t *ud) /* {{{ */
+{
+       struct VSM_data *vd;
+       const c_varnish_stats_t *stats;
+
+       user_config_t *conf;
+
+       if ((ud == NULL) || (ud->data == NULL))
+               return (EINVAL);
+
+       conf = ud->data;
+
+       vd = VSM_New();
+       VSC_Setup(vd);
+       if (VSC_Open (vd, /* diag = */ 1))
+       {
+               ERROR ("varnish plugin: Unable to load statistics.");
+
+               return (-1);
+       }
+
+       stats = VSC_Main(vd);
+
+       varnish_monitor (conf, stats);
+       VSM_Close (vd);
+
+       return (0);
+} /* }}} */
+#else /* if HAVE_VARNISH_V2 */
 static int varnish_read (user_data_t *ud) /* {{{ */
 {
-       struct varnish_stats *VSL_stats;
+       const c_varnish_stats_t *stats;
+
        user_config_t *conf;
 
        if ((ud == NULL) || (ud->data == NULL))
@@ -387,18 +438,19 @@ static int varnish_read (user_data_t *ud) /* {{{ */
 
        conf = ud->data;
 
-       VSL_stats = VSL_OpenStats (conf->instance);
-       if (VSL_stats == NULL)
+       stats = VSL_OpenStats (conf->instance);
+       if (stats == NULL)
        {
                ERROR ("Varnish plugin : unable to load statistics");
 
                return (-1);
        }
 
-       varnish_monitor (conf, VSL_stats);
+       varnish_monitor (conf, stats);
 
-    return (0);
+       return (0);
 } /* }}} */
+#endif
 
 static void varnish_config_free (void *ptr) /* {{{ */
 {
@@ -423,11 +475,13 @@ static int varnish_config_apply_default (user_config_t *conf) /* {{{ */
        conf->collect_fetch       = 0;
        conf->collect_hcb         = 0;
        conf->collect_shm         = 1;
+#if HAVE_VARNISH_V2
        conf->collect_sm          = 0;
        conf->collect_sma         = 0;
+#endif
        conf->collect_sms         = 0;
        conf->collect_totals      = 0;
-       
+
        return (0);
 } /* }}} int varnish_config_apply_default */
 
@@ -519,12 +573,14 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        cf_util_get_boolean (child, &conf->collect_hcb);
                else if (strcasecmp ("CollectSHM", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_shm);
-               else if (strcasecmp ("CollectSMA", child->key) == 0)
-                       cf_util_get_boolean (child, &conf->collect_sma);
                else if (strcasecmp ("CollectSMS", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_sms);
+#if HAVE_VARNISH_V2
+               else if (strcasecmp ("CollectSMA", child->key) == 0)
+                       cf_util_get_boolean (child, &conf->collect_sma);
                else if (strcasecmp ("CollectSM", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_sm);
+#endif
                else if (strcasecmp ("CollectTotals", child->key) == 0)
                        cf_util_get_boolean (child, &conf->collect_totals);
                else if (strcasecmp ("CollectWorkers", child->key) == 0)
@@ -544,9 +600,11 @@ static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
                        && !conf->collect_fetch
                        && !conf->collect_hcb
                        && !conf->collect_shm
-                       && !conf->collect_sma
                        && !conf->collect_sms
+#if HAVE_VARNISH_V2
+                       && !conf->collect_sma
                        && !conf->collect_sm
+#endif
                        && !conf->collect_totals
                        && !conf->collect_workers)
        {
index 8341be0..e77569f 100644 (file)
@@ -1,6 +1,7 @@
 /**
  * collectd - src/zfs_arc.c
  * Copyright (C) 2009  Anthony Dewhurst
+ * Copyright (C) 2012  Aurelien Rougemont
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -17,6 +18,7 @@
  *
  * Authors:
  *   Anthony Dewhurst <dewhurst at gmail>
+ *   Aurelien Rougemont <beorn at gandi.net>
  **/
 
 #include "collectd.h"
@@ -52,12 +54,38 @@ static void za_submit_gauge (const char* type, const char* type_instance, gauge_
        za_submit (type, type_instance, &vv, 1);
 }
 
-static void za_submit_derive (const char* type, const char* type_instance, derive_t dv)
+static int za_read_derive (kstat_t *ksp, const char *kstat_value,
+    const char *type, const char *type_instance)
 {
-       value_t vv;
+  long long tmp;
+  value_t v;
+
+  tmp = get_kstat_value (ksp, kstat_value);
+  if (tmp == -1LL)
+  {
+    ERROR ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
+    return (-1);
+  }
+
+  v.derive = (derive_t) tmp;
+  za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1);
+}
 
-       vv.derive = dv;
-       za_submit (type, type_instance, &vv, 1);
+static int za_read_gauge (kstat_t *ksp, const char *kstat_value,
+    const char *type, const char *type_instance)
+{
+  long long tmp;
+  value_t v;
+
+  tmp = get_kstat_value (ksp, kstat_value);
+  if (tmp == -1LL)
+  {
+    ERROR ("zfs_arc plugin: Reading kstat value \"%s\" failed.", kstat_value);
+    return (-1);
+  }
+
+  v.gauge = (gauge_t) tmp;
+  za_submit (type, type_instance, /* values = */ &v, /* values_num = */ 1);
 }
 
 static void za_submit_ratio (const char* type_instance, gauge_t hits, gauge_t misses)
@@ -77,15 +105,6 @@ static void za_submit_ratio (const char* type_instance, gauge_t hits, gauge_t mi
 
 static int za_read (void)
 {
-       gauge_t  arc_size, l2_size;
-       derive_t demand_data_hits,
-                demand_metadata_hits,
-                prefetch_data_hits,
-                prefetch_metadata_hits,
-                demand_data_misses,
-                demand_metadata_misses,
-                prefetch_data_misses,
-                prefetch_metadata_misses;
        gauge_t  arc_hits, arc_misses, l2_hits, l2_misses;
        value_t  l2_io[2];
 
@@ -97,32 +116,32 @@ static int za_read (void)
        }
 
        /* Sizes */
-       arc_size   = get_kstat_value(ksp, "size");
-       l2_size    = get_kstat_value(ksp, "l2_size");
-
-       za_submit_gauge ("cache_size", "arc", arc_size);
-       za_submit_gauge ("cache_size", "L2", l2_size);
+       za_read_gauge (ksp, "size",    "cache_size", "arc");
+       za_read_gauge (ksp, "l2_size", "cache_size", "L2");
+
+        /* Operations */
+       za_read_derive (ksp, "allocated","cache_operation", "allocated");
+       za_read_derive (ksp, "deleted",  "cache_operation", "deleted");
+       za_read_derive (ksp, "stolen",   "cache_operation", "stolen");
+
+        /* Issue indicators */
+        za_read_derive (ksp, "mutex_miss", "mutex_operation", "miss");
+       za_read_derive (ksp, "hash_collisions", "hash_collisions", "");
+       
+        /* Evictions */
+       za_read_derive (ksp, "evict_l2_cached",     "cache_eviction", "cached");
+       za_read_derive (ksp, "evict_l2_eligible",   "cache_eviction", "eligible");
+       za_read_derive (ksp, "evict_l2_ineligible", "cache_eviction", "ineligible");
 
        /* Hits / misses */
-       demand_data_hits       = get_kstat_value(ksp, "demand_data_hits");
-       demand_metadata_hits   = get_kstat_value(ksp, "demand_metadata_hits");
-       prefetch_data_hits     = get_kstat_value(ksp, "prefetch_data_hits");
-       prefetch_metadata_hits = get_kstat_value(ksp, "prefetch_metadata_hits");
-
-       demand_data_misses       = get_kstat_value(ksp, "demand_data_misses");
-       demand_metadata_misses   = get_kstat_value(ksp, "demand_metadata_misses");
-       prefetch_data_misses     = get_kstat_value(ksp, "prefetch_data_misses");
-       prefetch_metadata_misses = get_kstat_value(ksp, "prefetch_metadata_misses");
-
-       za_submit_derive ("cache_result", "demand_data-hit",       demand_data_hits);
-       za_submit_derive ("cache_result", "demand_metadata-hit",   demand_metadata_hits);
-       za_submit_derive ("cache_result", "prefetch_data-hit",     prefetch_data_hits);
-       za_submit_derive ("cache_result", "prefetch_metadata-hit", prefetch_metadata_hits);
-
-       za_submit_derive ("cache_result", "demand_data-miss",       demand_data_misses);
-       za_submit_derive ("cache_result", "demand_metadata-miss",   demand_metadata_misses);
-       za_submit_derive ("cache_result", "prefetch_data-miss",     prefetch_data_misses);
-       za_submit_derive ("cache_result", "prefetch_metadata-miss", prefetch_metadata_misses);
+       za_read_derive (ksp, "demand_data_hits",         "cache_result", "demand_data-hit");
+       za_read_derive (ksp, "demand_metadata_hits",     "cache_result", "demand_metadata-hit");
+       za_read_derive (ksp, "prefetch_data_hits",       "cache_result", "prefetch_data-hit");
+       za_read_derive (ksp, "prefetch_metadata_hits",   "cache_result", "prefetch_metadata-hit");
+       za_read_derive (ksp, "demand_data_misses",       "cache_result", "demand_data-miss");
+       za_read_derive (ksp, "demand_metadata_misses",   "cache_result", "demand_metadata-miss");
+       za_read_derive (ksp, "prefetch_data_misses",     "cache_result", "prefetch_data-miss");
+       za_read_derive (ksp, "prefetch_metadata_misses", "cache_result", "prefetch_metadata-miss");
 
        /* Ratios */
        arc_hits   = (gauge_t) get_kstat_value(ksp, "hits");