NFS plugin: Add Solaris support.
- 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.
- 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).
#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"
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"
plugin_df="no"
plugin_disk="no"
plugin_entropy="no"
+plugin_ethstat="no"
plugin_fscache="no"
plugin_interface="no"
plugin_ipmi="no"
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"
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])
dns . . . . . . . . . $enable_dns
email . . . . . . . . $enable_email
entropy . . . . . . . $enable_entropy
+ ethstat . . . . . . . $enable_ethstat
exec . . . . . . . . $enable_exec
filecount . . . . . . $enable_filecount
fscache . . . . . . . $enable_fscache
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
#@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"
=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
--- /dev/null
+/**
+ * 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 : */
/* #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
/* #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
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;
}
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;
/* 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)
{
case SLOCK: blocked++; break;
case SZOMB: zombies++; break;
}
-
- ps_list_add (procs[i].ki_comm, cmdline_ptr, &pse);
}
kvm_close(kd);
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
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
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
#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;
_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;
};
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))
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) /* {{{ */
{
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 */
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)
&& !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)
{
/**
* 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
*
* Authors:
* Anthony Dewhurst <dewhurst at gmail>
+ * Aurelien Rougemont <beorn at gandi.net>
**/
#include "collectd.h"
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)
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];
}
/* 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");