Jason Pepas <cell at ices.utexas.edu>
- nfs plugin.
+Jérôme Renard <jerome.renard at gmail.com>
+ - varnish plugin.
+
Luboš Staněk <kolektor at atlas.cz>
- sensors plugin improvements.
- Time and effort to find a nasty bug in the ntpd-plugin.
Parse JSON data. This is needed for the `curl_json' plugin.
<http://github.com/lloyd/yajl>
+ * libvarnish (optional)
+ Fetches statistics from a Varnish instance. This is needed for the Varnish plugin
+ <http://varnish-cache.org>
+
Configuring / Compiling / Installing
------------------------------------
if test "x$enable_standards" = "xyes"
then
AC_DEFINE(_ISOC99_SOURCE, 1, [Define to enforce ISO C99 compliance.])
- AC_DEFINE(_POSIX_C_SOURCE, 200112L, [Define to enforce POSIX.1-2001 compliance.])
- AC_DEFINE(_XOPEN_SOURCE, 600, [Define to enforce X/Open 6 (XSI) compliance.])
+ AC_DEFINE(_POSIX_C_SOURCE, 200809L, [Define to enforce POSIX.1-2008 compliance.])
+ AC_DEFINE(_XOPEN_SOURCE, 700, [Define to enforce X/Open 7 (XSI) compliance.])
AC_DEFINE(_REENTRANT, 1, [Define to enable reentrancy interfaces.])
+ if test "x$GCC" = "xyes"
+ then
+ CFLAGS="$CFLAGS -std=c99"
+ fi
fi
AM_CONDITIONAL(BUILD_FEATURE_STANDARDS, test "x$enable_standards" = "xyes")
AC_CHECK_FUNCS(getutent, [have_getutent="yes"], [have_getutent="no"])
AC_CHECK_FUNCS(getutxent, [have_getutxent="yes"], [have_getutxent="no"])
AC_CHECK_FUNCS(swapctl, [have_swapctl="yes"], [have_swapctl="no"])
+if test "x$have_swapctl" = "xyes"; then
+ AC_CACHE_CHECK([whether swapctl takes two arguments],
+ [c_cv_have_swapctl_two_args],
+ AC_COMPILE_IFELSE(
+ AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# undef _LARGEFILE64_SOURCE
+#endif
+#include <sys/stat.h>
+#include <sys/swap.h>]],
+ [[
+ int num = swapctl(0, NULL);
+ ]]
+ ),
+ [c_cv_have_swapctl_two_args="yes"],
+ [c_cv_have_swapctl_two_args="no"]
+ )
+ )
+ AC_CACHE_CHECK([whether swapctl takes three arguments],
+ [c_cv_have_swapctl_three_args],
+ AC_COMPILE_IFELSE(
+ AC_LANG_PROGRAM([[AC_INCLUDES_DEFAULT
+#if HAVE_SYS_SWAP_H && !defined(_LP64) && _FILE_OFFSET_BITS == 64
+# undef _FILE_OFFSET_BITS
+# undef _LARGEFILE64_SOURCE
+#endif
+#include <sys/stat.h>
+#include <sys/swap.h>]],
+ [[
+ int num = swapctl(0, NULL,0);
+ ]]
+ ),
+ [c_cv_have_swapctl_three_args="yes"],
+ [c_cv_have_swapctl_three_args="no"]
+ )
+ )
+fi
+# Check for different versions of `swapctl' here..
+if test "x$have_swapctl" = "xyes"; then
+ if test "x$c_cv_have_swapctl_two_args" = "xyes"; then
+ AC_DEFINE(HAVE_SWAPCTL_TWO_ARGS, 1,
+ [Define if the function swapctl exists and takes two arguments.])
+ fi
+ if test "x$c_cv_have_swapctl_three_args" = "xyes"; then
+ AC_DEFINE(HAVE_SWAPCTL_THREE_ARGS, 1,
+ [Define if the function swapctl exists and takes three arguments.])
+ fi
+fi
# For load module
AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"])
AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
# }}}
+# --with-libvarnish {{{
+with_libvarnish_cppflags=""
+with_libvarnish_cflags=""
+with_libvarnish_libs=""
+AC_ARG_WITH(libvarnish, [AS_HELP_STRING([--with-libvarnish@<:@=PREFIX@:>@], [Path to libvarnish.])],
+[
+ if test "x$withval" = "xno"
+ then
+ with_libvarnish="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_libvarnish="use_pkgconfig"
+ else if test -d "$with_libvarnish/lib"
+ then
+ AC_MSG_NOTICE([Not checking for libvarnish: Manually configured])
+ with_libvarnish_cflags="-I$withval/include"
+ with_libvarnish_libs="-L$withval/lib -lvarnish -lvarnishcompat -lvarnishapi"
+ with_libvarnish="yes"
+ fi; fi; fi
+],
+[with_libvarnish="use_pkgconfig"])
+
+# configure using pkg-config
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+ if test "x$PKG_CONFIG" = "x"
+ then
+ with_libvarnish="no (Don't have pkg-config)"
+ fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+ AC_MSG_NOTICE([Checking for varnishapi using $PKG_CONFIG])
+ $PKG_CONFIG --exists 'varnishapi' 2>/dev/null
+ if test $? -ne 0
+ then
+ with_libvarnish="no (pkg-config doesn't know library)"
+ fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+ with_libvarnish_cflags="`$PKG_CONFIG --cflags 'varnishapi'`"
+ if test $? -ne 0
+ then
+ with_libvarnish="no ($PKG_CONFIG failed)"
+ fi
+ with_libvarnish_libs="`$PKG_CONFIG --libs 'varnishapi'`"
+ if test $? -ne 0
+ then
+ with_libvarnish="no ($PKG_CONFIG failed)"
+ fi
+fi
+if test "x$with_libvarnish" = "xuse_pkgconfig"
+then
+ with_libvarnish="yes"
+fi
+
+# with_libvarnish_cflags and with_libvarnish_libs are set up now, let's do
+# the actual checks.
+if test "x$with_libvarnish" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libvarnish_cflags"
+ AC_CHECK_HEADERS(varnish/varnishapi.h, [], [with_libvarnish="no (varnish/varnishapi.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libvarnish" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ #SAVE_LDFLAGS="$LDFLAGS"
+
+ 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])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ #LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libvarnish" = "xyes"
+then
+ BUILD_WITH_LIBVARNISH_CFLAGS="$with_libvarnish_cflags"
+ BUILD_WITH_LIBVARNISH_LIBS="$with_libvarnish_libs"
+ AC_SUBST(BUILD_WITH_LIBVARNISH_CFLAGS)
+ AC_SUBST(BUILD_WITH_LIBVARNISH_LIBS)
+fi
+# }}}
+
# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
with_libxml2="no (pkg-config isn't available)"
with_libxml2_cflags=""
AC_PLUGIN([target_replace], [yes], [The replace target])
AC_PLUGIN([target_scale],[yes], [The scale target])
AC_PLUGIN([target_set], [yes], [The set target])
+AC_PLUGIN([target_v5upgrade], [yes], [The v5upgrade target])
AC_PLUGIN([tcpconns], [$plugin_tcpconns], [TCP connection statistics])
AC_PLUGIN([teamspeak2], [yes], [TeamSpeak2 server statistics])
AC_PLUGIN([ted], [$plugin_ted], [Read The Energy Detective values])
AC_PLUGIN([uptime], [$plugin_uptime], [Uptime statistics])
AC_PLUGIN([users], [$plugin_users], [User statistics])
AC_PLUGIN([uuid], [yes], [UUID as hostname plugin])
+AC_PLUGIN([varnish], [$with_libvarnish], [Varnish cache statistics])
AC_PLUGIN([vmem], [$plugin_vmem], [Virtual memory statistics])
AC_PLUGIN([vserver], [$plugin_vserver], [Linux VServer statistics])
AC_PLUGIN([wireless], [$plugin_wireless], [Wireless statistics])
libstatgrab . . . . . $with_libstatgrab
libtokyotyrant . . . $with_libtokyotyrant
libupsclient . . . . $with_libupsclient
+ libvarnish . . . . . $with_libvarnish
libvirt . . . . . . . $with_libvirt
libxml2 . . . . . . . $with_libxml2
libxmms . . . . . . . $with_libxmms
target_replace . . . $enable_target_replace
target_scale . . . . $enable_target_scale
target_set . . . . . $enable_target_set
+ target_v5upgrade . . $enable_target_v5upgrade
tcpconns . . . . . . $enable_tcpconns
teamspeak2 . . . . . $enable_teamspeak2
ted . . . . . . . . . $enable_ted
uptime . . . . . . . $enable_uptime
users . . . . . . . . $enable_users
uuid . . . . . . . . $enable_uuid
+ varnish . . . . . . . $enable_varnish
vmem . . . . . . . . $enable_vmem
vserver . . . . . . . $enable_vserver
wireless . . . . . . $enable_wireless
collectd_DEPENDENCIES += target_set.la
endif
+if BUILD_PLUGIN_TARGET_V5UPGRADE
+pkglib_LTLIBRARIES += target_v5upgrade.la
+target_v5upgrade_la_SOURCES = target_v5upgrade.c
+target_v5upgrade_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" target_v5upgrade.la
+collectd_DEPENDENCIES += target_v5upgrade.la
+endif
+
if BUILD_PLUGIN_TCPCONNS
pkglib_LTLIBRARIES += tcpconns.la
tcpconns_la_SOURCES = tcpconns.c
collectd_DEPENDENCIES += uuid.la
endif
+if BUILD_PLUGIN_VARNISH
+pkglib_LTLIBRARIES += varnish.la
+varnish_la_SOURCES = varnish.c
+varnish_la_LDFLAGS = -module -avoid-version
+varnish_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBVARNISH_CFLAGS)
+varnish_la_LIBADD = $(BUILD_WITH_LIBVARNISH_LIBS)
+collectd_LDADD += "-dlopen" varnish.la
+collectd_DEPENDENCIES += varnish.la
+endif
+
if BUILD_PLUGIN_VMEM
pkglib_LTLIBRARIES += vmem.la
vmem_la_SOURCES = vmem.c
##############################################################################
#Hostname "localhost"
-FQDNLookup true
+#FQDNLookup true
#BaseDir "@prefix@/var/lib/@PACKAGE_NAME@"
#PIDFile "@prefix@/var/run/@PACKAGE_NAME@.pid"
#PluginDir "@prefix@/lib/@PACKAGE_NAME@"
#@BUILD_PLUGIN_UPTIME_TRUE@LoadPlugin uptime
#@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
#@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
+#@BUILD_PLUGIN_VARNISH_TRUE@LoadPlugin varnish
#@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
#@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
#@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
# InterfaceDevice "name:device"
# IgnoreSelected false
# HostnameFormat name
+# InterfaceFormat name
#</Plugin>
#<Plugin madwifi>
# UUIDFile "/etc/uuid"
#</Plugin>
+#<Plugin varnish>
+# This tag support an argument if you want to
+# monitor the local instance just use </Instance>
+# If you prefer defining another instance you can do
+# so by using <Instance "myinstance">
+# <Instance>
+# CollectCache true
+# CollectBackend true
+# CollectConnections true
+# CollectSHM true
+# CollectESI false
+# CollectFetch false
+# CollectHCB false
+# CollectSMA false
+# CollectSMS false
+# CollectSM false
+# CollectTotals false
+# CollectWorkers false
+# </Instance>
+#</Plugin>
+
#<Plugin vmem>
# Verbose false
#</Plugin>
If B<Hostname> is determined automatically this setting controls whether or not
the daemon should try to figure out the "fully qualified domain name", FQDN.
-This is done using a lookup of the name returned by C<gethostname>.
-
-Using this feature (i.E<nbsp>e. setting this option to B<true>) is recommended.
-However, to preserve backwards compatibility the default is set to B<false>.
-The sample config file that is installed with C<makeE<nbsp>install> includes a
-line which sets this option, though, so that default installations will have
-this setting enabled.
+This is done using a lookup of the name returned by C<gethostname>. This option
+is enabled by default.
=item B<PreCacheChain> I<ChainName>
means to concatenate the guest name and UUID (with a literal colon character
between, thus I<"foo:1234-1234-1234-1234">).
+=item B<InterfaceFormat> B<name>|B<address>
+
+When the libvirt plugin logs interface data, it sets the name of the collected
+data according to this setting. The default is to use the path as provided by
+the hypervisor (the "dev" property of the target node), which is equal to
+setting B<name>.
+
+B<address> means use the interface's mac address. This is useful since the
+interface path might change between reboots of a guest or across migrations.
+
=back
=head2 Plugin C<logfile>
WarningMin 100000000
</Type>
</Plugin>
+
+ <Type "load">
+ DataSource "midterm"
+ FailureMax 4
+ Hits 3
+ Hysteresis 3
+ </Type>
</Host>
</Threshold>
example for the "df" type, where you may want to issue a warning when less than
5E<nbsp>% of the total space is available. Defaults to B<false>.
+=item B<Hits> I<Value>
+
+Sets the number of occurrences which the threshold must be arised before to
+dispatch any notification or, in other words, the number of B<Interval>s
+than the threshold must be match before dispatch any notification.
+
+=item B<Hysteresis> I<Value>
+
+Sets the hysteresis value for threshold. The hysteresis is a method to
+prevent flapping between states, until a new received value for
+a previously matched threshold down below the threshold condition
+(B<WarningMax>, B<FailureMin> or everthing else) minus the hysteresis value,
+the failure (respectively warning) state will be keep.
+
+=item B<Interesting> B<true>|B<false>
+
+If set to B<true> (the default), the threshold must be treated as
+interesting and, when a number of B<Timeout> values will lost, then
+a missing notification will be dispatched. On the other hand, if set to
+B<false>, the missing notification will never dispatched for this threshold.
+
=back
=head1 FILTER CONFIGURATION
/**
* collectd - src/configfile.c
- * Copyright (C) 2005-2009 Florian octo Forster
+ * Copyright (C) 2005-2010 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
{"BaseDir", NULL, PKGLOCALSTATEDIR},
{"PIDFile", NULL, PIDFILE},
{"Hostname", NULL, NULL},
- {"FQDNLookup", NULL, "false"},
+ {"FQDNLookup", NULL, "true"},
{"Interval", NULL, "10"},
{"ReadThreads", NULL, "5"},
{"Timeout", NULL, "2"},
return (-1);
}
- *ret_bool = ci->values[0].value.boolean ? true : false;
+ *ret_bool = ci->values[0].value.boolean ? 1 : 0;
return (0);
} /* }}} int cf_util_get_boolean */
+int cf_util_get_flag (const oconfig_item_t *ci, /* {{{ */
+ unsigned int *ret_value, unsigned int flag)
+{
+ int status;
+ _Bool b;
+
+ if (ret_value == NULL)
+ return (EINVAL);
+
+ b = 0;
+ status = cf_util_get_boolean (ci, &b);
+ if (status != 0)
+ return (status);
+
+ if (b)
+ {
+ *ret_value |= flag;
+ }
+ else
+ {
+ *ret_value &= ~flag;
+ }
+
+ return (0);
+} /* }}} int cf_util_get_flag */
+
/* Assures that the config option is a string. The string is then converted to
* a port number using `service_name_to_port_number' and returned. Returns the
* port number in the range [1-65535] or less than zero upon failure. */
#define CONFIGFILE_H
/**
* collectd - src/configfile.h
- * Copyright (C) 2005,2006 Florian octo Forster
+ * Copyright (C) 2005-2010 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
* Otherwise, `ret_bool' is not changed and non-zero is returned. */
int cf_util_get_boolean (const oconfig_item_t *ci, _Bool *ret_bool);
+/* Assures the config option is a boolean and set or unset the given flag in
+ * `ret_value' as appropriate. Returns non-zero on error. */
+int cf_util_get_flag (const oconfig_item_t *ci,
+ unsigned int *ret_value, unsigned int flag);
+
/* Assures that the config option is a string. The string is then converted to
* a port number using `service_name_to_port_number' and returned. Returns the
* port number in the range [1-65535] or less than zero upon failure. */
static ignorelist_t *il_fstype = NULL;
static _Bool by_device = false;
-static _Bool report_reserved = false;
static _Bool report_inodes = false;
static int df_init (void)
}
else if (strcasecmp (key, "ReportReserved") == 0)
{
- if (IS_TRUE (value))
- report_reserved = true;
- else
- report_reserved = false;
-
+ /* Nop for backwards compatibility. */
return (0);
}
else if (strcasecmp (key, "ReportInodes") == 0)
return (-1);
}
-static void df_submit_two (char *df_name,
- const char *type,
- gauge_t df_used,
- gauge_t df_free)
-{
- value_t values[2];
- value_list_t vl = VALUE_LIST_INIT;
-
- values[0].gauge = df_used;
- values[1].gauge = df_free;
-
- vl.values = values;
- vl.values_len = 2;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, "df", sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, "", sizeof (vl.plugin_instance));
- sstrncpy (vl.type, type, sizeof (vl.type));
- sstrncpy (vl.type_instance, df_name, sizeof (vl.type_instance));
-
- plugin_dispatch_values (&vl);
-} /* void df_submit_two */
-
__attribute__ ((nonnull(2)))
static void df_submit_one (char *plugin_instance,
const char *type, const char *type_instance,
{
unsigned long long blocksize;
char disk_name[256];
+ uint64_t blk_free;
+ uint64_t blk_reserved;
+ uint64_t blk_used;
if (ignorelist_match (il_device,
(mnt_ptr->spec_device != NULL)
blocksize = BLOCKSIZE(statbuf);
- if (report_reserved)
- {
- uint64_t blk_free;
- uint64_t blk_reserved;
- uint64_t blk_used;
-
- /* Sanity-check for the values in the struct */
- if (statbuf.f_bfree < statbuf.f_bavail)
- statbuf.f_bfree = statbuf.f_bavail;
- if (statbuf.f_blocks < statbuf.f_bfree)
- statbuf.f_blocks = statbuf.f_bfree;
-
- blk_free = (uint64_t) statbuf.f_bavail;
- blk_reserved = (uint64_t) (statbuf.f_bfree - statbuf.f_bavail);
- blk_used = (uint64_t) (statbuf.f_blocks - statbuf.f_bfree);
-
- df_submit_one (disk_name, "df_complex", "free",
- (gauge_t) (blk_free * blocksize));
- df_submit_one (disk_name, "df_complex", "reserved",
- (gauge_t) (blk_reserved * blocksize));
- df_submit_one (disk_name, "df_complex", "used",
- (gauge_t) (blk_used * blocksize));
- }
- else /* compatibility code */
- {
- gauge_t df_free;
- gauge_t df_used;
-
- df_free = statbuf.f_bfree * blocksize;
- df_used = (statbuf.f_blocks - statbuf.f_bfree) * blocksize;
-
- df_submit_two (disk_name, "df", df_used, df_free);
- }
+ /* Sanity-check for the values in the struct */
+ if (statbuf.f_bfree < statbuf.f_bavail)
+ statbuf.f_bfree = statbuf.f_bavail;
+ if (statbuf.f_blocks < statbuf.f_bfree)
+ statbuf.f_blocks = statbuf.f_bfree;
+
+ blk_free = (uint64_t) statbuf.f_bavail;
+ blk_reserved = (uint64_t) (statbuf.f_bfree - statbuf.f_bavail);
+ blk_used = (uint64_t) (statbuf.f_blocks - statbuf.f_bfree);
+
+ df_submit_one (disk_name, "df_complex", "free",
+ (gauge_t) (blk_free * blocksize));
+ df_submit_one (disk_name, "df_complex", "reserved",
+ (gauge_t) (blk_reserved * blocksize));
+ df_submit_one (disk_name, "df_complex", "used",
+ (gauge_t) (blk_used * blocksize));
/* inode handling */
if (report_inodes)
vl.values_len = 2;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "interface", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, dev, sizeof (vl.plugin_instance));
sstrncpy (vl.type, type, sizeof (vl.type));
- sstrncpy (vl.type_instance, dev, sizeof (vl.type_instance));
plugin_dispatch_values (&vl);
} /* void if_submit */
"IgnoreSelected",
"HostnameFormat",
+ "InterfaceFormat",
NULL
};
struct interface_device {
virDomainPtr dom; /* domain */
char *path; /* name of interface device */
+ char *address; /* mac address of interface device */
};
static struct interface_device *interface_devices = NULL;
static int nr_interface_devices = 0;
static void free_interface_devices (void);
-static int add_interface_device (virDomainPtr dom, const char *path);
+static int add_interface_device (virDomainPtr dom, const char *path, const char *address);
/* HostnameFormat. */
#define HF_MAX_FIELDS 3
static enum hf_field hostname_format[HF_MAX_FIELDS] =
{ hf_name };
+/* InterfaceFormat. */
+enum if_field {
+ if_address,
+ if_name
+};
+
+static enum if_field interface_format = if_name;
+
/* Time that we last refreshed. */
static time_t last_refresh = (time_t) 0;
n = strsplit (value_copy, fields, HF_MAX_FIELDS);
if (n < 1) {
- free (value_copy);
+ sfree (value_copy);
ERROR ("HostnameFormat: no fields");
return -1;
}
else if (strcasecmp (fields[i], "uuid") == 0)
hostname_format[i] = hf_uuid;
else {
- free (value_copy);
+ sfree (value_copy);
ERROR ("unknown HostnameFormat field: %s", fields[i]);
return -1;
}
}
- free (value_copy);
+ sfree (value_copy);
for (i = n; i < HF_MAX_FIELDS; ++i)
hostname_format[i] = hf_none;
return 0;
}
+ if (strcasecmp (key, "InterfaceFormat") == 0) {
+ if (strcasecmp (value, "name") == 0)
+ interface_format = if_name;
+ else if (strcasecmp (value, "address") == 0)
+ interface_format = if_address;
+ else {
+ ERROR ("unknown InterfaceFormat: %s", value);
+ return -1;
+ }
+ return 0;
+ }
+
/* Unrecognised option. */
return -1;
}
if (virDomainGetVcpus (domains[i], vinfo, info.nrVirtCpu,
NULL, 0) != 0) {
- free (vinfo);
+ sfree (vinfo);
continue;
}
vcpu_submit (vinfo[j].cpuTime,
t, domains[i], vinfo[j].number, "virt_vcpu");
- free (vinfo);
+ sfree (vinfo);
}
/* Get block device stats for each domain. */
/* Get interface stats for each domain. */
for (i = 0; i < nr_interface_devices; ++i) {
struct _virDomainInterfaceStats stats;
+ char *display_name = interface_devices[i].path;
+
+ if (interface_format == if_address)
+ display_name = interface_devices[i].address;
if (virDomainInterfaceStats (interface_devices[i].dom,
interface_devices[i].path,
if ((stats.rx_bytes != -1) && (stats.tx_bytes != -1))
submit_counter2 ("if_octets",
(counter_t) stats.rx_bytes, (counter_t) stats.tx_bytes,
- t, interface_devices[i].dom, interface_devices[i].path);
+ t, interface_devices[i].dom, display_name);
if ((stats.rx_packets != -1) && (stats.tx_packets != -1))
submit_counter2 ("if_packets",
(counter_t) stats.rx_packets, (counter_t) stats.tx_packets,
- t, interface_devices[i].dom, interface_devices[i].path);
+ t, interface_devices[i].dom, display_name);
if ((stats.rx_errs != -1) && (stats.tx_errs != -1))
submit_counter2 ("if_errors",
(counter_t) stats.rx_errs, (counter_t) stats.tx_errs,
- t, interface_devices[i].dom, interface_devices[i].path);
+ t, interface_devices[i].dom, display_name);
if ((stats.rx_drop != -1) && (stats.tx_drop != -1))
submit_counter2 ("if_dropped",
(counter_t) stats.rx_drop, (counter_t) stats.tx_drop,
- t, interface_devices[i].dom, interface_devices[i].path);
+ t, interface_devices[i].dom, display_name);
} /* for (nr_interface_devices) */
return 0;
n = virConnectListDomains (conn, domids, n);
if (n < 0) {
VIRT_ERROR (conn, "reading list of domains");
- free (domids);
+ sfree (domids);
return -1;
}
/* Network interfaces. */
xpath_obj = xmlXPathEval
- ((xmlChar *) "/domain/devices/interface/target[@dev]",
+ ((xmlChar *) "/domain/devices/interface[target[@dev]]",
xpath_ctx);
if (xpath_obj == NULL || xpath_obj->type != XPATH_NODESET ||
xpath_obj->nodesetval == NULL)
goto cont;
- for (j = 0; j < xpath_obj->nodesetval->nodeNr; ++j) {
- xmlNodePtr node;
+ xmlNodeSetPtr xml_interfaces = xpath_obj->nodesetval;
+
+ for (j = 0; j < xml_interfaces->nodeNr; ++j) {
char *path = NULL;
+ char *address = NULL;
+ xmlNodePtr xml_interface;
- node = xpath_obj->nodesetval->nodeTab[j];
- if (!node) continue;
- path = (char *) xmlGetProp (node, (xmlChar *) "dev");
- if (!path) continue;
+ xml_interface = xml_interfaces->nodeTab[j];
+ if (!xml_interface) continue;
+ xmlNodePtr child = NULL;
+
+ for (child = xml_interface->children; child; child = child->next) {
+ if (child->type != XML_ELEMENT_NODE) continue;
+
+ if (xmlStrEqual(child->name, (const xmlChar *) "target")) {
+ path = (char *) xmlGetProp (child, (const xmlChar *) "dev");
+ if (!path) continue;
+ } else if (xmlStrEqual(child->name, (const xmlChar *) "mac")) {
+ address = (char *) xmlGetProp (child, (const xmlChar *) "address");
+ if (!address) continue;
+ }
+ }
if (il_interface_devices &&
- ignore_device_match (il_interface_devices, name, path) != 0)
+ (ignore_device_match (il_interface_devices, name, path) != 0 ||
+ ignore_device_match (il_interface_devices, name, address) != 0))
goto cont3;
- add_interface_device (dom, path);
- cont3:
- if (path) xmlFree (path);
+ add_interface_device (dom, path, address);
+ cont3:
+ if (path) xmlFree (path);
+ if (address) xmlFree (address);
}
cont:
if (xpath_obj) xmlXPathFreeObject (xpath_obj);
if (xpath_ctx) xmlXPathFreeContext (xpath_ctx);
if (xml_doc) xmlFreeDoc (xml_doc);
- if (xml) free (xml);
+ sfree (xml);
}
- free (domids);
+ sfree (domids);
}
return 0;
if (domains) {
for (i = 0; i < nr_domains; ++i)
virDomainFree (domains[i]);
- free (domains);
+ sfree (domains);
}
domains = NULL;
nr_domains = 0;
if (block_devices) {
for (i = 0; i < nr_block_devices; ++i)
- free (block_devices[i].path);
- free (block_devices);
+ sfree (block_devices[i].path);
+ sfree (block_devices);
}
block_devices = NULL;
nr_block_devices = 0;
new_ptr = malloc (new_size);
if (new_ptr == NULL) {
- free (path_copy);
+ sfree (path_copy);
return -1;
}
block_devices = new_ptr;
int i;
if (interface_devices) {
- for (i = 0; i < nr_interface_devices; ++i)
- free (interface_devices[i].path);
- free (interface_devices);
+ for (i = 0; i < nr_interface_devices; ++i) {
+ sfree (interface_devices[i].path);
+ sfree (interface_devices[i].address);
+ }
+ sfree (interface_devices);
}
interface_devices = NULL;
nr_interface_devices = 0;
}
static int
-add_interface_device (virDomainPtr dom, const char *path)
+add_interface_device (virDomainPtr dom, const char *path, const char *address)
{
struct interface_device *new_ptr;
int new_size = sizeof (interface_devices[0]) * (nr_interface_devices+1);
- char *path_copy;
+ char *path_copy, *address_copy;
path_copy = strdup (path);
if (!path_copy) return -1;
+ address_copy = strdup (address);
+ if (!address_copy) return -1;
+
if (interface_devices)
new_ptr = realloc (interface_devices, new_size);
else
new_ptr = malloc (new_size);
if (new_ptr == NULL) {
- free (path_copy);
+ sfree (path_copy);
+ sfree (address_copy);
return -1;
}
interface_devices = new_ptr;
interface_devices[nr_interface_devices].dom = dom;
interface_devices[nr_interface_devices].path = path_copy;
+ interface_devices[nr_interface_devices].address = address_copy;
return nr_interface_devices++;
}
}
ssnprintf (name, n, "%s:%s", domname, devpath);
r = ignorelist_match (il, name);
- free (name);
+ sfree (name);
return r;
}
static kstat_t *ksp;
/* #endif HAVE_LIBKSTAT */
-#elif HAVE_SWAPCTL
-/* No global variables */
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
+static derive_t pagesize;
/* #endif HAVE_SWAPCTL */
#elif defined(VM_SWAPUSAGE)
ksp = NULL;
/* #endif HAVE_LIBKSTAT */
-#elif HAVE_SWAPCTL
- /* No init stuff */
+#elif HAVE_SWAPCTL && HAVE_SWAPCTL_TWO_ARGS
+ /* getpagesize(3C) tells me this does not fail.. */
+ pagesize = (derive_t) getpagesize ();
/* #endif HAVE_SWAPCTL */
#elif defined(VM_SWAPUSAGE)
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SWAPCTL
+ #if HAVE_SWAPCTL_TWO_ARGS
+ swaptbl_t *s;
+ char strtab[255];
+ int swap_num;
+ int status;
+ int i;
+
+ derive_t avail = 0;
+ derive_t total = 0;
+
+ swap_num = swapctl (SC_GETNSWP, NULL);
+ if (swap_num < 0)
+ {
+ ERROR ("swap plugin: swapctl (SC_GETNSWP) failed with status %i.",
+ swap_num);
+ return (-1);
+ }
+ else if (swap_num == 0)
+ return (0);
+
+ s = (swaptbl_t *) smalloc (swap_num * sizeof (swapent_t) + sizeof (struct swaptable));
+ if (s == NULL)
+ {
+ ERROR ("swap plugin: smalloc failed.");
+ return (-1);
+ }
+ /* Initialize string pointers. We have them share the same buffer as we don't care
+ * about the device's name, only its size. This saves memory and alloc/free ops */
+ for (i = 0; i < (swap_num + 1); i++) {
+ s->swt_ent[i].ste_path = strtab;
+ }
+ s->swt_n = swap_num + 1;
+ status = swapctl (SC_LIST, s);
+ if (status != swap_num)
+ {
+ ERROR ("swap plugin: swapctl (SC_LIST) failed with status %i.",
+ status);
+ sfree (s);
+ return (-1);
+ }
+
+ for (i = 0; i < swap_num; i++)
+ {
+ if ((s->swt_ent[i].ste_flags & ST_INDEL) != 0)
+ continue;
+
+ avail += ((derive_t) s->swt_ent[i].ste_free)
+ * pagesize;
+ total += ((derive_t) s->swt_ent[i].ste_pages)
+ * pagesize;
+ }
+
+ if (total < avail)
+ {
+ ERROR ("swap plugin: Total swap space (%"PRIi64") "
+ "is less than free swap space (%"PRIi64").",
+ total, avail);
+ sfree (s);
+ return (-1);
+ }
+
+ swap_submit ("used", total - avail, DS_TYPE_GAUGE);
+ swap_submit ("free", avail, DS_TYPE_GAUGE);
+
+ sfree (s);
+ /* #endif HAVE_SWAPCTL_TWO_ARGS */
+ #elif HAVE_SWAPCTL_THREE_ARGS
+
struct swapent *swap_entries;
int swap_num;
int status;
derive_t used = 0;
derive_t total = 0;
- /*
- * XXX: This is the syntax for the *BSD `swapctl', which has the
- * following prototype:
- * swapctl (int cmd, void *arg, int misc);
- *
- * HP-UX and Solaris (and possibly other UNIXes) provide `swapctl',
- * too, but with the following prototype:
- * swapctl (int cmd, void *arg);
- *
- * Solaris is usually handled in the KSTAT case above. For other UNIXes
- * a separate case for the other version of `swapctl' may be necessary.
- */
swap_num = swapctl (SWAP_NSWAP, NULL, 0);
if (swap_num < 0)
{
swap_submit ("free", total - used, DS_TYPE_GAUGE);
sfree (swap_entries);
+ #endif /* HAVE_SWAPCTL_THREE_ARGS */
/* #endif HAVE_SWAPCTL */
#elif defined(VM_SWAPUSAGE)
--- /dev/null
+/**
+ * collectd - src/target_set.c
+ * Copyright (C) 2008-2010 Florian Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; only version 2.1 of the License is
+ * applicable.
+ *
+ * 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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:
+ * Florian Forster <octo at verplant.org>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "filter_chain.h"
+
+static void v5_swap_instances (value_list_t *vl) /* {{{ */
+{
+ char tmp[DATA_MAX_NAME_LEN];
+
+ assert (sizeof (tmp) == sizeof (vl->plugin_instance));
+ assert (sizeof (tmp) == sizeof (vl->type_instance));
+
+ memcpy (tmp, vl->plugin_instance, sizeof (tmp));
+ memcpy (vl->plugin_instance, vl->type_instance, sizeof (tmp));
+ memcpy (vl->type_instance, tmp, sizeof (tmp));
+} /* }}} void v5_swap_instances */
+
+/*
+ * Df type
+ *
+ * By default, the "df" plugin of version 4.* uses the "df" type and puts the
+ * mount point in the type instance. Detect this behavior and convert the type
+ * to "df_complex". This can be selected in versions 4.9 and 4.10 by setting
+ * the "ReportReserved" option of the "df" plugin.
+ */
+static int v5_df (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+ value_list_t new_vl;
+ value_t new_value;
+
+ /* Can't upgrade if both instances have been set. */
+ if ((vl->plugin_instance[0] != 0)
+ && (vl->type_instance[0] != 0))
+ return (FC_TARGET_CONTINUE);
+
+ /* Copy everything: Time, interval, host, ... */
+ memcpy (&new_vl, vl, sizeof (new_vl));
+
+ /* Reset data we can't simply copy */
+ new_vl.values = &new_value;
+ new_vl.values_len = 1;
+ new_vl.meta = NULL;
+
+ /* Move the mount point name to the plugin instance */
+ if (new_vl.plugin_instance[0] == 0)
+ v5_swap_instances (&new_vl);
+
+ /* Change the type to "df_complex" */
+ memcpy (new_vl.type, "df_complex", sizeof (new_vl.type));
+
+ /* Dispatch two new value lists instead of this one */
+ new_vl.values[0].gauge = vl->values[0].gauge;
+ memcpy (new_vl.type_instance, "used", sizeof (new_vl.type_instance));
+ plugin_dispatch_values (&new_vl);
+
+ new_vl.values[0].gauge = vl->values[1].gauge;
+ memcpy (new_vl.type_instance, "free", sizeof (new_vl.type_instance));
+ plugin_dispatch_values (&new_vl);
+
+ /* Abort processing */
+ return (FC_TARGET_STOP);
+} /* }}} int v5_df */
+
+/*
+ * Interface plugin
+ *
+ * 4.* stores the interface in the type instance and leaves the plugin
+ * instance empty. If this is the case, put the interface name into the plugin
+ * instance and clear the type instance.
+ */
+static int v5_interface (const data_set_t *ds, value_list_t *vl) /* {{{ */
+{
+ if ((vl->plugin_instance[0] != 0) || (vl->type_instance[0] == 0))
+ return (FC_TARGET_CONTINUE);
+
+ v5_swap_instances (vl);
+ return (FC_TARGET_CONTINUE);
+} /* }}} int v5_interface */
+
+static int v5_destroy (void **user_data) /* {{{ */
+{
+ return (0);
+} /* }}} int v5_destroy */
+
+static int v5_create (const oconfig_item_t *ci, void **user_data) /* {{{ */
+{
+ *user_data = NULL;
+ return (0);
+} /* }}} int v5_create */
+
+static int v5_invoke (const data_set_t *ds, value_list_t *vl, /* {{{ */
+ notification_meta_t __attribute__((unused)) **meta,
+ void __attribute__((unused)) **user_data)
+{
+ if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
+ return (-EINVAL);
+
+ if (strcmp ("df", vl->type) == 0)
+ return (v5_df (ds, vl));
+ else if (strcmp ("interface", vl->plugin) == 0)
+ return (v5_interface (ds, vl));
+
+ return (FC_TARGET_CONTINUE);
+} /* }}} int v5_invoke */
+
+void module_register (void)
+{
+ target_proc_t tproc;
+
+ memset (&tproc, 0, sizeof (tproc));
+ tproc.create = v5_create;
+ tproc.destroy = v5_destroy;
+ tproc.invoke = v5_invoke;
+ fc_register_target ("v5upgrade", tproc);
+} /* module_register */
+
+/* vim: set sw=2 sts=2 tw=78 et fdm=marker : */
+
ath_stat value:COUNTER:0:4294967295
bitrate value:GAUGE:0:4294967295
bytes value:GAUGE:0:U
+cache_operation value:DERIVE:0:U
cache_ratio value:GAUGE:0:100
-cache_result value:COUNTER:0:4294967295
+cache_result value:DERIVE:0:U
cache_size value:GAUGE:0:4294967295
charge value:GAUGE:0:U
compression uncompressed:COUNTER:0:U, compressed:COUNTER:0:U
ps_state value:GAUGE:0:65535
ps_vm value:GAUGE:0:9223372036854775807
queue_length value:GAUGE:0:U
-response_time value:GAUGE:0:U
records count:GAUGE:0:U
+requests value:GAUGE:0:U
+response_time value:GAUGE:0:U
route_etx value:GAUGE:0:U
route_metric value:GAUGE:0:U
routes value:GAUGE:0:U
timeleft timeleft:GAUGE:0:3600
time_offset seconds:GAUGE:-1000000:1000000
total_bytes value:DERIVE:0:U
+total_operations value:DERIVE:0:U
total_requests value:DERIVE:0:U
+total_threads value:DERIVE:0:U
total_time_in_ms value:DERIVE:0:U
total_values value:DERIVE:0:U
uptime value:GAUGE:0:4294967295
#define UT_FLAG_INVERT 0x01
#define UT_FLAG_PERSIST 0x02
#define UT_FLAG_PERCENTAGE 0x04
+#define UT_FLAG_INTERESTING 0x08
/* }}} */
/*
return (0);
} /* int ut_config_type_min */
-static int ut_config_type_invert (threshold_t *th, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("threshold values: The `Invert' option needs exactly one "
- "boolean argument.");
- return (-1);
- }
-
- if (ci->values[0].value.boolean)
- th->flags |= UT_FLAG_INVERT;
- else
- th->flags &= ~UT_FLAG_INVERT;
-
- return (0);
-} /* int ut_config_type_invert */
-
-static int ut_config_type_persist (threshold_t *th, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("threshold values: The `Persist' option needs exactly one "
- "boolean argument.");
- return (-1);
- }
-
- if (ci->values[0].value.boolean)
- th->flags |= UT_FLAG_PERSIST;
- else
- th->flags &= ~UT_FLAG_PERSIST;
-
- return (0);
-} /* int ut_config_type_persist */
-
-static int ut_config_type_percentage(threshold_t *th, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("threshold values: The `Percentage' option needs exactly one "
- "boolean argument.");
- return (-1);
- }
-
- if (ci->values[0].value.boolean)
- th->flags |= UT_FLAG_PERCENTAGE;
- else
- th->flags &= ~UT_FLAG_PERCENTAGE;
-
- return (0);
-} /* int ut_config_type_percentage */
-
static int ut_config_type_hits (threshold_t *th, oconfig_item_t *ci)
{
if ((ci->values_num != 1)
th.failure_max = NAN;
th.hits = 0;
th.hysteresis = 0;
+ th.flags = UT_FLAG_INTERESTING; /* interesting by default */
for (i = 0; i < ci->children_num; i++)
{
else if ((strcasecmp ("WarningMin", option->key) == 0)
|| (strcasecmp ("FailureMin", option->key) == 0))
status = ut_config_type_min (&th, option);
+ else if (strcasecmp ("Interesting", option->key) == 0)
+ status = cf_util_get_flag (option, &th.flags, UT_FLAG_INTERESTING);
else if (strcasecmp ("Invert", option->key) == 0)
- status = ut_config_type_invert (&th, option);
+ status = cf_util_get_flag (option, &th.flags, UT_FLAG_INVERT);
else if (strcasecmp ("Persist", option->key) == 0)
- status = ut_config_type_persist (&th, option);
+ status = cf_util_get_flag (option, &th.flags, UT_FLAG_PERSIST);
else if (strcasecmp ("Percentage", option->key) == 0)
- status = ut_config_type_percentage (&th, option);
+ status = cf_util_get_flag (option, &th.flags, UT_FLAG_PERCENTAGE);
else if (strcasecmp ("Hits", option->key) == 0)
status = ut_config_type_hits (&th, option);
else if (strcasecmp ("Hysteresis", option->key) == 0)
th.hits = 0;
th.hysteresis = 0;
+ th.flags = UT_FLAG_INTERESTING; /* interesting by default */
for (i = 0; i < ci->children_num; i++)
{
th = threshold_search (&vl);
if (th == NULL)
return (0);
+
+ if ((th->flags & UT_FLAG_INTERESTING) == 0)
+ return (0);
+
if ((th->flags & UT_FLAG_PERSIST) == 0)
return (1);
return (2);
gauge_t failure_min;
gauge_t failure_max;
gauge_t hysteresis;
- int flags;
+ unsigned int flags;
int hits;
struct threshold_s *next;
} threshold_t;
--- /dev/null
+/**
+ * collectd - src/varnish.c
+ * Copyright (C) 2010 Jerome Renard
+ *
+ * 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; only version 2 of the License is applicable.
+ *
+ * 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:
+ * Florian octo Forster <octo at verplant.org>
+ * Jerome Renard <jerome.renard@gmail.com>
+ **/
+
+/**
+ * Current list of what is monitored and what is not monitored (yet)
+ * {{{
+ * Field name Description Monitored
+ * ---------- ----------- ---------
+ * uptime Child uptime N
+ * client_conn Client connections accepted Y
+ * client_drop Connection dropped, no sess Y
+ * client_req Client requests received Y
+ * cache_hit Cache hits Y
+ * cache_hitpass Cache hits for pass Y
+ * cache_miss Cache misses Y
+ * backend_conn Backend conn. success Y
+ * backend_unhealthy Backend conn. not attempted Y
+ * backend_busy Backend conn. too many Y
+ * backend_fail Backend conn. failures Y
+ * backend_reuse Backend conn. reuses Y
+ * backend_toolate Backend conn. was closed Y
+ * backend_recycle Backend conn. recycles Y
+ * backend_unused Backend conn. unused Y
+ * fetch_head Fetch head Y
+ * fetch_length Fetch with Length Y
+ * fetch_chunked Fetch chunked Y
+ * fetch_eof Fetch EOF Y
+ * fetch_bad Fetch had bad headers Y
+ * fetch_close Fetch wanted close Y
+ * fetch_oldhttp Fetch pre HTTP/1.1 closed Y
+ * fetch_zero Fetch zero len Y
+ * fetch_failed Fetch failed Y
+ * n_sess_mem N struct sess_mem N
+ * n_sess N struct sess N
+ * n_object N struct object N
+ * n_vampireobject N unresurrected objects N
+ * n_objectcore N struct objectcore N
+ * n_objecthead N struct objecthead N
+ * n_smf N struct smf N
+ * n_smf_frag N small free smf N
+ * n_smf_large N large free smf N
+ * n_vbe_conn N struct vbe_conn N
+ * n_wrk N worker threads Y
+ * n_wrk_create N worker threads created Y
+ * n_wrk_failed N worker threads not created Y
+ * n_wrk_max N worker threads limited Y
+ * n_wrk_queue N queued work requests Y
+ * n_wrk_overflow N overflowed work requests Y
+ * n_wrk_drop N dropped work requests Y
+ * n_backend N backends N
+ * n_expired N expired objects N
+ * n_lru_nuked N LRU nuked objects N
+ * n_lru_saved N LRU saved objects N
+ * n_lru_moved N LRU moved objects N
+ * n_deathrow N objects on deathrow N
+ * losthdr HTTP header overflows N
+ * n_objsendfile Objects sent with sendfile N
+ * n_objwrite Objects sent with write N
+ * n_objoverflow Objects overflowing workspace N
+ * s_sess Total Sessions Y
+ * s_req Total Requests Y
+ * s_pipe Total pipe Y
+ * s_pass Total pass Y
+ * s_fetch Total fetch Y
+ * s_hdrbytes Total header bytes Y
+ * s_bodybytes Total body bytes Y
+ * sess_closed Session Closed N
+ * sess_pipeline Session Pipeline N
+ * sess_readahead Session Read Ahead N
+ * sess_linger Session Linger N
+ * sess_herd Session herd N
+ * shm_records SHM records Y
+ * shm_writes SHM writes Y
+ * shm_flushes SHM flushes due to overflow Y
+ * shm_cont SHM MTX contention Y
+ * shm_cycles SHM cycles through buffer Y
+ * sm_nreq allocator requests Y
+ * sm_nobj outstanding allocations Y
+ * sm_balloc bytes allocated Y
+ * sm_bfree bytes free Y
+ * sma_nreq SMA allocator requests Y
+ * sma_nobj SMA outstanding allocations Y
+ * sma_nbytes SMA outstanding bytes Y
+ * sma_balloc SMA bytes allocated Y
+ * sma_bfree SMA bytes free Y
+ * sms_nreq SMS allocator requests Y
+ * sms_nobj SMS outstanding allocations Y
+ * sms_nbytes SMS outstanding bytes Y
+ * sms_balloc SMS bytes allocated Y
+ * sms_bfree SMS bytes freed Y
+ * backend_req Backend requests made N
+ * n_vcl N vcl total N
+ * n_vcl_avail N vcl available N
+ * n_vcl_discard N vcl discarded N
+ * n_purge N total active purges N
+ * n_purge_add N new purges added N
+ * n_purge_retire N old purges deleted N
+ * n_purge_obj_test N objects tested N
+ * n_purge_re_test N regexps tested against N
+ * n_purge_dups N duplicate purges removed N
+ * hcb_nolock HCB Lookups without lock Y
+ * hcb_lock HCB Lookups with lock Y
+ * hcb_insert HCB Inserts Y
+ * esi_parse Objects ESI parsed (unlock) Y
+ * esi_errors ESI parse errors (unlock) Y
+ * }}}
+ */
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+
+#include <varnish/varnishapi.h>
+
+/* {{{ user_config_s */
+struct user_config_s {
+ char *instance;
+
+ _Bool collect_cache;
+ _Bool collect_connections;
+ _Bool collect_esi;
+ _Bool collect_backend;
+ _Bool collect_fetch;
+ _Bool collect_hcb;
+ _Bool collect_shm;
+ _Bool collect_sma;
+ _Bool collect_sms;
+ _Bool collect_sm;
+ _Bool collect_totals;
+ _Bool collect_workers;
+};
+typedef struct user_config_s user_config_t; /* }}} */
+
+static _Bool have_instance = 0;
+
+static int varnish_submit (const char *plugin_instance, /* {{{ */
+ const char *type, const char *type_instance, value_t value)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = &value;
+ vl.values_len = 1;
+
+ sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+
+ sstrncpy(vl.plugin, "varnish", sizeof(vl.plugin));
+ if (plugin_instance != NULL)
+ sstrncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
+
+ sstrncpy(vl.type, type, sizeof(vl.type));
+ if (type_instance != NULL)
+ sstrncpy(vl.type_instance, type_instance,
+ sizeof(vl.type_instance));
+
+ return (plugin_dispatch_values(&vl));
+} /* }}} int varnish_submit */
+
+static int varnish_submit_gauge (const char *plugin_instance, /* {{{ */
+ const char *type, const char *type_instance,
+ uint64_t gauge_value)
+{
+ value_t value;
+
+ value.gauge = (gauge_t) gauge_value;
+
+ return (varnish_submit (plugin_instance, type, type_instance, value));
+} /* }}} int varnish_submit_gauge */
+
+static int varnish_submit_derive (const char *plugin_instance, /* {{{ */
+ const char *type, const char *type_instance,
+ uint64_t derive_value)
+{
+ value_t value;
+
+ value.derive = (derive_t) derive_value;
+
+ return (varnish_submit (plugin_instance, type, type_instance, value));
+} /* }}} int varnish_submit_derive */
+
+static void varnish_monitor(const user_config_t *conf, struct varnish_stats *VSL_stats) /* {{{ */
+{
+ if(conf->collect_cache)
+ {
+ /* Cache hits */
+ varnish_submit_derive (conf->instance, "cache_result", "hit" , VSL_stats->cache_hit);
+ /* Cache misses */
+ varnish_submit_derive (conf->instance, "cache_result", "miss" , VSL_stats->cache_miss);
+ /* Cache hits for pass */
+ varnish_submit_derive (conf->instance, "cache_result", "hitpass", VSL_stats->cache_hitpass);
+ }
+
+ if(conf->collect_connections)
+ {
+ /* Client connections accepted */
+ varnish_submit_derive (conf->instance, "connections", "client-accepted", VSL_stats->client_conn);
+ /* Connection dropped, no sess */
+ varnish_submit_derive (conf->instance, "connections", "client-dropped" , VSL_stats->client_drop);
+ /* Client requests received */
+ varnish_submit_derive (conf->instance, "connections", "client-received", VSL_stats->client_req);
+ }
+
+ if(conf->collect_esi)
+ {
+ /* Objects ESI parsed (unlock) */
+ varnish_submit_derive (conf->instance, "total_operations", "esi-parsed", VSL_stats->esi_parse);
+ /* ESI parse errors (unlock) */
+ varnish_submit_derive (conf->instance, "total_operations", "esi-error", VSL_stats->esi_errors);
+ }
+
+ if(conf->collect_backend)
+ {
+ /* Backend conn. success */
+ varnish_submit_derive (conf->instance, "connections", "backend-success" , VSL_stats->backend_conn);
+ /* Backend conn. not attempted */
+ varnish_submit_derive (conf->instance, "connections", "backend-not-attempted", VSL_stats->backend_unhealthy);
+ /* Backend conn. too many */
+ varnish_submit_derive (conf->instance, "connections", "backend-too-many" , VSL_stats->backend_busy);
+ /* Backend conn. failures */
+ varnish_submit_derive (conf->instance, "connections", "backend-failures" , VSL_stats->backend_fail);
+ /* Backend conn. reuses */
+ varnish_submit_derive (conf->instance, "connections", "backend-reuses" , VSL_stats->backend_reuse);
+ /* Backend conn. was closed */
+ varnish_submit_derive (conf->instance, "connections", "backend-was-closed" , VSL_stats->backend_toolate);
+ /* Backend conn. recycles */
+ varnish_submit_derive (conf->instance, "connections", "backend-recycled" , VSL_stats->backend_recycle);
+ /* Backend conn. unused */
+ varnish_submit_derive (conf->instance, "connections", "backend-unused" , VSL_stats->backend_unused);
+ }
+
+ if(conf->collect_fetch)
+ {
+ /* Fetch head */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-head" , VSL_stats->fetch_head);
+ /* Fetch with length */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-length" , VSL_stats->fetch_length);
+ /* Fetch chunked */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-chunked" , VSL_stats->fetch_chunked);
+ /* Fetch EOF */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-eof" , VSL_stats->fetch_eof);
+ /* Fetch bad headers */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-bad_headers", VSL_stats->fetch_bad);
+ /* Fetch wanted close */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-close" , VSL_stats->fetch_close);
+ /* Fetch pre HTTP/1.1 closed */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-oldhttp" , VSL_stats->fetch_oldhttp);
+ /* Fetch zero len */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-zero" , VSL_stats->fetch_zero);
+ /* Fetch failed */
+ varnish_submit_derive (conf->instance, "http_requests", "fetch-failed" , VSL_stats->fetch_failed);
+ }
+
+ if(conf->collect_hcb)
+ {
+ /* HCB Lookups without lock */
+ varnish_submit_derive (conf->instance, "cache_operation", "lookup_nolock", VSL_stats->hcb_nolock);
+ /* HCB Lookups with lock */
+ varnish_submit_derive (conf->instance, "cache_operation", "lookup_lock", VSL_stats->hcb_lock);
+ /* HCB Inserts */
+ varnish_submit_derive (conf->instance, "cache_operation", "insert", VSL_stats->hcb_insert);
+ }
+
+ if(conf->collect_shm)
+ {
+ /* SHM records */
+ varnish_submit_derive (conf->instance, "total_operations", "shmlog-records" , VSL_stats->shm_records);
+ /* SHM writes */
+ varnish_submit_derive (conf->instance, "total_operations", "shmlog-writes" , VSL_stats->shm_writes);
+ /* SHM flushes due to overflow */
+ varnish_submit_derive (conf->instance, "total_operations", "shmlog-flushes" , VSL_stats->shm_flushes);
+ /* SHM MTX contention */
+ varnish_submit_derive (conf->instance, "total_operations", "shmlog-contention", VSL_stats->shm_cont);
+ /* SHM cycles through buffer */
+ varnish_submit_derive (conf->instance, "total_operations", "shmlog-cycles" , VSL_stats->shm_cycles);
+ }
+
+ if(conf->collect_sm)
+ {
+ /* allocator requests */
+ varnish_submit_derive (conf->instance, "total_requests", "storage-file", VSL_stats->sm_nreq);
+ /* outstanding allocations */
+ varnish_submit_gauge (conf->instance, "requests", "storage-file-outstanding", VSL_stats->sm_nobj);
+ /* bytes allocated */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-file-allocated", VSL_stats->sm_balloc);
+ /* bytes free */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-file-free", VSL_stats->sm_bfree);
+ }
+
+ if(conf->collect_sma)
+ {
+ /* SMA allocator requests */
+ varnish_submit_derive (conf->instance, "total_requests", "storage-mem", VSL_stats->sma_nreq);
+ /* SMA outstanding allocations */
+ varnish_submit_gauge (conf->instance, "requests", "storage-mem-outstanding", VSL_stats->sma_nobj);
+ /* SMA outstanding bytes */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-mem-outstanding", VSL_stats->sma_nbytes);
+ /* SMA bytes allocated */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-mem-allocated", VSL_stats->sma_balloc);
+ /* SMA bytes free */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-mem-free" , VSL_stats->sma_bfree);
+ }
+
+ if(conf->collect_sms)
+ {
+ /* SMS allocator requests */
+ varnish_submit_derive (conf->instance, "total_requests", "storage-synth", VSL_stats->sms_nreq);
+ /* SMS outstanding allocations */
+ varnish_submit_gauge (conf->instance, "requests", "storage-synth-outstanding", VSL_stats->sms_nobj);
+ /* SMS outstanding bytes */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-synth-outstanding", VSL_stats->sms_nbytes);
+ /* SMS bytes allocated */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-synth-allocated", VSL_stats->sms_balloc);
+ /* SMS bytes freed */
+ varnish_submit_gauge (conf->instance, "bytes", "storage-synth-free", VSL_stats->sms_bfree);
+ }
+
+ if(conf->collect_totals)
+ {
+ /* Total Sessions */
+ varnish_submit_derive (conf->instance, "total_counters", "sessions", VSL_stats->s_sess);
+ /* Total Requests */
+ varnish_submit_derive (conf->instance, "total_requests", "requests", VSL_stats->s_req);
+ /* Total pipe */
+ varnish_submit_derive (conf->instance, "total_operations", "pipe", VSL_stats->s_pipe);
+ /* Total pass */
+ varnish_submit_derive (conf->instance, "total_operations", "pass", VSL_stats->s_pass);
+ /* Total fetch */
+ varnish_submit_derive (conf->instance, "total_operations", "fetches", VSL_stats->s_fetch);
+ /* Total header bytes */
+ varnish_submit_derive (conf->instance, "total_bytes", "header-bytes", VSL_stats->s_hdrbytes);
+ /* Total body byte */
+ varnish_submit_derive (conf->instance, "total_bytes", "body-bytes", VSL_stats->s_bodybytes);
+ }
+
+ if(conf->collect_workers)
+ {
+ /* worker threads */
+ varnish_submit_gauge (conf->instance, "threads", "worker", VSL_stats->n_wrk);
+ /* worker threads created */
+ varnish_submit_gauge (conf->instance, "total_threads", "threads-created", VSL_stats->n_wrk_create);
+ /* worker threads not created */
+ varnish_submit_gauge (conf->instance, "total_threads", "threads-failed", VSL_stats->n_wrk_failed);
+ /* worker threads limited */
+ varnish_submit_gauge (conf->instance, "total_threads", "threads-limited", VSL_stats->n_wrk_max);
+ /* queued work requests */
+ varnish_submit_gauge (conf->instance, "total_requests", "worker-queued", VSL_stats->n_wrk_queue);
+ /* overflowed work requests */
+ varnish_submit_gauge (conf->instance, "total_requests", "worker-overflowed", VSL_stats->n_wrk_overflow);
+ /* dropped work requests */
+ varnish_submit_gauge (conf->instance, "total_requests", "worker-dropped", VSL_stats->n_wrk_drop);
+ }
+} /* }}} void varnish_monitor */
+
+static int varnish_read(user_data_t *ud) /* {{{ */
+{
+ struct varnish_stats *VSL_stats;
+ user_config_t *conf;
+
+ if ((ud == NULL) || (ud->data == NULL))
+ return (EINVAL);
+
+ conf = ud->data;
+
+ VSL_stats = VSL_OpenStats(conf->instance);
+ if (VSL_stats == NULL)
+ {
+ ERROR("Varnish plugin : unable to load statistics");
+
+ return (-1);
+ }
+
+ varnish_monitor(conf, VSL_stats);
+
+ return (0);
+} /* }}} */
+
+static void varnish_config_free (void *ptr) /* {{{ */
+{
+ user_config_t *conf = ptr;
+
+ if (conf == NULL)
+ return;
+
+ sfree (conf->instance);
+ sfree (conf);
+} /* }}} */
+
+static int varnish_config_apply_default (user_config_t *conf) /* {{{ */
+{
+ if (conf == NULL)
+ return (EINVAL);
+
+ conf->collect_backend = 1;
+ conf->collect_cache = 1;
+ conf->collect_connections = 1;
+ conf->collect_esi = 0;
+ conf->collect_fetch = 0;
+ conf->collect_hcb = 0;
+ conf->collect_shm = 1;
+ conf->collect_sm = 0;
+ conf->collect_sma = 0;
+ conf->collect_sms = 0;
+ conf->collect_totals = 0;
+
+ return (0);
+} /* }}} int varnish_config_apply_default */
+
+static int varnish_init (void) /* {{{ */
+{
+ user_config_t *conf;
+ user_data_t ud;
+
+ if (have_instance)
+ return (0);
+
+ conf = malloc (sizeof (*conf));
+ if (conf == NULL)
+ return (ENOMEM);
+ memset (conf, 0, sizeof (*conf));
+
+ /* Default settings: */
+ conf->instance = NULL;
+
+ varnish_config_apply_default (conf);
+
+ ud.data = conf;
+ ud.free_func = varnish_config_free;
+
+ plugin_register_complex_read (/* group = */ "varnish",
+ /* name = */ "varnish/localhost",
+ /* callback = */ varnish_read,
+ /* interval = */ NULL,
+ /* user data = */ &ud);
+
+ return (0);
+} /* }}} int varnish_init */
+
+static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
+{
+ user_config_t *conf;
+ user_data_t ud;
+ char callback_name[DATA_MAX_NAME_LEN];
+ int i;
+
+ conf = malloc (sizeof (*conf));
+ if (conf == NULL)
+ return (ENOMEM);
+ memset (conf, 0, sizeof (*conf));
+ conf->instance = NULL;
+
+ varnish_config_apply_default (conf);
+
+ if (ci->values_num == 1)
+ {
+ int status;
+
+ status = cf_util_get_string (ci, &conf->instance);
+ if (status != 0)
+ {
+ sfree (conf);
+ return (status);
+ }
+ assert (conf->instance != NULL);
+
+ if (strcmp ("localhost", conf->instance) == 0)
+ {
+ sfree (conf->instance);
+ conf->instance = NULL;
+ }
+ }
+ else if (ci->values_num > 1)
+ {
+ WARNING ("Varnish plugin: \"Instance\" blocks accept only "
+ "one argument.");
+ return (EINVAL);
+ }
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("CollectCache", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_cache);
+ else if (strcasecmp ("CollectConnections", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_connections);
+ else if (strcasecmp ("CollectESI", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_esi);
+ else if (strcasecmp ("CollectBackend", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_backend);
+ else if (strcasecmp ("CollectFetch", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_fetch);
+ else if (strcasecmp ("CollectHCB", child->key) == 0)
+ 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);
+ else if (strcasecmp ("CollectSM", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_sm);
+ else if (strcasecmp ("CollectTotals", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_totals);
+ else if (strcasecmp ("CollectWorkers", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_workers);
+ else
+ {
+ WARNING ("Varnish plugin: Ignoring unknown "
+ "configuration option: \"%s\"",
+ child->key);
+ }
+ }
+
+ if (!conf->collect_cache
+ && !conf->collect_connections
+ && !conf->collect_esi
+ && !conf->collect_backend
+ && !conf->collect_fetch
+ && !conf->collect_hcb
+ && !conf->collect_shm
+ && !conf->collect_sma
+ && !conf->collect_sms
+ && !conf->collect_sm
+ && !conf->collect_totals
+ && !conf->collect_workers)
+ {
+ WARNING ("Varnish plugin: No metric has been configured for "
+ "instance \"%s\". Disabling this instance.",
+ (conf->instance == NULL) ? "localhost" : conf->instance);
+ return (EINVAL);
+ }
+
+ ssnprintf (callback_name, sizeof (callback_name), "varnish/%s",
+ (conf->instance == NULL) ? "localhost" : conf->instance);
+
+ ud.data = conf;
+ ud.free_func = varnish_config_free;
+
+ plugin_register_complex_read (/* group = */ "varnish",
+ /* name = */ callback_name,
+ /* callback = */ varnish_read,
+ /* interval = */ NULL,
+ /* user data = */ &ud);
+
+ have_instance = 1;
+
+ return (0);
+} /* }}} int varnish_config_instance */
+
+static int varnish_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("Instance", child->key) == 0)
+ varnish_config_instance (child);
+ else
+ {
+ WARNING ("Varnish plugin: Ignoring unknown "
+ "configuration option: \"%s\"",
+ child->key);
+ }
+ }
+
+ return (0);
+} /* }}} int varnish_config */
+
+void module_register (void) /* {{{ */
+{
+ plugin_register_complex_config("varnish", varnish_config);
+ plugin_register_init ("varnish", varnish_init);
+} /* }}} */
+
+/* vim: set sw=8 noet fdm=marker : */