author | Marc Fournier <marc.fournier@camptocamp.com> | |
Wed, 2 Dec 2015 08:14:59 +0000 (09:14 +0100) | ||
committer | Marc Fournier <marc.fournier@camptocamp.com> | |
Wed, 2 Dec 2015 08:14:59 +0000 (09:14 +0100) |
Read threads timing
51 files changed:
diff --git a/.travis.yml b/.travis.yml
index 09adb4d9a5e79b8c404365f9c0dc045c001e5c73..435669bcb691775ff350f09d43cd747c073165c2 100644 (file)
--- a/.travis.yml
+++ b/.travis.yml
-sudo: false
+sudo: required
+dist: trusty
compiler:
- gcc
- clang
-addons:
- apt:
- packages:
- - iptables-dev
- - libcap-dev
- - libdbi-dev
- - libhiredis-dev
- - libnfnetlink-dev
- - libnotify-dev
- - libpcap-dev
- - libperl-dev
- - libprotobuf-c0-dev
- - librrd-dev
- - libsnmp-dev
- - libudev-dev
- - libvarnishapi-dev
- - libyajl-dev
- - linux-libc-dev
- - protobuf-c-compiler
language: c
+before_install:
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq --no-install-recommends
+ libatasmart-dev
+ libcap-dev
+ libcurl4-gnutls-dev
+ libdbi0-dev
+ libesmtp-dev
+ libganglia1-dev
+ libgcrypt11-dev
+ libglib2.0-dev
+ libhiredis-dev
+ libi2c-dev
+ libldap2-dev
+ libltdl-dev
+ liblvm2-dev
+ libmemcached-dev
+ libmnl-dev
+ libmodbus-dev
+ libmosquitto0-dev
+ libmysqlclient-dev
+ libnotify-dev
+ libopenipmi-dev
+ liboping-dev
+ libow-dev
+ libpcap-dev
+ libperl-dev
+ libpq-dev
+ libprotobuf-c0-dev
+ librabbitmq-dev
+ librdkafka-dev
+ librrd-dev
+ libsensors4-dev
+ libsigrok-dev
+ libsnmp-dev
+ libstatgrab-dev
+ libtokyocabinet-dev
+ libtokyotyrant-dev
+ libudev-dev
+ libupsclient-dev
+ libvarnish-dev
+ libvirt-dev
+ libxml2-dev
+ libyajl-dev
+ linux-libc-dev
+ perl
+ protobuf-c-compiler
+ python-dev
script: sh build.sh && ./configure && make distcheck
diff --git a/bindings/java/org/collectd/java/GenericJMXConfValue.java b/bindings/java/org/collectd/java/GenericJMXConfValue.java
index 4b42c91171036ca70d213d0f1131373f79b7f572..25b70d4ad7166dfda421f8b29fb37a757a837673 100644 (file)
import java.util.Arrays;
import java.util.List;
+import java.util.Collection;
import java.util.Set;
import java.util.Iterator;
import java.util.ArrayList;
import javax.management.ObjectName;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
import javax.management.openmbean.InvalidKeyException;
import org.collectd.api.Collectd;
private List<String> _attributes;
private String _instance_prefix;
private List<String> _instance_from;
+ private String _plugin_name;
private boolean _is_table;
/**
{
if (value instanceof CompositeData)
return (queryAttributeRecursive ((CompositeData) value, attrName));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive ((TabularData) value, attrName));
+ else
+ return (null);
+ }
+ } /* }}} queryAttributeRecursive */
+
+ private Object queryAttributeRecursive (TabularData parent, /* {{{ */
+ List<String> attrName)
+ {
+ String key;
+ Object value = null;
+
+ key = attrName.remove (0);
+
+ TabularData tabularData = (TabularData) parent;
+ Collection<CompositeData> table =
+ (Collection<CompositeData>)tabularData.values();
+ for (CompositeData compositeData : table)
+ {
+ if (key.equals(compositeData.get("key")))
+ {
+ value = compositeData.get("value");
+ }
+ }
+ if (null == value)
+ {
+ return (null);
+ }
+
+ if (attrName.size () == 0)
+ {
+ return (value);
+ }
+ else
+ {
+ if (value instanceof CompositeData)
+ return (queryAttributeRecursive ((CompositeData) value, attrName));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive ((TabularData) value, attrName));
else
return (null);
}
{
if (value instanceof CompositeData)
return (queryAttributeRecursive((CompositeData) value, attrNameList));
+ else if (value instanceof TabularData)
+ return (queryAttributeRecursive((TabularData) value, attrNameList));
else if (value instanceof OpenType)
{
OpenType ot = (OpenType) value;
else
{
Collectd.logError ("GenericJMXConfValue: Received object of "
- + "unknown class.");
+ + "unknown class. " + attrName + " " + ((value == null)?"null":value.getClass().getName()));
return (null);
}
}
this._attributes = new ArrayList<String> ();
this._instance_prefix = null;
this._instance_from = new ArrayList<String> ();
+ this._plugin_name = null;
this._is_table = false;
/*
if (tmp != null)
this._instance_from.add (tmp);
}
+ else if (child.getKey ().equalsIgnoreCase ("PluginName"))
+ {
+ String tmp = getConfigString (child);
+ if (tmp != null)
+ this._plugin_name = tmp;
+ }
else
throw (new IllegalArgumentException ("Unknown option: "
+ child.getKey ()));
vl = new ValueList (pd);
vl.setType (this._ds_name);
+ if (this._plugin_name != null)
+ {
+ vl.setPlugin (this._plugin_name);
+ }
/*
* Build the instnace prefix from the fixed string prefix and the
index 69c755b6a92996cd192b9845ea87c866dd51b741..d927d13e4bc486b48110c5d786ad537d763f8de8 100644 (file)
$self->_socket_chat($msg, sub {
local $_ = shift;
my $ret = shift;
- /^\s*([^:]+):\s*(.*)/ and do {
- $1 =~ s/\s*$//;
- $ret->{$1} = $2;
- };
+ my ( $key, $val );
+ ( $key, $val ) = /^\s*([^:]+):\s*(.*)/ and do {
+ $key =~ s/\s*$//;
+ $ret->{$key} = $val;
+ };
}, $ret
);
return $ret;
diff --git a/configure.ac b/configure.ac
index 3f5f2d8b19e1d65b84268cdb93ae321f40e5998f..2a9b84a9a5e13ed4daa19cdcfef5c4484c1de1fe 100644 (file)
--- a/configure.ac
+++ b/configure.ac
PKG_PROG_PKG_CONFIG
AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
-AC_CHECK_HEADERS([google/protobuf-c/protobuf-c.h],
- [have_protobuf_c_h="yes"],
- [have_protobuf_c_h="no"])
-if test "x$have_protoc_c" = "xyes" && test "x$have_protobuf_c_h" != "xyes"
+if test "x$have_protoc_c" = "xno"
then
- have_protoc_c="no (unable to find <google/protobuf-c/protobuf-c.h>)"
+ have_protoc_c="no (protoc-c compiler not found)"
+fi
+
+if test "x$have_protoc_c" = "xyes"
+then
+ AC_CHECK_HEADERS([protobuf-c/protobuf-c.h google/protobuf-c/protobuf-c.h],
+ [have_protoc_c="yes"; break],
+ [have_protoc_c="no (<google/protobuf-c/protobuf-c.h> not found)"])
+fi
+if test "x$have_protoc_c" = "xyes"
+then
+ AC_CHECK_LIB([protobuf-c], [protobuf_c_message_pack],
+ [have_protoc_c="yes"],
+ [have_protoc_c="no (libprotobuf-c not found)"])
+
fi
AM_CONDITIONAL(HAVE_PROTOC_C, test "x$have_protoc_c" = "xyes")
AC_CHECK_FUNCS(getvfsstat, [have_getvfsstat="yes"])
have_listmntent="no"
AC_CHECK_FUNCS(listmntent, [have_listmntent="yes"])
+have_getmntent_r="no"
+AC_CHECK_FUNCS(getmntent_r, [have_getmntent_r="yes"])
have_getmntent="no"
AC_CHECK_FUNCS(getmntent, [have_getmntent="c"])
GCRYPT_CPPFLAGS=`"$with_libgcrypt_config" --cflags 2>/dev/null`
fi
- if test "x$GCRYPT_LDFLAGS" = "x"
- then
- gcrypt_exec_prefix=`"$with_libgcrypt_config" --exec-prefix 2>/dev/null`
- GCRYPT_LDFLAGS="-L$gcrypt_exec_prefix/lib"
- fi
-
if test "x$GCRYPT_LIBS" = "x"
then
GCRYPT_LIBS=`"$with_libgcrypt_config" --libs 2>/dev/null`
SAVE_CPPFLAGS="$CPPFLAGS"
SAVE_LDFLAGS="$LDFLAGS"
+SAVE_LIBS="$LIBS"
CPPFLAGS="$CPPFLAGS $GCRYPT_CPPFLAGS"
LDFLAGS="$LDFLAGS $GCRYPT_LDFLAGS"
+LIBS="$LIBS $GCRYPT_LIBS"
if test "x$with_libgcrypt" = "xyes"
then
if test "x$with_libgcrypt" = "xyes"
then
- if test "x$GCRYPT_LDFLAGS" != "x"
- then
- AC_MSG_NOTICE([gcrypt LDFLAGS: $GCRYPT_LDFLAGS])
- fi
AC_CHECK_LIB(gcrypt, gcry_md_hash_buffer,
[with_libgcrypt="yes"],
[with_libgcrypt="no (symbol gcry_md_hash_buffer not found)"])
-
- if test "$with_libgcrypt" != "no"; then
- m4_ifdef([AM_PATH_LIBGCRYPT],[AM_PATH_LIBGCRYPT(1:1.2.0,,with_libgcrypt="no (version 1.2.0+ required)")])
- GCRYPT_CPPFLAGS="$LIBGCRYPT_CPPFLAGS $LIBGCRYPT_CFLAGS"
- GCRYPT_LIBS="$LIBGCRYPT_LIBS"
- fi
fi
CPPFLAGS="$SAVE_CPPFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
+LIBS="$SAVE_LIBS"
if test "x$with_libgcrypt" = "xyes"
then
plugin_df="yes"
fi
+if test "x$c_cv_have_getmntent_r" = "xyes"
+then
+ plugin_df="yes"
+fi
+
# Df plugin: Check if we have either `statfs' or `statvfs' second.
if test "x$plugin_df" = "xyes"
then
AC_PLUGIN([nginx], [$with_libcurl], [nginx statistics])
AC_PLUGIN([notify_desktop], [$with_libnotify], [Desktop notifications])
AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
+AC_PLUGIN([notify_nagios], [yes], [Nagios notification plugin])
AC_PLUGIN([ntpd], [yes], [NTPd statistics])
AC_PLUGIN([numa], [$plugin_numa], [NUMA virtual memory statistics])
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
nginx . . . . . . . . $enable_nginx
notify_desktop . . . $enable_notify_desktop
notify_email . . . . $enable_notify_email
+ notify_nagios . . . . $enable_notify_nagios
ntpd . . . . . . . . $enable_ntpd
numa . . . . . . . . $enable_numa
nut . . . . . . . . . $enable_nut
index 2252181335cff9c2e116cc962b0836c6b61d1e22..4dfcc9a8b5aeeeef4269d403fdf6d186748da087 100644 (file)
%define with_nginx 0%{!?_without_nginx:1}
%define with_notify_desktop 0%{!?_without_notify_desktop:1}
%define with_notify_email 0%{!?_without_notify_email:1}
+%define with_notify_nagios 0%{!?_without_notify_nagios:1}
%define with_ntpd 0%{!?_without_ntpd:1}
%define with_numa 0%{!?_without_numa:1}
%define with_nut 0%{!?_without_nut:1}
%define _with_notify_email --disable-notify_email
%endif
+%if %{with_notify_nagios}
+%define _with_notify_nagios --enable-notify_nagios
+%else
+%define _with_notify_nagios --disable-notify_nagios
+%endif
+
%if %{with_ntpd}
%define _with_ntpd --enable-ntpd
%else
%{?_with_memory} \
%{?_with_network} \
%{?_with_nfs} \
+ %{?_with_notify_nagios} \
%{?_with_ntpd} \
%{?_with_numa} \
%{?_with_olsrd} \
%if %{with_nfs}
%{_libdir}/%{name}/nfs.so
%endif
+%if %{with_notify_nagios}
+%{_libdir}/%{name}/notify_nagios.so
+%endif
%if %{with_ntpd}
%{_libdir}/%{name}/ntpd.so
%endif
%changelog
#* TODO: next feature release changelog
#- New upstream version
-#- New plugins enabled by default: mqtt
+#- New plugins enabled by default: mqtt, notify_nagios
#- New plugins disabled by default: zone
#
* Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
index 96df8a576a694670f1af076e344b0be7f1c45767..0e758e40ef85a9fb6aba1c921da5a0f27c89a41d 100644 (file)
ExecStart=/usr/sbin/collectd
EnvironmentFile=-/etc/sysconfig/collectd
EnvironmentFile=-/etc/default/collectd
+ProtectSystem=full
+ProtectHome=true
+
+# drop all capabilities:
+CapabilityBoundingSet=
+# use this instead if you use the dns or ping plugin
+#CapabilityBoundingSet=CAP_NET_RAW
+# turn this on if you use the iptables next to the dns or ping plugin
+#CapabilityBoundingSet=CAP_NET_RAW CAP_NET_ADMIN
+
+NoNewPrivileges=true
# Tell systemd it will receive a notification from collectd over it's control
# socket once the daemon is ready. See systemd.service(5) for more details.
Type=notify
-NotifyAccess=main
# Restart the collectd daemon after a 10 seconds delay, in case it crashes.
-Restart=always
-RestartSec=10
-
-# Send all console messages to syslog.
-StandardOutput=syslog
-StandardError=syslog
+Restart=on-failure
[Install]
WantedBy=multi-user.target
diff --git a/src/Makefile.am b/src/Makefile.am
index d0bf5463d125b58b83d461b347961ff25e0a3208..d3b1acd35f8fca375d850b19e299a181e93aea14 100644 (file)
--- a/src/Makefile.am
+++ b/src/Makefile.am
if BUILD_PLUGIN_CGROUPS
pkglib_LTLIBRARIES += cgroups.la
-cgroups_la_SOURCES = cgroups.c \
- utils_ignorelist.c utils_ignorelist.h
+cgroups_la_SOURCES = cgroups.c
cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
cgroups_la_LIBADD = libmount.la
endif
if BUILD_PLUGIN_DF
pkglib_LTLIBRARIES += df.la
-df_la_SOURCES = df.c \
- utils_ignorelist.c utils_ignorelist.h
+df_la_SOURCES = df.c
df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
df_la_LIBADD = libmount.la
endif
if BUILD_PLUGIN_DISK
pkglib_LTLIBRARIES += disk.la
-disk_la_SOURCES = disk.c \
- utils_ignorelist.c utils_ignorelist.h
+disk_la_SOURCES = disk.c
disk_la_CFLAGS = $(AM_CFLAGS)
disk_la_LDFLAGS = $(PLUGIN_LDFLAGS)
disk_la_LIBADD =
if BUILD_PLUGIN_INTERFACE
pkglib_LTLIBRARIES += interface.la
-interface_la_SOURCES = interface.c \
- utils_ignorelist.c utils_ignorelist.h
+interface_la_SOURCES = interface.c
interface_la_CFLAGS = $(AM_CFLAGS)
interface_la_LDFLAGS = $(PLUGIN_LDFLAGS)
interface_la_LIBADD =
if BUILD_PLUGIN_IPMI
pkglib_LTLIBRARIES += ipmi.la
-ipmi_la_SOURCES = ipmi.c \
- utils_ignorelist.c utils_ignorelist.h
+ipmi_la_SOURCES = ipmi.c
ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
if BUILD_PLUGIN_IRQ
pkglib_LTLIBRARIES += irq.la
-irq_la_SOURCES = irq.c \
- utils_ignorelist.c utils_ignorelist.h
+irq_la_SOURCES = irq.c
irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_MADWIFI
pkglib_LTLIBRARIES += madwifi.la
-madwifi_la_SOURCES = madwifi.c madwifi.h \
- utils_ignorelist.c utils_ignorelist.h
+madwifi_la_SOURCES = madwifi.c madwifi.h
madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_MD
pkglib_LTLIBRARIES += md.la
-md_la_SOURCES = md.c \
- utils_ignorelist.c utils_ignorelist.h
+md_la_SOURCES = md.c
md_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_MIC
pkglib_LTLIBRARIES += mic.la
-mic_la_SOURCES = mic.c \
- utils_ignorelist.c utils_ignorelist.h
+mic_la_SOURCES = mic.c
mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LIBPATH)
mic_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
mic_la_LIBADD = $(BUILD_WITH_MIC_LDADD)
if BUILD_PLUGIN_NETAPP
pkglib_LTLIBRARIES += netapp.la
-netapp_la_SOURCES = netapp.c \
- utils_ignorelist.c utils_ignorelist.h
+netapp_la_SOURCES = netapp.c
netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS)
netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS)
netapp_la_LIBADD = $(LIBNETAPP_LIBS)
notify_email_la_LIBADD = -lesmtp -lssl -lcrypto -lpthread
endif
+if BUILD_PLUGIN_NOTIFY_NAGIOS
+pkglib_LTLIBRARIES += notify_nagios.la
+notify_nagios_la_SOURCES = notify_nagios.c
+notify_nagios_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
if BUILD_PLUGIN_NTPD
pkglib_LTLIBRARIES += ntpd.la
ntpd_la_SOURCES = ntpd.c
if BUILD_PLUGIN_ONEWIRE
pkglib_LTLIBRARIES += onewire.la
-onewire_la_SOURCES = onewire.c \
- utils_ignorelist.c utils_ignorelist.h
+onewire_la_SOURCES = onewire.c
onewire_la_CFLAGS = $(AM_CFLAGS)
onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
if BUILD_PLUGIN_PROTOCOLS
pkglib_LTLIBRARIES += protocols.la
-protocols_la_SOURCES = protocols.c \
- utils_ignorelist.c utils_ignorelist.h
+protocols_la_SOURCES = protocols.c
protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_SENSORS
pkglib_LTLIBRARIES += sensors.la
-sensors_la_SOURCES = sensors.c \
- utils_ignorelist.c utils_ignorelist.h
+sensors_la_SOURCES = sensors.c
sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS)
sensors_la_LIBADD = -lsensors
if BUILD_PLUGIN_SMART
if BUILD_WITH_LIBUDEV
pkglib_LTLIBRARIES += smart.la
-smart_la_SOURCES = smart.c \
- utils_ignorelist.c utils_ignorelist.h
+smart_la_SOURCES = smart.c
smart_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS)
smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS)
smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) -ludev
if BUILD_PLUGIN_THERMAL
pkglib_LTLIBRARIES += thermal.la
-thermal_la_SOURCES = thermal.c \
- utils_ignorelist.c utils_ignorelist.h
+thermal_la_SOURCES = thermal.c
thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_VIRT
pkglib_LTLIBRARIES += virt.la
-virt_la_SOURCES = virt.c \
- utils_ignorelist.c utils_ignorelist.h
+virt_la_SOURCES = virt.c
virt_la_CFLAGS = $(AM_CFLAGS) \
$(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
echo "$@ has some POD errors!"; false; \
fi
+AM_V_PROTOC_C = $(am__v_PROTOC_C_@AM_V@)
+am__v_PROTOC_C_ = $(am__v_PROTOC_C_@AM_DEFAULT_V@)
+am__v_PROTOC_C_0 = @echo " PROTOC-C " $@;
+am__v_PROTOC_C_1 =
+
# Protocol buffer for the "pinba" plugin.
EXTRA_DIST += pinba.proto
-if HAVE_PROTOC_C
+if BUILD_PLUGIN_PINBA
CLEANFILES += pinba.pb-c.c pinba.pb-c.h
BUILT_SOURCES += pinba.pb-c.c pinba.pb-c.h
pinba.pb-c.c pinba.pb-c.h: pinba.proto
- protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
+ $(AM_V_PROTOC_C)protoc-c -I$(srcdir) --c_out . $(srcdir)/pinba.proto
endif
# Protocol buffer for the "write_riemann" plugin.
EXTRA_DIST += riemann.proto
-if HAVE_PROTOC_C
+if BUILD_PLUGIN_WRITE_RIEMANN
CLEANFILES += riemann.pb-c.c riemann.pb-c.h
BUILT_SOURCES += riemann.pb-c.c riemann.pb-c.h
riemann.pb-c.c riemann.pb-c.h: riemann.proto
- protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto
+ $(AM_V_PROTOC_C)protoc-c -I$(srcdir) --c_out . $(srcdir)/riemann.proto
endif
install-exec-hook:
rm -f $(DESTDIR)$(sysconfdir)/collectd.conf
rm -f $(DESTDIR)$(pkgdatadir)/postgresql_default.conf;
-
+if BUILD_PLUGIN_CEPH
+test_plugin_ceph_SOURCES = ceph_test.c
+test_plugin_ceph_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+test_plugin_ceph_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+test_plugin_ceph_LDADD = daemon/libcommon.la daemon/libplugin_mock.la $(BUILD_WITH_LIBYAJL_LIBS)
+check_PROGRAMS += test_plugin_ceph
+TESTS += test_plugin_ceph
+endif
diff --git a/src/amqp.c b/src/amqp.c
index aba4f0122ca7c87ab4313da6cc3fd318872a9d88..4206bdc1e3ee36b99192452b377943e007fb8af8 100644 (file)
--- a/src/amqp.c
+++ b/src/amqp.c
switch (r.reply_type)
{
case AMQP_RESPONSE_NORMAL:
- sstrncpy (buffer, "Success", sizeof (buffer));
+ sstrncpy (buffer, "Success", buffer_size);
break;
case AMQP_RESPONSE_NONE:
- sstrncpy (buffer, "Missing RPC reply type", sizeof (buffer));
+ sstrncpy (buffer, "Missing RPC reply type", buffer_size);
break;
case AMQP_RESPONSE_LIBRARY_EXCEPTION:
return (sstrerror (r.library_error, buffer, buffer_size));
#endif
else
- sstrncpy (buffer, "End of stream", sizeof (buffer));
+ sstrncpy (buffer, "End of stream", buffer_size);
break;
case AMQP_RESPONSE_SERVER_EXCEPTION:
diff --git a/src/apache.c b/src/apache.c
index 41b807af7541fb748634d2b5c3660198659dc43a..b306032b6c55fddb512b17c0fb24aa252271dbf2 100644 (file)
--- a/src/apache.c
+++ b/src/apache.c
static int apache_read_host (user_data_t *user_data) /* {{{ */
{
- int i;
-
char *ptr;
char *saveptr;
- char *lines[16];
- int lines_num = 0;
+ char *line;
char *fields[4];
int fields_num;
ptr = st->apache_buffer;
saveptr = NULL;
- while ((lines[lines_num] = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
+ while ((line = strtok_r (ptr, "\n\r", &saveptr)) != NULL)
{
ptr = NULL;
- lines_num++;
-
- if (lines_num >= 16)
- break;
- }
-
- for (i = 0; i < lines_num; i++)
- {
- fields_num = strsplit (lines[i], fields, 4);
+ fields_num = strsplit (line, fields, STATIC_ARRAY_SIZE (fields));
if (fields_num == 3)
{
- if ((strcmp (fields[0], "Total") == 0)
- && (strcmp (fields[1], "Accesses:") == 0))
- submit_derive ("apache_requests", "",
- atoll (fields[2]), st);
- else if ((strcmp (fields[0], "Total") == 0)
- && (strcmp (fields[1], "kBytes:") == 0))
- submit_derive ("apache_bytes", "",
- 1024LL * atoll (fields[2]), st);
+ if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "Accesses:") == 0))
+ submit_derive ("apache_requests", "", atoll (fields[2]), st);
+ else if ((strcmp (fields[0], "Total") == 0) && (strcmp (fields[1], "kBytes:") == 0))
+ submit_derive ("apache_bytes", "", 1024LL * atoll (fields[2]), st);
}
else if (fields_num == 2)
{
diff --git a/src/apcups.c b/src/apcups.c
index 718061ae36e693a9125325f3403da98f25be2316..29d58c3ad6e0a2d1b2038bf6433d078113fe0497 100644 (file)
--- a/src/apcups.c
+++ b/src/apcups.c
if (status != 0)
{
char errbuf[1024];
- INFO ("getaddrinfo failed: %s",
+ INFO ("apcups plugin: getaddrinfo failed: %s",
(status == EAI_SYSTEM)
? sstrerror (errno, errbuf, sizeof (errbuf))
: gai_strerror (status));
if (sd < 0)
{
- DEBUG ("Unable to open a socket");
+ DEBUG ("apcups plugin: Unable to open a socket");
freeaddrinfo (ai_return);
return (-1);
}
if (status != 0) /* `connect(2)' failed */
{
char errbuf[1024];
- INFO ("connect failed: %s",
+ INFO ("apcups plugin: connect failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
close (sd);
return (-1);
}
- DEBUG ("Done opening a socket %i", sd);
+ DEBUG ("apcups plugin: Done opening a socket %i", sd);
return (sd);
} /* int net_open */
*/
if (status != 0)
{
- DEBUG ("apc_query_server (%s, %s) = %i",
+ DEBUG ("apcups plugin: apc_query_server (%s, %s) = %i",
(conf_node == NULL) ? APCUPS_DEFAULT_NODE : conf_node,
(conf_service == NULL) ? APCUPS_DEFAULT_SERVICE : conf_service,
status);
diff --git a/src/bind.c b/src/bind.c
index 06b4ace00393e2321fc7bef9762f4b320c582aa5..9fb3ec49e75ddda0756a4db1767bbec1e10a757b 100644 (file)
--- a/src/bind.c
+++ b/src/bind.c
if (tmp->name == NULL)
{
ERROR ("bind plugin: strdup failed.");
- free (tmp);
+ sfree (views);
return (-1);
}
diff --git a/src/ceph.c b/src/ceph.c
index 419ca6e56170758c5c05dea2e1e20994b53b2ff3..d762754d51733326aa58d466c60f29404675d762 100644 (file)
--- a/src/ceph.c
+++ b/src/ceph.c
/**
* collectd - src/ceph.c
* Copyright (C) 2011 New Dream Network
+ * Copyright (C) 2015 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
* 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* Authors:
- * Colin McCabe <cmccabe@alumni.cmu.edu>
- * Dennis Zou <yunzou@cisco.com>
- * Dan Ryder <daryder@cisco.com>
+ * Colin McCabe <cmccabe at alumni.cmu.edu>
+ * Dennis Zou <yunzou at cisco.com>
+ * Dan Ryder <daryder at cisco.com>
+ * Florian octo Forster <octo at collectd.org>
**/
#define _DEFAULT_SOURCE
sfree(d);
}
-/**
- * Compact ds name by removing special characters and trimming length to
- * DATA_MAX_NAME_LEN if necessary
- */
-static void compact_ds_name(char *source, char *dest)
+/* compact_ds_name removed the special characters ":", "_", "-" and "+" from the
+ * intput string. Characters following these special characters are capitalized.
+ * Trailing "+" and "-" characters are replaces with the strings "Plus" and
+ * "Minus". */
+static int compact_ds_name (char *buffer, size_t buffer_size, char const *src)
{
- int keys_num = 0, i;
- char *save_ptr = NULL, *tmp_ptr = source;
- char *keys[16];
- char len_str[3];
- char tmp[DATA_MAX_NAME_LEN];
- size_t key_chars_remaining = (DATA_MAX_NAME_LEN-1);
- int reserved = 0;
- int offset = 0;
- memset(tmp, 0, sizeof(tmp));
- if(source == NULL || dest == NULL || source[0] == '\0' || dest[0] != '\0')
- {
- return;
- }
- size_t src_len = strlen(source);
- snprintf(len_str, sizeof(len_str), "%zu", src_len);
- unsigned char append_status = 0x0;
- append_status |= (source[src_len - 1] == '-') ? 0x1 : 0x0;
- append_status |= (source[src_len - 1] == '+') ? 0x2 : 0x0;
- while ((keys[keys_num] = strtok_r(tmp_ptr, ":_-+", &save_ptr)) != NULL)
- {
- tmp_ptr = NULL;
- /** capitalize 1st char **/
- keys[keys_num][0] = toupper(keys[keys_num][0]);
- keys_num++;
- if(keys_num >= 16)
- {
- break;
- }
- }
- /** concatenate each part of source string **/
- for(i = 0; i < keys_num; i++)
- {
- strncat(tmp, keys[i], key_chars_remaining);
- key_chars_remaining -= strlen(keys[i]);
- }
- tmp[DATA_MAX_NAME_LEN - 1] = '\0';
- /** to coordinate limitation of length of type_instance
- * we will truncate ds_name
- * when the its length is more than
- * DATA_MAX_NAME_LEN
- */
- if(strlen(tmp) > DATA_MAX_NAME_LEN - 1)
+ char *src_copy;
+ size_t src_len;
+ char *ptr = buffer;
+ size_t ptr_size = buffer_size;
+ _Bool append_plus = 0;
+ _Bool append_minus = 0;
+
+ if ((buffer == NULL) || (buffer_size <= strlen ("Minus")) || (src == NULL))
+ return EINVAL;
+
+ src_copy = strdup (src);
+ src_len = strlen(src);
+
+ /* Remove trailing "+" and "-". */
+ if (src_copy[src_len - 1] == '+')
{
- append_status |= 0x4;
- /** we should reserve space for
- * len_str
- */
- reserved += 2;
+ append_plus = 1;
+ src_len--;
+ src_copy[src_len] = 0;
}
- if(append_status & 0x1)
+ else if (src_copy[src_len - 1] == '-')
{
- /** we should reserve space for
- * "Minus"
- */
- reserved += 5;
+ append_minus = 1;
+ src_len--;
+ src_copy[src_len] = 0;
}
- if(append_status & 0x2)
+
+ /* Split at special chars, capitalize first character, append to buffer. */
+ char *dummy = src_copy;
+ char *token;
+ char *save_ptr = NULL;
+ while ((token = strtok_r (dummy, ":_-+", &save_ptr)) != NULL)
{
- /** we should reserve space for
- * "Plus"
- */
- reserved += 4;
+ size_t len;
+
+ dummy = NULL;
+
+ token[0] = toupper ((int) token[0]);
+
+ assert (ptr_size > 1);
+
+ len = strlen (token);
+ if (len >= ptr_size)
+ len = ptr_size - 1;
+
+ assert (len > 0);
+ assert (len < ptr_size);
+
+ sstrncpy (ptr, token, len + 1);
+ ptr += len;
+ ptr_size -= len;
+
+ assert (*ptr == 0);
+ if (ptr_size <= 1)
+ break;
}
- snprintf(dest, DATA_MAX_NAME_LEN - reserved, "%s", tmp);
- offset = strlen(dest);
- switch (append_status)
+
+ /* Append "Plus" or "Minus" if "+" or "-" has been stripped above. */
+ if (append_plus || append_minus)
{
- case 0x1:
- memcpy(dest + offset, "Minus", 5);
- break;
- case 0x2:
- memcpy(dest + offset, "Plus", 5);
- break;
- case 0x4:
- memcpy(dest + offset, len_str, 2);
- break;
- case 0x5:
- memcpy(dest + offset, "Minus", 5);
- memcpy(dest + offset + 5, len_str, 2);
- break;
- case 0x6:
- memcpy(dest + offset, "Plus", 4);
- memcpy(dest + offset + 4, len_str, 2);
- break;
- default:
- break;
+ char const *append = "Plus";
+ if (append_minus)
+ append = "Minus";
+
+ size_t offset = buffer_size - (strlen (append) + 1);
+ if (offset > strlen (buffer))
+ offset = strlen (buffer);
+
+ sstrncpy (buffer + offset, append, buffer_size - offset);
}
+
+ sfree (src_copy);
+ return 0;
+}
+
+static _Bool has_suffix (char const *str, char const *suffix)
+{
+ size_t str_len = strlen (str);
+ size_t suffix_len = strlen (suffix);
+ size_t offset;
+
+ if (suffix_len > str_len)
+ return 0;
+ offset = str_len - suffix_len;
+
+ if (strcmp (str + offset, suffix) == 0)
+ return 1;
+
+ return 0;
+}
+
+/* count_parts returns the number of elements a "foo.bar.baz" style key has. */
+static size_t count_parts (char const *key)
+{
+ char const *ptr;
+ size_t parts_num = 0;
+
+ for (ptr = key; ptr != NULL; ptr = strchr (ptr + 1, '.'))
+ parts_num++;
+
+ return parts_num;
}
/**
* Parse key to remove "type" if this is for schema and initiate compaction
*/
-static int parse_keys(const char *key_str, char *ds_name)
+static int parse_keys (char *buffer, size_t buffer_size, const char *key_str)
{
- char *ptr, *rptr;
- size_t ds_name_len = 0;
- /**
- * allow up to 100 characters before compaction - compact_ds_name will not
- * allow more than DATA_MAX_NAME_LEN chars
- */
- int max_str_len = 100;
- char tmp_ds_name[max_str_len];
- memset(tmp_ds_name, 0, sizeof(tmp_ds_name));
- if(ds_name == NULL || key_str == NULL || key_str[0] == '\0' ||
- ds_name[0] != '\0')
- {
- return -1;
- }
- if((ptr = strchr(key_str, '.')) == NULL
- || (rptr = strrchr(key_str, '.')) == NULL)
+ char tmp[2 * buffer_size];
+
+ if (buffer == NULL || buffer_size == 0 || key_str == NULL || strlen (key_str) == 0)
+ return EINVAL;
+
+ if ((count_parts (key_str) > 2) && has_suffix (key_str, ".type"))
{
- memcpy(tmp_ds_name, key_str, max_str_len - 1);
- goto compact;
- }
+ /* strip ".type" suffix iff the key has more than two parts. */
+ size_t sz = strlen (key_str) - strlen (".type") + 1;
- ds_name_len = (rptr - ptr) > max_str_len ? max_str_len : (rptr - ptr);
- if((ds_name_len == 0) || strncmp(rptr + 1, "type", 4))
- { /** copy whole key **/
- memcpy(tmp_ds_name, key_str, max_str_len - 1);
+ if (sz > sizeof (tmp))
+ sz = sizeof (tmp);
+ sstrncpy (tmp, key_str, sz);
}
else
- {/** more than two keys **/
- memcpy(tmp_ds_name, key_str, ((rptr - key_str) > (max_str_len - 1) ?
- (max_str_len - 1) : (rptr - key_str)));
+ {
+ sstrncpy (tmp, key_str, sizeof (tmp));
}
- compact: compact_ds_name(tmp_ds_name, ds_name);
- return 0;
+ return compact_ds_name (buffer, buffer_size, tmp);
}
/**
((pc_type & PERFCOUNTER_LATENCY) ? DSET_LATENCY : DSET_BYTES);
d->ds_types[d->ds_num] = type;
- if(parse_keys(name, ds_name))
+ if (parse_keys(ds_name, sizeof (ds_name), name))
{
return 1;
}
char ds_name[DATA_MAX_NAME_LEN];
memset(ds_name, 0, sizeof(ds_name));
- if(parse_keys(key, ds_name))
+ if (parse_keys (ds_name, sizeof (ds_name), key))
{
return 1;
}
{
ERROR("ceph plugin: cconn_connect: connect(%d) failed: error %d",
fd, err);
+ close(fd);
return err;
}
err = -errno;
ERROR("ceph plugin: cconn_connect: fcntl(%d, O_NONBLOCK) error %d",
fd, err);
+ close(fd);
return err;
}
io->asok = fd;
diff --git a/src/ceph_test.c b/src/ceph_test.c
--- /dev/null
+++ b/src/ceph_test.c
@@ -0,0 +1,61 @@
+/**
+ * collectd - src/ceph_test.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; 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 collectd.org>
+ **/
+
+#include "ceph.c" /* sic */
+#include "testing.h"
+
+DEF_TEST(parse_keys)
+{
+ struct {
+ char *str;
+ char *want;
+ } cases[] = {
+ {"WBThrottle.bytes_dirtied.description.bytes_wb.description.ios_dirtied.description.ios_wb.type", "WBThrottle.bytesDirtied.description.bytesWb.description.iosDirt"},
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", "Aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"},
+ {"foo:bar", "FooBar"},
+ {"foo:bar+", "FooBarPlus"},
+ {"foo:bar-", "FooBarMinus"},
+ {"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa+", "AaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaPlus"},
+ {"aa.bb.cc.dd.ee.ff", "Aa.bb.cc.dd.ee.ff"},
+ {"aa.bb.cc.dd.ee.ff.type", "Aa.bb.cc.dd.ee.ff"},
+ {"aa.type", "Aa.type"},
+ };
+ size_t i;
+
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char got[DATA_MAX_NAME_LEN];
+
+ CHECK_ZERO (parse_keys (got, sizeof (got), cases[i].str));
+ EXPECT_EQ_STR (cases[i].want, got);
+ }
+
+ return 0;
+}
+
+int main (void)
+{
+ RUN_TEST(parse_keys);
+
+ END_TEST;
+}
+
+/* vim: set sw=2 sts=2 et : */
diff --git a/src/collectd-exec.pod b/src/collectd-exec.pod
index 10f9f618a2ef976f07222cf69e8edfc8d55727a6..0e4cd53af6d7dfeb9997b8971eb576b65b3f83d8 100644 (file)
--- a/src/collectd-exec.pod
+++ b/src/collectd-exec.pod
=head1 DESCRIPTION
-The C<exec plugin> forks of an executable either to receive values or to
+The C<exec plugin> forks off an executable either to receive values or to
dispatch notifications to the outside world. The syntax of the configuration is
explained in L<collectd.conf(5)> but summarized in the above synopsis.
See L<EXEC DATA FORMAT> below for a description of the output format expected
from these programs.
-B<Warning:> If the executable only writes one value and then exits I will be
+B<Warning:> If the executable only writes one value and then exits it will be
executed every I<Interval> seconds. If I<Interval> is short (the default is 10
seconds) this may result in serious system load.
diff --git a/src/collectd-java.pod b/src/collectd-java.pod
index aade08a456b701aff4fdc94f70f1907617de1127..afa7e48a6516c1bd82aef5358d3301cbb5827be6 100644 (file)
--- a/src/collectd-java.pod
+++ b/src/collectd-java.pod
Works like the option of the same name directly beneath the I<MBean> block, but
sets the type instance instead. I<(optional)>
+=item B<PluginName> I<name>
+
+When set, overrides the default setting for the I<plugin> field
+(C<GenericJMX>).
+
=item B<Table> B<true>|B<false>
Set this to true if the returned attribute is a I<composite type>. If set to
diff --git a/src/collectd.conf.in b/src/collectd.conf.in
index 1f4ccf8175a99d44cecfa325429ddb586631e0dc..6a3b580705ff38257bd095dcad02d2c6c8d1ac56 100644 (file)
--- a/src/collectd.conf.in
+++ b/src/collectd.conf.in
#@BUILD_PLUGIN_NGINX_TRUE@LoadPlugin nginx
#@BUILD_PLUGIN_NOTIFY_DESKTOP_TRUE@LoadPlugin notify_desktop
#@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
+#@BUILD_PLUGIN_NOTIFY_NAGIOS_TRUE@LoadPlugin notify_nagios
#@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
#@BUILD_PLUGIN_NUMA_TRUE@LoadPlugin numa
#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
#<Plugin "battery">
# ValuesPercentage false
-# ReportDegraded
+# ReportDegraded false
#</Plugin>
#<Plugin "bind">
# Prefix "collectd"
# StoreRates true
# Retain false
+# CACert "/etc/ssl/ca.crt"
+# CertificateFile "/etc/ssl/client.crt"
+# CertificateKeyFile "/etc/ssl/client.pem"
+# TLSProtocol "tlsv1.2"
+# CipherSuite "ciphers"
# </Publish>
# <Subscribe "name">
# Host "localhost"
# Recipient "email2@domain2.com"
#</Plugin>
+#<Plugin notify_nagios>
+# CommandFile "/usr/local/nagios/var/rw/nagios.cmd"
+#</Plugin>
+
#<Plugin ntpd>
# Host "localhost"
# Port 123
diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod
index 59247da02b8c11b2725b8244706abeaa8e779784..d7d1501656afd20f4ed87d34153c6d0ac4683c2b 100644 (file)
--- a/src/collectd.conf.pod
+++ b/src/collectd.conf.pod
@@ -3347,6 +3347,38 @@ Configures the topic(s) to subscribe to. You can use the single level C<+> and
multi level C<#> wildcards. Defaults to B<collectd/#>, i.e. all topics beneath
the B<collectd> branch.
+=item B<CACert> I<file>
+
+Path to the PEM-encoded CA certificate file. Setting this option enables TLS
+communication with the MQTT broker, and as such, B<Port> should be the TLS-enabled
+port of the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateFile> I<file>
+
+Path to the PEM-encoded certificate file to use as client certificate when
+connecting to the MQTT broker.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<CertificateKeyFile> I<file>
+
+Path to the unencrypted PEM-encoded key file corresponding to B<CertificateFile>.
+A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+
+=item B<TLSProtocol> I<protocol>
+
+If configured, this specifies the string protocol version (e.g. C<tlsv1>,
+C<tlsv1.2>) to use for the TLS connection to the broker. If not set a default
+version is used which depends on the version of OpenSSL the Mosquitto library
+was linked against.
+
+=item B<CipherSuite> I<ciphersuite>
+
+A string describing the ciphers available for use. See L<ciphers(1)> and the
+C<openssl ciphers> utility for more information. If unset, the default ciphers
+will be used.
+
+
=back
=head2 Plugin C<mysql>
=back
+=head2 Plugin C<notify_nagios>
+
+The I<notify_nagios> plugin writes notifications to Nagios' I<command file> as
+a I<passive service check result>.
+
+Available configuration options:
+
+=over 4
+
+=item B<CommandFile> I<Path>
+
+Sets the I<command file> to write to. Defaults to F</usr/local/nagios/var/rw/nagios.cmd>.
+
+=back
+
=head2 Plugin C<ntpd>
=over 4
Timeout 1000
Prefix "collectd/"
Database 1
+ MaxSetSize -1
+ StoreRates true
</Node>
</Plugin>
@@ -7632,7 +7681,7 @@ the timestamp as the score. Retrieving a date range can then be done using the
C<ZRANGEBYSCORE> I<Redis> command. Additionally, all the identifiers of these
I<Sorted Sets> are kept in a I<Set> called C<collectd/values> (or
C<${prefix}/values> if the B<Prefix> option was specified) and can be retrieved
-using the C<SMEMBERS> I<Redis> command. You can specify the database to use
+using the C<SMEMBERS> I<Redis> command. You can specify the database to use
with the B<Database> parameter (default is C<0>). See
L<http://redis.io/commands#sorted_set> and L<http://redis.io/commands#set> for
details.
=item B<Database> I<Index>
-This index selects the redis database to use for writing operations. Defaults to C<0>.
+This index selects the redis database to use for writing operations. Defaults
+to C<0>.
+
+=item B<MaxSetSize> I<Items>
+
+The B<MaxSetSize> option limits the number of items that the I<Sorted Sets> can
+hold. Negative values for I<Items> sets no limit, which is the default behavior.
+
+=item B<StoreRates> B<true>|B<false>
+
+If set to B<true> (the default), convert counter values to rates. If set to
+B<false> counter values are stored as is, i.e. as an increasing integer number.
=back
=item B<AlwaysAppendDS> B<false>|B<true>
-If set the B<true>, append the name of the I<Data Source> (DS) to the
+If set to B<true>, append the name of the I<Data Source> (DS) to the
"service", i.e. the field that, together with the "host" field, uniquely
identifies a metric in I<Riemann>. If set to B<false> (the default), this is
only done when there is more than one DS.
diff --git a/src/csv.c b/src/csv.c
index 15494f450dd60a852be2b948c8356c781194c2e1..7b513e7345199a508fc53531187aac959784c74b 100644 (file)
--- a/src/csv.c
+++ b/src/csv.c
&& (ds->ds[i].type != DS_TYPE_GAUGE)
&& (ds->ds[i].type != DS_TYPE_DERIVE)
&& (ds->ds[i].type != DS_TYPE_ABSOLUTE))
+ {
+ sfree (rates);
return (-1);
+ }
- if (ds->ds[i].type == DS_TYPE_GAUGE)
+ if (ds->ds[i].type == DS_TYPE_GAUGE)
{
status = ssnprintf (buffer + offset, buffer_len - offset,
",%lf", vl->values[i].gauge);
- }
+ }
else if (store_rates != 0)
{
if (rates == NULL)
diff --git a/src/curl_json.c b/src/curl_json.c
index 510d9b621d0b9a32b235337856f455c82eef2b3e..69d45e39b5f5249a07c6a09cb38db7635772f68c 100644 (file)
--- a/src/curl_json.c
+++ b/src/curl_json.c
return (len);
#endif
- if (status != yajl_status_ok)
- {
- unsigned char *msg =
- yajl_get_error(db->yajl, /* verbose = */ 1,
- /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
- ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
- yajl_free_error(db->yajl, msg);
- return (0); /* abort write callback */
- }
-
- return (len);
+ unsigned char *msg = yajl_get_error(db->yajl, /* verbose = */ 1,
+ /* jsonText = */ (unsigned char *) buf, (unsigned int) len);
+ ERROR ("curl_json plugin: yajl_parse failed: %s", msg);
+ yajl_free_error(db->yajl, msg);
+ return (0); /* abort write callback */
} /* }}} size_t cj_curl_callback */
static int cj_get_type (cj_key_t *key)
diff --git a/src/daemon/Makefile.am b/src/daemon/Makefile.am
index 4e383413589b6f9ef43e5a50fa91ed8f6a3bdf0c..3d50029bac73d6ea41a9124c9063e70cfca9f29d 100644 (file)
--- a/src/daemon/Makefile.am
+++ b/src/daemon/Makefile.am
plugin.c plugin.h \
utils_cache.c utils_cache.h \
utils_complain.c utils_complain.h \
+ utils_ignorelist.c utils_ignorelist.h \
utils_llist.c utils_llist.h \
utils_random.c utils_random.h \
utils_tail_match.c utils_tail_match.h \
diff --git a/src/daemon/collectd.c b/src/daemon/collectd.c
index 58325b95be73973b5cd5c596466255d3a325f6a5..fc52933111e79fec0c291d115618d4b57f6032e5 100644 (file)
--- a/src/daemon/collectd.c
+++ b/src/daemon/collectd.c
unsetenv ("NOTIFY_SOCKET");
+#if defined(SOCK_CLOEXEC)
+ fd = socket (AF_UNIX, SOCK_DGRAM|SOCK_CLOEXEC, /* protocol = */ 0);
+#else
fd = socket (AF_UNIX, SOCK_DGRAM, /* protocol = */ 0);
+#endif
if (fd < 0) {
char errbuf[1024];
ERROR ("creating UNIX socket failed: %s",
}
else
{
-#if KERNEL_LINUX
/* Linux abstract namespace socket: specify address as "\0foo", i.e.
* start with a null byte. Since null bytes have no special meaning in
* that case, we have to set su_size correctly to cover only the bytes
su_size = sizeof (sa_family_t) + strlen (notifysocket);
if (su_size > sizeof (su))
su_size = sizeof (su);
-#else
- ERROR ("Systemd socket uses Linux abstract namespace notation (\"%s\"), "
- "but I don't appear to be running on Linux.", notifysocket);
- return 0;
-#endif
}
if (sendto (fd, buffer, strlen (buffer), MSG_NOSIGNAL, (void *) &su, (socklen_t) su_size) < 0)
return 0;
}
+ unsetenv ("NOTIFY_SOCKET");
close(fd);
return 1;
}
diff --git a/src/daemon/common.c b/src/daemon/common.c
index 8f22011ed57c46c94244f8273461fce3fa7af155..dfaa61aa24fc4e49c6617497981b7f108819ef49 100644 (file)
--- a/src/daemon/common.c
+++ b/src/daemon/common.c
#include <sys/types.h>
#include <netdb.h>
+#include <poll.h>
+
#if HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
const char *ptr;
size_t nleft;
ssize_t status;
+ struct pollfd pfd;
ptr = (const char *) buf;
nleft = count;
+
+ /* checking for closed peer connection */
+ pfd.fd = fd;
+ pfd.events = POLLIN | POLLHUP;
+ pfd.revents = 0;
+ if (poll(&pfd, 1, 0) > 0) {
+ char buffer[32];
+ if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
+ // if recv returns zero (even though poll() said there is data to be read),
+ // that means the connection has been closed
+ return -1;
+ }
+ }
while (nleft > 0)
{
diff --git a/src/daemon/meta_data.c b/src/daemon/meta_data.c
index 6ee8446b37639dc38e479db4f6dcd48807cde725..4e46ed53355ff30346a239d3d8bcb3d3c5511e34 100644 (file)
--- a/src/daemon/meta_data.c
+++ b/src/daemon/meta_data.c
if (md == NULL)
return;
- pthread_mutex_destroy(&md->lock);
md_entry_free (md->head);
pthread_mutex_destroy (&md->lock);
free (md);
diff --git a/src/daemon/plugin.c b/src/daemon/plugin.c
index 206c6e21f67ab87a6114e169b50c743d4e7d8699..0919bdfe10a7fd459f79e6789653fecb3e5e2bd2 100644 (file)
--- a/src/daemon/plugin.c
+++ b/src/daemon/plugin.c
{
ERROR ("plugin: register_callback: "
"llentry_create failed.");
- free (key);
+ sfree (key);
destroy_callback (cf);
return (-1);
}
*str = '\0';
strjoin(str, len, keys, n, "', '");
INFO("%s ['%s']", comment, str);
- free(str);
+ sfree (str);
}
- free(keys);
+ sfree (keys);
} /* }}} void log_list_callbacks */
static int create_register_callback (llist_t **list, /* {{{ */
*/
void plugin_set_dir (const char *dir)
{
- if (plugindir != NULL)
- free (plugindir);
+ sfree (plugindir);
if (dir == NULL)
- plugindir = NULL;
- else if ((plugindir = strdup (dir)) == NULL)
{
- char errbuf[1024];
- ERROR ("strdup failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
+ plugindir = NULL;
+ return;
}
+
+ plugindir = strdup (dir);
+ if (plugindir == NULL)
+ ERROR ("plugin_set_dir: strdup(\"%s\") failed", dir);
}
static _Bool plugin_is_loaded (char const *name)
if (cb == NULL) return;
- sfree(cb->name);
- sfree(cb);
+ sfree (cb->name);
+ sfree (cb);
} /* static void plugin_flush_callback_free */
static char *plugin_flush_callback_name (const char *name)
if (cb == NULL)
{
ERROR ("plugin_register_flush: malloc failed.");
- sfree(flush_name);
+ sfree (flush_name);
return (-1);
}
if (cb->name == NULL)
{
ERROR ("plugin_register_flush: strdup failed.");
- sfree(cb);
- sfree(flush_name);
+ sfree (cb);
+ sfree (flush_name);
return (-1);
}
cb->timeout = ctx.flush_timeout;
/* interval = */ ctx.flush_interval,
/* user data = */ &ud);
- sfree(flush_name);
+ sfree (flush_name);
if (status != 0)
{
- sfree(cb->name);
- sfree(cb);
+ sfree (cb->name);
+ sfree (cb);
return status;
}
}
* ds->ds_num);
if (ds_copy->ds == NULL)
{
- free (ds_copy);
+ sfree (ds_copy);
return (-1);
}
if (flush_name != NULL)
{
plugin_unregister_read(flush_name);
- sfree(flush_name);
+ sfree (flush_name);
}
}
write_threads_num = 5;
}
- start_write_threads ((size_t) write_threads_num);
-
if ((list_init == NULL) && (read_heap == NULL))
return;
le = le->next;
}
+ start_write_threads ((size_t) write_threads_num);
+
max_read_interval = global_option_get_time ("MaxReadInterval",
DEFAULT_MAX_READ_INTERVAL);
* don't get confused.. */
if (saved_values != NULL)
{
- free (vl->values);
+ sfree (vl->values);
vl->values = saved_values;
vl->values_len = saved_values_len;
}
* confused.. */
if (saved_values != NULL)
{
- free (vl->values);
+ sfree (vl->values);
vl->values = saved_values;
vl->values_len = saved_values_len;
}
if (this->type == NM_TYPE_STRING)
{
- free ((char *)this->nm_value.nm_string);
+ /* Assign to a temporary variable to work around nm_string's const
+ * modifier. */
+ void *tmp = (void *) this->nm_value.nm_string;
+
+ sfree (tmp);
this->nm_value.nm_string = NULL;
}
sfree (this);
plugin_set_ctx (plugin_thread->ctx);
- free (plugin_thread);
+ sfree (plugin_thread);
return start_routine (plugin_arg);
} /* void *plugin_thread_start */
index f7bf1c016ad894f926003ad179112a6196edd161..b6efa3ad788387528074efc38b258b6ef309b6dd 100644 (file)
--- a/src/daemon/plugin_mock.c
+++ b/src/daemon/plugin_mock.c
kstat_ctl_t *kc = NULL;
#endif /* HAVE_LIBKSTAT */
+char hostname_g[] = "example.com";
+
+int plugin_register_complex_config (const char *type, int (*callback) (oconfig_item_t *))
+{
+ return ENOTSUP;
+}
+
+int plugin_register_init (const char *name, plugin_init_cb callback)
+{
+ return ENOTSUP;
+}
+
+int plugin_register_read (const char *name, int (*callback) (void))
+{
+ return ENOTSUP;
+}
+
+int plugin_register_shutdown (const char *name, int (*callback) (void))
+{
+ return ENOTSUP;
+}
+
+int plugin_dispatch_values (value_list_t const *vl)
+{
+ return ENOTSUP;
+}
+
void plugin_log (int level, char const *format, ...)
{
char buffer[1024];
printf ("plugin_log (%i, \"%s\");\n", level, buffer);
}
+cdtime_t plugin_get_interval (void)
+{
+ return TIME_T_TO_CDTIME_T (10);
+}
+
/* vim: set sw=2 sts=2 et : */
index e251975bac6479e8410d64aa9e16b898e38a8839..58b8b8479128b6a9b25377412e1e9e608070826a 100644 (file)
*value = n->value;
free_node (n);
+ --t->size;
rebalance (t, p);
return (0);
index 2a8244c9f3e6cd1008649091de98b595ebf386f6..6dbafe18a4bcfd3712af89bb3812ab3fc7e833bb 100644 (file)
#include "testing.h"
#include "collectd.h"
#include "utils_avltree.h"
+#include "common.h" /* STATIC_ARRAY_SIZE */
static int compare_total_count = 0;
#define RESET_COUNTS() do { compare_total_count = 0; } while (0)
DEF_TEST(success)
{
+ struct {
+ char *key;
+ char *value;
+ } cases[] = {
+ {"Eeph7chu", "vai1reiV"},
+ {"igh3Paiz", "teegh1Ee"},
+ {"caip6Uu8", "ooteQu8n"},
+ {"Aech6vah", "AijeeT0l"},
+ {"Xah0et2L", "gah8Taep"},
+ {"BocaeB8n", "oGaig8io"},
+ {"thai8AhM", "ohjeFo3f"},
+ {"ohth6ieC", "hoo8ieWo"},
+ {"aej7Woow", "phahuC2s"},
+ {"Hai8ier2", "Yie6eimi"},
+ {"phuXi3Li", "JaiF7ieb"},
+ {"Shaig5ef", "aihi5Zai"},
+ {"voh6Aith", "Oozaeto0"},
+ {"zaiP5kie", "seep5veM"},
+ {"pae7ba7D", "chie8Ojo"},
+ {"Gou2ril3", "ouVoo0ha"},
+ {"lo3Thee3", "ahDu4Zuj"},
+ {"Rah8kohv", "ieShoc7E"},
+ {"ieN5engi", "Aevou1ah"},
+ {"ooTe4OhP", "aingai5Y"},
+ };
+
c_avl_tree_t *t;
- char key_orig[] = "foo";
- char value_orig[] = "bar";
- char *key_ret = NULL;
- char *value_ret = NULL;
+ size_t i;
RESET_COUNTS ();
- t = c_avl_create (compare_callback);
- OK (t != NULL);
+ CHECK_NOT_NULL (t = c_avl_create (compare_callback));
+
+ /* insert */
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *key;
+ char *value;
- OK (c_avl_insert (t, key_orig, value_orig) == 0);
- OK (c_avl_size (t) == 1);
+ CHECK_NOT_NULL (key = strdup (cases[i].key));
+ CHECK_NOT_NULL (value = strdup (cases[i].value));
+
+ CHECK_ZERO (c_avl_insert (t, key, value));
+ EXPECT_EQ_INT ((int) (i + 1), c_avl_size (t));
+ }
/* Key already exists. */
- OK (c_avl_insert (t, "foo", "qux") > 0);
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ EXPECT_EQ_INT (1, c_avl_insert (t, cases[i].key, cases[i].value));
+
+ /* get */
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *value_ret = NULL;
+
+ CHECK_ZERO (c_avl_get (t, cases[i].key, (void *) &value_ret));
+ EXPECT_EQ_STR (cases[i].value, value_ret);
+ }
+
+ /* remove half */
+ for (i = 0; i < STATIC_ARRAY_SIZE (cases) / 2; i++)
+ {
+ char *key = NULL;
+ char *value = NULL;
+
+ int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+ CHECK_ZERO (c_avl_remove (t, cases[i].key, (void *) &key, (void *) &value));
+
+ EXPECT_EQ_STR (cases[i].key, key);
+ EXPECT_EQ_STR (cases[i].value, value);
+
+ free (key);
+ free (value);
+
+ EXPECT_EQ_INT (expected_size, c_avl_size (t));
+ }
+
+ /* pick the other half */
+ for (i = STATIC_ARRAY_SIZE (cases) / 2; i < STATIC_ARRAY_SIZE (cases); i++)
+ {
+ char *key = NULL;
+ char *value = NULL;
+
+ int expected_size = (int) (STATIC_ARRAY_SIZE (cases) - (i + 1));
+
+ EXPECT_EQ_INT (expected_size + 1, c_avl_size (t));
+ EXPECT_EQ_INT (0, c_avl_pick (t, (void *) &key, (void *) &value));
- OK (c_avl_get (t, "foo", (void *) &value_ret) == 0);
- OK (value_ret == &value_orig[0]);
+ free (key);
+ free (value);
- key_ret = value_ret = NULL;
- OK (c_avl_remove (t, "foo", (void *) &key_ret, (void *) &value_ret) == 0);
- OK (key_ret == &key_orig[0]);
- OK (value_ret == &value_orig[0]);
- OK (c_avl_size (t) == 0);
+ EXPECT_EQ_INT (expected_size, c_avl_size (t));
+ }
c_avl_destroy (t);
diff --git a/src/daemon/utils_ignorelist.c b/src/daemon/utils_ignorelist.c
--- /dev/null
@@ -0,0 +1,338 @@
+/**
+ * collectd - src/utils_ignorelist.c
+ * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+ * Copyright (C) 2008 Florian Forster <octo at collectd.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Lubos Stanek <lubek at users.sourceforge.net>
+ * Florian Forster <octo at collectd.org>
+ **/
+/**
+ * ignorelist handles plugin's list of configured collectable
+ * entries with global ignore action
+ **/
+/**
+ * Usage:
+ *
+ * Define plugin's global pointer variable of type ignorelist_t:
+ * ignorelist_t *myconfig_ignore;
+ * If you know the state of the global ignore (IgnoreSelected),
+ * allocate the variable with:
+ * myconfig_ignore = ignorelist_create (YourKnownIgnore);
+ * If you do not know the state of the global ignore,
+ * initialize the global variable and set the ignore flag later:
+ * myconfig_ignore = ignorelist_init ();
+ * Append single entries in your cf_register'ed callback function:
+ * ignorelist_add (myconfig_ignore, newentry);
+ * When you hit the IgnoreSelected config option,
+ * offer it to the list:
+ * ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
+ * That is all for the ignorelist initialization.
+ * Later during read and write (plugin's registered functions) get
+ * the information whether this entry would be collected or not:
+ * if (ignorelist_match (myconfig_ignore, thisentry))
+ * return;
+ **/
+
+#if HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+/*
+ * private prototypes
+ */
+struct ignorelist_item_s
+{
+#if HAVE_REGEX_H
+ regex_t *rmatch; /* regular expression entry identification */
+#endif
+ char *smatch; /* string entry identification */
+ struct ignorelist_item_s *next;
+};
+typedef struct ignorelist_item_s ignorelist_item_t;
+
+struct ignorelist_s
+{
+ int ignore; /* ignore entries */
+ ignorelist_item_t *head; /* pointer to the first entry */
+};
+
+/* *** *** *** ********************************************* *** *** *** */
+/* *** *** *** *** *** *** private functions *** *** *** *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
+
+static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
+{
+ assert ((il != NULL) && (item != NULL));
+
+ item->next = il->head;
+ il->head = item;
+}
+
+#if HAVE_REGEX_H
+static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
+{
+ regex_t *re;
+ ignorelist_item_t *entry;
+ int status;
+
+ re = malloc (sizeof (*re));
+ if (re == NULL)
+ {
+ ERROR ("utils_ignorelist: malloc failed");
+ return (ENOMEM);
+ }
+ memset (re, 0, sizeof (*re));
+
+ status = regcomp (re, re_str, REG_EXTENDED);
+ if (status != 0)
+ {
+ char errbuf[1024] = "";
+ regerror (status, re, errbuf, sizeof (errbuf));
+ ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
+ regfree (re);
+ sfree (re);
+ return (status);
+ }
+
+ entry = malloc (sizeof (*entry));
+ if (entry == NULL)
+ {
+ ERROR ("utils_ignorelist: malloc failed");
+ regfree (re);
+ sfree (re);
+ return (ENOMEM);
+ }
+ memset (entry, 0, sizeof (*entry));
+ entry->rmatch = re;
+
+ ignorelist_append (il, entry);
+ return (0);
+} /* int ignorelist_append_regex */
+#endif
+
+static int ignorelist_append_string(ignorelist_t *il, const char *entry)
+{
+ ignorelist_item_t *new;
+
+ /* create new entry */
+ if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
+ {
+ ERROR ("cannot allocate new entry");
+ return (1);
+ }
+ memset (new, '\0', sizeof(ignorelist_item_t));
+ new->smatch = sstrdup(entry);
+
+ /* append new entry */
+ ignorelist_append (il, new);
+
+ return (0);
+} /* int ignorelist_append_string(ignorelist_t *il, const char *entry) */
+
+#if HAVE_REGEX_H
+/*
+ * check list for entry regex match
+ * return 1 if found
+ */
+static int ignorelist_match_regex (ignorelist_item_t *item, const char *entry)
+{
+ assert ((item != NULL) && (item->rmatch != NULL)
+ && (entry != NULL) && (strlen (entry) > 0));
+
+ /* match regex */
+ if (regexec (item->rmatch, entry, 0, NULL, 0) == 0)
+ return (1);
+
+ return (0);
+} /* int ignorelist_match_regex (ignorelist_item_t *item, const char *entry) */
+#endif
+
+/*
+ * check list for entry string match
+ * return 1 if found
+ */
+static int ignorelist_match_string (ignorelist_item_t *item, const char *entry)
+{
+ assert ((item != NULL) && (item->smatch != NULL)
+ && (entry != NULL) && (strlen (entry) > 0));
+
+ if (strcmp (entry, item->smatch) == 0)
+ return (1);
+
+ return (0);
+} /* int ignorelist_match_string (ignorelist_item_t *item, const char *entry) */
+
+
+/* *** *** *** ******************************************** *** *** *** */
+/* *** *** *** *** *** *** public functions *** *** *** *** *** *** */
+/* *** *** *** ******************************************** *** *** *** */
+
+/*
+ * create the ignorelist_t with known ignore state
+ * return pointer to ignorelist_t
+ */
+ignorelist_t *ignorelist_create (int invert)
+{
+ ignorelist_t *il;
+
+ /* smalloc exits if it failes */
+ il = (ignorelist_t *) smalloc (sizeof (ignorelist_t));
+ memset (il, '\0', sizeof (ignorelist_t));
+
+ /*
+ * ->ignore == 0 => collect
+ * ->ignore == 1 => ignore
+ */
+ il->ignore = invert ? 0 : 1;
+
+ return (il);
+} /* ignorelist_t *ignorelist_create (int ignore) */
+
+/*
+ * free memory used by ignorelist_t
+ */
+void ignorelist_free (ignorelist_t *il)
+{
+ ignorelist_item_t *this;
+ ignorelist_item_t *next;
+
+ if (il == NULL)
+ return;
+
+ for (this = il->head; this != NULL; this = next)
+ {
+ next = this->next;
+#if HAVE_REGEX_H
+ if (this->rmatch != NULL)
+ {
+ regfree (this->rmatch);
+ sfree (this->rmatch);
+ this->rmatch = NULL;
+ }
+#endif
+ if (this->smatch != NULL)
+ {
+ sfree (this->smatch);
+ this->smatch = NULL;
+ }
+ sfree (this);
+ }
+
+ sfree (il);
+ il = NULL;
+} /* void ignorelist_destroy (ignorelist_t *il) */
+
+/*
+ * set ignore state of the ignorelist_t
+ */
+void ignorelist_set_invert (ignorelist_t *il, int invert)
+{
+ if (il == NULL)
+ {
+ DEBUG("ignore call with ignorelist_t == NULL");
+ return;
+ }
+
+ il->ignore = invert ? 0 : 1;
+} /* void ignorelist_set_invert (ignorelist_t *il, int ignore) */
+
+/*
+ * append entry into ignorelist_t
+ * return 0 for success
+ */
+int ignorelist_add (ignorelist_t *il, const char *entry)
+{
+ size_t entry_len;
+
+ if (il == NULL)
+ {
+ DEBUG ("add called with ignorelist_t == NULL");
+ return (1);
+ }
+
+ entry_len = strlen (entry);
+
+ /* append nothing */
+ if (entry_len == 0)
+ {
+ DEBUG("not appending: empty entry");
+ return (1);
+ }
+
+#if HAVE_REGEX_H
+ /* regex string is enclosed in "/.../" */
+ if ((entry_len > 2) && (entry[0] == '/') && entry[entry_len - 1] == '/')
+ {
+ char *entry_copy;
+ size_t entry_copy_size;
+ int status;
+
+ /* We need to copy `entry' since it's const */
+ entry_copy_size = entry_len - 1;
+ entry_copy = smalloc (entry_copy_size);
+ sstrncpy (entry_copy, entry + 1, entry_copy_size);
+
+ status = ignorelist_append_regex(il, entry_copy);
+ sfree (entry_copy);
+ return status;
+ }
+#endif
+
+ return ignorelist_append_string(il, entry);
+} /* int ignorelist_add (ignorelist_t *il, const char *entry) */
+
+/*
+ * check list for entry
+ * return 1 for ignored entry
+ */
+int ignorelist_match (ignorelist_t *il, const char *entry)
+{
+ ignorelist_item_t *traverse;
+
+ /* if no entries, collect all */
+ if ((il == NULL) || (il->head == NULL))
+ return (0);
+
+ if ((entry == NULL) || (strlen (entry) == 0))
+ return (0);
+
+ /* traverse list and check entries */
+ for (traverse = il->head; traverse != NULL; traverse = traverse->next)
+ {
+#if HAVE_REGEX_H
+ if (traverse->rmatch != NULL)
+ {
+ if (ignorelist_match_regex (traverse, entry))
+ return (il->ignore);
+ }
+ else
+#endif
+ {
+ if (ignorelist_match_string (traverse, entry))
+ return (il->ignore);
+ }
+ } /* for traverse */
+
+ return (1 - il->ignore);
+} /* int ignorelist_match (ignorelist_t *il, const char *entry) */
+
diff --git a/src/daemon/utils_ignorelist.h b/src/daemon/utils_ignorelist.h
--- /dev/null
@@ -0,0 +1,70 @@
+/**
+ * collectd - src/utils_ignorelist.h
+ * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * Licence along with this program; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+ * USA.
+ *
+ * Authors:
+ * Lubos Stanek <lubek at users.sourceforge.net>
+ **/
+/**
+ * ignorelist handles plugin's list of configured collectable
+ * entries with global ignore action
+ **/
+
+#ifndef UTILS_IGNORELIST_H
+#define UTILS_IGNORELIST_H 1
+
+#include "collectd.h"
+
+#if HAVE_REGEX_H
+# include <regex.h>
+#endif
+
+/* public prototypes */
+
+struct ignorelist_s;
+typedef struct ignorelist_s ignorelist_t;
+
+/*
+ * create the ignorelist_t with known ignore state
+ * return pointer to ignorelist_t
+ */
+ignorelist_t *ignorelist_create (int invert);
+
+/*
+ * free memory used by ignorelist_t
+ */
+void ignorelist_free (ignorelist_t *il);
+
+/*
+ * set ignore state of the ignorelist_t
+ */
+void ignorelist_set_invert (ignorelist_t *il, int invert);
+
+/*
+ * append entry to ignorelist_t
+ * returns zero on success, non-zero upon failure.
+ */
+int ignorelist_add (ignorelist_t *il, const char *entry);
+
+/*
+ * check list for entry
+ * return 1 for ignored entry
+ */
+int ignorelist_match (ignorelist_t *il, const char *entry);
+
+#endif /* UTILS_IGNORELIST_H */
index 2cc84b5dec4013eb00a720e0132280cafd00aa2a..6566a739bdf8be34b695a3d715dd90b7644e2f23 100644 (file)
--- a/src/daemon/utils_time.h
+++ b/src/daemon/utils_time.h
(tsp)->tv_sec = CDTIME_T_TO_TIME_T (cdt); \
(tsp)->tv_nsec = (long) CDTIME_T_TO_NS ((cdt) & 0x3fffffff); \
} while (0)
-#define TIMESPEC_TO_CDTIME_T(ts) NS_TO_CDTIME_T(1000000000 * (ts)->tv_sec + (ts)->tv_nsec)
+#define TIMESPEC_TO_CDTIME_T(ts) NS_TO_CDTIME_T(1000000000ULL * (ts)->tv_sec + (ts)->tv_nsec)
cdtime_t cdtime (void);
diff --git a/src/fhcount.c b/src/fhcount.c
index 4c409b58d894f20ed8544a2df964b379ced000ed..666dacc09db1b6e876cf5b11e769c37f97f05626 100644 (file)
--- a/src/fhcount.c
+++ b/src/fhcount.c
}
if (fgets(buffer, buffer_len, fp) == NULL) {
ERROR("fhcount: fgets: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ fclose(fp);
return(EXIT_FAILURE);
}
fclose(fp);
diff --git a/src/filecount.c b/src/filecount.c
index 47caf93f264af693e0e011634abbf62345b62908..9ea8af7abe2792ebc7235094cb67f37e75a668e8 100644 (file)
--- a/src/filecount.c
+++ b/src/filecount.c
if (dir->path == NULL)
{
ERROR ("filecount plugin: strdup failed.");
+ sfree (dir);
return (-1);
}
diff --git a/src/irq.c b/src/irq.c
index 6afacf0d0dfbee2ad740a00de6200ff66e289d11..93f3f53bea09b964db1f32109c88faf685465e15 100644 (file)
--- a/src/irq.c
+++ b/src/irq.c
} else {
ERROR ("irq plugin: unable to get CPU count from first line "
"of /proc/interrupts");
+ fclose (fh);
return (-1);
}
diff --git a/src/modbus.c b/src/modbus.c
index cfc6331e293218b4fdfaca1d99eadabae02754fa..d2b0a535ff9a0dd135f05fe2b217145ccc9c0315 100644 (file)
--- a/src/modbus.c
+++ b/src/modbus.c
status = cf_util_get_string_buffer (ci, host->host, sizeof (host->host));
if (status != 0)
+ {
+ sfree (host);
return (status);
+ }
if (host->host[0] == 0)
+ {
+ sfree (host);
return (EINVAL);
+ }
for (i = 0; i < ci->children_num; i++)
{
diff --git a/src/mqtt.c b/src/mqtt.c
index 1b71d423d458109247e095cd8b5ce97de30b0ce4..8bc412c9497213074a738ca7dfa355209c1872d1 100644 (file)
--- a/src/mqtt.c
+++ b/src/mqtt.c
* Authors:
* Marc Falzon <marc at baha dot mu>
* Florian octo Forster <octo at collectd.org>
+ * Jan-Piet Mens <jpmens at gmail.com>
**/
// Reference: http://mosquitto.org/api/files/mosquitto-h.html
#ifndef MQTT_KEEPALIVE
# define MQTT_KEEPALIVE 60
#endif
+#ifndef SSL_VERIFY_PEER
+# define SSL_VERIFY_PEER 1
+#endif
/*
char *username;
char *password;
int qos;
+ char *cacertificatefile;
+ char *certificatefile;
+ char *certificatekeyfile;
+ char *tlsprotocol;
+ char *ciphersuite;
/* For publishing */
char *topic_prefix;
char *payload;
int status;
- if ((msg->payloadlen <= 0)
- || (((uint8_t *) msg->payload)[msg->payloadlen - 1] != 0))
+ if (msg->payloadlen <= 0) {
+ DEBUG ("mqtt plugin: message has empty payload");
return;
+ }
topic = strdup (msg->topic);
name = strip_prefix (topic);
}
vl.values_len = ds->ds_num;
- payload = strdup ((void *) msg->payload);
+ payload = malloc (msg->payloadlen+1);
+ if (payload == NULL)
+ {
+ ERROR ("mqtt plugin: malloc for payload buffer failed.");
+ sfree (vl.values);
+ return;
+ }
+ memmove (payload, msg->payload, msg->payloadlen);
+ payload[msg->payloadlen] = 0;
+
DEBUG ("mqtt plugin: payload = \"%s\"", payload);
status = parse_values (payload, &vl, ds);
if (status != 0)
return (-1);
}
+#if LIBMOSQUITTO_MAJOR != 0
+ if (conf->cacertificatefile) {
+ status = mosquitto_tls_set(conf->mosq, conf->cacertificatefile, NULL,
+ conf->certificatefile, conf->certificatekeyfile, /* pw_callback */NULL);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ status = mosquitto_tls_opts_set(conf->mosq, SSL_VERIFY_PEER, conf->tlsprotocol, conf->ciphersuite);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_opts_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+
+ status = mosquitto_tls_insecure_set(conf->mosq, false);
+ if (status != MOSQ_ERR_SUCCESS) {
+ ERROR ("mqtt plugin: cannot mosquitto_tls_insecure_set: %s", mosquitto_strerror(status));
+ mosquitto_destroy (conf->mosq);
+ conf->mosq = NULL;
+ return (-1);
+ }
+ }
+#endif
+
if (conf->username && conf->password)
{
status = mosquitto_username_pw_set (conf->mosq, conf->username, conf->password);
* StoreRates true
* Retain false
* QoS 0
+ * CACert "ca.pem" Enables TLS if set
+ * CertificateFile "client-cert.pem" optional
+ * CertificateKeyFile "client-key.pem" optional
+ * TLSProtocol "tlsv1.2" optional
* </Publish>
*/
static int mqtt_config_publisher (oconfig_item_t *ci)
cf_util_get_boolean (child, &conf->store_rates);
else if (strcasecmp ("Retain", child->key) == 0)
cf_util_get_boolean (child, &conf->retain);
+ else if (strcasecmp ("CACert", child->key) == 0)
+ cf_util_get_string (child, &conf->cacertificatefile);
+ else if (strcasecmp ("CertificateFile", child->key) == 0)
+ cf_util_get_string (child, &conf->certificatefile);
+ else if (strcasecmp ("CertificateKeyFile", child->key) == 0)
+ cf_util_get_string (child, &conf->certificatekeyfile);
+ else if (strcasecmp ("TLSProtocol", child->key) == 0)
+ cf_util_get_string (child, &conf->tlsprotocol);
+ else if (strcasecmp ("CipherSuite", child->key) == 0)
+ cf_util_get_string (child, &conf->ciphersuite);
else
ERROR ("mqtt plugin: Unknown config option: %s", child->key);
}
* User "guest"
* Password "secret"
* Topic "collectd/#"
- * </Publish>
+ * </Subscribe>
*/
static int mqtt_config_subscriber (oconfig_item_t *ci)
{
ERROR ("mqtt plugin: Unknown config option: %s", child->key);
}
- tmp = realloc (subscribers, sizeof (*subscribers) * subscribers_num);
+ tmp = realloc (subscribers, sizeof (*subscribers) * (subscribers_num + 1) );
if (tmp == NULL)
{
ERROR ("mqtt plugin: realloc failed.");
diff --git a/src/notify_nagios.c b/src/notify_nagios.c
--- /dev/null
+++ b/src/notify_nagios.c
@@ -0,0 +1,170 @@
+/**
+ * collectd - src/notify_nagios.c
+ * Copyright (C) 2015 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ */
+
+#include "collectd.h"
+#include "plugin.h"
+#include "common.h"
+#include "configfile.h"
+
+#define NAGIOS_OK 0
+#define NAGIOS_WARNING 1
+#define NAGIOS_CRITICAL 2
+#define NAGIOS_UNKNOWN 3
+
+#ifndef NAGIOS_COMMAND_FILE
+# define NAGIOS_COMMAND_FILE "/usr/local/nagios/var/rw/nagios.cmd"
+#endif
+
+static char *nagios_command_file;
+
+static int nagios_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp ("CommandFile", child->key) == 0)
+ cf_util_get_string (child, &nagios_command_file);
+ else
+ WARNING ("notify_nagios plugin: Ignoring unknown config option \"%s\".",
+ child->key);
+ }
+
+ return 0;
+} /* }}} nagios_config */
+
+static int nagios_print (char const *buffer) /* {{{ */
+{
+ char const *file = NAGIOS_COMMAND_FILE;
+ int fd;
+ int status;
+ struct flock lock;
+
+ if (nagios_command_file != NULL)
+ file = nagios_command_file;
+
+ fd = open (file, O_WRONLY | O_APPEND);
+ if (fd < 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Opening \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ return status;
+ }
+
+ memset (&lock, 0, sizeof (lock));
+ lock.l_type = F_WRLCK;
+ lock.l_whence = SEEK_END;
+ lock.l_start = 0;
+ lock.l_len = 0; /* to end of file */
+
+ status = fcntl (fd, F_GETLK, &lock);
+ if (status != 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Failed to acquire write lock on \"%s\": %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ status = (int) lseek (fd, 0, SEEK_END);
+ if (status == -1)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Seeking to end of \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ status = (int) swrite (fd, buffer, strlen (buffer));
+ if (status != 0)
+ {
+ char errbuf[1024];
+ status = errno;
+ ERROR ("notify_nagios plugin: Writing to \"%s\" failed: %s",
+ file, sstrerror (status, errbuf, sizeof (errbuf)));
+ close (fd);
+ return status;
+ }
+
+ close (fd);
+ return status;
+} /* }}} int nagios_print */
+
+static int nagios_notify (const notification_t *n, /* {{{ */
+ __attribute__((unused)) user_data_t *user_data)
+{
+ char svc_description[4 * DATA_MAX_NAME_LEN];
+ char buffer[4096];
+ int code;
+ int status;
+
+ status = format_name (svc_description, (int) sizeof (svc_description),
+ /* host */ "", n->plugin, n->plugin_instance, n->type, n->type_instance);
+ if (status != 0)
+ {
+ ERROR ("notify_nagios plugin: Formatting service name failed.");
+ return status;
+ }
+
+ switch (n->severity)
+ {
+ case NOTIF_OKAY:
+ code = NAGIOS_OK;
+ break;
+ case NOTIF_WARNING:
+ code = NAGIOS_WARNING;
+ break;
+ case NOTIF_FAILURE:
+ code = NAGIOS_CRITICAL;
+ break;
+ default:
+ code = NAGIOS_UNKNOWN;
+ break;
+ }
+
+ ssnprintf (buffer, sizeof (buffer),
+ "[%.0f] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
+ CDTIME_T_TO_DOUBLE (n->time), n->host, &svc_description[1], code,
+ n->message);
+
+ return nagios_print (buffer);
+} /* }}} int nagios_notify */
+
+void module_register (void)
+{
+ plugin_register_complex_config ("notify_nagios", nagios_config);
+ plugin_register_notification ("notify_nagios", nagios_notify, NULL);
+} /* void module_register (void) */
+
+/* vim: set sw=2 sts=2 ts=8 et : */
diff --git a/src/perl.c b/src/perl.c
index 0a98684e9e809f30be3eb042abe3a254bb028510..cf09586f71abceeb644cc1fd8d9083867fd6da82 100644 (file)
--- a/src/perl.c
+++ b/src/perl.c
/* the ithread no longer exists */
if (NULL == t)
+ {
+ pthread_mutex_unlock (&perl_threads->mutex);
return;
+ }
c_ithread_destroy (ithread);
diff --git a/src/powerdns.c b/src/powerdns.c
index 1050e7fa40447546c6e9a629b2703d1e4fc84800..0400f3d9748a0d7764f7dda82eb85a6c28e13b2b 100644 (file)
--- a/src/powerdns.c
+++ b/src/powerdns.c
const char* const default_server_fields[] = /* {{{ */
{
- "latency"
+ "latency",
"packetcache-hit",
"packetcache-miss",
"packetcache-size",
diff --git a/src/processes.c b/src/processes.c
index 24dbf49299edfcaa964ce54fd8a5cf6ce7d695fd..4f98c01038a9d8412ebfd55bc4f3ccba5a50f304 100644 (file)
--- a/src/processes.c
+++ b/src/processes.c
ps->io_syscr = myUsage->pr_sysc;
ps->io_syscw = myUsage->pr_sysc;
+ /*
+ * TODO: context switch counters for Solaris
+ */
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
/*
* TODO: Find way of setting BLOCKED and PAGING status
pse.cpu_user_counter = task_absolutetime_info.total_user;
pse.cpu_system_counter = task_absolutetime_info.total_system;
+
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
}
status = task_threads (task_list[task], &thread_list,
pse.io_syscr = -1;
pse.io_syscw = -1;
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (procs[i].ki_comm, have_cmdline ? cmdline : NULL, &pse);
- } /* if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid)) */
- switch (procs[i].ki_stat)
- {
- case SSTOP: stopped++; break;
- case SSLEEP: sleeping++; break;
- case SRUN: running++; break;
- case SIDL: idle++; break;
- case SWAIT: wait++; break;
- case SLOCK: blocked++; break;
- case SZOMB: zombies++; break;
- }
+ switch (procs[i].ki_stat)
+ {
+ case SSTOP: stopped++; break;
+ case SSLEEP: sleeping++; break;
+ case SRUN: running++; break;
+ case SIDL: idle++; break;
+ case SWAIT: wait++; break;
+ case SLOCK: blocked++; break;
+ case SZOMB: zombies++; break;
+ }
+ } /* if ((proc_ptr == NULL) || (proc_ptr->ki_pid != procs[i].ki_pid)) */
}
kvm_close(kd);
pse.io_syscr = -1;
pse.io_syscw = -1;
- pse.cswitch_vol = -1;
+ /* context switch counters not implemented */
+ pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
ps_list_add (procs[i].p_comm, have_cmdline ? cmdline : NULL, &pse);
- } /* if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) */
- switch (procs[i].p_stat)
- {
- case SSTOP: stopped++; break;
- case SSLEEP: sleeping++; break;
- case SRUN: running++; break;
- case SIDL: idle++; break;
- case SONPROC: onproc++; break;
- case SDEAD: dead++; break;
- case SZOMB: zombies++; break;
- }
+ switch (procs[i].p_stat)
+ {
+ case SSTOP: stopped++; break;
+ case SSLEEP: sleeping++; break;
+ case SRUN: running++; break;
+ case SIDL: idle++; break;
+ case SONPROC: onproc++; break;
+ case SDEAD: dead++; break;
+ case SZOMB: zombies++; break;
+ }
+ } /* if ((proc_ptr == NULL) || (proc_ptr->p_pid != procs[i].p_pid)) */
}
kvm_close(kd);
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.cswitch_vol = -1;
+ pse.cswitch_invol = -1;
+
ps_list_add (cmdline, cargs, &pse);
} /* for (i = 0 .. nprocs) */
diff --git a/src/redis.c b/src/redis.c
index 7864ead07c01c1edf079cecfb9c79474470cb277..a40d2cd2b48b9f0880f61f61a2177b6a476e1a22 100644 (file)
--- a/src/redis.c
+++ b/src/redis.c
* Default to a gauge type.
*/
(void)strncpy(rq->type, "gauge", sizeof(rq->type));
- (void)strncpy(rq->instance, rq->query, sizeof(rq->instance));
+ (void)sstrncpy(rq->instance, rq->query, sizeof(rq->instance));
replace_special(rq->instance, sizeof(rq->instance));
for (i = 0; i < ci->children_num; i++) {
diff --git a/src/rrdtool.c b/src/rrdtool.c
index 764d6d65db0d2b545c94f41b8a105cd0cda3e97e..e093f2b27f5395c7ec304044d84fc305af6e0fef 100644 (file)
--- a/src/rrdtool.c
+++ b/src/rrdtool.c
{
rc = malloc (sizeof (*rc));
if (rc == NULL)
+ {
+ pthread_mutex_unlock (&cache_lock);
return (-1);
+ }
rc->values_num = 0;
rc->values = NULL;
rc->first_value = 0;
diff --git a/src/snmp.c b/src/snmp.c
index 265b622506525484f0e23bb0adbb9011e7b24509..9f4714d343bd41216dfa340fd11010f110e77c72 100644 (file)
--- a/src/snmp.c
+++ b/src/snmp.c
status = cf_util_get_string(ci, &hd->name);
if (status != 0)
+ {
+ sfree (hd);
return status;
+ }
hd->sess_handle = NULL;
hd->interval = 0;
tmp_unsigned = (uint32_t) *vl->val.integer;
tmp_signed = (int32_t) *vl->val.integer;
- if ((vl->type == ASN_INTEGER)
- || (vl->type == ASN_GAUGE))
+ if (vl->type == ASN_INTEGER)
prefer_signed = 1;
DEBUG ("snmp plugin: Parsed int32 value is %"PRIu64".", tmp_unsigned);
diff --git a/src/statsd.c b/src/statsd.c
index 9a6da1d34fafafa49f2681149e5d7161176a613e..8047b1a68911e69fda55b0073a90102d997c195e 100644 (file)
--- a/src/statsd.c
+++ b/src/statsd.c
else
values[0].gauge = (gauge_t) c_avl_size (metric->set);
}
- else
- values[0].derive = (derive_t) metric->value;
+ else { /* STATSD_COUNTER */
+ /*
+ * Expand a single value to two metrics:
+ *
+ * - The absolute counter, as a gauge
+ * - A derived rate for this counter
+ */
+ values[0].derive = (derive_t) metric->value;
+ plugin_dispatch_values(&vl);
+
+ sstrncpy(vl.type, "gauge", sizeof (vl.type));
+ values[0].gauge = (gauge_t) metric->value;
+ }
return (plugin_dispatch_values (&vl));
} /* }}} int statsd_metric_submit_unsafe */
while (c_avl_pick (metrics_tree, &key, &value) == 0)
{
sfree (key);
- sfree (value);
+ statsd_metric_free (value);
}
c_avl_destroy (metrics_tree);
metrics_tree = NULL;
diff --git a/src/table.c b/src/table.c
index b0bc95f80bb90c5f999c525d17aa9d94bbc1d8b7..4e34a9ec718ed9e90683981c93eb8a5bbc2c1588 100644 (file)
--- a/src/table.c
+++ b/src/table.c
}
if (i <= tbl->max_colnum) {
- log_err ("Not enough columns in line "
+ log_warn ("Not enough columns in line "
"(expected at least %zu, got %zu).",
tbl->max_colnum + 1, i);
return -1;
while (NULL != fgets (buf, sizeof (buf), fh)) {
if ('\0' != buf[sizeof (buf) - 1]) {
buf[sizeof (buf) - 1] = '\0';
- log_err ("Table %s: Truncated line: %s", tbl->file, buf);
+ log_warn ("Table %s: Truncated line: %s", tbl->file, buf);
}
if (0 != tbl_parse_line (tbl, buf, sizeof (buf))) {
- log_err ("Table %s: Failed to parse line: %s", tbl->file, buf);
+ log_warn ("Table %s: Failed to parse line: %s", tbl->file, buf);
continue;
}
}
diff --git a/src/types.db b/src/types.db
index 2fd59e56885f93d934e9c7f1bb8658d293305a95..5847218aa0fe1cb17a057e98bd596849cc7af4ce 100644 (file)
--- a/src/types.db
+++ b/src/types.db
cache_ratio value:GAUGE:0:100
cache_result value:DERIVE:0:U
cache_size value:GAUGE:0:1125899906842623
+capacity value:GAUGE:0:U
ceph_bytes value:GAUGE:U:U
ceph_latency value:GAUGE:U:U
ceph_rate value:DERIVE:0:U
diff --git a/src/utils_ignorelist.c b/src/utils_ignorelist.c
--- a/src/utils_ignorelist.c
+++ /dev/null
@@ -1,338 +0,0 @@
-/**
- * collectd - src/utils_ignorelist.c
- * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
- * Copyright (C) 2008 Florian Forster <octo at collectd.org>
- *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
- *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Authors:
- * Lubos Stanek <lubek at users.sourceforge.net>
- * Florian Forster <octo at collectd.org>
- **/
-/**
- * ignorelist handles plugin's list of configured collectable
- * entries with global ignore action
- **/
-/**
- * Usage:
- *
- * Define plugin's global pointer variable of type ignorelist_t:
- * ignorelist_t *myconfig_ignore;
- * If you know the state of the global ignore (IgnoreSelected),
- * allocate the variable with:
- * myconfig_ignore = ignorelist_create (YourKnownIgnore);
- * If you do not know the state of the global ignore,
- * initialize the global variable and set the ignore flag later:
- * myconfig_ignore = ignorelist_init ();
- * Append single entries in your cf_register'ed callback function:
- * ignorelist_add (myconfig_ignore, newentry);
- * When you hit the IgnoreSelected config option,
- * offer it to the list:
- * ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
- * That is all for the ignorelist initialization.
- * Later during read and write (plugin's registered functions) get
- * the information whether this entry would be collected or not:
- * if (ignorelist_match (myconfig_ignore, thisentry))
- * return;
- **/
-
-#if HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include "common.h"
-#include "plugin.h"
-#include "utils_ignorelist.h"
-
-/*
- * private prototypes
- */
-struct ignorelist_item_s
-{
-#if HAVE_REGEX_H
- regex_t *rmatch; /* regular expression entry identification */
-#endif
- char *smatch; /* string entry identification */
- struct ignorelist_item_s *next;
-};
-typedef struct ignorelist_item_s ignorelist_item_t;
-
-struct ignorelist_s
-{
- int ignore; /* ignore entries */
- ignorelist_item_t *head; /* pointer to the first entry */
-};
-
-/* *** *** *** ********************************************* *** *** *** */
-/* *** *** *** *** *** *** private functions *** *** *** *** *** *** */
-/* *** *** *** ********************************************* *** *** *** */
-
-static inline void ignorelist_append (ignorelist_t *il, ignorelist_item_t *item)
-{
- assert ((il != NULL) && (item != NULL));
-
- item->next = il->head;
- il->head = item;
-}
-
-#if HAVE_REGEX_H
-static int ignorelist_append_regex(ignorelist_t *il, const char *re_str)
-{
- regex_t *re;
- ignorelist_item_t *entry;
- int status;
-
- re = malloc (sizeof (*re));
- if (re == NULL)
- {
- ERROR ("utils_ignorelist: malloc failed");
- return (ENOMEM);
- }
- memset (re, 0, sizeof (*re));
-
- status = regcomp (re, re_str, REG_EXTENDED);
- if (status != 0)
- {
- char errbuf[1024] = "";
- regerror (status, re, errbuf, sizeof (errbuf));
- ERROR ("utils_ignorelist: regcomp failed: %s", errbuf);
- regfree (re);
- sfree (re);
- return (status);
- }
-
- entry = malloc (sizeof (*entry));
- if (entry == NULL)
- {
- ERROR ("utils_ignorelist: malloc failed");
- regfree (re);
- sfree (re);
- return (ENOMEM);
- }
- memset (entry, 0, sizeof (*entry));
- entry->rmatch = re;
-
- ignorelist_append (il, entry);
- return (0);
-} /* int ignorelist_append_regex */
-#endif
-
-static int ignorelist_append_string(ignorelist_t *il, const char *entry)
-{
- ignorelist_item_t *new;
-
- /* create new entry */
- if ((new = malloc(sizeof(ignorelist_item_t))) == NULL )
- {
- ERROR ("cannot allocate new entry");
- return (1);
- }
- memset (new, '\0', sizeof(ignorelist_item_t));
- new->smatch = sstrdup(entry);
-
- /* append new entry */
- ignorelist_append (il, new);
-
- return (0);
-} /* int ignorelist_append_string(ignorelist_t *il, const char *entry) */
-
-#if HAVE_REGEX_H
-/*
- * check list for entry regex match
- * return 1 if found
- */
-static int ignorelist_match_regex (ignorelist_item_t *item, const char *entry)
-{
- assert ((item != NULL) && (item->rmatch != NULL)
- && (entry != NULL) && (strlen (entry) > 0));
-
- /* match regex */
- if (regexec (item->rmatch, entry, 0, NULL, 0) == 0)
- return (1);
-
- return (0);
-} /* int ignorelist_match_regex (ignorelist_item_t *item, const char *entry) */
-#endif
-
-/*
- * check list for entry string match
- * return 1 if found
- */
-static int ignorelist_match_string (ignorelist_item_t *item, const char *entry)
-{
- assert ((item != NULL) && (item->smatch != NULL)
- && (entry != NULL) && (strlen (entry) > 0));
-
- if (strcmp (entry, item->smatch) == 0)
- return (1);
-
- return (0);
-} /* int ignorelist_match_string (ignorelist_item_t *item, const char *entry) */
-
-
-/* *** *** *** ******************************************** *** *** *** */
-/* *** *** *** *** *** *** public functions *** *** *** *** *** *** */
-/* *** *** *** ******************************************** *** *** *** */
-
-/*
- * create the ignorelist_t with known ignore state
- * return pointer to ignorelist_t
- */
-ignorelist_t *ignorelist_create (int invert)
-{
- ignorelist_t *il;
-
- /* smalloc exits if it failes */
- il = (ignorelist_t *) smalloc (sizeof (ignorelist_t));
- memset (il, '\0', sizeof (ignorelist_t));
-
- /*
- * ->ignore == 0 => collect
- * ->ignore == 1 => ignore
- */
- il->ignore = invert ? 0 : 1;
-
- return (il);
-} /* ignorelist_t *ignorelist_create (int ignore) */
-
-/*
- * free memory used by ignorelist_t
- */
-void ignorelist_free (ignorelist_t *il)
-{
- ignorelist_item_t *this;
- ignorelist_item_t *next;
-
- if (il == NULL)
- return;
-
- for (this = il->head; this != NULL; this = next)
- {
- next = this->next;
-#if HAVE_REGEX_H
- if (this->rmatch != NULL)
- {
- regfree (this->rmatch);
- sfree (this->rmatch);
- this->rmatch = NULL;
- }
-#endif
- if (this->smatch != NULL)
- {
- sfree (this->smatch);
- this->smatch = NULL;
- }
- sfree (this);
- }
-
- sfree (il);
- il = NULL;
-} /* void ignorelist_destroy (ignorelist_t *il) */
-
-/*
- * set ignore state of the ignorelist_t
- */
-void ignorelist_set_invert (ignorelist_t *il, int invert)
-{
- if (il == NULL)
- {
- DEBUG("ignore call with ignorelist_t == NULL");
- return;
- }
-
- il->ignore = invert ? 0 : 1;
-} /* void ignorelist_set_invert (ignorelist_t *il, int ignore) */
-
-/*
- * append entry into ignorelist_t
- * return 0 for success
- */
-int ignorelist_add (ignorelist_t *il, const char *entry)
-{
- size_t entry_len;
-
- if (il == NULL)
- {
- DEBUG ("add called with ignorelist_t == NULL");
- return (1);
- }
-
- entry_len = strlen (entry);
-
- /* append nothing */
- if (entry_len == 0)
- {
- DEBUG("not appending: empty entry");
- return (1);
- }
-
-#if HAVE_REGEX_H
- /* regex string is enclosed in "/.../" */
- if ((entry_len > 2) && (entry[0] == '/') && entry[entry_len - 1] == '/')
- {
- char *entry_copy;
- size_t entry_copy_size;
- int status;
-
- /* We need to copy `entry' since it's const */
- entry_copy_size = entry_len - 1;
- entry_copy = smalloc (entry_copy_size);
- sstrncpy (entry_copy, entry + 1, entry_copy_size);
-
- status = ignorelist_append_regex(il, entry_copy);
- sfree (entry_copy);
- return status;
- }
-#endif
-
- return ignorelist_append_string(il, entry);
-} /* int ignorelist_add (ignorelist_t *il, const char *entry) */
-
-/*
- * check list for entry
- * return 1 for ignored entry
- */
-int ignorelist_match (ignorelist_t *il, const char *entry)
-{
- ignorelist_item_t *traverse;
-
- /* if no entries, collect all */
- if ((il == NULL) || (il->head == NULL))
- return (0);
-
- if ((entry == NULL) || (strlen (entry) == 0))
- return (0);
-
- /* traverse list and check entries */
- for (traverse = il->head; traverse != NULL; traverse = traverse->next)
- {
-#if HAVE_REGEX_H
- if (traverse->rmatch != NULL)
- {
- if (ignorelist_match_regex (traverse, entry))
- return (il->ignore);
- }
- else
-#endif
- {
- if (ignorelist_match_string (traverse, entry))
- return (il->ignore);
- }
- } /* for traverse */
-
- return (1 - il->ignore);
-} /* int ignorelist_match (ignorelist_t *il, const char *entry) */
-
diff --git a/src/utils_ignorelist.h b/src/utils_ignorelist.h
--- a/src/utils_ignorelist.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/**
- * collectd - src/utils_ignorelist.h
- * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
- *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public
- * Licence along with this program; if not, write to the Free
- * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
- * USA.
- *
- * Authors:
- * Lubos Stanek <lubek at users.sourceforge.net>
- **/
-/**
- * ignorelist handles plugin's list of configured collectable
- * entries with global ignore action
- **/
-
-#ifndef UTILS_IGNORELIST_H
-#define UTILS_IGNORELIST_H 1
-
-#include "collectd.h"
-
-#if HAVE_REGEX_H
-# include <regex.h>
-#endif
-
-/* public prototypes */
-
-struct ignorelist_s;
-typedef struct ignorelist_s ignorelist_t;
-
-/*
- * create the ignorelist_t with known ignore state
- * return pointer to ignorelist_t
- */
-ignorelist_t *ignorelist_create (int invert);
-
-/*
- * free memory used by ignorelist_t
- */
-void ignorelist_free (ignorelist_t *il);
-
-/*
- * set ignore state of the ignorelist_t
- */
-void ignorelist_set_invert (ignorelist_t *il, int invert);
-
-/*
- * append entry to ignorelist_t
- * returns zero on success, non-zero upon failure.
- */
-int ignorelist_add (ignorelist_t *il, const char *entry);
-
-/*
- * check list for entry
- * return 1 for ignored entry
- */
-int ignorelist_match (ignorelist_t *il, const char *entry);
-
-#endif /* UTILS_IGNORELIST_H */
diff --git a/src/utils_mount.c b/src/utils_mount.c
index b63a81ad29b44fe13c113ca8843a7abb701bcfbf..afeb39e1162af515ddac44dfda578b3a76c2cdb4 100644 (file)
--- a/src/utils_mount.c
+++ b/src/utils_mount.c
#warn "This version of `getmntent' hat not yet been implemented!"
/* #endif HAVE_SEQ_GETMNTENT */
+#elif HAVE_GETMNTENT_R
+static cu_mount_t *cu_mount_getmntent (void)
+{
+ FILE *fp;
+ struct mntent me;
+ char mntbuf[1024];
+
+ cu_mount_t *first = NULL;
+ cu_mount_t *last = NULL;
+ cu_mount_t *new = NULL;
+
+ DEBUG ("utils_mount: (void); COLLECTD_MNTTAB = %s", COLLECTD_MNTTAB);
+
+ if ((fp = setmntent (COLLECTD_MNTTAB, "r")) == NULL)
+ {
+ char errbuf[1024];
+ ERROR ("setmntent (%s): %s", COLLECTD_MNTTAB,
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ return (NULL);
+ }
+
+ while (getmntent_r (fp, &me, mntbuf, sizeof (mntbuf) ))
+ {
+ if ((new = malloc (sizeof (cu_mount_t))) == NULL)
+ break;
+ memset (new, '\0', sizeof (cu_mount_t));
+
+ /* Copy values from `struct mntent *' */
+ new->dir = sstrdup (me.mnt_dir);
+ new->spec_device = sstrdup (me.mnt_fsname);
+ new->type = sstrdup (me.mnt_type);
+ new->options = sstrdup (me.mnt_opts);
+ new->device = get_device_name (new->options);
+ new->next = NULL;
+
+ DEBUG ("utils_mount: new = {dir = %s, spec_device = %s, type = %s, options = %s, device = %s}",
+ new->dir, new->spec_device, new->type, new->options, new->device);
+
+ /* Append to list */
+ if (first == NULL)
+ {
+ first = new;
+ last = new;
+ }
+ else
+ {
+ last->next = new;
+ last = new;
+ }
+ }
+
+ endmntent (fp);
+
+ DEBUG ("utils_mount: return (0x%p)", (void *) first);
+
+ return (first);
+} /* HAVE_GETMNTENT_R */
+
#elif HAVE_ONE_GETMNTENT
static cu_mount_t *cu_mount_getmntent (void)
{
diff --git a/src/write_kafka.c b/src/write_kafka.c
index 775e2e0934f55613d69e5521a3829a495a8a8c4a..a5977aba786770e1e29489b9590a26ed21561c0c 100644 (file)
--- a/src/write_kafka.c
+++ b/src/write_kafka.c
#define KAFKA_FORMAT_JSON 0
#define KAFKA_FORMAT_COMMAND 1
#define KAFKA_FORMAT_GRAPHITE 2
- uint8_t format;
+ uint8_t format;
unsigned int graphite_flags;
_Bool store_rates;
rd_kafka_topic_conf_t *conf;
rd_kafka_conf_t *kafka_conf;
rd_kafka_t *kafka;
int has_key;
- uint32_t key;
+ uint32_t key;
char *prefix;
char *postfix;
char escape_char;
char *topic_name;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
static int kafka_handle(struct kafka_topic_context *);
{
uint32_t key = *((uint32_t *)keydata );
uint32_t target = key % partition_cnt;
- int32_t i = partition_cnt;
+ int32_t i = partition_cnt;
while (--i > 0 && !rd_kafka_topic_partition_available(rkt, target)) {
target = (target + 1) % partition_cnt;
if ((ctx->kafka = rd_kafka_new(RD_KAFKA_PRODUCER, conf,
errbuf, sizeof(errbuf))) == NULL) {
- ERROR("write_kafka plugin: cannot create kafka handle.");
- return 1;
+ ERROR("write_kafka plugin: cannot create kafka handle.");
+ return 1;
}
- rd_kafka_conf_destroy(ctx->kafka_conf);
- ctx->kafka_conf = NULL;
+ rd_kafka_conf_destroy(ctx->kafka_conf);
+ ctx->kafka_conf = NULL;
- INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
+ INFO ("write_kafka plugin: created KAFKA handle : %s", rd_kafka_name(ctx->kafka));
#ifdef HAVE_LIBRDKAFKA_LOGGER
- rd_kafka_set_logger(ctx->kafka, kafka_log);
+ rd_kafka_set_logger(ctx->kafka, kafka_log);
#endif
}
if (ctx->topic == NULL ) {
- if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
+ if ((topic_conf = rd_kafka_topic_conf_dup(ctx->conf)) == NULL) {
ERROR("write_kafka plugin: cannot duplicate kafka topic config");
return 1;
- }
+ }
- if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
- topic_conf)) == NULL) {
- ERROR("write_kafka plugin: cannot create topic : %s\n",
- rd_kafka_err2str(rd_kafka_errno2err(errno)));
- return errno;
- }
+ if ((ctx->topic = rd_kafka_topic_new(ctx->kafka, ctx->topic_name,
+ topic_conf)) == NULL) {
+ ERROR("write_kafka plugin: cannot create topic : %s\n",
+ rd_kafka_err2str(rd_kafka_errno2err(errno)));
+ return errno;
+ }
- rd_kafka_topic_conf_destroy(ctx->conf);
- ctx->conf = NULL;
+ rd_kafka_topic_conf_destroy(ctx->conf);
+ ctx->conf = NULL;
- INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
+ INFO ("write_kafka plugin: handle created for topic : %s", rd_kafka_topic_name(ctx->topic));
}
return(0);
} /* }}} int kafka_handle */
static int kafka_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl,
- user_data_t *ud)
+ const value_list_t *vl,
+ user_data_t *ud)
{
- int status = 0;
- uint32_t key;
- char buffer[8192];
- size_t bfree = sizeof(buffer);
- size_t bfill = 0;
- size_t blen = 0;
- struct kafka_topic_context *ctx = ud->data;
+ int status = 0;
+ uint32_t key;
+ char buffer[8192];
+ size_t bfree = sizeof(buffer);
+ size_t bfill = 0;
+ size_t blen = 0;
+ struct kafka_topic_context *ctx = ud->data;
if ((ds == NULL) || (vl == NULL) || (ctx == NULL))
return EINVAL;
blen = strlen(buffer);
break;
case KAFKA_FORMAT_JSON:
-
format_json_initialize(buffer, &bfill, &bfree);
format_json_value_list(buffer, &bfill, &bfree, ds, vl,
ctx->store_rates);
RD_KAFKA_MSG_F_COPY, buffer, blen,
&key, sizeof(key), NULL);
- return status;
+ return status;
} /* }}} int kafka_write */
static void kafka_topic_context_free(void *p) /* {{{ */
{
- struct kafka_topic_context *ctx = p;
+ struct kafka_topic_context *ctx = p;
- if (ctx == NULL)
- return;
+ if (ctx == NULL)
+ return;
if (ctx->topic_name != NULL)
sfree(ctx->topic_name);
@@ -246,13 +245,13 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
char callback_name[DATA_MAX_NAME_LEN];
char errbuf[1024];
user_data_t ud;
- oconfig_item_t *child;
+ oconfig_item_t *child;
rd_kafka_conf_res_t ret;
- if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
- ERROR ("write_kafka plugin: calloc failed.");
+ if ((tctx = calloc(1, sizeof (*tctx))) == NULL) {
+ ERROR ("write_kafka plugin: calloc failed.");
return;
- }
+ }
tctx->escape_char = '.';
tctx->store_rates = 1;
@@ -290,33 +289,33 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
goto errout;
}
- for (i = 0; i < ci->children_num; i++) {
- /*
- * The code here could be simplified but makes room
- * for easy adding of new options later on.
- */
- child = &ci->children[i];
- status = 0;
-
- if (strcasecmp ("Property", child->key) == 0) {
- if (child->values_num != 2) {
- WARNING("kafka properties need both a key and a value.");
+ for (i = 0; i < ci->children_num; i++) {
+ /*
+ * The code here could be simplified but makes room
+ * for easy adding of new options later on.
+ */
+ child = &ci->children[i];
+ status = 0;
+
+ if (strcasecmp ("Property", child->key) == 0) {
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
goto errout;
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("kafka properties needs string arguments.");
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
goto errout;
- }
+ }
key = child->values[0].value.string;
val = child->values[1].value.string;
ret = rd_kafka_topic_conf_set(tctx->conf,key, val,
errbuf, sizeof(errbuf));
if (ret != RD_KAFKA_CONF_OK) {
- WARNING("cannot set kafka topic property %s to %s: %s.",
+ WARNING("cannot set kafka topic property %s to %s: %s.",
key, val, errbuf);
goto errout;
- }
+ }
} else if (strcasecmp ("Key", child->key) == 0) {
char *tmp_buf = NULL;
@@ -397,11 +396,11 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
ud.data = tctx;
ud.free_func = kafka_topic_context_free;
- status = plugin_register_write (callback_name, kafka_write, &ud);
- if (status != 0) {
- WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
- "failed with status %i.",
- callback_name, status);
+ status = plugin_register_write (callback_name, kafka_write, &ud);
+ if (status != 0) {
+ WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
+ "failed with status %i.",
+ callback_name, status);
goto errout;
}
@@ -414,14 +413,14 @@ static void kafka_config_topic(rd_kafka_conf_t *conf, oconfig_item_t *ci) /* {{{
if (tctx->conf != NULL)
rd_kafka_topic_conf_destroy(tctx->conf);
if (tctx->kafka_conf != NULL)
- rd_kafka_conf_destroy(tctx->kafka_conf);
+ rd_kafka_conf_destroy(tctx->kafka_conf);
sfree(tctx);
} /* }}} int kafka_config_topic */
static int kafka_config(oconfig_item_t *ci) /* {{{ */
{
- int i;
- oconfig_item_t *child;
+ int i;
+ oconfig_item_t *child;
rd_kafka_conf_t *conf;
rd_kafka_conf_res_t ret;
char errbuf[1024];
WARNING("cannot allocate kafka configuration.");
return -1;
}
- for (i = 0; i < ci->children_num; i++) {
- child = &ci->children[i];
+ for (i = 0; i < ci->children_num; i++) {
+ child = &ci->children[i];
- if (strcasecmp("Topic", child->key) == 0) {
- kafka_config_topic (conf, child);
- } else if (strcasecmp(child->key, "Property") == 0) {
- char *key = NULL;
- char *val = NULL;
+ if (strcasecmp("Topic", child->key) == 0) {
+ kafka_config_topic (conf, child);
+ } else if (strcasecmp(child->key, "Property") == 0) {
+ char *key = NULL;
+ char *val = NULL;
- if (child->values_num != 2) {
- WARNING("kafka properties need both a key and a value.");
+ if (child->values_num != 2) {
+ WARNING("kafka properties need both a key and a value.");
goto errout;
- }
- if (child->values[0].type != OCONFIG_TYPE_STRING ||
- child->values[1].type != OCONFIG_TYPE_STRING) {
- WARNING("kafka properties needs string arguments.");
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("kafka properties needs string arguments.");
goto errout;
- }
- if ((key = strdup(child->values[0].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute key.");
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
goto errout;
- }
- if ((val = strdup(child->values[1].value.string)) == NULL) {
- WARNING("cannot allocate memory for attribute value.");
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
goto errout;
- }
+ }
ret = rd_kafka_conf_set(conf, key, val, errbuf, sizeof(errbuf));
if (ret != RD_KAFKA_CONF_OK) {
WARNING("cannot set kafka property %s to %s: %s",
key, val, errbuf);
goto errout;
}
- sfree(key);
- sfree(val);
- } else {
- WARNING ("write_kafka plugin: Ignoring unknown "
- "configuration option \"%s\" at top level.",
- child->key);
- }
- }
+ sfree(key);
+ sfree(val);
+ } else {
+ WARNING ("write_kafka plugin: Ignoring unknown "
+ "configuration option \"%s\" at top level.",
+ child->key);
+ }
+ }
if (conf != NULL)
rd_kafka_conf_destroy(conf);
- return (0);
+ return (0);
errout:
if (conf != NULL)
rd_kafka_conf_destroy(conf);
void module_register(void)
{
- plugin_register_complex_config ("write_kafka", kafka_config);
+ plugin_register_complex_config ("write_kafka", kafka_config);
}
-/* vim: set sw=8 sts=8 ts=8 noet : */
diff --git a/src/write_redis.c b/src/write_redis.c
index 7ba476c92fa2164322c4d3ad5ba73b64ea67e322..4bfcc73d2b5b92fa61bd37e8855a6b2d2657aad9 100644 (file)
--- a/src/write_redis.c
+++ b/src/write_redis.c
struct timeval timeout;
char *prefix;
int database;
+ int max_set_size;
+ _Bool store_rates;
redisContext *conn;
pthread_mutex_t lock;
char *value_ptr;
int status;
redisReply *rr;
- int i;
status = FORMAT_VL (ident, sizeof (ident), vl);
if (status != 0)
memset (value, 0, sizeof (value));
value_size = sizeof (value);
value_ptr = &value[0];
-
-#define APPEND(...) do { \
- status = snprintf (value_ptr, value_size, __VA_ARGS__); \
- if (((size_t) status) > value_size) \
- { \
- value_ptr += value_size; \
- value_size = 0; \
- } \
- else \
- { \
- value_ptr += status; \
- value_size -= status; \
- } \
-} while (0)
-
- APPEND ("%s:", time);
-
- for (i = 0; i < ds->ds_num; i++)
- {
- if (ds->ds[i].type == DS_TYPE_COUNTER)
- APPEND ("%llu", vl->values[i].counter);
- else if (ds->ds[i].type == DS_TYPE_GAUGE)
- APPEND (GAUGE_FORMAT, vl->values[i].gauge);
- else if (ds->ds[i].type == DS_TYPE_DERIVE)
- APPEND ("%"PRIi64, vl->values[i].derive);
- else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
- APPEND ("%"PRIu64, vl->values[i].absolute);
- else
- assert (23 == 42);
- }
-
-#undef APPEND
-
- status = format_values (value_ptr, value_size, ds, vl, /* store rates = */ 0);
- pthread_mutex_lock (&node->lock);
+ status = format_values (value_ptr, value_size, ds, vl, node->store_rates);
if (status != 0)
return (status);
+ pthread_mutex_lock (&node->lock);
+
if (node->conn == NULL)
{
node->conn = redisConnectWithTimeout ((char *)node->host, node->port, node->timeout);
pthread_mutex_unlock (&node->lock);
return (-1);
}
-
+
rr = redisCommand(node->conn, "SELECT %d", node->database);
if (rr == NULL)
WARNING("SELECT command error. database:%d message:%s", node->database, node->conn->errstr);
else
freeReplyObject (rr);
+ if (node->max_set_size >= 0)
+ {
+ rr = redisCommand (node->conn, "ZREMRANGEBYRANK %s %d %d", key, 0, (-1 * node->max_set_size) - 1);
+ if (rr == NULL)
+ WARNING("ZREMRANGEBYRANK command error. key:%s message:%s", key, node->conn->errstr);
+ else
+ freeReplyObject (rr);
+ }
+
/* TODO(octo): This is more overhead than necessary. Use the cache and
* metadata to determine if it is a new metric and call SADD only once for
* each metric. */
node->conn = NULL;
node->prefix = NULL;
node->database = 0;
+ node->max_set_size = -1;
+ node->store_rates = 1;
pthread_mutex_init (&node->lock, /* attr = */ NULL);
status = cf_util_get_string_buffer (ci, node->name, sizeof (node->name));
else if (strcasecmp ("Database", child->key) == 0) {
status = cf_util_get_int (child, &node->database);
}
+ else if (strcasecmp ("MaxSetSize", child->key) == 0) {
+ status = cf_util_get_int (child, &node->max_set_size);
+ }
+ else if (strcasecmp ("StoreRates", child->key) == 0) {
+ status = cf_util_get_boolean (child, &node->store_rates);
+ }
else
WARNING ("write_redis plugin: Ignoring unknown config option \"%s\".",
child->key);
diff --git a/version-gen.sh b/version-gen.sh
index b09be8e78227f350edbe8fc6bf96634f67a0a057..493a6ebfb26c71580c87c2d62a631c6af4228ea4 100755 (executable)
--- a/version-gen.sh
+++ b/version-gen.sh
DEFAULT_VERSION="5.5.0.git"
-VERSION="`git describe 2> /dev/null | grep collectd | sed -e 's/^collectd-//'`"
+if [ -d .git ]; then
+ VERSION="`git describe --dirty=+ --abbrev=7 2> /dev/null | grep collectd | sed -e 's/^collectd-//' -e 's/-/./g'`"
+fi
if test -z "$VERSION"; then
VERSION="$DEFAULT_VERSION"
fi
-VERSION="`echo \"$VERSION\" | sed -e 's/-/./g'`"
-
printf "%s" "$VERSION"