-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
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
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")
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
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
%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
check_PROGRAMS += test_utils_latency
TESTS += test_utils_latency
test_utils_latency_SOURCES = utils_latency_test.c testing.h
-test_utils_latency_LDADD = liblatency.la daemon/libcommon.la daemon/libplugin_mock.la -lm
+test_utils_latency_LDADD = liblatency.la daemon/libplugin_mock.la -lm
noinst_LTLIBRARIES += liblookup.la
liblookup_la_SOURCES = utils_vl_lookup.c utils_vl_lookup.h
check_PROGRAMS += test_utils_vl_lookup
TESTS += test_utils_vl_lookup
test_utils_vl_lookup_SOURCES = utils_vl_lookup_test.c testing.h
-test_utils_vl_lookup_LDADD = liblookup.la daemon/libcommon.la daemon/libplugin_mock.la
+test_utils_vl_lookup_LDADD = liblookup.la daemon/libplugin_mock.la
if BUILD_WITH_LIBKSTAT
test_utils_vl_lookup_LDADD += -lkstat
endif
check_PROGRAMS += test_utils_mount
TESTS += test_utils_mount
test_utils_mount_SOURCES = utils_mount_test.c testing.h
-test_utils_mount_LDADD = libmount.la daemon/libcommon.la daemon/libplugin_mock.la
+test_utils_mount_LDADD = libmount.la daemon/libplugin_mock.la
if BUILD_WITH_LIBKSTAT
test_utils_mount_LDADD += -lkstat
endif
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
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
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:
if (tmp->name == NULL)
{
ERROR ("bind plugin: strdup failed.");
- free (tmp);
+ sfree (views);
return (-1);
}
/**
* 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;
--- /dev/null
+/**
+ * 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 : */
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
#@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
# Recipient "email2@domain2.com"
#</Plugin>
+#<Plugin notify_nagios>
+# CommandFile "/usr/local/nagios/var/rw/nagios.cmd"
+#</Plugin>
+
#<Plugin ntpd>
# Host "localhost"
# Port 123
=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
&& (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)
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)
libmetadata_la_SOURCES = meta_data.c meta_data.h
-libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c utils_time_mock.c
-libplugin_mock_la_LIBADD = $(COMMON_LIBS)
+libplugin_mock_la_SOURCES = plugin_mock.c utils_cache_mock.c \
+ utils_time.c utils_time.h
+libplugin_mock_la_CPPFLAGS = $(AM_CPPFLAGS) -DMOCK_TIME
+libplugin_mock_la_LIBADD = $(COMMON_LIBS) libcommon.la
collectd_SOURCES = collectd.c collectd.h \
configfile.c configfile.h \
TESTS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
test_common_SOURCES = common_test.c ../testing.h
-test_common_LDADD = libcommon.la libplugin_mock.la
+test_common_LDADD = libplugin_mock.la
test_meta_data_SOURCES = meta_data_test.c ../testing.h
test_meta_data_LDADD = libmetadata.la libplugin_mock.la
test_utils_subst_SOURCES = utils_subst_test.c ../testing.h \
utils_subst.c utils_subst.h
-test_utils_subst_LDADD = libcommon.la libplugin_mock.la
+test_utils_subst_LDADD = libplugin_mock.la
{
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, /* {{{ */
{
read_func_t *rf;
plugin_ctx_t old_ctx;
+ cdtime_t start;
cdtime_t now;
+ cdtime_t elapsed;
int status;
int rf_type;
int rc;
DEBUG ("plugin_read_thread: Handling `%s'.", rf->rf_name);
+ start = cdtime ();
+
old_ctx = plugin_set_ctx (rf->rf_ctx);
if (rf_type == RF_SIMPLE)
/* update the ``next read due'' field */
now = cdtime ();
+ /* calculate the time spent in the read function */
+ elapsed = (now - start);
+
+ if (elapsed > rf->rf_effective_interval)
+ WARNING ("plugin_read_thread: read-function of the `%s' plugin took %.3f "
+ "seconds, which is above its read interval (%.3f seconds). You might "
+ "want to adjust the `Interval' or `ReadThreads' settings.",
+ rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed),
+ CDTIME_T_TO_DOUBLE(rf->rf_effective_interval));
+
+ DEBUG ("plugin_read_thread: read-function of the `%s' plugin took "
+ "%.6f seconds.",
+ rf->rf_name, CDTIME_T_TO_DOUBLE(elapsed));
+
DEBUG ("plugin_read_thread: Effective interval of the "
- "%s plugin is %.3f seconds.",
+ "`%s' plugin is %.3f seconds.",
rf->rf_name,
CDTIME_T_TO_DOUBLE (rf->rf_effective_interval));
rf->rf_next_read = now;
}
- DEBUG ("plugin_read_thread: Next read of the %s plugin at %.3f.",
+ DEBUG ("plugin_read_thread: Next read of the `%s' plugin at %.3f.",
rf->rf_name,
CDTIME_T_TO_DOUBLE (rf->rf_next_read));
*/
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);
}
}
* 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 */
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 : */
/**
* collectd - src/utils_time.c
- * Copyright (C) 2010 Florian octo Forster
+ * Copyright (C) 2010-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"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <ff at octo.it>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
#include "plugin.h"
#include "common.h"
-#if HAVE_CLOCK_GETTIME
+#ifndef DEFAULT_MOCK_TIME
+# define DEFAULT_MOCK_TIME 1542455354518929408ULL
+#endif
+
+#ifdef MOCK_TIME
+cdtime_t cdtime_mock = (cdtime_t) MOCK_TIME;
+
+cdtime_t cdtime (void)
+{
+ return cdtime_mock;
+}
+#else /* !MOCK_TIME */
+# if HAVE_CLOCK_GETTIME
cdtime_t cdtime (void) /* {{{ */
{
int status;
return (TIMESPEC_TO_CDTIME_T (&ts));
} /* }}} cdtime_t cdtime */
-#else
+# else /* !HAVE_CLOCK_GETTIME */
/* Work around for Mac OS X which doesn't have clock_gettime(2). *sigh* */
cdtime_t cdtime (void) /* {{{ */
{
return (TIMEVAL_TO_CDTIME_T (&tv));
} /* }}} cdtime_t cdtime */
+# endif
#endif
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t) /* {{{ */
+/* format_zone reads time zone information from "extern long timezone", exported
+ * by <time.h>, and formats it according to RFC 3339. This differs from
+ * strftime()'s "%z" format by including a colon between hour and minute. */
+static void format_zone (char *buffer, size_t buffer_size) /* {{{ */
+{
+ _Bool east = 0;
+ long hours;
+ long minutes;
+
+ minutes = timezone / 60;
+ if (minutes == 0) {
+ sstrncpy (buffer, "Z", buffer_size);
+ return;
+ }
+
+ if (minutes < 0)
+ {
+ east = 1;
+ minutes = minutes * (-1);
+ }
+
+ hours = minutes / 60;
+ minutes = minutes % 60;
+
+ ssnprintf (buffer, buffer_size, "%s%02ld:%02ld",
+ (east ? "+" : "-"), hours, minutes);
+} /* }}} int format_zone */
+
+static int format_rfc3339 (char *buffer, size_t buffer_size, cdtime_t t, _Bool print_nano) /* {{{ */
{
struct timespec t_spec;
struct tm t_tm;
-
+ char base[20]; /* 2006-01-02T15:04:05 */
+ char nano[11]; /* .999999999 */
+ char zone[7]; /* +00:00 */
+ char *fields[] = {base, nano, zone};
size_t len;
CDTIME_T_TO_TIMESPEC (t, &t_spec);
NORMALIZE_TIMESPEC (t_spec);
- if (localtime_r ((time_t *)&t_spec.tv_sec, &t_tm) == NULL) {
+ if (localtime_r (&t_spec.tv_sec, &t_tm) == NULL) {
char errbuf[1024];
- ERROR ("cdtime_to_iso8601: localtime_r failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
- return (0);
+ int status = errno;
+ ERROR ("format_rfc3339: localtime_r failed: %s",
+ sstrerror (status, errbuf, sizeof (errbuf)));
+ return (status);
}
- len = strftime (s, max, "%Y-%m-%dT%H:%M:%S", &t_tm);
+ len = strftime (base, sizeof (base), "%Y-%m-%dT%H:%M:%S", &t_tm);
if (len == 0)
- return 0;
+ return ENOMEM;
- if (max - len > 2) {
- int n = snprintf (s + len, max - len, ".%09i", (int)t_spec.tv_nsec);
- len += (n < 0) ? 0
- : (((size_t) n) < (max - len)) ? ((size_t) n)
- : (max - len);
- }
+ if (print_nano)
+ ssnprintf (nano, sizeof (nano), ".%09ld", (long) t_spec.tv_nsec);
+ else
+ sstrncpy (nano, "", sizeof (nano));
- if (max - len > 3) {
- size_t n = strftime (s + len, max - len, "%z", &t_tm);
- len += (n < max - len) ? n : max - len;
- }
+ format_zone (zone, sizeof (zone));
+
+ if (strjoin (buffer, buffer_size, fields, STATIC_ARRAY_SIZE (fields), "") < 0)
+ return ENOMEM;
+ return 0;
+} /* }}} int cdtime_to_rfc3339nano */
+
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+ if (buffer_size < RFC3339_SIZE)
+ return ENOMEM;
+
+ return format_rfc3339 (buffer, buffer_size, t, 0);
+} /* }}} size_t cdtime_to_rfc3339 */
+
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t) /* {{{ */
+{
+ if (buffer_size < RFC3339NANO_SIZE)
+ return ENOMEM;
- s[max - 1] = '\0';
- return len;
-} /* }}} size_t cdtime_to_iso8601 */
+ return format_rfc3339 (buffer, buffer_size, t, 1);
+} /* }}} size_t cdtime_to_rfc3339nano */
/* vim: set sw=2 sts=2 et fdm=marker : */
#include "collectd.h"
+#ifdef TESTING_H
+/* cdtime_mock is the time returned by cdtime() when build with
+ * -DMOCK_TIME */
+extern cdtime_t cdtime_mock;
+#endif
+
/*
* "cdtime_t" is a 64bit unsigned integer. The time is stored at a 2^-30 second
* resolution, i.e. the most significant 34 bit are used to store the time in
cdtime_t cdtime (void);
-/* format a cdtime_t value in ISO 8601 format:
- * returns the number of characters written to the string (not including the
- * terminating null byte or 0 on error; the function ensures that the string
- * is null terminated */
-size_t cdtime_to_iso8601 (char *s, size_t max, cdtime_t t);
+#define RFC3339_SIZE 26
+#define RFC3339NANO_SIZE 36
+
+/* rfc3339 formats a cdtime_t time in RFC 3339 format with second precision. */
+int rfc3339 (char *buffer, size_t buffer_size, cdtime_t t);
+
+/* rfc3339nano formats a cdtime_t time in RFC 3339 format with nanosecond
+ * precision. */
+int rfc3339nano (char *buffer, size_t buffer_size, cdtime_t t);
#endif /* UTILS_TIME_H */
/* vim: set sw=2 sts=2 et : */
+++ /dev/null
-/**
- * collectd - src/tests/mock/utils_time.c
- * Copyright (C) 2013 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 "utils_time.h"
-
-cdtime_t cdtime (void)
-{
- return ((cdtime_t) 1542455354518929408ULL);
-}
-
}
if (fgets(buffer, buffer_len, fp) == NULL) {
ERROR("fhcount: fgets: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
+ fclose(fp);
return(EXIT_FAILURE);
}
fclose(fp);
if (dir->path == NULL)
{
ERROR ("filecount plugin: strdup failed.");
+ sfree (dir);
return (-1);
}
} else {
ERROR ("irq plugin: unable to get CPU count from first line "
"of /proc/interrupts");
+ fclose (fh);
return (-1);
}
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++)
{
if (payload == NULL)
{
ERROR ("mqtt plugin: malloc for payload buffer failed.");
+ sfree (vl.values);
return;
}
memmove (payload, msg->payload, msg->payloadlen);
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.");
--- /dev/null
+/**
+ * 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 : */
/* the ithread no longer exists */
if (NULL == t)
+ {
+ pthread_mutex_unlock (&perl_threads->mutex);
return;
+ }
c_ithread_destroy (ithread);
{
c_psql_database_t *db;
- char time_str[32];
+ char time_str[RFC3339NANO_SIZE];
char values_name_str[1024];
char values_type_str[1024];
char values_str[1024];
assert (db->database != NULL);
assert (db->writers != NULL);
- if (cdtime_to_iso8601 (time_str, sizeof (time_str), vl->time) == 0) {
- log_err ("c_psql_write: Failed to convert time to ISO 8601 format");
+ if (rfc3339nano (time_str, sizeof (time_str), vl->time) != 0) {
+ log_err ("c_psql_write: Failed to convert time to RFC 3339 format");
return -1;
}
const char* const default_server_fields[] = /* {{{ */
{
- "latency"
+ "latency",
"packetcache-hit",
"packetcache-miss",
"packetcache-size",
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);
switch (procs[i].ki_stat)
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);
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) */
* 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++) {
{
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;
status = cf_util_get_string(ci, &hd->name);
if (status != 0)
+ {
+ sfree (hd);
return status;
+ }
hd->sess_handle = NULL;
hd->interval = 0;
static int csnmp_read_host (user_data_t *ud)
{
host_definition_t *host;
- cdtime_t time_start;
- cdtime_t time_end;
int status;
int success;
int i;
if (host->interval == 0)
host->interval = plugin_get_interval ();
- time_start = cdtime ();
-
if (host->sess_handle == NULL)
csnmp_host_open_session (host);
success++;
}
- time_end = cdtime ();
- if ((time_end - time_start) > host->interval)
- {
- WARNING ("snmp plugin: Host `%s' should be queried every %.3f "
- "seconds, but reading all values takes %.3f seconds.",
- host->name,
- CDTIME_T_TO_DOUBLE (host->interval),
- CDTIME_T_TO_DOUBLE (time_end - time_start));
- }
-
if (success == 0)
return (-1);
* Florian octo Forster <octo at collectd.org>
*/
+#ifndef TESTING_H
+#define TESTING_H 1
+
#include <inttypes.h>
static int fail_count__ = 0;
status_ = (long) (expr); \
OK1(status_ == 0L, #expr); \
} while (0)
+
+#endif /* TESTING_H */
{
struct VSM_data *vd;
const c_varnish_stats_t *stats;
+ _Bool ok;
user_config_t *conf;
}
#if HAVE_VARNISH_V3
- if (VSC_Open (vd, /* diag = */ 1))
+ ok = (VSC_Open (vd, /* diag = */ 1) == 0);
#else /* if HAVE_VARNISH_V4 */
- if (VSM_Open (vd))
+ ok = (VSM_Open (vd) == 0);
#endif
+ if (!ok)
{
VSM_Delete (vd);
ERROR ("varnish plugin: Unable to open connection.");
#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);
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;
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;
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;
}
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 : */
value_size = sizeof (value);
value_ptr = &value[0];
status = format_values (value_ptr, value_size, ds, vl, node->store_rates);
- pthread_mutex_lock (&node->lock);
if (status != 0)
return (status);
+ pthread_mutex_lock (&node->lock);
+
if (node->conn == NULL)
{
node->conn = redisConnectWithTimeout ((char *)node->host, node->port, node->timeout);
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"