.libs/
src/collectd
src/collectd-nagios
+src/collectdctl
src/collectdmon
src/*.1
src/*.5
Fabian Linzberger <e at lefant.net>
- Percentage aggregation for `collectd-nagios'.
+Fabien Wernli <cpan at faxm0dem.org>
+ - Solaris improvements in the memory and interfaces plugin.
+
Flavio Stanchina <flavio at stanchina.net>
- mbmon plugin.
+2012-01-21, Version 5.0.2
+ * curl_xml plugin: Fix handling of file:// and other URLs (which don't
+ follow HTTP status codes). Thanks to Fabien Wernli for his patch!
+ * df plugin: Fix handling of negative "available" counts. This can
+ occur with some file systems, for example UFS. Thanks to Toni Ylenius
+ for his patch.
+ * interface plugin: "mac" interfaces are now ignored on Solaris. These
+ pseudo-interfaces occur multiple times, causing warnings. Also switch
+ to 64-bit counters on Solaris, improving overflow behavior for
+ high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for
+ their patches.
+ * memory plugin: Account kernel and unused memory under Solaris. Thanks
+ to Fabien Wernli for his patch.
+ * network plugin: A bug in the interaction between the Network plugin
+ and filter chains has been fixed: When a filter modified a field such
+ as the hostname, subsequent values in the same network packets could
+ have ended up using the modified name rather than the original name.
+ Thanks to Sebastian Harl for identifying the problem.
+ * oracle plugin: A memory leak has been fixed in the parameter handling.
+ * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel
+ for fixing this bug!
+
+2011-10-07, Version 5.0.1
+ * collectd: A mutex leak has been fixed in the meta data code. Thanks
+ to Rafal Lesniak for his patch.
+ * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks
+ to Peter Green for his patch.
+ * csv plugin: The line buffer size has been increased. Thanks to Colin
+ McCabe for the patch.
+ * curl_json plugin: Don't use the "parent" node to build the type
+ instance, if it is empty. Compatibility with libyajl 2 has been
+ added. Thanks to "spupykin" of the Arch Linux project for the initial
+ code. Formatting of time has been fixed in the JSON module.
+ * exec plugin: Fix the timestamp value passed to notification scripts.
+ Thanks to Alexander Kovalenko for fixing this.
+ * iptables plugin: Fix linking with some versions of libiptc.
+ * irq plugin: Fix support for interrupts under Linux. The old code
+ assumed that interrupts have a numeric value -- this is no longer
+ true for Linux. Thanks to Bostjan Skufca for implementing this.
+ * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+ added. Thanks to Samuli Suominen for his patch.
+ * processes plugin: Fix handling of regular expressions containing
+ spaces. Thanks for Sebastian Harl for fixing this.
+ * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+ Previously, values like 0.999 would have been rounded to 1.0. Thanks
+ to Francois-Xavier Bourlet for fixing this.
+ * varnish plugin: Fix data type handling of some metrics. Some values
+ were submitted as gauge even though they were derives.
+ * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+ Flisher for the fix.
+
2011-03-28, Version 5.0.0
* collectd: The "FQDNLookup" option is now enabled by default.
* collectd: The internal representation of time has been changed to
* v5upgrade target: Target for converting v4 data sets to the v5
schema.
+2012-01-21, Version 4.10.5
+ * curl_xml plugin: Fix handling of file:// and other URLs (which don't
+ follow HTTP status codes). Thanks to Fabien Wernli for his patch!
+ * df plugin: Fix handling of negative "available" counts. This can
+ occur with some file systems, for example UFS. Thanks to Toni Ylenius
+ for his patch.
+ * interface plugin: "mac" interfaces are now ignored on Solaris. These
+ pseudo-interfaces occur multiple times, causing warnings. Also switch
+ to 64-bit counters on Solaris, improving overflow behavior for
+ high-speed interfaces. Thanks to Eddy Geez and Fabien Wernli for
+ their patches.
+ * memory plugin: Account kernel and unused memory under Solaris. Thanks
+ to Fabien Wernli for his patch.
+ * network plugin: A bug in the interaction between the Network plugin
+ and filter chains has been fixed: When a filter modified a field such
+ as the hostname, subsequent values in the same network packets could
+ have ended up using the modified name rather than the original name.
+ Thanks to Sebastian Harl for identifying the problem.
+ * oracle plugin: A memory leak has been fixed in the parameter handling.
+ * python plugin: A memory leak has been fixed. Thanks to Sven Trenkel
+ for fixing this bug!
+
+2011-10-14, Version 4.10.4
+ * collectd: A mutex leak has been fixed in the meta data code. Thanks
+ to Rafal Lesniak for his patch.
+ * collectd: Compatibility fixes for GCC 4.6 have been applied. Thanks
+ to Peter Green for his patch.
+ * csv plugin: The line buffer size has been increased. Thanks to Colin
+ McCabe for the patch.
+ * curl_json plugin: Don't use the "parent" node to build the type
+ instance, if it is empty. Compatibility with libyajl 2 has been
+ added. Thanks to "spupykin" of the Arch Linux project for the initial
+ code.
+ * iptables plugin: Fix linking with some versions of libiptc.
+ * irq plugin: Fix support for interrupts under Linux. The old code
+ assumed that interrupts have a numeric value -- this is no longer
+ true for Linux. Thanks to Bostjan Skufca for implementing this.
+ * notify_desktop plugin: Compatibility with libnotify 0.7 has been
+ added. Thanks to Samuli Suominen for his patch.
+ * processes plugin: Fix handling of regular expressions containing
+ spaces. Thanks for Sebastian Harl for fixing this.
+ * rrdtool, rrdcached plugins: Improve precision of the XFF parameter.
+ Previously, values like 0.999 would have been rounded to 1.0. Thanks
+ to Francois-Xavier Bourlet for fixing this.
+ * Various plugin: Set a multi-threading flag in libcurl. Thanks to Mike
+ Flisher for the fix.
+
2011-03-26, Version 4.10.3
* Documentation: Several updates and additions. Thanks to Sebastian Harl.
* collectd: Build issues (compiler warnings) have been fixed. Thanks to
AC_INIT(collectd, m4_esyscmd(./version-gen.sh))
AC_CONFIG_SRCDIR(src/collectd.c)
AC_CONFIG_HEADERS(src/config.h)
+AC_CONFIG_AUX_DIR([libltdl/config])
m4_ifdef([LT_PACKAGE_VERSION],
# libtool >= 2.2
[
with_libiptc="yes"
with_own_libiptc="yes"
- ])
+ ],
+ [-lip4tc -lip6tc])
fi
# The system wide version failed for some reason. Check if we have the required
# headers to build the shipped version.
CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
AC_CHECK_HEADERS(yajl/yajl_parse.h, [with_libyajl="yes"], [with_libyajl="no (yajl/yajl_parse.h not found)"])
+ AC_CHECK_HEADERS(yajl/yajl_version.h)
CPPFLAGS="$SAVE_CPPFLAGS"
fi
--- /dev/null
+
+%define name collectd
+%define version 4.10.1
+%define release 1
+
+Name: %{name}
+Summary: Statistics collection daemon for filling RRD files.
+Version: %{version}
+Release: %{release}
+#Source: http://collectd.org/files/%{name}-%{version}.tar.gz
+Source0: %{name}-%{version}.tar.gz
+Group: System Environment/Daemons
+BuildRoot: %{_tmppath}/%{name}-%{version}-buildroot
+License: GPL
+BuildPrereq: rrdtool-devel,net-snmp-devel
+Requires: rrdtool,net-snmp
+Packager: Aurelien Reynaud <collectd@wattapower.net>
+Vendor: collectd development team <collectd@verplant.org>
+
+%description
+collectd is a small daemon which collects system information periodically and
+provides mechanisms to monitor and store the values in a variety of ways. It
+is written in C for performance. Since the daemon doesn't need to startup
+every time it wants to update the values it's very fast and easy on the
+system. Also, the statistics are very fine grained since the files are updated
+every 10 seconds.
+
+%prep
+%setup
+
+%build
+# The RM variable in the RPM environment conflicts with that of the build environment,
+# at least when building on AIX 6.1. This is definitely a bug in one of the tools but
+# for now we work around it by unsetting the variable below.
+[ -n "$RM" ] && unset RM
+./configure LDFLAGS="-Wl,-brtl" --prefix=/opt/freeware --mandir=/opt/freeware/man --disable-dns --with-libnetsnmp=/opt/freeware/bin/net-snmp-config
+make
+
+%install
+make install DESTDIR=$RPM_BUILD_ROOT
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/lib/%{name}
+mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run
+mkdir -p $RPM_BUILD_ROOT/etc/rc.d/init.d
+cp contrib/aix/init.d-collectd $RPM_BUILD_ROOT/etc/rc.d/init.d/collectd
+
+%clean
+[ "$RPM_BUILD_ROOT" != "/" ] && rm -rf "$RPM_BUILD_ROOT"
+
+%files
+%defattr(-,root,system)
+%doc AUTHORS COPYING ChangeLog INSTALL NEWS README
+%config(noreplace) %attr(0644,root,system) %{_sysconfdir}/collectd.conf
+%attr(0755,root,system) /etc/rc.d/init.d/collectd
+%attr(0755,root,system) %{_sbindir}/collectd
+%attr(0755,root,system) %{_bindir}/collectd-nagios
+%attr(0755,root,system) %{_sbindir}/collectdmon
+%attr(0644,root,system) %{_mandir}/man1/*
+%attr(0644,root,system) %{_mandir}/man5/*
+
+# client
+%attr(0644,root,system) %{_includedir}/%{name}/client.h
+%attr(0644,root,system) %{_includedir}/%{name}/lcc_features.h
+
+%attr(0644,root,system) %{_libdir}/libcollectdclient.*
+%attr(0644,root,system) %{_libdir}/pkgconfig/libcollectdclient.pc
+
+%attr(0444,root,system) %{_libdir}/%{name}/*.so
+%attr(0444,root,system) %{_libdir}/%{name}/*.a
+%attr(0444,root,system) %{_libdir}/%{name}/*.la
+
+%attr(0644,root,system) %{_datadir}/%{name}/types.db
+
+%dir %{_localstatedir}/lib/%{name}
+%dir %{_localstatedir}/run
+
--- /dev/null
+#!/bin/sh
+#
+# description: collectd startup script
+#
+# March 2010, Aurelien Reynaud <collectd@wattapower.net>
+#
+
+# Some plugins need libs in non-standard paths
+case `uname` in
+ SunOS)
+ LD_LIBRARY_PATH="$LD_LIBRARY_PATH:/usr/local/lib:/usr/local/ssl/lib"
+ export LD_LIBRARY_PATH
+ ;;
+ *)
+ ;;
+esac
+
+# Set umask
+umask 022
+
+COLLECTD_BIN=/opt/freeware/sbin/collectd
+PIDFILE=/opt/freeware/var/run/collectd.pid
+
+# Check for missing binaries (stale symlinks should not happen)
+if [ ! -x $COLLECTD_BIN ]; then
+ echo "$COLLECTD_BIN not installed"
+ [ "$1" = "stop" ] && exit 0
+ exit 5
+fi
+
+# Check for existence of needed config file and read it
+COLLECTD_CONFIG=/opt/freeware/etc/collectd.conf
+if [ ! -r $COLLECTD_CONFIG ]; then
+ echo "$COLLECTD_CONFIG not existing"
+ [ "$1" = "stop" ] && exit 0
+ exit 6
+fi
+
+case "$1" in
+ start)
+ if [ -r $PIDFILE ]; then
+ echo "collectd daemon is already running with PID `cat $PIDFILE`."
+ exit 1
+ fi
+ echo "Starting collectd..."
+
+ ## Start daemon
+ $COLLECTD_BIN
+ ;;
+ stop)
+ echo "Shutting down collectd daemon... "
+ ## Stop daemon.
+ if [ -r $PIDFILE ]; then
+ pid=`cat $PIDFILE`
+ kill -15 $pid
+ while ps -p $pid >/dev/null; do
+ sleep 1
+ done
+ rm -f $PIDFILE
+ fi
+ ;;
+ status)
+ if [ -r $PIDFILE ]; then
+ echo "collectd daemon is running with PID `cat $PIDFILE`."
+ else
+ echo "collectd daemon is not running."
+ fi
+ ;;
+ restart)
+ ## Stop the service and regardless of whether it was
+ ## running or not, start it again.
+ $0 stop
+ $0 start
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|status|restart}"
+ exit 1
+ ;;
+esac
"""
numvalues = self._cmd('GETTHRESHOLD "%s"' % identifier)
lines = []
- if numvalues:
- lines = self._readlines(numvalues)
+ if not numvalues or numvalues < 0:
+ raise KeyError("Identifier '%s' not found" % identifier)
+ lines = self._readlines(numvalues)
return lines
def getval(self, identifier, flush_after=True):
"""
numvalues = self._cmd('GETVAL "%s"' % identifier)
lines = []
- if numvalues:
- lines = self._readlines(numvalues)
+ if not numvalues or numvalues < 0:
+ raise KeyError("Identifier '%s' not found" % identifier)
+ lines = self._readlines(numvalues)
if flush_after:
self.flush(identifiers=[identifier])
return lines
&& (!$plugin_inst) && ($type_inst))
{
my $dir = join ('/', @path);
+ print "mkdir -p \"$dir/$plugin-$type_inst\"\n";
print "mv \"$path\" \"$dir/$plugin-$type_inst/$type.rrd\"\n";
}
} # }}} sub handle_file
return (-1);
}
+ curl_easy_setopt (st->curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (st->curl, CURLOPT_WRITEFUNCTION, apache_curl_callback);
curl_easy_setopt (st->curl, CURLOPT_WRITEDATA, st);
return (-1);
}
+ curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ascent_curl_callback);
curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, ascent_curl_error);
return (-1);
}
+ curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback);
curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error);
sub foobar_read
{
- my $vl = { plugin => 'foobar' };
+ my $vl = { plugin => 'foobar', type => 'gauge' };
$vl->{'values'} = [ rand(42) ];
- plugin_dispatch_values ('gauge', $vl);
+ plugin_dispatch_values ($vl);
return 1;
}
#@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
#@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
#@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
-#@BUILD_PLUGIN_PERL_TRUE@LoadPlugin perl
+#@BUILD_PLUGIN_PERL_TRUE@<LoadPlugin perl>
+#@BUILD_PLUGIN_PERL_TRUE@ Globals true
+#@BUILD_PLUGIN_PERL_TRUE@</LoadPlugin>
#@BUILD_PLUGIN_PINBA_TRUE@LoadPlugin pinba
#@BUILD_PLUGIN_PING_TRUE@LoadPlugin ping
#@BUILD_PLUGIN_POSTGRESQL_TRUE@LoadPlugin postgresql
#@BUILD_PLUGIN_POWERDNS_TRUE@LoadPlugin powerdns
#@BUILD_PLUGIN_PROCESSES_TRUE@LoadPlugin processes
#@BUILD_PLUGIN_PROTOCOLS_TRUE@LoadPlugin protocols
-#@BUILD_PLUGIN_PYTHON_TRUE@LoadPlugin python
+#@BUILD_PLUGIN_PYTHON_TRUE@<LoadPlugin python>
+#@BUILD_PLUGIN_PYTHON_TRUE@ Globals true
+#@BUILD_PLUGIN_PYTHON_TRUE@</LoadPlugin>
#@BUILD_PLUGIN_REDIS_TRUE@LoadPlugin redis
#@BUILD_PLUGIN_ROUTEROS_TRUE@LoadPlugin routeros
#@BUILD_PLUGIN_RRDCACHED_TRUE@LoadPlugin rrdcached
</Plugin>
In the B<Plugin> block, there may be one or more B<URL> blocks, each defining a
-URL to be fetched via HTTP (using libcurl). Within each B<URL> block there are
+URL to be fetched using libcurl. Within each B<URL> block there are
options which specify the connection parameters, for example authentication
information, and one or more B<XPath> blocks.
}
if (value == endptr) {
- ERROR ("parse_value: Failed to parse string as number: %s.", value);
+ ERROR ("parse_value: Failed to parse string as %s: %s.",
+ DS_TYPE_TO_STRING (ds_type), value);
return -1;
}
else if ((NULL != endptr) && ('\0' != *endptr))
- WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
- endptr);
+ INFO ("parse_value: Ignoring trailing garbage \"%s\" after %s value. "
+ "Input string was \"%s\".",
+ endptr, DS_TYPE_TO_STRING (ds_type), value);
+
return 0;
} /* int parse_value */
{
struct stat statbuf;
char filename[512];
- char values[512];
+ char values[4096];
FILE *csv;
int csv_fd;
struct flock fl;
return (-1);
}
+ curl_easy_setopt (wp->curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (wp->curl, CURLOPT_WRITEFUNCTION, cc_curl_callback);
curl_easy_setopt (wp->curl, CURLOPT_WRITEDATA, wp);
curl_easy_setopt (wp->curl, CURLOPT_USERAGENT,
/**
* collectd - src/curl_json.c
* Copyright (C) 2009 Doug MacEachern
- * Copyright (C) 2006-2010 Florian octo Forster
+ * Copyright (C) 2006-2011 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
*
* Authors:
* Doug MacEachern <dougm at hyperic.com>
- * Florian octo Forster <octo at verplant.org>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
#include "plugin.h"
#include "configfile.h"
#include "utils_avltree.h"
+#include "utils_complain.h"
#include <curl/curl.h>
#include <yajl/yajl_parse.h>
+#if HAVE_YAJL_YAJL_VERSION_H
+# include <yajl/yajl_version.h>
+#endif
+
+#if defined(YAJL_MAJOR) && (YAJL_MAJOR > 1)
+# define HAVE_YAJL_V2 1
+#endif
#define CJ_DEFAULT_HOST "localhost"
#define CJ_KEY_MAGIC 0x43484b59UL /* CHKY */
};
typedef struct cj_s cj_t; /* }}} */
+#if HAVE_YAJL_V2
+typedef size_t yajl_len_t;
+#else
+typedef unsigned int yajl_len_t;
+#endif
+
static int cj_read (user_data_t *ud);
static int cj_curl_perform (cj_t *db, CURL *curl);
static void cj_submit (cj_t *db, cj_key_t *key, value_t *value);
if (db == NULL)
return (0);
- status = yajl_parse(db->yajl, (unsigned char *)buf, len);
- if ((status != yajl_status_ok)
- && (status != yajl_status_insufficient_data))
+ status = yajl_parse(db->yajl, (unsigned char *) buf, len);
+ if (status == yajl_status_ok)
+ {
+#if HAVE_YAJL_V2
+ status = yajl_complete_parse(db->yajl);
+#else
+ status = yajl_parse_complete(db->yajl);
+#endif
+ return (len);
+ }
+#if !HAVE_YAJL_V2
+ else if (status == yajl_status_insufficient_data)
+ return (len);
+#endif
+
+ if (status != yajl_status_ok)
{
unsigned char *msg =
yajl_get_error(db->yajl, /* verbose = */ 1,
ds = plugin_get_ds (key->type);
if (ds == NULL)
- return -1; /* let plugin_write do the complaining */
- else
- return ds->ds[0].type; /* XXX support ds->ds_len > 1 */
+ {
+ static char type[DATA_MAX_NAME_LEN] = "!!!invalid!!!";
+
+ assert (key->type != NULL);
+ if (strcmp (type, key->type) != 0)
+ {
+ ERROR ("curl_json plugin: Unable to look up DS type \"%s\".",
+ key->type);
+ sstrncpy (type, key->type, sizeof (type));
+ }
+
+ return -1;
+ }
+ else if (ds->ds_num > 1)
+ {
+ static c_complain_t complaint = C_COMPLAIN_INIT_STATIC;
+
+ c_complain_once (LOG_WARNING, &complaint,
+ "curl_json plugin: The type \"%s\" has more than one data source. "
+ "This is currently not supported. I will return the type of the "
+ "first data source, but this will likely lead to problems later on.",
+ key->type);
+ }
+
+ return ds->ds[0].type;
}
/* yajl callbacks */
/* "number" may not be null terminated, so copy it into a buffer before
* parsing. */
static int cj_cb_number (void *ctx,
- const char *number, unsigned int number_len)
+ const char *number, yajl_len_t number_len)
{
char buffer[number_len + 1];
} /* int cj_cb_number */
static int cj_cb_map_key (void *ctx, const unsigned char *val,
- unsigned int len)
+ yajl_len_t len)
{
cj_t *db = (cj_t *)ctx;
c_avl_tree_t *tree;
}
static int cj_cb_string (void *ctx, const unsigned char *val,
- unsigned int len)
+ yajl_len_t len)
{
cj_t *db = (cj_t *)ctx;
char str[len + 1];
return (-1);
}
+ curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cj_curl_callback);
curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
host = db->host;
if (key->instance == NULL)
- ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
- db->state[db->depth-1].name, db->state[db->depth].name);
+ {
+ if ((db->depth == 0) || (strcmp ("", db->state[db->depth-1].name) == 0))
+ sstrncpy (vl.type_instance, db->state[db->depth].name, sizeof (vl.type_instance));
+ else
+ ssnprintf (vl.type_instance, sizeof (vl.type_instance), "%s-%s",
+ db->state[db->depth-1].name, db->state[db->depth].name);
+ }
else
sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
char *url;
yajl_handle yprev = db->yajl;
- db->yajl = yajl_alloc (&ycallbacks, NULL, NULL, (void *)db);
+ db->yajl = yajl_alloc (&ycallbacks,
+#if HAVE_YAJL_V2
+ /* alloc funcs = */ NULL,
+#else
+ /* alloc funcs = */ NULL, NULL,
+#endif
+ /* context = */ (void *)db);
if (db->yajl == NULL)
{
ERROR ("curl_json plugin: yajl_alloc failed.");
return (-1);
}
- status = yajl_parse_complete (db->yajl);
+#if HAVE_YAJL_V2
+ status = yajl_complete_parse(db->yajl);
+#else
+ status = yajl_parse_complete(db->yajl);
+#endif
if (status != yajl_status_ok)
{
unsigned char *errmsg;
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
- if (rc != 200)
+ /* The response code is zero if a non-HTTP transport was used. */
+ if ((rc != 0) && (rc != 200))
{
ERROR ("curl_xml plugin: curl_easy_perform failed with response code %ld (%s)",
rc, url);
return (-1);
}
+ curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cx_curl_callback);
curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
# include <sys/statvfs.h>
# endif
# define STATANYFS statvfs
+# define STATANYFS_STR "statvfs"
# define BLOCKSIZE(s) ((s).f_frsize ? (s).f_frsize : (s).f_bsize)
#elif HAVE_STATFS
# if HAVE_SYS_STATFS_H
# include <sys/statfs.h>
# endif
# define STATANYFS statfs
+# define STATANYFS_STR "statfs"
# define BLOCKSIZE(s) (s).f_bsize
#else
# error "No applicable input method."
if (STATANYFS (mnt_ptr->dir, &statbuf) < 0)
{
char errbuf[1024];
- ERROR ("statv?fs failed: %s",
+ ERROR (STATANYFS_STR"(%s) failed: %s",
+ mnt_ptr->dir,
sstrerror (errno, errbuf,
sizeof (errbuf)));
continue;
blocksize = BLOCKSIZE(statbuf);
- /* Sanity-check for the values in the struct */
+ /*
+ * Sanity-check for the values in the struct
+ */
+ /* Check for negative "available" byes. For example UFS can
+ * report negative free space for user. Notice. blk_reserved
+ * will start to diminish after this. */
+#if HAVE_STATVFS
+ /* Cast is needed to avoid compiler warnings.
+ * ((struct statvfs).f_bavail is unsigned (POSIX)) */
+ if (((int64_t) statbuf.f_bavail) < 0)
+ statbuf.f_bavail = 0;
+#elif HAVE_STATFS
+ if (statbuf.f_bavail < 0)
+ statbuf.f_bavail = 0;
+#endif
+ /* Make sure that f_blocks >= f_bfree >= f_bavail */
if (statbuf.f_bfree < statbuf.f_bavail)
statbuf.f_bfree = statbuf.f_bavail;
if (statbuf.f_blocks < statbuf.f_bfree)
int numfields;
int fieldshift = 0;
- int major = 0;
int minor = 0;
derive_t read_sectors = 0;
if ((numfields != (14 + fieldshift)) && (numfields != 7))
continue;
- major = atoll (fields[0]);
minor = atoll (fields[1]);
disk_name = fields[2 + fieldshift];
fprintf (fh,
"Severity: %s\n"
- "Time: %u\n",
- severity, (unsigned int) n->time);
+ "Time: %.3f\n",
+ severity, CDTIME_T_TO_DOUBLE (n->time));
/* Print the optional fields */
if (strlen (n->host) > 0)
{
if (strncmp (ksp_chain->ks_class, "net", 3))
continue;
+ /* Ignore kstat entry if not the regular statistic set. This
+ * avoids problems with "bogus" interfaces, such as
+ * "wrsmd<num>" */
+ if (strncmp (ksp_chain->ks_name, ksp_chain->ks_module,
+ strlen (ksp_chain->ks_module)) != 0)
+ continue;
if (ksp_chain->ks_type != KSTAT_TYPE_NAMED)
continue;
if (kstat_read (kc, ksp_chain, NULL) == -1)
continue;
- if ((val = get_kstat_value (ksp_chain, "obytes")) == -1LL)
+ if ((val = get_kstat_value (ksp_chain, "ifspeed")) == -1LL)
continue;
ksp[numif++] = ksp_chain;
}
if (kstat_read (kc, ksp[i], NULL) == -1)
continue;
- rx = get_kstat_value (ksp[i], "rbytes");
- tx = get_kstat_value (ksp[i], "obytes");
+ /* try to get 64bit counters */
+ rx = get_kstat_value (ksp[i], "rbytes64");
+ tx = get_kstat_value (ksp[i], "obytes64");
+ /* or fallback to 32bit */
+ if (rx == -1LL)
+ rx = get_kstat_value (ksp[i], "rbytes");
+ if (tx == -1LL)
+ tx = get_kstat_value (ksp[i], "obytes");
if ((rx != -1LL) || (tx != -1LL))
if_submit (ksp[i]->ks_name, "if_octets", rx, tx);
- rx = get_kstat_value (ksp[i], "ipackets");
- tx = get_kstat_value (ksp[i], "opackets");
+ /* try to get 64bit counters */
+ rx = get_kstat_value (ksp[i], "ipackets64");
+ tx = get_kstat_value (ksp[i], "opackets64");
+ /* or fallback to 32bit */
+ if (rx == -1LL)
+ rx = get_kstat_value (ksp[i], "ipackets");
+ if (tx == -1LL)
+ tx = get_kstat_value (ksp[i], "opackets");
if ((rx != -1LL) || (tx != -1LL))
if_submit (ksp[i]->ks_name, "if_packets", rx, tx);
+ /* no 64bit error counters yet */
rx = get_kstat_value (ksp[i], "ierrors");
tx = get_kstat_value (ksp[i], "oerrors");
if ((rx != -1LL) || (tx != -1LL))
# error "No applicable input method."
#endif
-#define BUFSIZE 128
-
/*
* (Module-)Global variables
*/
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-static unsigned int *irq_list;
-static unsigned int irq_list_num;
+static char **irq_list;
+static unsigned int irq_list_num = 0;
/*
* irq_list_action:
{
if (strcasecmp (key, "Irq") == 0)
{
- unsigned int *temp;
- unsigned int irq;
- char *endptr;
+ char **temp;
- temp = (unsigned int *) realloc (irq_list, (irq_list_num + 1) * sizeof (unsigned int *));
+ temp = realloc (irq_list, (irq_list_num + 1) * sizeof (*irq_list));
if (temp == NULL)
{
fprintf (stderr, "irq plugin: Cannot allocate more memory.\n");
}
irq_list = temp;
- /* Clear errno, because we need it to see if an error occured. */
- errno = 0;
-
- irq = strtol(value, &endptr, 10);
- if ((endptr == value) || (errno != 0))
+ irq_list[irq_list_num] = strdup (value);
+ if (irq_list[irq_list_num] == NULL)
{
- fprintf (stderr, "irq plugin: Irq value is not a "
- "number: `%s'\n", value);
- ERROR ("irq plugin: Irq value is not a "
- "number: `%s'", value);
+ ERROR ("irq plugin: strdup(3) failed.");
return (1);
}
- irq_list[irq_list_num] = irq;
+
irq_list_num++;
}
else if (strcasecmp (key, "IgnoreSelected") == 0)
* both, `submit' and `write' to give client and server the ability to
* ignore certain stuff..
*/
-static int check_ignore_irq (const unsigned int irq)
+static int check_ignore_irq (const char *irq)
{
- int i;
+ unsigned int i;
if (irq_list_num < 1)
return (0);
- for (i = 0; (unsigned int)i < irq_list_num; i++)
- if (irq == irq_list[i])
+ for (i = 0; i < irq_list_num; i++)
+ if (strcmp (irq, irq_list[i]) == 0)
return (irq_list_action);
return (1 - irq_list_action);
}
-static void irq_submit (unsigned int irq, derive_t value)
+static void irq_submit (const char *irq_name, derive_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- int status;
- if (check_ignore_irq (irq))
+ if (check_ignore_irq (irq_name))
return;
values[0].derive = value;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "irq", sizeof (vl.plugin));
sstrncpy (vl.type, "irq", sizeof (vl.type));
-
- status = ssnprintf (vl.type_instance, sizeof (vl.type_instance),
- "%u", irq);
- if ((status < 1) || ((unsigned int)status >= sizeof (vl.type_instance)))
- return;
+ sstrncpy (vl.type_instance, irq_name, sizeof (vl.type_instance));
plugin_dispatch_values (&vl);
} /* void irq_submit */
return (-1);
}
- while (fgets (buffer, BUFSIZE, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
- unsigned int irq;
+ char *irq_name;
+ size_t irq_name_len;
derive_t irq_value;
- char *endptr;
int i;
char *fields[64];
if (fields_num < 2)
continue;
- errno = 0; /* To distinguish success/failure after call */
- irq = (unsigned int) strtoul (fields[0], &endptr, /* base = */ 10);
+ irq_name = fields[0];
+ irq_name_len = strlen (irq_name);
+ if (irq_name_len < 2)
+ continue;
- if ((endptr == fields[0]) || (errno != 0) || (*endptr != ':'))
+ /* Check if irq name ends with colon.
+ * Otherwise it's a header. */
+ if (irq_name[irq_name_len - 1] != ':')
continue;
+ irq_name[irq_name_len - 1] = 0;
+ irq_name_len--;
+
irq_value = 0;
for (i = 1; i < fields_num; i++)
{
irq_value += v.derive;
} /* for (i) */
- if (i < fields_num)
+ /* No valid fields -> do not submit anything. */
+ if (i <= 1)
continue;
- irq_submit (irq, irq_value);
+ irq_submit (irq_name, irq_value);
}
fclose (fh);
config_keys, config_keys_num);
plugin_register_read ("irq", irq_read);
} /* void module_register */
-
-#undef BUFSIZE
cjni_callback_info_t *cbi;
jobject o_ocitem;
const char *name;
- int status;
size_t i;
jclass class;
method = (*jvm_env)->GetMethodID (jvm_env, class,
"config", "(Lorg/collectd/api/OConfigItem;)I");
- status = (*jvm_env)->CallIntMethod (jvm_env,
+ (*jvm_env)->CallIntMethod (jvm_env,
cbi->object, method, o_ocitem);
(*jvm_env)->DeleteLocalRef (jvm_env, o_ocitem);
if (config_block != NULL)
{
- int status;
- status = cjni_config_perform (config_block);
+ cjni_config_perform (config_block);
oconfig_free (config_block);
config_block = NULL;
}
int i, n;
const char *name;
char uuid[VIR_UUID_STRING_BUFLEN];
- char *host_ptr;
- size_t host_len;
vl->interval = interval_g;
sstrncpy (vl->plugin, "libvirt", sizeof (vl->plugin));
vl->host[0] = '\0';
- host_ptr = vl->host;
- host_len = sizeof (vl->host);
/* Construct the hostname field according to HostnameFormat. */
for (i = 0; i < HF_MAX_FIELDS; ++i) {
const value_list_t *vl,
notification_meta_t __attribute__((unused)) **meta, void **user_data)
{
- mec_match_t *m;
int num_counters;
int num_empty;
int i;
if ((user_data == NULL) || (*user_data == NULL))
return (-1);
- m = *user_data;
num_counters = 0;
num_empty = 0;
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
+ /* Most of the additions here were taken as-is from the k9toolkit from
+ * Brendan Gregg and are subject to change I guess */
long long mem_used;
long long mem_free;
long long mem_lock;
+ long long mem_kern;
+ long long mem_unus;
+
+ long long pp_kernel;
+ long long physmem;
+ long long availrmem;
if (ksp == NULL)
return (-1);
mem_used = get_kstat_value (ksp, "pagestotal");
mem_free = get_kstat_value (ksp, "pagesfree");
mem_lock = get_kstat_value (ksp, "pageslocked");
+ mem_kern = 0;
+ mem_unus = 0;
+
+ pp_kernel = get_kstat_value (ksp, "pp_kernel");
+ physmem = get_kstat_value (ksp, "physmem");
+ availrmem = get_kstat_value (ksp, "availrmem");
if ((mem_used < 0LL) || (mem_free < 0LL) || (mem_lock < 0LL))
+ {
+ WARNING ("memory plugin: one of used, free or locked is negative.");
return (-1);
+ }
+
+ mem_unus = physmem - mem_used;
+
if (mem_used < (mem_free + mem_lock))
- return (-1);
+ {
+ /* source: http://wesunsolve.net/bugid/id/4909199
+ * this seems to happen when swap space is small, e.g. 2G on a 32G system
+ * we will make some assumptions here
+ * educated solaris internals help welcome here */
+ DEBUG ("memory plugin: pages total is smaller than \"free\" "
+ "+ \"locked\". This is probably due to small "
+ "swap space");
+ mem_free = availrmem;
+ mem_used = 0;
+ }
+ else
+ {
+ mem_used -= mem_free + mem_lock;
+ }
+
+ /* mem_kern is accounted for in mem_lock */
+ if ( pp_kernel < mem_lock )
+ {
+ mem_kern = pp_kernel;
+ mem_lock -= pp_kernel;
+ }
+ else
+ {
+ mem_kern = mem_lock;
+ mem_lock = 0;
+ }
- mem_used -= mem_free + mem_lock;
mem_used *= pagesize; /* If this overflows you have some serious */
mem_free *= pagesize; /* memory.. Why not call me up and give me */
mem_lock *= pagesize; /* some? ;) */
+ mem_kern *= pagesize; /* it's 2011 RAM is cheap */
+ mem_unus *= pagesize;
memory_submit ("used", mem_used);
memory_submit ("free", mem_free);
memory_submit ("locked", mem_lock);
+ memory_submit ("kernel", mem_kern);
+ memory_submit ("unusable", mem_unus);
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
/**
* collectd - src/meta_data.c
- * Copyright (C) 2008,2009 Florian octo Forster
+ * Copyright (C) 2008-2011 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
return (e);
} /* }}} meta_entry_t *md_entry_alloc */
+static meta_entry_t *md_entry_clone (const meta_entry_t *orig) /* {{{ */
+{
+ meta_entry_t *copy;
+
+ if (orig == NULL)
+ return (NULL);
+
+ copy = md_entry_alloc (orig->key);
+ copy->type = orig->type;
+ if (copy->type == MD_TYPE_STRING)
+ copy->value.mv_string = strdup (orig->value.mv_string);
+ else
+ copy->value = orig->value;
+
+ copy->next = md_entry_clone (orig->next);
+ return (copy);
+} /* }}} meta_entry_t *md_entry_clone */
+
static void md_entry_free (meta_entry_t *e) /* {{{ */
{
if (e == NULL)
return (md);
} /* }}} meta_data_t *meta_data_create */
+meta_data_t *meta_data_clone (meta_data_t *orig) /* {{{ */
+{
+ meta_data_t *copy;
+
+ if (orig == NULL)
+ return (NULL);
+
+ copy = meta_data_create ();
+ if (copy == NULL)
+ return (NULL);
+
+ pthread_mutex_lock (&orig->lock);
+ copy->head = md_entry_clone (orig->head);
+ pthread_mutex_unlock (&orig->lock);
+
+ return (copy);
+} /* }}} meta_data_t *meta_data_clone */
+
void meta_data_destroy (meta_data_t *md) /* {{{ */
{
if (md == NULL)
return;
md_entry_free (md->head);
+ pthread_mutex_destroy (&md->lock);
free (md);
} /* }}} void meta_data_destroy */
/**
* collectd - src/meta_data.h
- * Copyright (C) 2008,2009 Florian octo Forster
+ * Copyright (C) 2008-2011 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
typedef struct meta_data_s meta_data_t;
meta_data_t *meta_data_create (void);
+meta_data_t *meta_data_clone (meta_data_t *orig);
void meta_data_destroy (meta_data_t *md);
int meta_data_exists (meta_data_t *md, const char *key);
MYSQL_RES *res;
MYSQL_ROW row;
char *query;
- int field_num;
derive_t qcache_hits = 0;
derive_t qcache_inserts = 0;
if (res == NULL)
return (-1);
- field_num = mysql_num_fields (res);
while ((row = mysql_fetch_row (res)))
{
char *key;
}
}
- plugin_dispatch_values (vl);
+ plugin_dispatch_values_secure (vl);
stats_values_dispatched++;
meta_data_destroy (vl->meta);
size_t exp_size = 2 * sizeof (uint16_t) + sizeof (uint64_t);
uint16_t pkg_length;
- uint16_t pkg_type;
if ((buffer_len < 0) || ((size_t) buffer_len < exp_size))
{
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
- pkg_type = ntohs (tmp16);
+ /* pkg_type = ntohs (tmp16); */
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
size_t header_size = 2 * sizeof (uint16_t);
uint16_t pkg_length;
- uint16_t pkg_type;
if ((buffer_len < 0) || (buffer_len < header_size))
{
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
- pkg_type = ntohs (tmp16);
+ /* pkg_type = ntohs (tmp16); */
memcpy ((void *) &tmp16, buffer, sizeof (tmp16));
buffer += sizeof (tmp16);
vl.values[0].derive = (derive_t) copy_octets_rx;
vl.values[1].derive = (derive_t) copy_octets_tx;
sstrncpy (vl.type, "if_octets", sizeof (vl.type));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
/* Packets received / send */
vl.values[0].derive = (derive_t) copy_packets_rx;
vl.values[1].derive = (derive_t) copy_packets_tx;
sstrncpy (vl.type, "if_packets", sizeof (vl.type));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
/* Values (not) dispatched and (not) send */
sstrncpy (vl.type, "total_values", sizeof (vl.type));
vl.values[0].derive = (derive_t) copy_values_dispatched;
sstrncpy (vl.type_instance, "dispatch-accepted",
sizeof (vl.type_instance));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
vl.values[0].derive = (derive_t) copy_values_not_dispatched;
sstrncpy (vl.type_instance, "dispatch-rejected",
sizeof (vl.type_instance));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
vl.values[0].derive = (derive_t) copy_values_sent;
sstrncpy (vl.type_instance, "send-accepted",
sizeof (vl.type_instance));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
vl.values[0].derive = (derive_t) copy_values_not_sent;
sstrncpy (vl.type_instance, "send-rejected",
sizeof (vl.type_instance));
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
/* Receive queue length */
vl.values[0].gauge = (gauge_t) copy_receive_list_length;
sstrncpy (vl.type, "queue_length", sizeof (vl.type));
vl.type_instance[0] = 0;
- plugin_dispatch_values (&vl);
+ plugin_dispatch_values_secure (&vl);
return (0);
} /* }}} int network_stats_read */
return (-1);
}
+ curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, nginx_curl_callback);
curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, nginx_curl_error);
#include <glib.h>
#include <libnotify/notify.h>
+#ifndef NOTIFY_CHECK_VERSION
+# define NOTIFY_CHECK_VERSION(x,y,z) 0
+#endif
+
#define log_info(...) INFO ("notify_desktop: " __VA_ARGS__)
#define log_warn(...) WARNING ("notify_desktop: " __VA_ARGS__)
#define log_err(...) ERROR ("notify_desktop: " __VA_ARGS__)
: (NOTIF_WARNING == n->severity) ? "WARNING"
: (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
- notification = notify_notification_new (summary, n->message, NULL, NULL);
+ notification = notify_notification_new (summary, n->message, NULL
+#if NOTIFY_CHECK_VERSION (0, 7, 0)
+ );
+#else
+ , NULL);
+#endif
if (NULL == notification) {
log_err ("Failed to create a new notification.");
return -1;
static int notify_email_notification (const notification_t *n,
user_data_t __attribute__((unused)) *user_data)
{
- smtp_recipient_t recipient;
time_t tt;
struct tm timestamp_tm;
smtp_set_message_str (message, buf);
for (i = 0; i < recipients_len; i++)
- recipient = smtp_add_recipient (message, recipients[i]);
+ smtp_add_recipient (message, recipients[i]);
/* Initiate a connection to the SMTP server and transfer the message. */
if (!smtp_start_session (session)) {
pthread_mutex_unlock (&session_lock);
return (-1);
} else {
+ #if COLLECT_DEBUG
const smtp_status_t *status;
/* Report on the success or otherwise of the mail transfer. */
status = smtp_message_transfer_status (message);
DEBUG ("notify_email plugin: SMTP server report: %d %s",
- status->code, (status->text != NULL) ? status->text : "\n");
+ status->code, (status->text != NULL) ? status->text : "\n");
+ #endif
smtp_enumerate_recipients (message, print_recipient_status, NULL);
}
/**
* collectd - src/oracle.c
- * Copyright (C) 2008,2009 Florian octo Forster
+ * Copyright (C) 2008,2009 noris network AG
+ * Copyright (C) 2012 Florian octo Forster
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* affiliates. Other names may be trademarks of their respective owners.
*
* Authors:
- * Florian octo Forster <octo at noris.net>
+ * Florian octo Forster <octo at collectd.org>
**/
#include "collectd.h"
sb4 error_code;
int status;
- status = OCIErrorGet (eh, /* record number = */ 1,
- /* sqlstate = */ NULL,
- &error_code,
- (text *) &buffer[0],
- (ub4) sizeof (buffer),
- OCI_HTYPE_ERROR);
- buffer[sizeof (buffer) - 1] = 0;
-
- if (status == OCI_SUCCESS)
+ /* An operation may cause / return multiple errors. Loop until we have
+ * handled all errors available. */
+ while (42)
{
- size_t buffer_length;
+ memset (buffer, 0, sizeof (buffer));
+ error_code = -1;
+
+ status = OCIErrorGet (eh, /* record number = */ 1,
+ /* sqlstate = */ NULL,
+ &error_code,
+ (text *) &buffer[0],
+ (ub4) sizeof (buffer),
+ OCI_HTYPE_ERROR);
+ buffer[sizeof (buffer) - 1] = 0;
+
+ if (status == OCI_NO_DATA)
+ return;
- buffer_length = strlen (buffer);
- while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32))
+ if (status == OCI_SUCCESS)
{
- buffer_length--;
- buffer[buffer_length] = 0;
- }
+ size_t buffer_length;
- ERROR ("oracle plugin: %s: %s failed: %s",
- where, what, buffer);
- }
- else
- {
- ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.",
- where, what, status);
+ buffer_length = strlen (buffer);
+ while ((buffer_length > 0) && (buffer[buffer_length - 1] < 32))
+ {
+ buffer_length--;
+ buffer[buffer_length] = 0;
+ }
+
+ ERROR ("oracle plugin: %s: %s failed: %s",
+ where, what, buffer);
+ }
+ else
+ {
+ ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.",
+ where, what, status);
+ return;
+ }
}
} /* }}} void o_report_error */
&column_name, &column_name_length, OCI_ATTR_NAME, oci_error);
if (status != OCI_SUCCESS)
{
+ OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
o_report_error ("o_read_database_query", "OCIAttrGet (OCI_ATTR_NAME)",
oci_error);
continue;
}
+ OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
+ oci_param = NULL;
+
/* Copy the name to column_names. Warning: The ``string'' returned by OCI
* may not be null terminated! */
memset (column_names[i], 0, DATA_MAX_NAME_LEN);
}
OCIHandleFree (oci_env, OCI_HTYPE_ENV);
+ oci_env = NULL;
udb_query_free (queries, queries_num);
queries = NULL;
*/
static int iptcc_chain_index_delete_chain(struct chain_head *c, TC_HANDLE_T h)
{
- struct list_head *index_ptr, *index_ptr2, *next;
+ struct list_head *index_ptr, *next;
struct chain_head *c2;
unsigned int idx, idx2;
* is located in the same index bucket.
*/
c2 = list_entry(next, struct chain_head, list);
- index_ptr2 = iptcc_bsearch_chain_index(c2->name, &idx2, h);
+ iptcc_bsearch_chain_index(c2->name, &idx2, h);
if (idx != idx2) {
/* Rebuild needed */
return iptcc_chain_index_rebuild(h);
static TC_HANDLE_T
alloc_handle(const char *tablename, unsigned int size, unsigned int num_rules)
{
- size_t len;
TC_HANDLE_T h;
- len = sizeof(STRUCT_TC_HANDLE) + size;
h = malloc(sizeof(STRUCT_TC_HANDLE));
if (!h) {
if ((vl == NULL) || (vl->type[0] == 0)
|| (vl->values == NULL) || (vl->values_len < 1))
{
- ERROR ("plugin_dispatch_values: Invalid value list.");
+ ERROR ("plugin_dispatch_values: Invalid value list "
+ "from plugin %s.", vl->plugin);
return (-1);
}
return (0);
} /* int plugin_dispatch_values */
+int plugin_dispatch_values_secure (const value_list_t *vl)
+{
+ value_list_t vl_copy;
+ int status;
+
+ if (vl == NULL)
+ return EINVAL;
+
+ memcpy (&vl_copy, vl, sizeof (vl_copy));
+
+ /* Write callbacks must not change the values and meta pointers, so we can
+ * savely skip copying those and make this more efficient. */
+ if ((pre_cache_chain == NULL) && (post_cache_chain == NULL))
+ return (plugin_dispatch_values (&vl_copy));
+
+ /* Set pointers to NULL, just to be on the save side. */
+ vl_copy.values = NULL;
+ vl_copy.meta = NULL;
+
+ vl_copy.values = malloc (sizeof (*vl_copy.values) * vl->values_len);
+ if (vl_copy.values == NULL)
+ {
+ ERROR ("plugin_dispatch_values_secure: malloc failed.");
+ return (ENOMEM);
+ }
+ memcpy (vl_copy.values, vl->values, sizeof (*vl_copy.values) * vl->values_len);
+
+ if (vl->meta != NULL)
+ {
+ vl_copy.meta = meta_data_clone (vl->meta);
+ if (vl_copy.meta == NULL)
+ {
+ ERROR ("plugin_dispatch_values_secure: meta_data_clone failed.");
+ free (vl_copy.values);
+ return (ENOMEM);
+ }
+ } /* if (vl->meta) */
+
+ status = plugin_dispatch_values (&vl_copy);
+
+ meta_data_destroy (vl_copy.meta);
+ free (vl_copy.values);
+
+ return (status);
+} /* int plugin_dispatch_values_secure */
+
int plugin_dispatch_notification (const notification_t *notif)
{
llentry_t *le;
#define PLUGIN_H
/**
* collectd - src/plugin.h
- * Copyright (C) 2005-2010 Florian octo Forster
+ * Copyright (C) 2005-2011 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
* function.
*/
int plugin_dispatch_values (value_list_t *vl);
+int plugin_dispatch_values_secure (const value_list_t *vl);
int plugin_dispatch_missing (const value_list_t *vl);
int plugin_dispatch_notification (const notification_t *notif);
# define ARG_MAX 4096
#endif
-static const char *config_keys[] =
-{
- "Process",
- "ProcessMatch"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
-
typedef struct procstat_entry_s
{
unsigned long id;
}
/* put all pre-defined 'Process' names from config to list_head_g tree */
-static int ps_config (const char *key, const char *value)
+static int ps_config (oconfig_item_t *ci)
{
- if (strcasecmp (key, "Process") == 0)
- {
- ps_list_register (value, NULL);
- }
- else if (strcasecmp (key, "ProcessMatch") == 0)
- {
- char *new_val;
- char *fields[3];
- int fields_num;
-
- new_val = strdup (value);
- if (new_val == NULL) {
- ERROR ("processes plugin: strdup failed when processing "
- "`ProcessMatch %s'.", value);
- return (1);
+ int i;
+
+ for (i = 0; i < ci->children_num; ++i) {
+ oconfig_item_t *c = ci->children + i;
+
+ if (strcasecmp (c->key, "Process") == 0)
+ {
+ if ((c->values_num != 1)
+ || (OCONFIG_TYPE_STRING != c->values[0].type)) {
+ ERROR ("processes plugin: `Process' expects exactly "
+ "one string argument (got %i).",
+ c->values_num);
+ continue;
+ }
+
+ if (c->children_num != 0) {
+ WARNING ("processes plugin: the `Process' config option "
+ "does not expect any child elements -- ignoring "
+ "content (%i elements) of the <Process '%s'> block.",
+ c->children_num, c->values[0].value.string);
+ }
+
+ ps_list_register (c->values[0].value.string, NULL);
}
+ else if (strcasecmp (c->key, "ProcessMatch") == 0)
+ {
+ if ((c->values_num != 2)
+ || (OCONFIG_TYPE_STRING != c->values[0].type)
+ || (OCONFIG_TYPE_STRING != c->values[1].type))
+ {
+ ERROR ("processes plugin: `ProcessMatch' needs exactly "
+ "two string arguments (got %i).",
+ c->values_num);
+ continue;
+ }
- fields_num = strsplit (new_val, fields,
- STATIC_ARRAY_SIZE (fields));
- if (fields_num != 2)
+ if (c->children_num != 0) {
+ WARNING ("processes plugin: the `ProcessMatch' config option "
+ "does not expect any child elements -- ignoring "
+ "content (%i elements) of the <ProcessMatch '%s' '%s'> "
+ "block.", c->children_num, c->values[0].value.string,
+ c->values[1].value.string);
+ }
+
+ ps_list_register (c->values[0].value.string,
+ c->values[1].value.string);
+ }
+ else
{
- ERROR ("processes plugin: `ProcessMatch' needs exactly "
- "two string arguments.");
- sfree (new_val);
- return (1);
+ ERROR ("processes plugin: The `%s' configuration option is not "
+ "understood and will be ignored.", c->key);
+ continue;
}
- ps_list_register (fields[0], fields[1]);
- sfree (new_val);
- }
- else
- {
- ERROR ("processes plugin: The `%s' configuration option is not "
- "understood and will be ignored.", key);
- return (-1);
}
return (0);
int i;
- int ppid;
int name_len;
derive_t cpu_user_counter;
fields[1][name_len] = '\0';
strncpy (ps->name, fields[1], PROCSTAT_NAME_LEN);
- ppid = atoi (fields[3]);
*state = fields[2][0];
void module_register (void)
{
- plugin_register_config ("processes", ps_config,
- config_keys, config_keys_num);
+ plugin_register_complex_config ("processes", ps_config);
plugin_register_init ("processes", ps_init);
plugin_register_read ("processes", ps_read);
} /* void module_register */
if (!meta)
return NULL;
+ l = PyDict_Items(meta); /* New reference. */
+ if (!l) {
+ cpy_log_exception("building meta data");
+ return NULL;
+ }
m = meta_data_create();
- l = PyDict_Items(meta);
s = PyList_Size(l);
for (i = 0; i < s; ++i) {
const char *string, *keystring;
Py_XDECREF(value);
Py_DECREF(key);
}
+ Py_XDECREF(l);
return m;
}
value = malloc(size * sizeof(*value));
for (i = 0; i < size; ++i) {
PyObject *item, *num;
- item = PySequence_GetItem(values, i);
+ item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
if (ds->ds->type == DS_TYPE_COUNTER) {
- num = PyNumber_Long(item);
- if (num != NULL)
+ num = PyNumber_Long(item); /* New reference. */
+ if (num != NULL) {
value[i].counter = PyLong_AsUnsignedLongLong(num);
+ Py_XDECREF(num);
+ }
} else if (ds->ds->type == DS_TYPE_GAUGE) {
- num = PyNumber_Float(item);
- if (num != NULL)
+ num = PyNumber_Float(item); /* New reference. */
+ if (num != NULL) {
value[i].gauge = PyFloat_AsDouble(num);
+ Py_XDECREF(num);
+ }
} else if (ds->ds->type == DS_TYPE_DERIVE) {
/* This might overflow without raising an exception.
* Not much we can do about it */
- num = PyNumber_Long(item);
- if (num != NULL)
+ num = PyNumber_Long(item); /* New reference. */
+ if (num != NULL) {
value[i].derive = PyLong_AsLongLong(num);
+ Py_XDECREF(num);
+ }
} else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
/* This might overflow without raising an exception.
* Not much we can do about it */
- num = PyNumber_Long(item);
- if (num != NULL)
+ num = PyNumber_Long(item); /* New reference. */
+ if (num != NULL) {
value[i].absolute = PyLong_AsUnsignedLongLong(num);
+ Py_XDECREF(num);
+ }
} else {
free(value);
PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
Py_BEGIN_ALLOW_THREADS;
ret = plugin_dispatch_values(&value_list);
Py_END_ALLOW_THREADS;
+ meta_data_destroy(value_list.meta);
+ free(value);
if (ret != 0) {
PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
return NULL;
}
- free(value);
Py_RETURN_NONE;
}
value = malloc(size * sizeof(*value));
for (i = 0; i < size; ++i) {
PyObject *item, *num;
- item = PySequence_GetItem(values, i);
+ item = PySequence_Fast_GET_ITEM(values, i); /* Borrowed reference. */
if (ds->ds->type == DS_TYPE_COUNTER) {
- num = PyNumber_Long(item);
- if (num != NULL)
+ num = PyNumber_Long(item); /* New reference. */
+ if (num != NULL) {
value[i].counter = PyLong_AsUnsignedLongLong(num);
+ Py_XDECREF(num);
+ }
} else if (ds->ds->type == DS_TYPE_GAUGE) {
- num = PyNumber_Float(item);
- if (num != NULL)
+ num = PyNumber_Float(item); /* New reference. */
+ if (num != NULL) {
value[i].gauge = PyFloat_AsDouble(num);
+ Py_XDECREF(num);
+ }
} else if (ds->ds->type == DS_TYPE_DERIVE) {
/* This might overflow without raising an exception.
* Not much we can do about it */
- num = PyNumber_Long(item);
- if (num != NULL)
+ num = PyNumber_Long(item); /* New reference. */
+ if (num != NULL) {
value[i].derive = PyLong_AsLongLong(num);
+ Py_XDECREF(num);
+ }
} else if (ds->ds->type == DS_TYPE_ABSOLUTE) {
/* This might overflow without raising an exception.
* Not much we can do about it */
- num = PyNumber_Long(item);
- if (num != NULL)
+ num = PyNumber_Long(item); /* New reference. */
+ if (num != NULL) {
value[i].absolute = PyLong_AsUnsignedLongLong(num);
+ Py_XDECREF(num);
+ }
} else {
free(value);
PyErr_Format(PyExc_RuntimeError, "unknown data type %d for %s", ds->ds->type, type);
Py_BEGIN_ALLOW_THREADS;
ret = plugin_write(dest, NULL, &value_list);
Py_END_ALLOW_THREADS;
+ meta_data_destroy(value_list.meta);
+ free(value);
if (ret != 0) {
PyErr_SetString(PyExc_RuntimeError, "error dispatching values, read the logs");
return NULL;
}
- free(value);
Py_RETURN_NONE;
}
}
else if (strcasecmp ("StepSize", key) == 0)
{
- int temp = atoi (value);
+ unsigned long temp = strtoul (value, NULL, 0);
if (temp > 0)
rrdcreate_config.stepsize = temp;
}
return (0);
init_once = 1;
- if (rrdcreate_config.stepsize < 0)
- rrdcreate_config.stepsize = 0;
if (rrdcreate_config.heartbeat <= 0)
rrdcreate_config.heartbeat = 2 * rrdcreate_config.stepsize;
}
queue_thread_running = 1;
- DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %i;"
+ DEBUG ("rrdtool plugin: rrd_init: datadir = %s; stepsize = %lu;"
" heartbeat = %i; rrarows = %i; xff = %lf;",
(datadir == NULL) ? "(null)" : datadir,
rrdcreate_config.stepsize,
char *buffer_ptr;
buffer_ptr = fgets (buffer, sizeof (buffer), global_read_fh);
+ if (buffer_ptr == NULL)
+ {
+ WARNING ("teamspeak2 plugin: Unexpected EOF received "
+ "from remote host %s:%s.",
+ config_host ? config_host : DEFAULT_HOST,
+ config_port ? config_port : DEFAULT_PORT);
+ }
buffer[sizeof (buffer) - 1] = 0;
if (memcmp ("[TS]\r\n", buffer, 6) != 0)
int nexthdr;
struct in6_addr s_addr;
- struct in6_addr d_addr;
uint16_t payload_len;
if (0 > len)
offset = sizeof (struct ip6_hdr);
nexthdr = ipv6->ip6_nxt;
s_addr = ipv6->ip6_src;
- d_addr = ipv6->ip6_dst;
payload_len = ntohs (ipv6->ip6_plen);
if (ignore_list_match (&s_addr))
return (status);
BUFFER_ADD (",\"dsnames\":%s", temp);
- BUFFER_ADD (",\"time\":%lu", (unsigned long) vl->time);
+ BUFFER_ADD (",\"time\":%.3f", CDTIME_T_TO_DOUBLE (vl->time));
BUFFER_ADD (",\"interval\":%.3f", CDTIME_T_TO_DOUBLE (vl->interval));
#define BUFFER_ADD_KEYVAL(key, value) do { \
if (rra_num >= rra_max)
break;
- status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%3.1f:%u:%u",
+ status = ssnprintf (buffer, sizeof (buffer), "RRA:%s:%.10f:%u:%u",
rra_types[j], cfg->xff, cdp_len, cdp_num);
if ((status < 0) || ((size_t) status >= sizeof (buffer)))
int ds_num;
int status = 0;
time_t last_up;
- int stepsize;
+ unsigned long stepsize;
if (check_create_dir (filename))
return (-1);
if (cfg->stepsize > 0)
stepsize = cfg->stepsize;
else
- stepsize = (int) CDTIME_T_TO_TIME_T (vl->interval);
+ stepsize = (unsigned long) CDTIME_T_TO_TIME_T (vl->interval);
- status = srrd_create (filename,
- (cfg->stepsize > 0) ? cfg->stepsize : CDTIME_T_TO_TIME_T (vl->interval),
- last_up,
+ status = srrd_create (filename, stepsize, last_up,
argc, (const char **) argv);
free (argv);
struct rrdcreate_config_s
{
- int stepsize;
+ unsigned long stepsize;
int heartbeat;
int rrarows;
double xff;
/* outstanding allocations */
varnish_submit_gauge (conf->instance, "sm", "requests", "outstanding", VSL_stats->sm_nobj);
/* bytes allocated */
- varnish_submit_gauge (conf->instance, "sm", "total_bytes", "allocated", VSL_stats->sm_balloc);
+ varnish_submit_derive (conf->instance, "sm", "total_bytes", "allocated", VSL_stats->sm_balloc);
/* bytes free */
- varnish_submit_gauge (conf->instance, "sm", "total_bytes", "free", VSL_stats->sm_bfree);
+ varnish_submit_derive (conf->instance, "sm", "total_bytes", "free", VSL_stats->sm_bfree);
}
if (conf->collect_sma)
/* SMA outstanding bytes */
varnish_submit_gauge (conf->instance, "sma", "bytes", "outstanding", VSL_stats->sma_nbytes);
/* SMA bytes allocated */
- varnish_submit_gauge (conf->instance, "sma", "total_bytes", "allocated", VSL_stats->sma_balloc);
+ varnish_submit_derive (conf->instance, "sma", "total_bytes", "allocated", VSL_stats->sma_balloc);
/* SMA bytes free */
- varnish_submit_gauge (conf->instance, "sma", "total_bytes", "free" , VSL_stats->sma_bfree);
+ varnish_submit_derive (conf->instance, "sma", "total_bytes", "free" , VSL_stats->sma_bfree);
}
if (conf->collect_sms)
/* SMS outstanding bytes */
varnish_submit_gauge (conf->instance, "sms", "bytes", "outstanding", VSL_stats->sms_nbytes);
/* SMS bytes allocated */
- varnish_submit_gauge (conf->instance, "sms", "total_bytes", "allocated", VSL_stats->sms_balloc);
+ varnish_submit_derive (conf->instance, "sms", "total_bytes", "allocated", VSL_stats->sms_balloc);
/* SMS bytes freed */
- varnish_submit_gauge (conf->instance, "sms", "total_bytes", "free", VSL_stats->sms_bfree);
+ varnish_submit_derive (conf->instance, "sms", "total_bytes", "free", VSL_stats->sms_bfree);
}
if (conf->collect_totals)
/* worker threads */
varnish_submit_gauge (conf->instance, "workers", "threads", "worker", VSL_stats->n_wrk);
/* worker threads created */
- varnish_submit_gauge (conf->instance, "workers", "total_threads", "created", VSL_stats->n_wrk_create);
+ varnish_submit_derive (conf->instance, "workers", "total_threads", "created", VSL_stats->n_wrk_create);
/* worker threads not created */
- varnish_submit_gauge (conf->instance, "workers", "total_threads", "failed", VSL_stats->n_wrk_failed);
+ varnish_submit_derive (conf->instance, "workers", "total_threads", "failed", VSL_stats->n_wrk_failed);
/* worker threads limited */
- varnish_submit_gauge (conf->instance, "workers", "total_threads", "limited", VSL_stats->n_wrk_max);
+ varnish_submit_derive (conf->instance, "workers", "total_threads", "limited", VSL_stats->n_wrk_max);
/* queued work requests */
- varnish_submit_gauge (conf->instance, "workers", "total_requests", "queued", VSL_stats->n_wrk_queue);
+ varnish_submit_derive (conf->instance, "workers", "total_requests", "queued", VSL_stats->n_wrk_queue);
/* overflowed work requests */
- varnish_submit_gauge (conf->instance, "workers", "total_requests", "overflowed", VSL_stats->n_wrk_overflow);
+ varnish_submit_derive (conf->instance, "workers", "total_requests", "overflowed", VSL_stats->n_wrk_overflow);
/* dropped work requests */
- varnish_submit_gauge (conf->instance, "workers", "total_requests", "dropped", VSL_stats->n_wrk_drop);
+ varnish_submit_derive (conf->instance, "workers", "total_requests", "dropped", VSL_stats->n_wrk_drop);
}
} /* }}} void varnish_monitor */
return (-1);
}
+ curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1);
curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
headers = NULL;
#!/bin/sh
-DEFAULT_VERSION="5.0.0.git"
+DEFAULT_VERSION="5.0.2.git"
VERSION="`git describe 2> /dev/null | sed -e 's/^collectd-//'`"