author | Florian Forster <octo@collectd.org> | |
Sat, 1 Jun 2013 07:25:28 +0000 (09:25 +0200) | ||
committer | Florian Forster <octo@collectd.org> | |
Sat, 1 Jun 2013 07:25:28 +0000 (09:25 +0200) |
22 files changed:
AUTHORS | patch | blob | history | |
README | patch | blob | history | |
configure.in | patch | blob | history | |
contrib/redhat/init.d-collectd | patch | blob | history | |
src/Makefile.am | patch | blob | history | |
src/amqp.c | patch | blob | history | |
src/cgroups.c | [new file with mode: 0644] | patch | blob |
src/collectd.conf.in | patch | blob | history | |
src/collectd.conf.pod | patch | blob | history | |
src/common.c | patch | blob | history | |
src/common.h | patch | blob | history | |
src/configfile.c | patch | blob | history | |
src/curl_xml.c | patch | blob | history | |
src/df.c | patch | blob | history | |
src/lvm.c | [new file with mode: 0644] | patch | blob |
src/mic.c | [new file with mode: 0644] | patch | blob |
src/plugin.c | patch | blob | history | |
src/plugin.h | patch | blob | history | |
src/snmp.c | patch | blob | history | |
src/thermal.c | patch | blob | history | |
src/types.db | patch | blob | history | |
src/varnish.c | patch | blob | history |
index 45645d1a26e52700130ed68c6dc7042307f27895..9df0f7aeea53ed6a46be615cfa3668acef0dcadc 100644 (file)
--- a/AUTHORS
+++ b/AUTHORS
especially a nasty bug in the network plugin.
- Wireshark dissector.
+Chad Malfait <malfaitc at yahoo.com>
+ - LVM plugin.
+
Chris Lundquist <clundquist at bluebox.net>
- Improvements to the write_mongodb plugin.
Edward “Koko” Konetzko <konetzed at quixoticagony.com>
- fscache plugin.
+Evan Felix <evan.felix at pnnl.gov>
+ - mic plugin.
+
Fabian Linzberger <e at lefant.net>
- Percentage aggregation for `collectd-nagios'.
Michael Stapelberg <michael+git at stapelberg.de>
- OpenBSD port of the tcpconns plugin.
+ - cgroups plugin.
Michał Mirosław <mirq-linux at rere.qmqm.pl>
- thermal plugin.
index c3c454720484f71c3915bf6f0917ce2e27dd93ae..04e87abfb5edc5a15b5e311c8d8d53ab72028149 100644 (file)
--- a/README
+++ b/README
Name server and resolver statistics from the `statistics-channel'
interface of BIND 9.5, 9,6 and later.
+ - cgroups
+ CPU accounting information for process groups under Linux.
+
- conntrack
Number of nf_conntrack entries.
- libvirt
CPU, memory, disk and network I/O statistics from virtual machines.
+ - lvm
+ Size of “Logical Volumes” (LV) and “Volume Groups” (VG) of Linux'
+ “Logical Volume Manager” (LVM).
+
- madwifi
Queries very detailed usage statistics from wireless LAN adapters and
interfaces that use the Atheros chipset and the MadWifi driver.
Memory utilization: Memory occupied by running processes, page cache,
buffer cache and free.
+ - mic
+ Collects CPU usage, memory usage, temperatures and power consumption from
+ Intel Many Integrated Core (MIC) CPUs.
+
- modbus
Reads values from Modbus/TCP enabled devices. Supports reading values
from multiple "slaves" so gateway devices can be used.
diff --git a/configure.in b/configure.in
index a62d608bf21fe35ac40df7662f6c64ea67a24264..ba52389eb3c48b28dbec8abfb4a82f6f7eb0e99f 100644 (file)
--- a/configure.in
+++ b/configure.in
AM_CONDITIONAL(BUILD_WITH_JAVA, test "x$with_java" = "xyes")
# }}}
+# --with-liblvm2app {{{
+with_liblvm2app_cppflags=""
+with_liblvm2app_ldflags=""
+AC_ARG_WITH(liblvm2app, [AS_HELP_STRING([--with-liblvm2app@<:@=PREFIX@:>@], [Path to liblvm2app.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_liblvm2app_cppflags="-I$withval/include"
+ with_liblvm2app_ldflags="-L$withval/lib"
+ with_liblvm2app="yes"
+ else
+ with_liblvm2app="$withval"
+ fi
+],
+[
+ with_liblvm2app="yes"
+])
+if test "x$with_liblvm2app" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_liblvm2app_cppflags"
+
+ AC_CHECK_HEADERS(lvm2app.h, [with_liblvm2app="yes"], [with_liblvm2app="no (lvm2app.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+
+if test "x$with_liblvm2app" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_liblvm2app_cppflags"
+ LDFLAGS="$LDFLAGS $with_liblvm2app_ldflags"
+
+ AC_CHECK_LIB(lvm2app, lvm_init, [with_liblvm2app="yes"], [with_liblvm2app="no (Symbol 'lvm_init' not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_liblvm2app" = "xyes"
+then
+ BUILD_WITH_LIBLVM2APP_CPPFLAGS="$with_liblvm2app_cppflags"
+ BUILD_WITH_LIBLVM2APP_LDFLAGS="$with_liblvm2app_ldflags"
+ BUILD_WITH_LIBLVM2APP_LIBS="-llvm2app"
+ AC_SUBST(BUILD_WITH_LIBLVM2APP_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBLVM2APP_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBLVM2APP_LIBS)
+ AC_DEFINE(HAVE_LIBLVM2APP, 1, [Define if liblvm2app is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBLVM2APP, test "x$with_liblvm2app" = "xyes")
+# }}}
+
# --with-libmemcached {{{
with_libmemcached_cppflags=""
with_libmemcached_ldflags=""
AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
# }}}
+# --with-mic {{{
+with_mic_cflags="-I/opt/intel/mic/sysmgmt/sdk/include"
+with_mic_ldpath="-L/opt/intel/mic/sysmgmt/sdk/lib/Linux"
+with_mic_libs=""
+AC_ARG_WITH(mic,[AS_HELP_STRING([--with-mic@<:@=PREFIX@:>@], [Path to Intel MIC Access API.])],
+[
+ if test "x$withval" = "xno"
+ then
+ with_mic="no"
+ else if test "x$withval" = "xyes"
+ then
+ with_mic="yes"
+ else if test -d "$with_mic/lib"
+ then
+ AC_MSG_NOTICE([Not checking for Intel Mic: Manually configured])
+ with_mic_cflags="-I$withval/include"
+ with_mic_ldpath="-L$withval/lib/Linux"
+ with_mic_libs="-lMicAccessSDK -lscif -lpthread"
+ with_mic="yes"
+ fi; fi; fi
+],
+[with_mic="yes"])
+if test "x$with_mic" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_mic_cflags"
+ AC_CHECK_HEADERS(MicAccessApi.h,[],[with_mic="no (MicAccessApi not found)"])
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_mic" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+
+ CPPFLAGS="$CPPFLAGS $with_mic_cflags"
+ LDFLAGS="$LDFLAGS $with_mic_ldpath"
+
+ AC_CHECK_LIB(MicAccessSDK, MicInitAPI,
+ [with_mic_ldpath="$with_mic_ldpath"
+ with_mic_libs="-lMicAccessSDK -lscif -lpthread"],
+ [with_mic="no (symbol MicInitAPI not found)"],[-lscif -lpthread])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+
+if test "x$with_mic" = "xyes"
+then
+ BUILD_WITH_MIC_CPPFLAGS="$with_mic_cflags"
+ BUILD_WITH_MIC_LIBPATH="$with_mic_ldpath"
+ BUILD_WITH_MIC_LDADD="$with_mic_libs"
+ AC_SUBST(BUILD_WITH_MIC_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_MIC_LIBPATH)
+ AC_SUBST(BUILD_WITH_MIC_LDADD)
+fi
+#}}}
+
# --with-libvarnish {{{
with_libvarnish_cppflags=""
with_libvarnish_cflags=""
plugin_ascent="no"
plugin_battery="no"
plugin_bind="no"
+plugin_cgroups="no"
plugin_conntrack="no"
plugin_contextswitch="no"
plugin_cpu="no"
plugin_battery="yes"
plugin_conntrack="yes"
plugin_contextswitch="yes"
+ plugin_cgroups="yes"
plugin_cpu="yes"
plugin_cpufreq="yes"
plugin_disk="yes"
plugin_interface="yes"
plugin_irq="yes"
plugin_load="yes"
+ plugin_lvm="yes"
plugin_memory="yes"
plugin_nfs="yes"
plugin_numa="yes"
AC_PLUGIN([curl], [$with_libcurl], [CURL generic web statistics])
AC_PLUGIN([curl_json], [$plugin_curl_json], [CouchDB statistics])
AC_PLUGIN([curl_xml], [$plugin_curl_xml], [CURL generic xml statistics])
+AC_PLUGIN([cgroups], [$plugin_cgroups], [CGroups CPU usage accounting])
AC_PLUGIN([dbi], [$with_libdbi], [General database statistics])
AC_PLUGIN([df], [$plugin_df], [Filesystem usage statistics])
AC_PLUGIN([disk], [$plugin_disk], [Disk usage statistics])
AC_PLUGIN([load], [$plugin_load], [System load])
AC_PLUGIN([logfile], [yes], [File logging plugin])
AC_PLUGIN([lpar], [$with_perfstat], [AIX logical partitions statistics])
+AC_PLUGIN([lvm], [$with_liblvm2app], [LVM statistics])
AC_PLUGIN([madwifi], [$have_linux_wireless_h], [Madwifi wireless statistics])
AC_PLUGIN([match_empty_counter], [yes], [The empty counter match])
AC_PLUGIN([match_hashed], [yes], [The hashed match])
AC_PLUGIN([memcachec], [$with_libmemcached], [memcachec statistics])
AC_PLUGIN([memcached], [yes], [memcached statistics])
AC_PLUGIN([memory], [$plugin_memory], [Memory usage])
+AC_PLUGIN([mic], [$with_mic], [Intel Many Integrated Core stats])
AC_PLUGIN([modbus], [$with_libmodbus], [Modbus plugin])
AC_PLUGIN([multimeter], [$plugin_multimeter], [Read multimeter values])
AC_PLUGIN([mysql], [$with_libmysql], [MySQL statistics])
Configuration:
Libraries:
+ intel mic . . . . . . $with_mic
libcurl . . . . . . . $with_libcurl
libdbi . . . . . . . $with_libdbi
libcredis . . . . . . $with_libcredis
bind . . . . . . . . $enable_bind
conntrack . . . . . . $enable_conntrack
contextswitch . . . . $enable_contextswitch
+ cgroups . . . . . . . $enable_cgroups
cpu . . . . . . . . . $enable_cpu
cpufreq . . . . . . . $enable_cpufreq
csv . . . . . . . . . $enable_csv
load . . . . . . . . $enable_load
logfile . . . . . . . $enable_logfile
lpar... . . . . . . . $enable_lpar
+ lvm . . . . . . . . . $enable_lvm
madwifi . . . . . . . $enable_madwifi
match_empty_counter . $enable_match_empty_counter
match_hashed . . . . $enable_match_hashed
index ec55a52a55d75e68613e06b35e989601d0d25bd5..abdb168f15d28cce78db59ca29589d2ef0a40e5d 100644 (file)
service="collectd"
CONFIG=/etc/collectd.conf
COLLECTD=/usr/sbin/collectd
-COLLECTDMONPID=/var/run/collectdmon.pid
+COLLECTDMONPIDDIR="/var/run"
+COLLECTDMONPID="$COLLECTDMONPIDDIR/collectdmon.pid"
if [ -r /etc/sysconfig/$service ]; then
. /etc/sysconfig/$service
fi
+if [[ ! -d $COLLECTDMONPIDDIR ]]; then
+ mkdir -p $COLLECTDMONPIDDIR
+ [ -n "${RUNAS}" ] && chown "${RUNAS}:" "$COLLECTDMONPIDDIR"
+fi
+
check_config() {
if test ! -r "$CONFIG"; then
return 2
echo $"not starting due to configuration error"
failure $"not starting $service due to configuration error"
else
- daemon $prog -P $COLLECTDMONPID -c $COLLECTD -- -C "$CONFIG" $ARGS
+ daemon --user "${RUNAS:-root}" $prog -P $COLLECTDMONPID -c $COLLECTD -- -C "$CONFIG" $ARGS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$service
}
stop () {
echo -n $"Stopping collectd: "
- killproc $prog
+ killproc -p $COLLECTDMONPID $prog
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$service
stop
;;
status)
- status $prog
+ status -p $COLLECTDMONPID $prog
;;
restart|reload)
check_config
fi
;;
condrestart)
- [ -f /var/lock/subsys/$prog ] && restart || :
+ [ -f /var/lock/subsys/$service ] && restart || :
;;
*)
echo $"Usage: $0 {start|stop|status|restart|reload|condrestart}"
diff --git a/src/Makefile.am b/src/Makefile.am
index 2bebec55c6d88ff320f94689c4eb795ead97a7cf..d67deca55e3d133b023ab2cdaa4df2a6665ebd23 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
collectd_DEPENDENCIES += bind.la
endif
+if BUILD_PLUGIN_CGROUPS
+pkglib_LTLIBRARIES += cgroups.la
+cgroups_la_SOURCES = cgroups.c utils_mount.c utils_mount.h
+cgroups_la_LDFLAGS = -module -avoid-version
+collectd_LDADD += "-dlopen" cgroups.la
+collectd_DEPENDENCIES += cgroups.la
+endif
+
if BUILD_PLUGIN_CONNTRACK
pkglib_LTLIBRARIES += conntrack.la
conntrack_la_SOURCES = conntrack.c
lpar_la_LIBADD = -lperfstat
endif
+if BUILD_PLUGIN_LVM
+pkglib_LTLIBRARIES += lvm.la
+lvm_la_SOURCES = lvm.c
+lvm_la_LDFLAGS = -module -avoid-version
+lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
+collectd_LDADD += "-dlopen" lvm.la
+collectd_DEPENDENCIES += lvm.la
+endif
+
if BUILD_PLUGIN_MADWIFI
pkglib_LTLIBRARIES += madwifi.la
madwifi_la_SOURCES = madwifi.c madwifi.h
collectd_DEPENDENCIES += uuid.la
endif
+if BUILD_PLUGIN_MIC
+pkglib_LTLIBRARIES += mic.la
+mic_la_SOURCES = mic.c
+mic_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_MIC_LIBPATH)
+mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
+mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
+collectd_LDADD += "-dlopen" mic.la
+collectd_DEPENDENCIES += mic.la
+endif
+
if BUILD_PLUGIN_VARNISH
pkglib_LTLIBRARIES += varnish.la
varnish_la_SOURCES = varnish.c
diff --git a/src/amqp.c b/src/amqp.c
index 767a8776bbfb07ce2a26f932cf7fb5da4d22d047..edd4f749396bbb14c501792b62db70d188ade0de 100644 (file)
--- a/src/amqp.c
+++ b/src/amqp.c
/* publish only */
conf->delivery_mode = CAMQP_DM_VOLATILE;
conf->store_rates = 0;
+ conf->graphite_flags = 0;
/* publish & graphite only */
conf->prefix = NULL;
conf->postfix = NULL;
}
else if ((strcasecmp ("Format", child->key) == 0) && publish)
status = camqp_config_set_format (child, conf);
+ else if ((strcasecmp ("GraphiteSeparateInstances", child->key) == 0) && publish)
+ status = cf_util_get_flag (child, &conf->graphite_flags,
+ GRAPHITE_SEPARATE_INSTANCES);
+ else if ((strcasecmp ("GraphiteAlwaysAppendDS", child->key) == 0) && publish)
+ status = cf_util_get_flag (child, &conf->graphite_flags,
+ GRAPHITE_ALWAYS_APPEND_DS);
else if ((strcasecmp ("GraphitePrefix", child->key) == 0) && publish)
status = cf_util_get_string (child, &conf->prefix);
else if ((strcasecmp ("GraphitePostfix", child->key) == 0) && publish)
diff --git a/src/cgroups.c b/src/cgroups.c
--- /dev/null
+++ b/src/cgroups.c
@@ -0,0 +1,251 @@
+/**
+ * collectd - src/cgroups.c
+ * Copyright (C) 2011 Michael Stapelberg
+ * Copyright (C) 2013 Florian 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; 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:
+ * Michael Stapelberg <michael at stapelberg.de>
+ * Florian Forster <octo at collectd.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+#include "configfile.h"
+#include "utils_mount.h"
+#include "utils_ignorelist.h"
+
+static char const *config_keys[] =
+{
+ "CGroup",
+ "IgnoreSelected"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static ignorelist_t *il_cgroup = NULL;
+
+__attribute__ ((nonnull(1)))
+__attribute__ ((nonnull(2)))
+static void cgroups_submit_one (char const *plugin_instance,
+ char const *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, "cgroups", sizeof (vl.plugin));
+ sstrncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "cpu", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance,
+ sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+} /* void cgroups_submit_one */
+
+/*
+ * This callback reads the user/system CPU time for each cgroup.
+ */
+static int read_cpuacct_procs (const char *dirname, char const *cgroup_name,
+ void *user_data)
+{
+ char abs_path[PATH_MAX];
+ struct stat statbuf;
+ char buf[1024];
+ int status;
+
+ FILE *fh;
+
+ if (ignorelist_match (il_cgroup, cgroup_name))
+ return (0);
+
+ ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, cgroup_name);
+
+ status = lstat (abs_path, &statbuf);
+ if (status != 0)
+ {
+ ERROR ("cgroups plugin: stat (\"%s\") failed.",
+ abs_path);
+ return (-1);
+ }
+
+ /* We are only interested in directories, so skip everything else. */
+ if (!S_ISDIR (statbuf.st_mode))
+ return (0);
+
+ ssnprintf (abs_path, sizeof (abs_path), "%s/%s/cpuacct.stat",
+ dirname, cgroup_name);
+ fh = fopen (abs_path, "r");
+ if (fh == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("cgroups pluign: fopen (\"%s\") failed: %s",
+ abs_path,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (-1);
+ }
+
+ while (fgets (buf, sizeof (buf), fh) != NULL)
+ {
+ char *fields[8];
+ int numfields = 0;
+ char *key;
+ size_t key_len;
+ value_t value;
+
+ /* Expected format:
+ *
+ * user: 12345
+ * system: 23456
+ */
+ strstripnewline (buf);
+ numfields = strsplit (buf, fields, STATIC_ARRAY_SIZE (fields));
+ if (numfields != 2)
+ continue;
+
+ key = fields[0];
+ key_len = strlen (key);
+ if (key_len < 2)
+ continue;
+
+ /* Strip colon off the first column */
+ if (key[key_len - 1] != ':')
+ continue;
+ key[key_len - 1] = 0;
+
+ status = parse_value (fields[1], &value, DS_TYPE_DERIVE);
+ if (status != 0)
+ continue;
+
+ cgroups_submit_one (cgroup_name, key, value);
+ }
+
+ fclose (fh);
+ return (0);
+} /* int read_cpuacct_procs */
+
+/*
+ * Gets called for every file/folder in /sys/fs/cgroup/cpu,cpuacct (or
+ * whereever cpuacct is mounted on the system). Calls walk_directory with the
+ * read_cpuacct_procs callback on every folder it finds, such as "system".
+ */
+static int read_cpuacct_root (const char *dirname, const char *filename,
+ void *user_data)
+{
+ char abs_path[PATH_MAX];
+ struct stat statbuf;
+ int status;
+
+ ssnprintf (abs_path, sizeof (abs_path), "%s/%s", dirname, filename);
+
+ status = lstat (abs_path, &statbuf);
+ if (status != 0)
+ {
+ ERROR ("cgroups plugin: stat (%s) failed.", abs_path);
+ return (-1);
+ }
+
+ if (S_ISDIR (statbuf.st_mode))
+ {
+ status = walk_directory (abs_path, read_cpuacct_procs,
+ /* user_data = */ NULL,
+ /* include_hidden = */ 0);
+ return (status);
+ }
+
+ return (0);
+}
+
+static int cgroups_init (void)
+{
+ if (il_cgroup == NULL)
+ il_cgroup = ignorelist_create (1);
+
+ return (0);
+}
+
+static int cgroups_config (const char *key, const char *value)
+{
+ cgroups_init ();
+
+ if (strcasecmp (key, "CGroup") == 0)
+ {
+ if (ignorelist_add (il_cgroup, value))
+ return (1);
+ return (0);
+ }
+ else if (strcasecmp (key, "IgnoreSelected") == 0)
+ {
+ if (IS_TRUE (value))
+ ignorelist_set_invert (il_cgroup, 0);
+ else
+ ignorelist_set_invert (il_cgroup, 1);
+ return (0);
+ }
+
+ return (-1);
+}
+
+static int cgroups_read (void)
+{
+ cu_mount_t *mnt_list;
+ cu_mount_t *mnt_ptr;
+ _Bool cgroup_found = 0;
+
+ mnt_list = NULL;
+ if (cu_mount_getlist (&mnt_list) == NULL)
+ {
+ ERROR ("cgroups plugin: cu_mount_getlist failed.");
+ return (-1);
+ }
+
+ for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next)
+ {
+ /* Find the cgroup mountpoint which contains the cpuacct
+ * controller. */
+ if (strcmp(mnt_ptr->type, "cgroup") != 0 ||
+ !cu_mount_getoptionvalue(mnt_ptr->options, "cpuacct"))
+ continue;
+
+ walk_directory (mnt_ptr->dir, read_cpuacct_root,
+ /* user_data = */ NULL,
+ /* include_hidden = */ 0);
+ cgroup_found = 1;
+ /* It doesn't make sense to check other cpuacct mount-points
+ * (if any), they contain the same data. */
+ break;
+ }
+
+ cu_mount_freelist (mnt_list);
+
+ if (!cgroup_found)
+ {
+ WARNING ("cgroups plugin: Unable to find cgroup "
+ "mount-point with the \"cpuacct\" option.");
+ return (-1);
+ }
+
+ return (0);
+} /* int cgroup_read */
+
+void module_register (void)
+{
+ plugin_register_config ("cgroups", cgroups_config,
+ config_keys, config_keys_num);
+ plugin_register_init ("cgroups", cgroups_init);
+ plugin_register_read ("cgroups", cgroups_read);
+} /* void module_register */
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 5af15684092acb486b57d90023f7203da1a9abaa..4a88e6646f7dec844ea208231e6867676c4d2e60 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
#PluginDir "@libdir@/@PACKAGE_NAME@"
#TypesDB "@prefix@/share/@PACKAGE_NAME@/types.db"
+#----------------------------------------------------------------------------#
+# When enabled, plugins are loaded automatically with the default options #
+# when an appropriate <Plugin ...> block is encountered. #
+# Disabled by default. #
+#----------------------------------------------------------------------------#
+#AutoLoadPlugin false
+
#----------------------------------------------------------------------------#
# Interval at which to query values. This may be overwritten on a per-plugin #
# base by using the 'Interval' option of the LoadPlugin block: #
#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
#@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
+#@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
#@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
@LOAD_PLUGIN_CSV@LoadPlugin csv
#@BUILD_PLUGIN_LIBVIRT_TRUE@LoadPlugin libvirt
@BUILD_PLUGIN_LOAD_TRUE@@BUILD_PLUGIN_LOAD_TRUE@LoadPlugin load
#@BUILD_PLUGIN_LPAR_TRUE@LoadPlugin lpar
+#@BUILD_PLUGIN_LVM_TRUE@LoadPlugin lvm
#@BUILD_PLUGIN_MADWIFI_TRUE@LoadPlugin madwifi
#@BUILD_PLUGIN_MBMON_TRUE@LoadPlugin mbmon
#@BUILD_PLUGIN_MD_TRUE@LoadPlugin md
#@BUILD_PLUGIN_USERS_TRUE@LoadPlugin users
#@BUILD_PLUGIN_UUID_TRUE@LoadPlugin uuid
#@BUILD_PLUGIN_VARNISH_TRUE@LoadPlugin varnish
+#@BUILD_PLUGIN_MIC_TRUE@LoadPlugin mic
#@BUILD_PLUGIN_VMEM_TRUE@LoadPlugin vmem
#@BUILD_PLUGIN_VSERVER_TRUE@LoadPlugin vserver
#@BUILD_PLUGIN_WIRELESS_TRUE@LoadPlugin wireless
# UUIDFile "/etc/uuid"
#</Plugin>
+#<Plugin mic>
+# ShowCPU true
+# ShowCPUCores true
+# ShowMemory true
+# ShowTemperatures true
+## Temperature Sensors can be ignored/shown by repeated #Temperature lines, and
+## then inverted with a IgnoreSelectedTemperature.
+## Known Temperature sensors: die, devmem, fin, fout, vccp, vddg, vddq
+# Temperature vddg
+# IgnoreSelectedTemperature true
+# ShowPower true
+## Power Sensors can be ignored/shown by repeated #Power lines, and
+## then inverted with a IgnoreSelectedTemperature.
+## Known Temperature sensors: total0, total1, inst, imax, pci3, c2x3, c2x4, vccp, vddg, vddq
+# Power total1
+# IgnoreSelectedPower true
+#</Plugin>
+
#<Plugin varnish>
# This tag support an argument if you want to
# monitor the local instance just use </Instance>
# <Instance>
# CollectCache true
# CollectBackend true
+# CollectBan false # Varnish 3 only
# CollectConnections true
+# CollectDirectorDNS false # Varnish 3 only
# CollectSHM true
# CollectESI false
# CollectFetch false
# CollectHCB false
-# CollectSMA false
+# CollectObjects false
+# CollectPurge false # Varnish 2 only
+# CollectSession false
+# CollectSMA false # Varnish 2 only
# CollectSMS false
-# CollectSM false
+# CollectSM false # Varnish 2 only
+# CollectStruct false
# CollectTotals false
+# CollectUptime false
+# CollectVCL false
# CollectWorkers false
# </Instance>
#</Plugin>
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 8606d3e05533ff123f606e30ea7ef1f514c8857b..b66c4350305a8a217b2ebbdfbd78aa6341d54302 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
=item B<LoadPlugin> I<Plugin>
-Loads the plugin I<Plugin>. There must be at least one such line or B<collectd>
-will be mostly useless.
+Loads the plugin I<Plugin>. This is required to load plugins, unless the
+B<AutoLoadPlugin> option is enabled (see below). Without any loaded plugins,
+I<collectd> will be mostly useless.
-Starting with collectd 4.9, this may also be a block in which further options
-affecting the behavior of B<LoadPlugin> may be specified. The following
-options are allowed inside a B<LoadPlugin> block:
+Only the first B<LoadPlugin> statement or block for a given plugin name has any
+effect. This is useful when you want to split up the configuration into smaller
+files and want each file to be "self contained", i.e. it contains a B<Plugin>
+block I<and> then appropriate B<LoadPlugin> statement. The downside is that if
+you have multiple conflicting B<LoadPlugin> blocks, e.g. when they specify
+different intervals, only one of them (the first one encountered) will take
+effect and all others will be silently ignored.
- <LoadPlugin perl>
- Globals true
- Interval 10
- </LoadPlugin>
+B<LoadPlugin> may either be a simple configuration I<statement> or a I<block>
+with additional options, affecting the behavior of B<LoadPlugin>. A simple
+statement looks like this:
+
+ LoadPlugin "cpu"
+
+Options inside a B<LoadPlugin> block can override default settings and
+influence the way plugins are loaded, e.g.:
+
+ <LoadPlugin perl>
+ Globals true
+ Interval 60
+ </LoadPlugin>
+
+The following options are valid inside B<LoadPlugin> blocks:
=over 4
=back
+=item B<AutoLoadPlugin> B<false>|B<true>
+
+When set to B<false> (the default), each plugin needs to be loaded explicitly,
+using the B<LoadPlugin> statement documented above. If a
+B<E<lt>PluginE<nbsp>...E<gt>> block is encountered and no configuration
+handling callback for this plugin has been registered, a warning is logged and
+the block is ignored.
+
+When set to B<true>, explicit B<LoadPlugin> statements are not required. Each
+B<E<lt>PluginE<nbsp>...E<gt>> block acts as if it was immediately preceded by a
+B<LoadPlugin> statement. B<LoadPlugin> statements are still required for
+plugins that don't provide any configuration, e.g. the I<Load plugin>.
+
=item B<Include> I<Path> [I<pattern>]
If I<Path> points to a file, includes that file. If I<Path> points to a
=back
+=head2 Plugin C<cgroups>
+
+This plugin collects the CPU user/system time for each I<cgroup> by reading the
+F<cpuacct.stat> files in the first cpuacct-mountpoint (typically
+F</sys/fs/cgroup/cpu.cpuacct> on machines using systemd).
+
+=over 4
+
+=item B<CGroup> I<Directory>
+
+Select I<cgroup> based on the name. Whether only matching I<cgroups> are
+collected or if they are ignored is controlled by the B<IgnoreSelected> option;
+see below.
+
+=item B<IgnoreSelected> B<true>|B<false>
+
+Invert the selection: If set to true, all cgroups I<except> the ones that
+match any one of the criteria are collected. By default only selected
+cgroups are collected if a selection is made. If no selection is configured
+at all, B<all> cgroups are selected.
+
+=back
+
=head2 Plugin C<cpufreq>
This plugin doesn't have any options. It reads
many small files are stored on the disk. This is a usual scenario for mail
transfer agents and web caches.
+=item B<ReportPercentage> B<false>|B<true>
+
+Enables or disables reporting of disk space and inodes as a percentage.
+Defaults to B<false>.
+
+This is useful for deploying I<collectd> on the cloud, where machines with
+different disk size may exist. Then it is more practical to configure
+thresholds based on relative disk size.
+
=back
=head2 Plugin C<disk>
=head2 Plugin C<memcached>
-The C<memcached plugin> connects to a memcached server and queries statistics
+The B<memcached plugin> connects to a memcached server and queries statistics
about cache utilization, memory and bandwidth used.
L<http://www.danga.com/memcached/>
=back
+=head2 Plugin C<mic>
+
+The B<mic plugin> gathers CPU statistics, memory usage and temperatures from
+Intel's Many Integrated Core (MIC) systems.
+
+B<Synopsis:>
+
+ <Plugin mic>
+ ShowCPU true
+ ShowCPUCores true
+ ShowMemory true
+
+ ShowTemperatures true
+ Temperature vddg
+ Temperature vddq
+ IgnoreSelectedTemperature true
+
+ ShowPower true
+ Power total0
+ Power total1
+ IgnoreSelectedPower true
+ </Plugin>
+
+The following options are valid inside the B<PluginE<nbsp>mic> block:
+
+=over 4
+
+=item B<ShowCPU> B<true>|B<false>
+
+If enabled (the default) a sum of the CPU usage accross all cores is reported.
+
+=item B<ShowCPUCores> B<true>|B<false>
+
+If enabled (the default) per-core CPU usage is reported.
+
+=item B<ShowMemory> B<true>|B<false>
+
+If enabled (the default) the physical memory usage of the MIC system is
+reported.
+
+=item B<ShowTemperatures> B<true>|B<false>
+
+If enabled (the default) various temperatures of the MIC system are reported.
+
+=item B<Temperature> I<Name>
+
+This option controls which temperatures are being reported. Whether matching
+temperatures are being ignored or I<only> matching temperatures are reported
+depends on the B<IgnoreSelectedTemperature> setting below. By default I<all>
+temperatures are reported.
+
+=item B<IgnoreSelectedTemperature> B<false>|B<true>
+
+Controls the behavior of the B<Temperature> setting above. If set to B<false>
+(the default) only temperatures matching a B<Temperature> option are reported
+or, if no B<Temperature> option is specified, all temperatures are reported. If
+set to B<true>, matching temperatures are I<ignored> and all other temperatures
+are reported.
+
+Known temperature names are:
+
+=over 4
+
+=item die
+
+Die of the CPU
+
+=item devmem
+
+Device Memory
+
+=item fin
+
+Fan In
+
+=item fout
+
+Fan Out
+
+=item vccp
+
+Voltage ccp
+
+=item vddg
+
+Voltage ddg
+
+=item vddq
+
+Voltage ddq
+
+=back
+
+=item B<ShowPower> B<true>|B<false>
+
+If enabled (the default) various temperatures of the MIC system are reported.
+
+=item B<Power> I<Name>
+
+This option controls which power readings are being reported. Whether matching
+power readings are being ignored or I<only> matching power readings are reported
+depends on the B<IgnoreSelectedPower> setting below. By default I<all>
+power readings are reported.
+
+=item B<IgnoreSelectedPower> B<false>|B<true>
+
+Controls the behavior of the B<Power> setting above. If set to B<false>
+(the default) only power readings matching a B<Power> option are reported
+or, if no B<Power> option is specified, all power readings are reported. If
+set to B<true>, matching power readings are I<ignored> and all other power readings
+are reported.
+
+Known power names are:
+
+=over 4
+
+=item total0
+
+Total power utilization averaged over Time Window 0 (uWatts).
+
+=item total1
+
+Total power utilization averaged over Time Window 0 (uWatts).
+
+=item inst
+
+Instantaneous power (uWatts).
+
+=item imax
+
+Max instantaneous power (uWatts).
+
+=item pcie
+
+PCI-E connector power (uWatts).
+
+=item c2x3
+
+2x3 connector power (uWatts).
+
+=item c2x4
+
+2x4 connector power (uWatts).
+
+=item vccp
+
+Core rail (uVolts).
+
+=item vddg
+
+Uncore rail (uVolts).
+
+=item vddq
+
+Memory subsystem rail (uVolts).
+
+=back
+
+=back
+
=head2 Plugin C<modbus>
The B<modbus plugin> connects to a Modbus "slave" via Modbus/TCP and reads
values), large integer values (unsigned 32E<nbsp>bit values) and floating point
values (two registers interpreted as IEEE floats in big endian notation).
-Synopsis:
+B<Synopsis:>
<Data "voltage-input-1">
RegisterBase 0
Statistics about the shared memory log, a memory region to store
log messages which is flushed to disk when full. True by default.
+=item B<CollectBan> B<true>|B<false>
+
+Statistics about ban operations, such as number of bans added, retired, and
+number of objects tested against ban operations. Only available with Varnish
+3.x. False by default.
+
+=item B<CollectDirectorDNS> B<true>|B<false>
+
+DNS director lookup cache statistics. Only available with Varnish 3.x. False by
+default.
+
=item B<CollectESI> B<true>|B<false>
Edge Side Includes (ESI) parse statistics. False by default.
@@ -5510,10 +5742,27 @@ Statistics about fetches (HTTP requests sent to the backend). False by default.
Inserts and look-ups in the crit bit tree based hash. Look-ups are
divided into locked and unlocked look-ups. False by default.
+=item B<CollectObjects> B<true>|B<false>
+
+Statistics on cached objects: number of objects expired, nuked (prematurely
+expired), saved, moved, etc. False by default.
+
+=item B<CollectPurge> B<true>|B<false>
+
+Statistics about purge operations, such as number of purges added, retired, and
+number of objects tested against purge operations. Only available with Varnish
+2.x. False by default.
+
+=item B<CollectSession> B<true>|B<false>
+
+Client session statistics. Number of past and current sessions, session herd and
+linger counters, etc. False by default.
+
=item B<CollectSMA> B<true>|B<false>
-malloc or umem (umem_alloc(3MALLOC) based) storage statistics.
-The umem storage component is Solaris specific. False by default.
+malloc or umem (umem_alloc(3MALLOC) based) storage statistics. The umem storage
+component is Solaris specific. Only available with Varnish 2.x. False by
+default.
=item B<CollectSMS> B<true>|B<false>
=item B<CollectSM> B<true>|B<false>
-file (memory mapped file) storage statistics. False by default.
+file (memory mapped file) storage statistics. Only available with Varnish 2.x.
+False by default.
+
+=item B<CollectStruct> B<true>|B<false>
+
+Current varnish internal state statistics. Number of current sessions, objects
+in cache store, open connections to backends (with Varnish 2.x), etc. False by
+default.
=item B<CollectTotals> B<true>|B<false>
Collects overview counters, such as the number of sessions created,
the number of requests and bytes transferred. False by default.
+=item B<CollectUptime> B<true>|B<false>
+
+Varnish uptime. False by default.
+
+=item B<CollectVCL> B<true>|B<false>
+
+Number of total (available + discarded) VCL (config files). False by default.
+
=item B<CollectWorkers> B<true>|B<false>
Collect statistics about worker threads. False by default.
diff --git a/src/common.c b/src/common.c
index d617832ca48d6a29680ea7482df8b67e13255b5f..d963efa556a6f60ce6f71c3472f90e791dc48c4e 100644 (file)
--- a/src/common.c
+++ b/src/common.c
return (ret);
} /* int ssnprintf */
+char *ssnprintf_alloc (char const *format, ...) /* {{{ */
+{
+ char static_buffer[1024] = "";
+ char *alloc_buffer;
+ size_t alloc_buffer_size;
+ int status;
+ va_list ap;
+
+ /* Try printing into the static buffer. In many cases it will be
+ * sufficiently large and we can simply return a strdup() of this
+ * buffer. */
+ va_start (ap, format);
+ status = vsnprintf (static_buffer, sizeof (static_buffer), format, ap);
+ va_end (ap);
+ if (status < 0)
+ return (NULL);
+
+ /* "status" does not include the null byte. */
+ alloc_buffer_size = (size_t) (status + 1);
+ if (alloc_buffer_size <= sizeof (static_buffer))
+ return (strdup (static_buffer));
+
+ /* Allocate a buffer large enough to hold the string. */
+ alloc_buffer = malloc (alloc_buffer_size);
+ if (alloc_buffer == NULL)
+ return (NULL);
+ memset (alloc_buffer, 0, alloc_buffer_size);
+
+ /* Print again into this new buffer. */
+ va_start (ap, format);
+ status = vsnprintf (alloc_buffer, alloc_buffer_size, format, ap);
+ va_end (ap);
+ if (status < 0)
+ {
+ sfree (alloc_buffer);
+ return (NULL);
+ }
+
+ return (alloc_buffer);
+} /* }}} char *ssnprintf_alloc */
+
char *sstrdup (const char *s)
{
char *r;
return (0);
}
-int read_file_contents (const char *filename, char *buf, int bufsize)
+ssize_t read_file_contents (const char *filename, char *buf, size_t bufsize)
{
FILE *fh;
- int n;
+ ssize_t ret;
- if ((fh = fopen (filename, "r")) == NULL)
- return -1;
+ fh = fopen (filename, "r");
+ if (fh == NULL)
+ return (-1);
- n = fread(buf, 1, bufsize, fh);
- fclose(fh);
+ ret = (ssize_t) fread (buf, 1, bufsize, fh);
+ if ((ret == 0) && (ferror (fh) != 0))
+ {
+ ERROR ("read_file_contents: Reading file \"%s\" failed.",
+ filename);
+ ret = -1;
+ }
- return n;
+ fclose(fh);
+ return (ret);
}
counter_t counter_diff (counter_t old_value, counter_t new_value)
diff --git a/src/common.h b/src/common.h
index ae8e311f9983e8ff63441c0ab2936d287220ae67..317be8d1579d063cc23338e229abcdede533da84 100644 (file)
--- a/src/common.h
+++ b/src/common.h
typedef struct rate_to_value_state_s rate_to_value_state_t;
char *sstrncpy (char *dest, const char *src, size_t n);
+
+__attribute__ ((format(printf,3,4)))
int ssnprintf (char *dest, size_t n, const char *format, ...);
+
+__attribute__ ((format(printf,1,2)))
+char *ssnprintf_alloc (char const *format, ...);
+
char *sstrdup(const char *s);
void *smalloc(size_t size);
char *sstrerror (int errnum, char *buf, size_t buflen);
int walk_directory (const char *dir, dirwalk_callback_f callback,
void *user_data, int hidden);
/* Returns the number of bytes read or negative on error. */
-int read_file_contents (const char *filename, char *buf, int bufsize);
+ssize_t read_file_contents (char const *filename, char *buf, size_t bufsize);
counter_t counter_diff (counter_t old_value, counter_t new_value);
diff --git a/src/configfile.c b/src/configfile.c
index ac5e8edcb94f2bfda66c5eefab67dfab3c66e6db..876ee23ee71c8c33d2f230170bf94147a6012404 100644 (file)
--- a/src/configfile.c
+++ b/src/configfile.c
{"ReadThreads", NULL, "5"},
{"WriteThreads", NULL, "5"},
{"Timeout", NULL, "2"},
+ {"AutoLoadPlugin", NULL, "false"},
{"PreCacheChain", NULL, "PreCache"},
{"PostCacheChain", NULL, "PostCache"}
};
memset (&ctx, 0, sizeof (ctx));
ctx.interval = cf_get_default_interval ();
- /*
- * XXX: Magic at work:
- *
- * Some of the language bindings, for example the Python and Perl
- * plugins, need to be able to export symbols to the scripts they run.
- * For this to happen, the "Globals" flag needs to be set.
- * Unfortunately, this technical detail is hard to explain to the
- * average user and she shouldn't have to worry about this, ideally.
- * So in order to save everyone's sanity use a different default for a
- * handful of special plugins. --octo
- */
- if ((strcasecmp ("Perl", name) == 0)
- || (strcasecmp ("Python", name) == 0))
- flags |= PLUGIN_FLAGS_GLOBAL;
-
for (i = 0; i < ci->children_num; ++i) {
if (strcasecmp("Globals", ci->children[i].key) == 0)
cf_util_get_flag (ci->children + i, &flags, PLUGIN_FLAGS_GLOBAL);
name = ci->values[0].value.string;
+ if (IS_TRUE (global_option_get ("AutoLoadPlugin")))
+ {
+ int status;
+
+ status = plugin_load (name, /* flags = */ 0);
+ if (status != 0)
+ {
+ ERROR ("Automatically loading plugin \"%s\" failed "
+ "with status %i.", name, status);
+ return (status);
+ }
+ }
+
/* Check for a complex callback first */
for (cb = complex_callback_head; cb != NULL; cb = cb->next)
{
diff --git a/src/curl_xml.c b/src/curl_xml.c
index 0b4130473f4e3359dc9cbb66059831ac09386a34..5adaf067a157e44220655adb79855c6fee0d3b26 100644 (file)
--- a/src/curl_xml.c
+++ b/src/curl_xml.c
if (status == 0)
{
user_data_t ud;
- char cb_name[DATA_MAX_NAME_LEN];
+ char *cb_name;
if (db->instance == NULL)
db->instance = strdup("default");
ud.data = (void *) db;
ud.free_func = cx_free;
- ssnprintf (cb_name, sizeof (cb_name), "curl_xml-%s-%s",
- db->instance, db->url);
-
- plugin_register_complex_read (/* group = */ NULL, cb_name, cx_read,
+ cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
+ plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
/* interval = */ NULL, &ud);
+ sfree (cb_name);
}
else
{
diff --git a/src/df.c b/src/df.c
index ded374b942e5d08d804dd027292eef2ef9f50fcb..5ff3f59be8cbcb401dd288c17ec4b89777251b43 100644 (file)
--- a/src/df.c
+++ b/src/df.c
"IgnoreSelected",
"ReportByDevice",
"ReportReserved",
- "ReportInodes"
+ "ReportInodes",
+ "ReportPercentage"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static _Bool by_device = 0;
static _Bool report_inodes = 0;
+static _Bool report_percentage = 0;
static int df_init (void)
{
return (0);
}
+ else if (strcasecmp (key, "ReportPercentage") == 0)
+ {
+ if (IS_TRUE (value))
+ report_percentage = 1;
+ else
+ report_percentage = 0;
+
+ return (0);
+ }
return (-1);
}
if (!statbuf.f_blocks)
continue;
- if (by_device)
+ if (by_device)
{
/* eg, /dev/hda1 -- strip off the "/dev/" */
if (strncmp (mnt_ptr->spec_device, "/dev/", strlen ("/dev/")) == 0)
else
sstrncpy (disk_name, mnt_ptr->spec_device, sizeof (disk_name));
- if (strlen(disk_name) < 1)
+ if (strlen(disk_name) < 1)
{
DEBUG("df: no device name name for mountpoint %s, skipping", mnt_ptr->dir);
continue;
}
- }
- else
+ }
+ else
{
if (strcmp (mnt_ptr->dir, "/") == 0)
{
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",
+ if (report_percentage && (statbuf.f_blocks > 0))
+ {
+ uint64_t blk_total = (uint64_t) statbuf.f_blocks;
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
+ ssnprintf (plugin_instance, sizeof (plugin_instance),
+ "%s-bytes", disk_name);
+
+ df_submit_one (plugin_instance, "percent", "free",
+ 100.0 * ((gauge_t) blk_free) / ((gauge_t) blk_total));
+ df_submit_one (plugin_instance, "percent", "reserved",
+ 100.0 * ((gauge_t) blk_reserved) / ((gauge_t) blk_total));
+ df_submit_one (plugin_instance, "percent", "used",
+ 100.0 * ((gauge_t) blk_used) / ((gauge_t) blk_total));
+ }
+ else if (!report_percentage)
+ {
+ df_submit_one (disk_name, "df_complex", "free",
(gauge_t) (blk_free * blocksize));
- df_submit_one (disk_name, "df_complex", "reserved",
+ df_submit_one (disk_name, "df_complex", "reserved",
(gauge_t) (blk_reserved * blocksize));
- df_submit_one (disk_name, "df_complex", "used",
+ df_submit_one (disk_name, "df_complex", "used",
(gauge_t) (blk_used * blocksize));
+ }
/* inode handling */
if (report_inodes)
inode_free = (uint64_t) statbuf.f_favail;
inode_reserved = (uint64_t) (statbuf.f_ffree - statbuf.f_favail);
inode_used = (uint64_t) (statbuf.f_files - statbuf.f_ffree);
-
- df_submit_one (disk_name, "df_inodes", "free",
- (gauge_t) inode_free);
- df_submit_one (disk_name, "df_inodes", "reserved",
- (gauge_t) inode_reserved);
- df_submit_one (disk_name, "df_inodes", "used",
- (gauge_t) inode_used);
+
+ if (report_percentage && (statbuf.f_files > 0))
+ {
+ uint64_t inode_total = (uint64_t) statbuf.f_files;
+ char plugin_instance[DATA_MAX_NAME_LEN];
+
+ ssnprintf (plugin_instance, sizeof (plugin_instance),
+ "%s-inodes", disk_name);
+
+ df_submit_one (plugin_instance, "percent", "free",
+ 100.0 * ((gauge_t) inode_free) / ((gauge_t) inode_total));
+ df_submit_one (plugin_instance, "percent", "reserved",
+ 100.0 * ((gauge_t) inode_reserved) / ((gauge_t) inode_total));
+ df_submit_one (plugin_instance, "percent", "used",
+ 100.0 * ((gauge_t) inode_used) / ((gauge_t) inode_total));
+ }
+ else if (!report_percentage)
+ {
+ df_submit_one (disk_name, "df_inodes", "free",
+ (gauge_t) inode_free);
+ df_submit_one (disk_name, "df_inodes", "reserved",
+ (gauge_t) inode_reserved);
+ df_submit_one (disk_name, "df_inodes", "used",
+ (gauge_t) inode_used);
+ }
}
}
diff --git a/src/lvm.c b/src/lvm.c
--- /dev/null
+++ b/src/lvm.c
@@ -0,0 +1,103 @@
+/**
+ * collectd - src/lvm.c
+ * Copyright (C) 2013 Chad Malfait
+ *
+ * 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:
+ * Chad Malfait <malfaitc at yahoo.com>
+ **/
+
+#include <lvm2app.h>
+
+#include "collectd.h"
+#include "common.h"
+#include "plugin.h"
+
+static void lvm_submit (char const *plugin_instance, char const *type_instance,
+ uint64_t ivalue)
+{
+ value_t v;
+ value_list_t vl = VALUE_LIST_INIT;
+
+ v.gauge = (gauge_t) ivalue;
+
+ vl.values = &v;
+ vl.values_len = 1;
+
+ sstrncpy(vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy(vl.plugin, "lvm", sizeof (vl.plugin));
+ sstrncpy(vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
+ sstrncpy(vl.type, "df_complex", sizeof (vl.type));
+ sstrncpy(vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+static int vg_read(vg_t vg, char const *vg_name)
+{
+ struct dm_list *lvs;
+ struct lvm_lv_list *lvl;
+
+ lvm_submit (vg_name, "free", lvm_vg_get_free_size(vg));
+
+ lvs = lvm_vg_list_lvs(vg);
+ dm_list_iterate_items(lvl, lvs) {
+ lvm_submit(vg_name, lvm_lv_get_name(lvl->lv), lvm_lv_get_size(lvl->lv));
+ }
+
+ return (0);
+}
+
+static int lvm_read(void)
+{
+ lvm_t lvm;
+ struct dm_list *vg_names;
+ struct lvm_str_list *name_list;
+
+ lvm = lvm_init(NULL);
+ if (!lvm) {
+ ERROR("lvm plugin: lvm_init failed.");
+ return (-1);
+ }
+
+ vg_names = lvm_list_vg_names(lvm);
+ if (!vg_names) {
+ ERROR("lvm plugin lvm_list_vg_name failed %s", lvm_errmsg(lvm));
+ lvm_quit(lvm);
+ return (-1);
+ }
+
+ dm_list_iterate_items(name_list, vg_names) {
+ vg_t vg;
+
+ vg = lvm_vg_open(lvm, name_list->str, "r", 0);
+ if (!vg) {
+ ERROR ("lvm plugin: lvm_vg_open (%s) failed: %s",
+ name_list->str, lvm_errmsg(lvm));
+ continue;
+ }
+
+ vg_read(vg, name_list->str);
+ lvm_vg_close(vg);
+ }
+
+ lvm_quit(lvm);
+ return (0);
+} /*lvm_read */
+
+void module_register(void)
+{
+ plugin_register_read("lvm", lvm_read);
+} /* void module_register */
diff --git a/src/mic.c b/src/mic.c
--- /dev/null
+++ b/src/mic.c
@@ -0,0 +1,417 @@
+/**
+ * collectd - src/mic.c
+ * Copyright (C) 2013 Battelle Memorial Institute
+ *
+ * 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:
+ * Evan Felix <evan.felix at pnnl.gov>
+ **/
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "utils_ignorelist.h"
+
+#include <MicAccessTypes.h>
+#include <MicAccessErrorTypes.h>
+#include <MicAccessApi.h>
+#include <MicThermalAPI.h>
+#include <MicPowerManagerAPI.h>
+
+#define MAX_MICS 32
+#define MAX_CORES 256
+
+static MicDeviceOnSystem mics[MAX_MICS];
+static U32 num_mics = 0;
+static HANDLE mic_handle = NULL;
+
+static int const therm_ids[] = {
+ eMicThermalDie, eMicThermalDevMem, eMicThermalFin, eMicThermalFout,
+ eMicThermalVccp, eMicThermalVddg, eMicThermalVddq };
+static char const * const therm_names[] = {
+ "die", "devmem", "fin", "fout",
+ "vccp", "vddg", "vddq" };
+
+static const char *config_keys[] =
+{
+ "ShowCPU",
+ "ShowCPUCores",
+ "ShowMemory",
+ "ShowTemperatures",
+ "Temperature",
+ "IgnoreSelectedTemperature",
+ "ShowPower",
+ "Power",
+ "IgnoreSelectedPower"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static _Bool show_cpu = 1;
+static _Bool show_cpu_cores = 1;
+static _Bool show_memory = 1;
+static _Bool show_temps = 1;
+static ignorelist_t *temp_ignore = NULL;
+static _Bool show_power = 1;
+static ignorelist_t *power_ignore = NULL;
+
+static int mic_init (void)
+{
+ U32 ret;
+ U32 mic_count;
+
+ if (mic_handle)
+ return (0);
+
+ mic_count = (U32) STATIC_ARRAY_SIZE(mics);
+ ret = MicInitAPI(&mic_handle, eTARGET_SCIF_DRIVER, mics, &mic_count);
+ if (ret != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Problem initializing MicAccessAPI: %s",
+ MicGetErrorString(ret));
+ }
+ DEBUG("mic plugin: found: %"PRIu32" MIC(s)",mic_count);
+
+ if (mic_count<0 || mic_count>=MAX_MICS) {
+ ERROR("mic plugin: No Intel MICs in system");
+ return (1);
+ }
+ else {
+ num_mics = mic_count;
+ return (0);
+ }
+}
+
+static int mic_config (const char *key, const char *value) {
+ if (temp_ignore == NULL)
+ temp_ignore = ignorelist_create(1);
+ if (power_ignore == NULL)
+ power_ignore = ignorelist_create(1);
+ if (temp_ignore == NULL || power_ignore == NULL)
+ return (1);
+
+ if (strcasecmp("ShowCPU",key) == 0)
+ {
+ show_cpu = IS_TRUE(value);
+ }
+ else if (strcasecmp("ShowCPUCores",key) == 0)
+ {
+ show_cpu_cores = IS_TRUE(value);
+ }
+ else if (strcasecmp("ShowTemperatures",key) == 0)
+ {
+ show_temps = IS_TRUE(value);
+ }
+ else if (strcasecmp("ShowMemory",key) == 0)
+ {
+ show_memory = IS_TRUE(value);
+ }
+ else if (strcasecmp("ShowPower",key) == 0)
+ {
+ show_power = IS_TRUE(value);
+ }
+ else if (strcasecmp("Temperature",key) == 0)
+ {
+ ignorelist_add(temp_ignore,value);
+ }
+ else if (strcasecmp("IgnoreSelectedTemperature",key) == 0)
+ {
+ int invert = 1;
+ if (IS_TRUE(value))
+ invert = 0;
+ ignorelist_set_invert(temp_ignore,invert);
+ }
+ else if (strcasecmp("Power",key) == 0)
+ {
+ ignorelist_add(power_ignore,value);
+ }
+ else if (strcasecmp("IgnoreSelectedPower",key) == 0)
+ {
+ int invert = 1;
+ if (IS_TRUE(value))
+ invert = 0;
+ ignorelist_set_invert(power_ignore,invert);
+ }
+ else
+ {
+ return (-1);
+ }
+ return (0);
+}
+
+static void mic_submit_memory_use(int micnumber, const char *type_instance, U32 val)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ /* MicAccessAPI reports KB's of memory, adjust for this */
+ DEBUG("mic plugin: Memory Value Report; %u %lf",val,((gauge_t)val)*1024.0);
+ values[0].gauge = ((gauge_t)val)*1024.0;
+
+ vl.values=values;
+ vl.values_len=1;
+
+ strncpy (vl.host, hostname_g, sizeof (vl.host));
+ strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance), "%i", micnumber);
+ strncpy (vl.type, "memory", sizeof (vl.type));
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+/* Gather memory Utilization */
+static int mic_read_memory(int mic)
+{
+ U32 ret;
+ U32 mem_total,mem_free,mem_bufs;
+
+ ret = MicGetMemoryUtilization(mic_handle,&mem_total,&mem_free,&mem_bufs);
+ if (ret != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Problem getting Memory Utilization: %s",
+ MicGetErrorString(ret));
+ return (1);
+ }
+ mic_submit_memory_use(mic,"free",mem_free);
+ mic_submit_memory_use(mic,"used",mem_total-mem_free-mem_bufs);
+ mic_submit_memory_use(mic,"buffered",mem_bufs);
+ DEBUG("mic plugin: Memory Read: %u %u %u",mem_total,mem_free,mem_bufs);
+ return (0);
+}
+
+static void mic_submit_temp(int micnumber, const char *type, gauge_t val)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = val;
+
+ vl.values=values;
+ vl.values_len=1;
+
+ strncpy (vl.host, hostname_g, sizeof (vl.host));
+ strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ "%i", micnumber);
+ strncpy (vl.type, "temperature", sizeof (vl.type));
+ strncpy (vl.type_instance, type, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+/* Gather Temperature Information */
+static int mic_read_temps(int mic)
+{
+ size_t num_therms = STATIC_ARRAY_SIZE(therm_ids);
+ size_t j;
+
+ for (j = 0; j < num_therms; j++) {
+ U32 status;
+ U32 temp_buffer;
+ U32 buffer_size = (U32)sizeof(temp_buffer);
+ char const *name = therm_names[j];
+
+ if (ignorelist_match(temp_ignore, name) != 0)
+ continue;
+
+ status = MicGetTemperature(mic_handle, therm_ids[j],
+ &temp_buffer, &buffer_size);
+ if (status != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Error reading temperature \"%s\": "
+ "%s", name, MicGetErrorString(status));
+ return (1);
+ }
+ mic_submit_temp(mic, name, temp_buffer);
+ }
+ return (0);
+}
+
+static void mic_submit_cpu(int micnumber, const char *type_instance,
+ int core, derive_t val)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].derive = val;
+
+ vl.values=values;
+ vl.values_len=1;
+
+ strncpy (vl.host, hostname_g, sizeof (vl.host));
+ strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+ if (core < 0) /* global aggregation */
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ "%i", micnumber);
+ else /* per-core statistics */
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ "%i-cpu-%i", micnumber, core);
+ strncpy (vl.type, "cpu", sizeof (vl.type));
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+/*Gather CPU Utilization Information */
+static int mic_read_cpu(int mic)
+{
+ MicCoreUtil core_util;
+ MicCoreJiff core_jiffs[MAX_CORES];
+ U32 core_jiffs_size;
+ U32 status;
+
+ core_jiffs_size = MAX_CORES * sizeof(MicCoreJiff);
+ status = MicGetCoreUtilization(mic_handle, &core_util,
+ core_jiffs, &core_jiffs_size);
+ if (status != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Problem getting CPU utilization: %s",
+ MicGetErrorString(status));
+ return(-1);
+ }
+
+ if (show_cpu) {
+ mic_submit_cpu(mic, "user", -1, core_util.sum.user);
+ mic_submit_cpu(mic, "sys", -1, core_util.sum.sys);
+ mic_submit_cpu(mic, "nice", -1, core_util.sum.nice);
+ mic_submit_cpu(mic, "idle", -1, core_util.sum.idle);
+ }
+
+ if (show_cpu_cores) {
+ int j;
+ for (j = 0; j < core_util.core; j++) {
+ mic_submit_cpu(mic, "user", j, core_jiffs[j].user);
+ mic_submit_cpu(mic, "sys", j, core_jiffs[j].sys);
+ mic_submit_cpu(mic, "nice", j, core_jiffs[j].nice);
+ mic_submit_cpu(mic, "idle", j, core_jiffs[j].idle);
+ }
+ }
+ return (0);
+}
+
+static void mic_submit_power(int micnumber, const char *type, const char *type_instance, gauge_t val)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = val;
+
+ vl.values=values;
+ vl.values_len=1;
+
+ strncpy (vl.host, hostname_g, sizeof (vl.host));
+ strncpy (vl.plugin, "mic", sizeof (vl.plugin));
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance), "%i", micnumber);
+ strncpy (vl.type, type, sizeof (vl.type));
+ strncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+
+ plugin_dispatch_values (&vl);
+}
+
+/* Gather Power Information */
+static int mic_read_power(int mic)
+{
+ U32 ret;
+ MicPwrUsage power_use;
+
+ ret = MicGetPowerUsage(mic_handle,&power_use);
+ if (ret != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Problem getting Power Usage: %s",
+ MicGetErrorString(ret));
+ return (1);
+ }
+
+ /* power is in uWatts, current in mA, voltage in uVolts.. convert to
+ * base unit */
+ #define SUB_POWER(name) do { if (ignorelist_match(power_ignore,#name)==0) \
+ mic_submit_power(mic,"power",#name,(gauge_t)power_use.name.prr*0.000001); \
+ } while(0)
+ #define SUB_VOLTS(name) do { if (ignorelist_match(power_ignore,#name)==0) {\
+ mic_submit_power(mic,"power",#name,(gauge_t)(power_use.name.pwr*0.000001)); \
+ mic_submit_power(mic,"current",#name,(gauge_t)(power_use.name.cur*0.001)); \
+ mic_submit_power(mic,"voltage",#name,(gauge_t)(power_use.name.volt*0.000001)); \
+ }} while(0)
+
+ SUB_POWER(total0);
+ SUB_POWER(total1);
+ SUB_POWER(inst);
+ SUB_POWER(imax);
+ SUB_POWER(pcie);
+ SUB_POWER(c2x3);
+ SUB_POWER(c2x4);
+ SUB_VOLTS(vccp);
+ SUB_VOLTS(vddg);
+ SUB_VOLTS(vddq);
+
+ return (0);
+}
+
+static int mic_read (void)
+{
+ int i;
+ U32 ret;
+ int error;
+
+ error=0;
+ for (i=0;i<num_mics;i++) {
+ ret = MicInitAdapter(&mic_handle,&mics[i]);
+ if (ret != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Problem initializing MicAdapter: %s",
+ MicGetErrorString(ret));
+ error=1;
+ }
+
+ if (error == 0 && show_memory)
+ error = mic_read_memory(i);
+
+ if (error == 0 && show_temps)
+ error = mic_read_temps(i);
+
+ if (error == 0 && (show_cpu || show_cpu_cores))
+ error = mic_read_cpu(i);
+
+ if (error == 0 && (show_power))
+ error = mic_read_power(i);
+
+ ret = MicCloseAdapter(mic_handle);
+ if (ret != MIC_ACCESS_API_SUCCESS) {
+ ERROR("mic plugin: Problem closing MicAdapter: %s",
+ MicGetErrorString(ret));
+ error=2;
+ break;
+ }
+ }
+ if (num_mics==0)
+ error=3;
+ return error;
+}
+
+
+static int mic_shutdown (void)
+{
+ if (mic_handle)
+ MicCloseAPI(&mic_handle);
+ mic_handle = NULL;
+
+ return (0);
+}
+
+void module_register (void)
+{
+ plugin_register_init ("mic", mic_init);
+ plugin_register_shutdown ("mic", mic_shutdown);
+ plugin_register_read ("mic", mic_read);
+ plugin_register_config ("mic",mic_config, config_keys, config_keys_num);
+} /* void module_register */
+
+/*
+ * vim: set shiftwidth=8 softtabstop=8 noet textwidth=78 :
+ */
diff --git a/src/plugin.c b/src/plugin.c
index 4c6a0322f18200f92caee47adbe41ab089ee94f5..894b0e51d72731ba1f7faab5c032a122063e85be 100644 (file)
--- a/src/plugin.c
+++ b/src/plugin.c
#define rf_ctx rf_super.cf_ctx
callback_func_t rf_super;
char rf_group[DATA_MAX_NAME_LEN];
- char rf_name[DATA_MAX_NAME_LEN];
+ char *rf_name;
int rf_type;
cdtime_t rf_interval;
cdtime_t rf_effective_interval;
/*
* Private variables
*/
+static c_avl_tree_t *plugins_loaded = NULL;
+
static llist_t *list_init;
static llist_t *list_write;
static llist_t *list_flush;
{
DEBUG ("plugin_read_thread: Destroying the `%s' "
"callback.", rf->rf_name);
+ sfree (rf->rf_name);
destroy_callback ((callback_func_t *) rf);
rf = NULL;
continue;
}
}
+static _Bool plugin_is_loaded (char const *name)
+{
+ int status;
+
+ if (plugins_loaded == NULL)
+ plugins_loaded = c_avl_create ((void *) strcasecmp);
+ assert (plugins_loaded != NULL);
+
+ status = c_avl_get (plugins_loaded, name, /* ret_value = */ NULL);
+ return (status == 0);
+}
+
+static int plugin_mark_loaded (char const *name)
+{
+ char *name_copy;
+ int status;
+
+ name_copy = strdup (name);
+ if (name_copy == NULL)
+ return (ENOMEM);
+
+ status = c_avl_insert (plugins_loaded,
+ /* key = */ name_copy, /* value = */ NULL);
+ return (status);
+}
+
+static void plugin_free_loaded ()
+{
+ void *key;
+ void *value;
+
+ if (plugins_loaded == NULL)
+ return;
+
+ while (c_avl_pick (plugins_loaded, &key, &value) == 0)
+ {
+ sfree (key);
+ assert (value == NULL);
+ }
+
+ c_avl_destroy (plugins_loaded);
+ plugins_loaded = NULL;
+}
+
#define BUFSIZE 512
-int plugin_load (const char *type, uint32_t flags)
+int plugin_load (char const *plugin_name, uint32_t flags)
{
DIR *dh;
const char *dir;
struct dirent *de;
int status;
+ if (plugin_name == NULL)
+ return (EINVAL);
+
+ /* Check if plugin is already loaded and don't do anything in this
+ * case. */
+ if (plugin_is_loaded (plugin_name))
+ return (0);
+
dir = plugin_get_dir ();
ret = 1;
+ /*
+ * XXX: Magic at work:
+ *
+ * Some of the language bindings, for example the Python and Perl
+ * plugins, need to be able to export symbols to the scripts they run.
+ * For this to happen, the "Globals" flag needs to be set.
+ * Unfortunately, this technical detail is hard to explain to the
+ * average user and she shouldn't have to worry about this, ideally.
+ * So in order to save everyone's sanity use a different default for a
+ * handful of special plugins. --octo
+ */
+ if ((strcasecmp ("perl", plugin_name) == 0)
+ || (strcasecmp ("python", plugin_name) == 0))
+ flags |= PLUGIN_FLAGS_GLOBAL;
+
/* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
* type when matching the filename */
- status = ssnprintf (typename, sizeof (typename), "%s.so", type);
+ status = ssnprintf (typename, sizeof (typename), "%s.so", plugin_name);
if ((status < 0) || ((size_t) status >= sizeof (typename)))
{
- WARNING ("plugin_load: Filename too long: \"%s.so\"", type);
+ WARNING ("plugin_load: Filename too long: \"%s.so\"", plugin_name);
return (-1);
}
typename_len = strlen (typename);
if (status == 0)
{
/* success */
+ plugin_mark_loaded (plugin_name);
ret = 0;
break;
}
else
{
ERROR ("plugin_load: Load plugin \"%s\" failed with "
- "status %i.", type, status);
+ "status %i.", plugin_name, status);
}
}
if (filename[0] == 0)
ERROR ("plugin_load: Could not find plugin \"%s\" in %s",
- type, dir);
+ plugin_name, dir);
return (ret);
}
rf->rf_udata.free_func = NULL;
rf->rf_ctx = plugin_get_ctx ();
rf->rf_group[0] = '\0';
- sstrncpy (rf->rf_name, name, sizeof (rf->rf_name));
+ rf->rf_name = strdup (name);
rf->rf_type = RF_SIMPLE;
rf->rf_interval = plugin_get_interval ();
sstrncpy (rf->rf_group, group, sizeof (rf->rf_group));
else
rf->rf_group[0] = '\0';
- sstrncpy (rf->rf_name, name, sizeof (rf->rf_name));
+ rf->rf_name = strdup (name);
rf->rf_type = RF_COMPLEX;
if (interval != NULL)
rf->rf_interval = TIMESPEC_TO_CDTIME_T (interval);
destroy_all_callbacks (&list_notification);
destroy_all_callbacks (&list_shutdown);
destroy_all_callbacks (&list_log);
+
+ plugin_free_loaded ();
} /* void plugin_shutdown_all */
int plugin_dispatch_missing (const value_list_t *vl) /* {{{ */
diff --git a/src/plugin.h b/src/plugin.h
index 635ff308f2cd4f83278554f4f79759a5b2efaeb4..8f0c6d86105fbfe56547d6b5d78ac9fd7a7f4b26 100644 (file)
--- a/src/plugin.h
+++ b/src/plugin.h
* and a value below zero if an error occurs.
*
* NOTES
- * No attempt is made to re-load an already loaded module.
+ * Re-loading an already loaded module is detected and zero is returned in
+ * this case.
*/
int plugin_load (const char *name, uint32_t flags);
diff --git a/src/snmp.c b/src/snmp.c
index cff38a4066d83f748b32bb2c2abecfb228dadd54..4f849320a3f3f6bdc2bdfb3730bf60fdc08016c5 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
@@ -1378,9 +1378,8 @@ static int csnmp_read_table (host_definition_t *host, data_definition_t *data)
/* Calculate the current suffix. This is later used to check that the
* suffix is increasing. This also checks if we left the subtree */
- int ret;
- ret = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
- if (ret != 0)
+ status = csnmp_oid_suffix (&suffix, &vb_name, data->values + i);
+ if (status != 0)
{
DEBUG ("snmp plugin: host = %s; data = %s; i = %i; "
"Value probably left its subtree.",
diff --git a/src/thermal.c b/src/thermal.c
index 603f85bbf6a96595ee04891127f37006d90730aa..27c92bc730c65b44c54c25bd9dc27a75c279980c 100644 (file)
--- a/src/thermal.c
+++ b/src/thermal.c
if (device_list && ignorelist_match (device_list, name))
return -1;
- len = snprintf (filename, sizeof (filename),
+ len = ssnprintf (filename, sizeof (filename),
"%s/%s/temp", dirname_sysfs, name);
if ((len < 0) || ((size_t) len >= sizeof (filename)))
return -1;
- len = read_file_contents (filename, data, sizeof(data));
+ len = (ssize_t) read_file_contents (filename, data, sizeof(data));
if (len > 1 && data[--len] == '\n') {
char *endptr = NULL;
double temp;
@@ -100,12 +100,12 @@ static int thermal_sysfs_device_read (const char __attribute__((unused)) *dir,
}
}
- len = snprintf (filename, sizeof (filename),
+ len = ssnprintf (filename, sizeof (filename),
"%s/%s/cur_state", dirname_sysfs, name);
if ((len < 0) || ((size_t) len >= sizeof (filename)))
return -1;
- len = read_file_contents (filename, data, sizeof(data));
+ len = (ssize_t) read_file_contents (filename, data, sizeof(data));
if (len > 1 && data[--len] == '\n') {
char *endptr = NULL;
double state;
@@ -139,12 +139,12 @@ static int thermal_procfs_device_read (const char __attribute__((unused)) *dir,
* temperature: 55 C
*/
- len = snprintf (filename, sizeof (filename),
+ len = ssnprintf (filename, sizeof (filename),
"%s/%s/temperature", dirname_procfs, name);
if ((len < 0) || ((size_t) len >= sizeof (filename)))
return -1;
- len = read_file_contents (filename, data, sizeof(data));
+ len = (ssize_t) read_file_contents (filename, data, sizeof(data));
if ((len > 0) && ((size_t) len > sizeof(str_temp))
&& (data[--len] == '\n')
&& (! strncmp(data, str_temp, sizeof(str_temp)-1))) {
diff --git a/src/types.db b/src/types.db
index fa24e6e2c002e96d71f950aeb8e820c345bccd94..950f6b0d842dd087b9db3e7b012d280da6ec417b 100644 (file)
--- a/src/types.db
+++ b/src/types.db
apache_scoreboard value:GAUGE:0:65535
ath_nodes value:GAUGE:0:65535
ath_stat value:DERIVE:0:U
+backends value:GAUGE:0:65535
bitrate value:GAUGE:0:4294967295
bytes value:GAUGE:0:U
cache_eviction value:DERIVE:0:U
node_rssi value:GAUGE:0:255
node_stat value:DERIVE:0:U
node_tx_rate value:GAUGE:0:127
+objects value:GAUGE:0:U
operations value:DERIVE:0:U
percent value:GAUGE:0:100.1
pf_counters value:DERIVE:0:U
time_offset value:GAUGE:-1000000:1000000
total_bytes value:DERIVE:0:U
total_connections value:DERIVE:0:U
+total_objects value:DERIVE:0:U
total_operations value:DERIVE:0:U
total_requests value:DERIVE:0:U
total_sessions value:DERIVE:0:U
total_values value:DERIVE:0:U
uptime value:GAUGE:0:4294967295
users value:GAUGE:0:65535
+vcl value:GAUGE:0:65535
vcpu value:GAUGE:0:U
virt_cpu_total value:DERIVE:0:U
virt_vcpu value:DERIVE:0:U
vs_memory value:GAUGE:0:9223372036854775807
vs_processes value:GAUGE:0:65535
vs_threads value:GAUGE:0:65535
+
#
# Legacy types
# (required for the v5 upgrade target)
diff --git a/src/varnish.c b/src/varnish.c
index 602f47af6231f59d40b51ccbd86800d1ca31bf3d..f7bca416880648a0e2a7843c8877a466a3149c96 100644 (file)
--- a/src/varnish.c
+++ b/src/varnish.c
* Florian octo Forster <octo at collectd.org>
**/
-/**
- * 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"
_Bool collect_connections;
_Bool collect_esi;
_Bool collect_backend;
+#ifdef HAVE_VARNISH_V3
+ _Bool collect_dirdns;
+#endif
_Bool collect_fetch;
_Bool collect_hcb;
+ _Bool collect_objects;
+#if HAVE_VARNISH_V2
+ _Bool collect_purge;
+#else
+ _Bool collect_ban;
+#endif
+ _Bool collect_session;
_Bool collect_shm;
_Bool collect_sms;
#if HAVE_VARNISH_V2
_Bool collect_sm;
_Bool collect_sma;
#endif
+ _Bool collect_struct;
_Bool collect_totals;
+ _Bool collect_uptime;
+ _Bool collect_vcl;
_Bool collect_workers;
};
typedef struct user_config_s user_config_t; /* }}} */
varnish_submit_derive (conf->instance, "connections", "connections", "received", stats->client_req);
}
+#ifdef HAVE_VARNISH_V3
+ if (conf->collect_dirdns)
+ {
+ /* DNS director lookups */
+ varnish_submit_derive (conf->instance, "dirdns", "cache_operation", "lookups", stats->dir_dns_lookups);
+ /* DNS director failed lookups */
+ varnish_submit_derive (conf->instance, "dirdns", "cache_result", "failed", stats->dir_dns_failed);
+ /* DNS director cached lookups hit */
+ varnish_submit_derive (conf->instance, "dirdns", "cache_result", "hits", stats->dir_dns_hit);
+ /* DNS director full dnscache */
+ varnish_submit_derive (conf->instance, "dirdns", "cache_result", "cache_full", stats->dir_dns_cache_full);
+ }
+#endif
+
if (conf->collect_esi)
{
/* ESI parse errors (unlock) */
- varnish_submit_derive (conf->instance, "esi", "total_operations", "error", 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);
+ varnish_submit_derive (conf->instance, "esi", "total_operations", "parsed", stats->esi_parse);
+#else
+ /* ESI parse warnings (unlock) */
+ varnish_submit_derive (conf->instance, "esi", "total_operations", "warning", stats->esi_warnings);
#endif
}
#if HAVE_VARNISH_V2
/* Backend conn. unused */
varnish_submit_derive (conf->instance, "backend", "connections", "unused" , stats->backend_unused);
+#else
+ /* Backend conn. retry */
+ varnish_submit_derive (conf->instance, "backend", "connections", "retries" , stats->backend_retry);
#endif
+ /* Backend requests mades */
+ varnish_submit_derive (conf->instance, "backend", "http_requests", "requests" , stats->backend_req);
+ /* N backends */
+ varnish_submit_gauge (conf->instance, "backend", "backends", "n_backends" , stats->n_backend);
}
if (conf->collect_fetch)
varnish_submit_derive (conf->instance, "fetch", "http_requests", "zero" , stats->fetch_zero);
/* Fetch failed */
varnish_submit_derive (conf->instance, "fetch", "http_requests", "failed" , stats->fetch_failed);
+#if HAVE_VARNISH_V3
+ /* Fetch no body (1xx) */
+ varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_1xx", stats->fetch_1xx);
+ /* Fetch no body (204) */
+ varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_204", stats->fetch_204);
+ /* Fetch no body (304) */
+ varnish_submit_derive (conf->instance, "fetch", "http_requests", "no_body_304", stats->fetch_304);
+#endif
}
if (conf->collect_hcb)
varnish_submit_derive (conf->instance, "hcb", "cache_operation", "insert", stats->hcb_insert);
}
+ if (conf->collect_objects)
+ {
+ /* N expired objects */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "expired", stats->n_expired);
+ /* N LRU nuked objects */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_nuked", stats->n_lru_nuked);
+#if HAVE_VARNISH_V2
+ /* N LRU saved objects */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_saved", stats->n_lru_saved);
+#endif
+ /* N LRU moved objects */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "lru_moved", stats->n_lru_moved);
+#if HAVE_VARNISH_V2
+ /* N objects on deathrow */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "deathrow", stats->n_deathrow);
+#endif
+ /* HTTP header overflows */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "header_overflow", stats->losthdr);
+ /* Objects sent with sendfile */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_sendfile", stats->n_objsendfile);
+ /* Objects sent with write */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "sent_write", stats->n_objwrite);
+ /* Objects overflowing workspace */
+ varnish_submit_derive (conf->instance, "objects", "total_objects", "workspace_overflow", stats->n_objoverflow);
+ }
+
+#if HAVE_VARNISH_V2
+ if (conf->collect_purge)
+ {
+ /* N total active purges */
+ varnish_submit_derive (conf->instance, "purge", "total_operations", "total", stats->n_purge);
+ /* N new purges added */
+ varnish_submit_derive (conf->instance, "purge", "total_operations", "added", stats->n_purge_add);
+ /* N old purges deleted */
+ varnish_submit_derive (conf->instance, "purge", "total_operations", "deleted", stats->n_purge_retire);
+ /* N objects tested */
+ varnish_submit_derive (conf->instance, "purge", "total_operations", "objects_tested", stats->n_purge_obj_test);
+ /* N regexps tested against */
+ varnish_submit_derive (conf->instance, "purge", "total_operations", "regexps_tested", stats->n_purge_re_test);
+ /* N duplicate purges removed */
+ varnish_submit_derive (conf->instance, "purge", "total_operations", "duplicate", stats->n_purge_dups);
+ }
+#else
+ if (conf->collect_ban)
+ {
+ /* N total active bans */
+ varnish_submit_derive (conf->instance, "ban", "total_operations", "total", stats->n_ban);
+ /* N new bans added */
+ varnish_submit_derive (conf->instance, "ban", "total_operations", "added", stats->n_ban_add);
+ /* N old bans deleted */
+ varnish_submit_derive (conf->instance, "ban", "total_operations", "deleted", stats->n_ban_retire);
+ /* N objects tested */
+ varnish_submit_derive (conf->instance, "ban", "total_operations", "objects_tested", stats->n_ban_obj_test);
+ /* N regexps tested against */
+ varnish_submit_derive (conf->instance, "ban", "total_operations", "regexps_tested", stats->n_ban_re_test);
+ /* N duplicate bans removed */
+ varnish_submit_derive (conf->instance, "ban", "total_operations", "duplicate", stats->n_ban_dups);
+ }
+#endif
+
+ if (conf->collect_session)
+ {
+ /* Session Closed */
+ varnish_submit_derive (conf->instance, "session", "total_operations", "closed", stats->sess_closed);
+ /* Session Pipeline */
+ varnish_submit_derive (conf->instance, "session", "total_operations", "pipeline", stats->sess_pipeline);
+ /* Session Read Ahead */
+ varnish_submit_derive (conf->instance, "session", "total_operations", "readahead", stats->sess_readahead);
+ /* Session Linger */
+ varnish_submit_derive (conf->instance, "session", "total_operations", "linger", stats->sess_linger);
+ /* Session herd */
+ varnish_submit_derive (conf->instance, "session", "total_operations", "herd", stats->sess_herd);
+ }
+
if (conf->collect_shm)
{
/* SHM records */
varnish_submit_derive (conf->instance, "sms", "total_bytes", "free", stats->sms_bfree);
}
+ if (conf->collect_struct)
+ {
+ /* N struct sess_mem */
+ varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess_mem", stats->n_sess_mem);
+ /* N struct sess */
+ varnish_submit_gauge (conf->instance, "struct", "current_sessions", "sess", stats->n_sess);
+ /* N struct object */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "object", stats->n_object);
+ /* N unresurrected objects */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "vampireobject", stats->n_vampireobject);
+ /* N struct objectcore */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "objectcore", stats->n_objectcore);
+ /* N struct objecthead */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "objecthead", stats->n_objecthead);
+#ifdef HAVE_VARNISH_V2
+ /* N struct smf */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "smf", stats->n_smf);
+ /* N small free smf */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "smf_frag", stats->n_smf_frag);
+ /* N large free smf */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "smf_large", stats->n_smf_large);
+ /* N struct vbe_conn */
+ varnish_submit_gauge (conf->instance, "struct", "objects", "vbe_conn", stats->n_vbe_conn);
+#endif
+ }
+
if (conf->collect_totals)
{
/* Total Sessions */
varnish_submit_derive (conf->instance, "totals", "total_bytes", "body-bytes", stats->s_bodybytes);
}
+ if (conf->collect_uptime)
+ {
+ /* Client uptime */
+ varnish_submit_gauge (conf->instance, "uptime", "uptime", "client_uptime", stats->uptime);
+ }
+
+ if (conf->collect_vcl)
+ {
+ /* N vcl total */
+ varnish_submit_gauge (conf->instance, "vcl", "vcl", "total_vcl", stats->n_vcl);
+ /* N vcl available */
+ varnish_submit_gauge (conf->instance, "vcl", "vcl", "avail_vcl", stats->n_vcl_avail);
+ /* N vcl discarded */
+ varnish_submit_gauge (conf->instance, "vcl", "vcl", "discarded_vcl", stats->n_vcl_discard);
+ }
+
if (conf->collect_workers)
{
/* worker threads */
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", stats->n_wrk_overflow);
+#else
+ /* queued work requests */
+ varnish_submit_derive (conf->instance, "workers", "total_requests", "queued", stats->n_wrk_queued);
+ /* work request queue length */
+ varnish_submit_derive (conf->instance, "workers", "total_requests", "queue_length", stats->n_wrk_lqueue);
#endif
}
} /* }}} void varnish_monitor */
conf->collect_backend = 1;
conf->collect_cache = 1;
conf->collect_connections = 1;
+#ifdef HAVE_VARNISH_V3
+ conf->collect_dirdns = 0;
+#endif
conf->collect_esi = 0;
conf->collect_fetch = 0;
conf->collect_hcb = 0;
+ conf->collect_objects = 0;
+#if HAVE_VARNISH_V2
+ conf->collect_purge = 0;
+#else
+ conf->collect_ban = 0;
+#endif
+ conf->collect_session = 0;
conf->collect_shm = 1;
#if HAVE_VARNISH_V2
conf->collect_sm = 0;
conf->collect_sma = 0;
#endif
conf->collect_sms = 0;
+ conf->collect_struct = 0;
conf->collect_totals = 0;
+ conf->collect_uptime = 0;
+ conf->collect_vcl = 0;
+ conf->collect_workers = 0;
return (0);
} /* }}} int varnish_config_apply_default */
cf_util_get_boolean (child, &conf->collect_connections);
else if (strcasecmp ("CollectESI", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_esi);
+#ifdef HAVE_VARNISH_V3
+ else if (strcasecmp ("CollectDirectorDNS", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_dirdns);
+#endif
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 ("CollectObjects", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_objects);
+#if HAVE_VARNISH_V2
+ else if (strcasecmp ("CollectPurge", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_purge);
+#else
+ else if (strcasecmp ("CollectBan", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_ban);
+#endif
+ else if (strcasecmp ("CollectSession", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_session);
else if (strcasecmp ("CollectSHM", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_shm);
else if (strcasecmp ("CollectSMS", child->key) == 0)
else if (strcasecmp ("CollectSM", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_sm);
#endif
+ else if (strcasecmp ("CollectStruct", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_struct);
else if (strcasecmp ("CollectTotals", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_totals);
+ else if (strcasecmp ("CollectUptime", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_uptime);
+ else if (strcasecmp ("CollectVCL", child->key) == 0)
+ cf_util_get_boolean (child, &conf->collect_vcl);
else if (strcasecmp ("CollectWorkers", child->key) == 0)
cf_util_get_boolean (child, &conf->collect_workers);
else
&& !conf->collect_connections
&& !conf->collect_esi
&& !conf->collect_backend
+#ifdef HAVE_VARNISH_V3
+ && !conf->collect_dirdns
+#endif
&& !conf->collect_fetch
&& !conf->collect_hcb
+ && !conf->collect_objects
+#if HAVE_VARNISH_V2
+ && !conf->collect_purge
+#else
+ && !conf->collect_ban
+#endif
+ && !conf->collect_session
&& !conf->collect_shm
&& !conf->collect_sms
#if HAVE_VARNISH_V2
&& !conf->collect_sma
&& !conf->collect_sm
#endif
+ && !conf->collect_struct
&& !conf->collect_totals
+ && !conf->collect_uptime
+ && !conf->collect_vcl
&& !conf->collect_workers)
{
WARNING ("Varnish plugin: No metric has been configured for "