libformat_graphite.la \
libformat_json.la \
libheap.la \
+ libignorelist.la \
liblatency.la \
liblookup.la \
libmetadata.la \
src/daemon/utils_cache.h \
src/daemon/utils_complain.c \
src/daemon/utils_complain.h \
- src/daemon/utils_ignorelist.c \
- src/daemon/utils_ignorelist.h \
src/daemon/utils_llist.c \
src/daemon/utils_llist.h \
src/daemon/utils_random.c \
src/daemon/utils_heap.c \
src/daemon/utils_heap.h
+libignorelist_la_SOURCES = \
+ src/utils_ignorelist.c \
+ src/utils_ignorelist.h
+
libmetadata_la_SOURCES = \
src/daemon/meta_data.c \
src/daemon/meta_data.h
src/daemon/utils_cache_mock.c \
src/daemon/utils_complain.c \
src/daemon/utils_complain.h \
- src/daemon/utils_ignorelist.c \
- src/daemon/utils_ignorelist.h \
src/daemon/utils_time.c \
src/daemon/utils_time.h
libplugin_mock_la_CPPFLAGS = $(AM_CPPFLAGS) -DMOCK_TIME
-libplugin_mock_la_LIBADD = libcommon.la $(COMMON_LIBS)
+libplugin_mock_la_LIBADD = libcommon.la libignorelist.la $(COMMON_LIBS)
libformat_graphite_la_SOURCES = \
src/utils_format_graphite.c \
pkglib_LTLIBRARIES += cgroups.la
cgroups_la_SOURCES = src/cgroups.c
cgroups_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-cgroups_la_LIBADD = libmount.la
+cgroups_la_LIBADD = libignorelist.la libmount.la
endif
if BUILD_PLUGIN_CHRONY
pkglib_LTLIBRARIES += df.la
df_la_SOURCES = src/df.c
df_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-df_la_LIBADD = libmount.la
+df_la_LIBADD = libignorelist.la libmount.la
endif
if BUILD_PLUGIN_DISK
disk_la_CFLAGS = $(AM_CFLAGS)
disk_la_CPPFLAGS = $(AM_CPPFLAGS)
disk_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-disk_la_LIBADD =
+disk_la_LIBADD = libignorelist.la
if BUILD_WITH_LIBKSTAT
disk_la_LIBADD += -lkstat
endif
interface_la_SOURCES = src/interface.c
interface_la_CFLAGS = $(AM_CFLAGS)
interface_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-interface_la_LIBADD =
+interface_la_LIBADD = libignorelist.la
if BUILD_WITH_LIBSTATGRAB
interface_la_CFLAGS += $(BUILD_WITH_LIBSTATGRAB_CFLAGS)
interface_la_LIBADD += $(BUILD_WITH_LIBSTATGRAB_LDFLAGS)
ipmi_la_SOURCES = src/ipmi.c
ipmi_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_OPENIPMI_CFLAGS)
ipmi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-ipmi_la_LIBADD = $(BUILD_WITH_OPENIPMI_LIBS)
+ipmi_la_LIBADD = libignorelist.la $(BUILD_WITH_OPENIPMI_LIBS)
endif
if BUILD_PLUGIN_IPVS
pkglib_LTLIBRARIES += irq.la
irq_la_SOURCES = src/irq.c
irq_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+irq_la_LIBADD = libignorelist.la
endif
if BUILD_PLUGIN_JAVA
src/madwifi.c \
src/madwifi.h
madwifi_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+madwifi_la_LIBADD = libignorelist.la
endif
if BUILD_PLUGIN_MATCH_EMPTY_COUNTER
pkglib_LTLIBRARIES += md.la
md_la_SOURCES = src/md.c
md_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+md_la_LIBADD = libignorelist.la
endif
if BUILD_PLUGIN_MEMCACHEC
mic_la_SOURCES = src/mic.c
mic_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_MIC_CPPFLAGS)
mic_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_MIC_LDFLAGS)
-mic_la_LIBADD = $(BUILD_WITH_MIC_LIBS)
+mic_la_LIBADD = libignorelist.la $(BUILD_WITH_MIC_LIBS)
endif
if BUILD_PLUGIN_MODBUS
netapp_la_SOURCES = src/netapp.c
netapp_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBNETAPP_CPPFLAGS)
netapp_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBNETAPP_LDFLAGS)
-netapp_la_LIBADD = $(LIBNETAPP_LIBS)
+netapp_la_LIBADD = libignorelist.la $(LIBNETAPP_LIBS)
endif
if BUILD_PLUGIN_NETLINK
pkglib_LTLIBRARIES += onewire.la
onewire_la_SOURCES = src/onewire.c
onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
-onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOWCAPI_LDFLAGS)
+onewire_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBOWCAPI_LIBS)
endif
if BUILD_PLUGIN_OPENLDAP
pkglib_LTLIBRARIES += protocols.la
protocols_la_SOURCES = src/protocols.c
protocols_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+protocols_la_LIBADD = libignorelist.la
endif
if BUILD_PLUGIN_REDIS
sensors_la_SOURCES = src/sensors.c
sensors_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBSENSORS_CPPFLAGS)
sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBSENSORS_LDFLAGS)
-sensors_la_LIBADD = $(BUILD_WITH_LIBSENSORS_LIBS)
+sensors_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBSENSORS_LIBS)
endif
if BUILD_PLUGIN_SERIAL
smart_la_SOURCES = src/smart.c
smart_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBATASMART_CPPFLAGS) $(BUILD_WITH_LIBUDEV_CPPFLAGS)
smart_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBATASMART_LDFLAGS) $(BUILD_WITH_LIBUDEV_LDFLAGS)
-smart_la_LIBADD = $(BUILD_WITH_LIBATASMART_LIBS) $(BUILD_WITH_LIBUDEV_LIBS)
+smart_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBATASMART_LIBS) $(BUILD_WITH_LIBUDEV_LIBS)
endif
endif
pkglib_LTLIBRARIES += thermal.la
thermal_la_SOURCES = src/thermal.c
thermal_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+thermal_la_LIBADD = libignorelist.la
endif
if BUILD_PLUGIN_THRESHOLD
virt_la_SOURCES = src/virt.c
virt_la_CFLAGS = $(AM_CFLAGS) \
$(BUILD_WITH_LIBVIRT_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
-virt_la_LIBADD = $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
virt_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+virt_la_LIBADD = libignorelist.la $(BUILD_WITH_LIBVIRT_LIBS) $(BUILD_WITH_LIBXML2_LIBS)
# TODO: enable once we support only modern libvirts which depends on libnl-3
# the libvirt on wheezy is linked in libnl v1, and there is a small leak here,
if BUILD_PLUGIN_WRITE_MONGODB
pkglib_LTLIBRARIES += write_mongodb.la
write_mongodb_la_SOURCES = src/write_mongodb.c
-write_mongodb_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBMONGOC_CPPFLAGS)
+write_mongodb_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMONGOC_CFLAGS)
write_mongodb_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBMONGOC_LDFLAGS)
-write_mongodb_la_LIBADD = -lmongoc
endif
if BUILD_PLUGIN_WRITE_PROMETHEUS
done
}
-check_for_application lex bison autoheader aclocal automake autoconf
-
-# Actually we don't need the pkg-config executable, but we need the M4 macros.
-# We check for `pkg-config' here and hope that M4 macros will then be
-# available, too.
-check_for_application pkg-config
+check_for_application lex bison autoheader aclocal automake autoconf pkg-config
libtoolize=""
libtoolize --version >/dev/null 2>/dev/null
else if test "x$withval" = "xno"; then
with_libmongoc="no"
else
- with_libmongoc="yes"
- LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS -I$withval/include"
- LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS -L$withval/lib"
+ with_libmongoc="no"
fi; fi
],
[with_libmongoc="yes"]
)
-SAVE_CPPFLAGS="$CPPFLAGS"
-SAVE_LDFLAGS="$LDFLAGS"
-
-CPPFLAGS="$CPPFLAGS $LIBMONGOC_CPPFLAGS"
-LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
+if test "x$with_libmongoc" = "xyes"; then
+ PKG_CHECK_MODULES([LIBMONGOC], [libmongoc-1.0],
+ [with_libmongoc="yes"],
+ [with_libmongoc="no (pkg-config could not find libmongoc)"]
+ )
+fi
if test "x$with_libmongoc" = "xyes"; then
- if test "x$LIBMONGOC_CPPFLAGS" != "x"; then
- AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CPPFLAGS])
+ SAVE_CPPFLAGS="$CPPFLAGS"
+
+ CPPFLAGS="$CPPFLAGS $LIBMONGOC_CFLAGS"
+
+ if test "x$CPPFLAGS" != "x"; then
+ AC_MSG_NOTICE([libmongoc CPPFLAGS: $LIBMONGOC_CFLAGS])
fi
- AC_CHECK_HEADERS([mongo.h],
+ AC_CHECK_HEADERS([mongoc.h],
[with_libmongoc="yes"],
- [with_libmongoc="no ('mongo.h' not found)"],
- [[#define MONGO_HAVE_STDINT 1]]
+ [with_libmongoc="no ('mongoc.h' not found)"]
)
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
fi
if test "x$with_libmongoc" = "xyes"; then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+
+ CPPFLAGS="$CPPFLAGS $LIBMONGOC_CFLAGS"
+ LDFLAGS="$LDFLAGS $LIBMONGOC_LDFLAGS"
+
if test "x$LIBMONGOC_LDFLAGS" != "x"; then
AC_MSG_NOTICE([libmongoc LDFLAGS: $LIBMONGOC_LDFLAGS])
fi
- AC_CHECK_LIB([mongoc], [mongo_run_command],
+ AC_CHECK_LIB([mongoc-1.0], [mongoc_init],
[with_libmongoc="yes"],
- [with_libmongoc="no (symbol 'mongo_run_command' not found)"]
+ [with_libmongoc="no (symbol 'mongoc_init' not found)"]
)
-fi
-CPPFLAGS="$SAVE_CPPFLAGS"
-LDFLAGS="$SAVE_LDFLAGS"
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
if test "x$with_libmongoc" = "xyes"; then
- BUILD_WITH_LIBMONGOC_CPPFLAGS="$LIBMONGOC_CPPFLAGS"
+ BUILD_WITH_LIBMONGOC_CFLAGS="$LIBMONGOC_CFLAGS"
BUILD_WITH_LIBMONGOC_LDFLAGS="$LIBMONGOC_LDFLAGS"
fi
-AC_SUBST([BUILD_WITH_LIBMONGOC_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBMONGOC_CFLAGS])
AC_SUBST([BUILD_WITH_LIBMONGOC_LDFLAGS])
# }}}
if test "x$c_cv_have_clock_boottime_monotonic" = "xyes"; then
plugin_cpusleep="yes"
fi
+
+ if test "x$with_libyajl" = "xyes" && test "x$with_libyajl2" = "xyes"; then
+ plugin_ovs_events="yes"
+ plugin_ovs_stats="yes"
+ fi
fi
if test "x$ac_system" = "xOpenBSD"; then
plugin_log_logstash="yes"
fi
-if test "x$with_libyajl" = "xyes" && test "x$with_libyajl2" = "xyes"; then
- plugin_ovs_events="yes"
- plugin_ovs_stats="yes"
-fi
-
if test "x$with_libperl" = "xyes" && test "x$c_cv_have_perl_ithreads" = "xyes"; then
plugin_perl="yes"
fi
* The same PCI device configuration should be passed to the primary process as
the secondary process uses the same port indexes as the primary.
* A blacklist / whitelist of NICs isn't supported yet.
+ * Plugin initialization time depends on read interval. It requires 5 read
+ cycles to set up internal buffers and states. During that time no statistics
+ are submitted.
+ * If number of DPDK ports is increased while plugin is running, internal
+ buffers are resized. That requires 3 read cycles and no port statistics
+ are submitted in that time.
## License
# Address "127.0.0.1"
# Socket "/var/run/openvswitch/db.sock"
# Interfaces "br0" "veth0"
-# SendNotification false
-# DispatchValues true
+# SendNotification true
+# DispatchValues false
#</Plugin>
#<Plugin ovs_stats>
#</Plugin>
#<Plugin processes>
+# CollectFileDescriptor true
+# CollectContextSwitch true
# Process "name"
+# ProcessMatch "name" "regex"
+# <Process "collectd">
+# CollectFileDescriptor false
+# CollectContextSwitch false
+# </Process>
+# <ProcessMatch "name" "regex">
+# CollectFileDescriptor false
+# CollectContextSwitch true
+# </Process>
#</Plugin>
#<Plugin protocols>
# Header "X-Custom-Header: custom_value"
# SSLVersion "TLSv1"
# Format "Command"
+# Attribute "key" "value" # only available for KAIROSDB format
# Metrics true
# Notifications false
# StoreRates false
Address "127.0.0.1"
Socket "/var/run/openvswitch/db.sock"
Interfaces "br0" "veth0"
- SendNotification false
- DispatchValues true
+ SendNotification true
+ DispatchValues false
</Plugin>
The plugin provides the following configuration options:
=item B<SendNotification> I<true|false>
If set to true, OVS link notifications (interface status and OVS DB connection
-terminate) are sent to collectd. Default value is false.
+terminate) are sent to collectd. Default value is true.
=item B<DispatchValues> I<true|false>
Dispatch the OVS DB interface link status value with configured plugin interval.
-Defaults to true. Please note, if B<SendNotification> and B<DispatchValues>
+Defaults to false. Please note, if B<SendNotification> and B<DispatchValues>
options are false, no OVS information will be provided by the plugin.
=back
=item B<Process> I<Name>
Select more detailed statistics of processes matching this name. The statistics
-collected for these selected processes are size of the resident segment size
-(RSS), user- and system-time used, number of processes and number of threads,
-io data (where available) and minor and major pagefaults.
+collected for these selected processes are:
+ - size of the resident segment size (RSS)
+ - user- and system-time used
+ - number of processes
+ - number of threads
+ - number of open files (under Linux)
+ - io data (where available)
+ - context switches (under Linux)
+ - minor and major pagefaults.
Some platforms have a limit on the length of process names. I<Name> must stay
below this limit.
Defaults to B<Command>.
+=item B<Attribute> I<String> I<String>
+
+Only available for KAIROSDB output format.
+
+Consider the two given strings to be the key and value of an additional tag for
+each metric being sent out.
+
+You can add multiple B<Attribute>.
+
=item B<Metrics> B<true>|B<false>
Controls whether I<metrics> are POSTed to this location. Defaults to B<true>.
+++ /dev/null
-/**
- * collectd - src/utils_ignorelist.c
- * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
- * Copyright (C) 2008 Florian Forster <octo at collectd.org>
- *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
- *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public 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:
- * Lubos Stanek <lubek at users.sourceforge.net>
- * Florian Forster <octo at collectd.org>
- **/
-/**
- * ignorelist handles plugin's list of configured collectable
- * entries with global ignore action
- **/
-/**
- * Usage:
- *
- * Define plugin's global pointer variable of type ignorelist_t:
- * ignorelist_t *myconfig_ignore;
- * If you know the state of the global ignore (IgnoreSelected),
- * allocate the variable with:
- * myconfig_ignore = ignorelist_create (YourKnownIgnore);
- * If you do not know the state of the global ignore,
- * initialize the global variable and set the ignore flag later:
- * myconfig_ignore = ignorelist_init ();
- * Append single entries in your cf_register'ed callback function:
- * ignorelist_add (myconfig_ignore, newentry);
- * When you hit the IgnoreSelected config option,
- * offer it to the list:
- * ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
- * That is all for the ignorelist initialization.
- * Later during read and write (plugin's registered functions) get
- * the information whether this entry would be collected or not:
- * if (ignorelist_match (myconfig_ignore, thisentry))
- * return;
- **/
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "common.h"
-#include "plugin.h"
-#include "utils_ignorelist.h"
-
-/*
- * private prototypes
- */
-struct ignorelist_item_s {
-#if HAVE_REGEX_H
- regex_t *rmatch; /* regular expression entry identification */
-#endif
- char *smatch; /* string entry identification */
- struct ignorelist_item_s *next;
-};
-typedef struct ignorelist_item_s ignorelist_item_t;
-
-struct ignorelist_s {
- int ignore; /* ignore entries */
- ignorelist_item_t *head; /* pointer to the first entry */
-};
-
-/* *** *** *** ********************************************* *** *** *** */
-/* *** *** *** *** *** *** private functions *** *** *** *** *** *** */
-/* *** *** *** ********************************************* *** *** *** */
-
-static inline void ignorelist_append(ignorelist_t *il,
- ignorelist_item_t *item) {
- assert((il != NULL) && (item != NULL));
-
- item->next = il->head;
- il->head = item;
-}
-
-#if HAVE_REGEX_H
-static int ignorelist_append_regex(ignorelist_t *il, const char *re_str) {
- regex_t *re;
- ignorelist_item_t *entry;
- int status;
-
- re = calloc(1, sizeof(*re));
- if (re == NULL) {
- ERROR("ignorelist_append_regex: calloc failed.");
- return (ENOMEM);
- }
-
- status = regcomp(re, re_str, REG_EXTENDED);
- if (status != 0) {
- char errbuf[1024];
- (void)regerror(status, re, errbuf, sizeof(errbuf));
- ERROR("utils_ignorelist: regcomp failed: %s", errbuf);
- ERROR("ignorelist_append_regex: Compiling regular expression \"%s\" "
- "failed: %s",
- re_str, errbuf);
- sfree(re);
- return (status);
- }
-
- entry = calloc(1, sizeof(*entry));
- if (entry == NULL) {
- ERROR("ignorelist_append_regex: calloc failed.");
- regfree(re);
- sfree(re);
- return (ENOMEM);
- }
- entry->rmatch = re;
-
- ignorelist_append(il, entry);
- return (0);
-} /* int ignorelist_append_regex */
-#endif
-
-static int ignorelist_append_string(ignorelist_t *il, const char *entry) {
- ignorelist_item_t *new;
-
- /* create new entry */
- if ((new = calloc(1, sizeof(*new))) == NULL) {
- ERROR("cannot allocate new entry");
- return (1);
- }
- new->smatch = sstrdup(entry);
-
- /* append new entry */
- ignorelist_append(il, new);
-
- return (0);
-} /* int ignorelist_append_string(ignorelist_t *il, const char *entry) */
-
-#if HAVE_REGEX_H
-/*
- * check list for entry regex match
- * return 1 if found
- */
-static int ignorelist_match_regex(ignorelist_item_t *item, const char *entry) {
- assert((item != NULL) && (item->rmatch != NULL) && (entry != NULL) &&
- (strlen(entry) > 0));
-
- /* match regex */
- if (regexec(item->rmatch, entry, 0, NULL, 0) == 0)
- return (1);
-
- return (0);
-} /* int ignorelist_match_regex (ignorelist_item_t *item, const char *entry) */
-#endif
-
-/*
- * check list for entry string match
- * return 1 if found
- */
-static int ignorelist_match_string(ignorelist_item_t *item, const char *entry) {
- assert((item != NULL) && (item->smatch != NULL) && (entry != NULL) &&
- (strlen(entry) > 0));
-
- if (strcmp(entry, item->smatch) == 0)
- return (1);
-
- return (0);
-} /* int ignorelist_match_string (ignorelist_item_t *item, const char *entry) */
-
-/* *** *** *** ******************************************** *** *** *** */
-/* *** *** *** *** *** *** public functions *** *** *** *** *** *** */
-/* *** *** *** ******************************************** *** *** *** */
-
-/*
- * create the ignorelist_t with known ignore state
- * return pointer to ignorelist_t
- */
-ignorelist_t *ignorelist_create(int invert) {
- ignorelist_t *il;
-
- il = calloc(1, sizeof(*il));
- if (il == NULL)
- return NULL;
-
- /*
- * ->ignore == 0 => collect
- * ->ignore == 1 => ignore
- */
- il->ignore = invert ? 0 : 1;
-
- return (il);
-} /* ignorelist_t *ignorelist_create (int ignore) */
-
-/*
- * free memory used by ignorelist_t
- */
-void ignorelist_free(ignorelist_t *il) {
- ignorelist_item_t *this;
- ignorelist_item_t *next;
-
- if (il == NULL)
- return;
-
- for (this = il->head; this != NULL; this = next) {
- next = this->next;
-#if HAVE_REGEX_H
- if (this->rmatch != NULL) {
- regfree(this->rmatch);
- sfree(this->rmatch);
- this->rmatch = NULL;
- }
-#endif
- if (this->smatch != NULL) {
- sfree(this->smatch);
- this->smatch = NULL;
- }
- sfree(this);
- }
-
- sfree(il);
-} /* void ignorelist_destroy (ignorelist_t *il) */
-
-/*
- * set ignore state of the ignorelist_t
- */
-void ignorelist_set_invert(ignorelist_t *il, int invert) {
- if (il == NULL) {
- DEBUG("ignore call with ignorelist_t == NULL");
- return;
- }
-
- il->ignore = invert ? 0 : 1;
-} /* void ignorelist_set_invert (ignorelist_t *il, int ignore) */
-
-/*
- * append entry into ignorelist_t
- * return 0 for success
- */
-int ignorelist_add(ignorelist_t *il, const char *entry) {
- size_t len;
-
- if (il == NULL) {
- DEBUG("add called with ignorelist_t == NULL");
- return (1);
- }
-
- len = strlen(entry);
-
- /* append nothing */
- if (len == 0) {
- DEBUG("not appending: empty entry");
- return (1);
- }
-
-#if HAVE_REGEX_H
- /* regex string is enclosed in "/.../" */
- if ((len > 2) && (entry[0] == '/') && entry[len - 1] == '/') {
- char *copy;
- int status;
-
- /* skip leading slash */
- copy = strdup(entry + 1);
- if (copy == NULL)
- return ENOMEM;
-
- /* trim trailing slash */
- copy[strlen(copy) - 1] = 0;
-
- status = ignorelist_append_regex(il, copy);
- sfree(copy);
- return status;
- }
-#endif
-
- return ignorelist_append_string(il, entry);
-} /* int ignorelist_add (ignorelist_t *il, const char *entry) */
-
-/*
- * check list for entry
- * return 1 for ignored entry
- */
-int ignorelist_match(ignorelist_t *il, const char *entry) {
- /* if no entries, collect all */
- if ((il == NULL) || (il->head == NULL))
- return (0);
-
- if ((entry == NULL) || (strlen(entry) == 0))
- return (0);
-
- /* traverse list and check entries */
- for (ignorelist_item_t *traverse = il->head; traverse != NULL;
- traverse = traverse->next) {
-#if HAVE_REGEX_H
- if (traverse->rmatch != NULL) {
- if (ignorelist_match_regex(traverse, entry))
- return (il->ignore);
- } else
-#endif
- {
- if (ignorelist_match_string(traverse, entry))
- return (il->ignore);
- }
- } /* for traverse */
-
- return (1 - il->ignore);
-} /* int ignorelist_match (ignorelist_t *il, const char *entry) */
+++ /dev/null
-/**
- * collectd - src/utils_ignorelist.h
- * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
- *
- * This program is free software; you can redistribute it and/
- * or modify it under the terms of the GNU General Public Li-
- * cence as published by the Free Software Foundation; either
- * version 2 of the Licence, or any later version.
- *
- * This program is distributed in the hope that it will be use-
- * ful, but WITHOUT ANY WARRANTY; without even the implied war-
- * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
- * See the GNU General Public Licence for more details.
- *
- * You should have received a copy of the GNU General Public 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:
- * Lubos Stanek <lubek at users.sourceforge.net>
- **/
-/**
- * ignorelist handles plugin's list of configured collectable
- * entries with global ignore action
- **/
-
-#ifndef UTILS_IGNORELIST_H
-#define UTILS_IGNORELIST_H 1
-
-#include "collectd.h"
-
-#if HAVE_REGEX_H
-#include <regex.h>
-#endif
-
-/* public prototypes */
-
-struct ignorelist_s;
-typedef struct ignorelist_s ignorelist_t;
-
-/*
- * create the ignorelist_t with known ignore state
- * return pointer to ignorelist_t
- */
-ignorelist_t *ignorelist_create(int invert);
-
-/*
- * free memory used by ignorelist_t
- */
-void ignorelist_free(ignorelist_t *il);
-
-/*
- * set ignore state of the ignorelist_t
- */
-void ignorelist_set_invert(ignorelist_t *il, int invert);
-
-/*
- * append entry to ignorelist_t
- * returns zero on success, non-zero upon failure.
- */
-int ignorelist_add(ignorelist_t *il, const char *entry);
-
-/*
- * check list for entry
- * return 1 for ignored entry
- */
-int ignorelist_match(ignorelist_t *il, const char *entry);
-
-#endif /* UTILS_IGNORELIST_H */
for (int i = 0; i < RTE_MAX_ETHPORTS; i++) {
ec->config.port_name[i][0] = 0;
}
+ /* Enable all ports by default */
+ ec->config.enabled_port_mask = ~0;
}
static int dpdk_stats_preinit(void) {
* `item' Config option containing core groups.
* `groups' Table of core groups to set values in.
* `max_groups' Maximum number of core groups allowed.
- * `max_core' Maximum allowed core value.
*
* RETURN VALUE
* On success, the number of core groups set up. On error, appropriate
* negative error value.
*/
static int oconfig_to_cgroups(oconfig_item_t *item, rdt_core_group_t *groups,
- size_t max_groups, uint64_t max_core) {
+ size_t max_groups) {
int index = 0;
assert(groups != NULL);
return (-EINVAL);
}
- for (int i = 0; i < n; i++) {
- if (cores[i] > max_core) {
- ERROR(RDT_PLUGIN ": Core group (%s) contains invalid core id (%d)",
- item->values[j].value.string, (int)cores[i]);
- return (-EINVAL);
- }
- }
-
/* set core group info */
ret = cgroup_set(&groups[index], item->values[j].value.string, cores, n);
if (ret < 0)
return g_rdt->pqos_cpu->num_cores;
}
+static int rdt_is_core_id_valid(int core_id) {
+
+ for (int i = 0; i < g_rdt->pqos_cpu->num_cores; i++)
+ if (core_id == g_rdt->pqos_cpu->cores[i].lcore)
+ return 1;
+
+ return 0;
+}
+
static int rdt_config_cgroups(oconfig_item_t *item) {
int n = 0;
enum pqos_mon_event events = 0;
DEBUG(RDT_PLUGIN ": [%d]: %s", j, item->values[j].value.string);
}
- n = oconfig_to_cgroups(item, g_rdt->cgroups, RDT_MAX_CORES,
- g_rdt->pqos_cpu->num_cores - 1);
+ n = oconfig_to_cgroups(item, g_rdt->cgroups, g_rdt->pqos_cpu->num_cores);
if (n < 0) {
rdt_free_cgroups();
ERROR(RDT_PLUGIN ": Error parsing core groups configuration.");
return (-EINVAL);
}
+ /* validate configured core id values */
+ for (int group_idx = 0; group_idx < n; group_idx++) {
+ for (int core_idx = 0; core_idx < g_rdt->cgroups[group_idx].num_cores;
+ core_idx++) {
+ if (!rdt_is_core_id_valid(g_rdt->cgroups[group_idx].cores[core_idx])) {
+ ERROR(RDT_PLUGIN ": Core group '%s' contains invalid core id '%d'",
+ g_rdt->cgroups[group_idx].desc,
+ (int)g_rdt->cgroups[group_idx].cores[core_idx]);
+ rdt_free_cgroups();
+ return (-EINVAL);
+ }
+ }
+ }
+
if (n == 0) {
/* create default core groups if "Cores" config option is empty */
n = rdt_default_cgroups();
*/
static ovs_events_ctx_t ovs_events_ctx = {
.mutex = PTHREAD_MUTEX_INITIALIZER,
- .config = {.ovs_db_node = "localhost", /* use default OVS DB node */
+ .config = {.send_notification = 1, /* send notification by default */
+ .ovs_db_node = "localhost", /* use default OVS DB node */
.ovs_db_serv = "6640"} /* use default OVS DB service */
};
* in allocated memory. Returns negative value in case of error.
*/
static int ovs_events_plugin_config(oconfig_item_t *ci) {
- _Bool dispatch_values = 1;
+ _Bool dispatch_values = 0;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
if (strcasecmp("SendNotification", child->key) == 0) {
if (br_ports && YAJL_IS_ARRAY(br_ports)) {
char *tmp = YAJL_GET_STRING(br_ports->u.array.values[0]);
if (tmp != NULL && strcmp("set", tmp) == 0) {
- yajl_val *ports_arr =
- YAJL_GET_ARRAY(br_ports->u.array.values[1])->values;
- size_t ports_num = YAJL_GET_ARRAY(br_ports->u.array.values[1])->len;
-
- for (size_t i = 0; i < ports_num; i++)
- ovs_stats_new_port(
- br, YAJL_GET_STRING(ports_arr[i]->u.array.values[1]));
+ yajl_val *array = YAJL_GET_ARRAY(br_ports)->values;
+ size_t array_len = YAJL_GET_ARRAY(br_ports)->len;
+ if (array != NULL && array_len > 0 && YAJL_IS_ARRAY(array[1])) {
+ yajl_val *ports_arr = YAJL_GET_ARRAY(array[1])->values;
+ size_t ports_num = YAJL_GET_ARRAY(array[1])->len;
+ for (size_t i = 0; i < ports_num && ports_arr != NULL; i++)
+ ovs_stats_new_port(
+ br, YAJL_GET_STRING(ports_arr[i]->u.array.values[1]));
+ }
} else
ovs_stats_new_port(br, YAJL_GET_STRING(br_ports->u.array.values[1]));
}
if (stats && YAJL_IS_ARRAY(stats))
for (size_t i = 0; i < YAJL_GET_ARRAY(stats)->len; i++) {
stat = YAJL_GET_ARRAY(stats)->values[i];
+ if (!YAJL_IS_ARRAY(stat))
+ return (-1);
counter_name = YAJL_GET_STRING(YAJL_GET_ARRAY(stat)->values[0]);
counter_index = ovs_stats_counter_name_to_type(counter_name);
counter_value = YAJL_GET_INTEGER(YAJL_GET_ARRAY(stat)->values[1]);
if (ext_ids && YAJL_IS_ARRAY(ext_ids))
for (size_t i = 0; i < YAJL_GET_ARRAY(ext_ids)->len; i++) {
ext_id = YAJL_GET_ARRAY(ext_ids)->values[i];
+ if (!YAJL_IS_ARRAY(ext_id))
+ return (-1);
key = YAJL_GET_STRING(YAJL_GET_ARRAY(ext_id)->values[0]);
value = YAJL_GET_STRING(YAJL_GET_ARRAY(ext_id)->values[1]);
if (key && value) {
* Manuel Sanmartin
* Clément Stenac <clement.stenac at diwi.org>
* Cosmin Ioiart <cioiart at gmail.com>
+ * Pavel Rochnyack <pavel2000 at ngs.ru>
**/
#include "collectd.h"
#endif
#endif
-typedef struct procstat_entry_s {
+#define PROCSTAT_NAME_LEN 256
+typedef struct process_entry_s {
unsigned long id;
- unsigned long age;
+ char name[PROCSTAT_NAME_LEN];
unsigned long num_proc;
unsigned long num_lwp;
+ unsigned long num_fd;
unsigned long vmem_size;
unsigned long vmem_rss;
unsigned long vmem_data;
derive_t cswitch_invol;
_Bool has_cswitch;
+ _Bool has_fd;
+} process_entry_t;
+
+typedef struct procstat_entry_s {
+ unsigned long id;
+ unsigned long age;
+
+ derive_t vmem_minflt_counter;
+ derive_t vmem_majflt_counter;
+
+ derive_t cpu_user_counter;
+ derive_t cpu_system_counter;
+
+ /* io data */
+ derive_t io_rchar;
+ derive_t io_wchar;
+ derive_t io_syscr;
+ derive_t io_syscw;
+
+ derive_t cswitch_vol;
+ derive_t cswitch_invol;
+
struct procstat_entry_s *next;
} procstat_entry_t;
-#define PROCSTAT_NAME_LEN 256
typedef struct procstat {
char name[PROCSTAT_NAME_LEN];
#if HAVE_REGEX_H
unsigned long num_proc;
unsigned long num_lwp;
+ unsigned long num_fd;
unsigned long vmem_size;
unsigned long vmem_rss;
unsigned long vmem_data;
derive_t cswitch_vol;
derive_t cswitch_invol;
+ _Bool report_fd_num;
+ _Bool report_ctx_switch;
+
struct procstat *next;
struct procstat_entry_s *instances;
} procstat_t;
static _Bool want_init = 1;
static _Bool report_ctx_switch = 0;
+static _Bool report_fd_num = 0;
#if HAVE_THREAD_INFO
static mach_port_t port_host_self;
#elif KERNEL_LINUX
static long pagesize_g;
-static void ps_fill_details(const procstat_t *ps, procstat_entry_t *entry);
+static void ps_fill_details(const procstat_t *ps, process_entry_t *entry);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKVM_GETPROCS && \
/* put name of process from config to list_head_g tree
* list_head_g is a list of 'procstat_t' structs with
* processes names we want to watch */
-static void ps_list_register(const char *name, const char *regexp) {
+static procstat_t *ps_list_register(const char *name, const char *regexp) {
procstat_t *new;
procstat_t *ptr;
int status;
new = calloc(1, sizeof(*new));
if (new == NULL) {
ERROR("processes plugin: ps_list_register: calloc failed.");
- return;
+ return (NULL);
}
sstrncpy(new->name, name, sizeof(new->name));
+ new->io_rchar = -1;
+ new->io_wchar = -1;
+ new->io_syscr = -1;
+ new->io_syscw = -1;
+ new->cswitch_vol = -1;
+ new->cswitch_invol = -1;
+
+ new->report_fd_num = report_fd_num;
+ new->report_ctx_switch = report_ctx_switch;
+
#if HAVE_REGEX_H
if (regexp != NULL) {
DEBUG("ProcessMatch: adding \"%s\" as criteria to process %s.", regexp,
if (new->re == NULL) {
ERROR("processes plugin: ps_list_register: malloc failed.");
sfree(new);
- return;
+ return (NULL);
}
status = regcomp(new->re, regexp, REG_EXTENDED | REG_NOSUB);
regexp);
sfree(new->re);
sfree(new);
- return;
+ return (NULL);
}
}
#else
"has been disabled at compile time.",
regexp);
sfree(new);
- return;
+ return (NULL);
}
#endif
sfree(new->re);
#endif
sfree(new);
- return;
+ return (NULL);
}
if (ptr->next == NULL)
list_head_g = new;
else
ptr->next = new;
+
+ return (new);
} /* void ps_list_register */
/* try to match name against entry, returns 1 if success */
else
curr_value = new_counter - *curr_counter;
+ if (*group_counter == -1)
+ *group_counter = 0;
+
*curr_counter = new_counter;
*group_counter += curr_value;
}
/* add process entry to 'instances' of process 'name' (or refresh it) */
static void ps_list_add(const char *name, const char *cmdline,
- procstat_entry_t *entry) {
+ process_entry_t *entry) {
procstat_entry_t *pse;
if (entry->id == 0)
}
pse->age = 0;
- pse->num_proc = entry->num_proc;
- pse->num_lwp = entry->num_lwp;
- pse->vmem_size = entry->vmem_size;
- pse->vmem_rss = entry->vmem_rss;
- pse->vmem_data = entry->vmem_data;
- pse->vmem_code = entry->vmem_code;
- pse->stack_size = entry->stack_size;
- pse->io_rchar = entry->io_rchar;
- pse->io_wchar = entry->io_wchar;
- pse->io_syscr = entry->io_syscr;
- pse->io_syscw = entry->io_syscw;
- pse->cswitch_vol = entry->cswitch_vol;
- pse->cswitch_invol = entry->cswitch_invol;
-
- ps->num_proc += pse->num_proc;
- ps->num_lwp += pse->num_lwp;
- ps->vmem_size += pse->vmem_size;
- ps->vmem_rss += pse->vmem_rss;
- ps->vmem_data += pse->vmem_data;
- ps->vmem_code += pse->vmem_code;
- ps->stack_size += pse->stack_size;
-
- ps->io_rchar += ((pse->io_rchar == -1) ? 0 : pse->io_rchar);
- ps->io_wchar += ((pse->io_wchar == -1) ? 0 : pse->io_wchar);
- ps->io_syscr += ((pse->io_syscr == -1) ? 0 : pse->io_syscr);
- ps->io_syscw += ((pse->io_syscw == -1) ? 0 : pse->io_syscw);
-
- ps->cswitch_vol += ((pse->cswitch_vol == -1) ? 0 : pse->cswitch_vol);
- ps->cswitch_invol += ((pse->cswitch_invol == -1) ? 0 : pse->cswitch_invol);
+
+ ps->num_proc += entry->num_proc;
+ ps->num_lwp += entry->num_lwp;
+ ps->num_fd += entry->num_fd;
+ ps->vmem_size += entry->vmem_size;
+ ps->vmem_rss += entry->vmem_rss;
+ ps->vmem_data += entry->vmem_data;
+ ps->vmem_code += entry->vmem_code;
+ ps->stack_size += entry->stack_size;
+
+ if ((entry->io_rchar != -1) && (entry->io_wchar != -1)) {
+ ps_update_counter(&ps->io_rchar, &pse->io_rchar, entry->io_rchar);
+ ps_update_counter(&ps->io_wchar, &pse->io_wchar, entry->io_wchar);
+ }
+
+ if ((entry->io_syscr != -1) && (entry->io_syscw != -1)) {
+ ps_update_counter(&ps->io_syscr, &pse->io_syscr, entry->io_syscr);
+ ps_update_counter(&ps->io_syscw, &pse->io_syscw, entry->io_syscw);
+ }
+
+ if ((entry->cswitch_vol != -1) && (entry->cswitch_vol != -1)) {
+ ps_update_counter(&ps->cswitch_vol, &pse->cswitch_vol,
+ entry->cswitch_vol);
+ ps_update_counter(&ps->cswitch_invol, &pse->cswitch_invol,
+ entry->cswitch_invol);
+ }
ps_update_counter(&ps->vmem_minflt_counter, &pse->vmem_minflt_counter,
entry->vmem_minflt_counter);
for (procstat_t *ps = list_head_g; ps != NULL; ps = ps->next) {
ps->num_proc = 0;
ps->num_lwp = 0;
+ ps->num_fd = 0;
ps->vmem_size = 0;
ps->vmem_rss = 0;
ps->vmem_data = 0;
ps->vmem_code = 0;
ps->stack_size = 0;
- ps->io_rchar = -1;
- ps->io_wchar = -1;
- ps->io_syscr = -1;
- ps->io_syscw = -1;
- ps->cswitch_vol = -1;
- ps->cswitch_invol = -1;
pse_prev = NULL;
pse = ps->instances;
} /* for (ps = list_head_g; ps != NULL; ps = ps->next) */
}
+static void ps_tune_instance(oconfig_item_t *ci, procstat_t *ps) {
+ for (int i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *c = ci->children + i;
+
+ if (strcasecmp(c->key, "CollectContextSwitch") == 0)
+ cf_util_get_boolean(c, &ps->report_ctx_switch);
+ else if (strcasecmp(c->key, "CollectFileDescriptor") == 0)
+ cf_util_get_boolean(c, &ps->report_fd_num);
+ else {
+ ERROR("processes plugin: Option `%s' not allowed here.", c->key);
+ }
+ } /* for (ci->children) */
+} /* void ps_tune_instance */
+
/* put all pre-defined 'Process' names from config to list_head_g tree */
static int ps_config(oconfig_item_t *ci) {
#if KERNEL_LINUX
const size_t max_procname_len = MAXCOMLEN - 1;
#endif
+ procstat_t *ps;
+
for (int i = 0; i < ci->children_num; ++i) {
oconfig_item_t *c = ci->children + i;
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);
- }
-
#if KERNEL_LINUX || KERNEL_SOLARIS || KERNEL_FREEBSD
if (strlen(c->values[0].value.string) > max_procname_len) {
WARNING("processes plugin: this platform has a %zu character limit "
}
#endif
- ps_list_register(c->values[0].value.string, NULL);
+ ps = ps_list_register(c->values[0].value.string, NULL);
+
+ if (c->children_num != 0 && ps != NULL)
+ ps_tune_instance(c, ps);
} 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)) {
continue;
}
- 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 = ps_list_register(c->values[0].value.string,
+ c->values[1].value.string);
- ps_list_register(c->values[0].value.string, c->values[1].value.string);
+ if (c->children_num != 0 && ps != NULL)
+ ps_tune_instance(c, ps);
} else if (strcasecmp(c->key, "CollectContextSwitch") == 0) {
cf_util_get_boolean(c, &report_ctx_switch);
+ } else if (strcasecmp(c->key, "CollectFileDescriptor") == 0) {
+ cf_util_get_boolean(c, &report_fd_num);
} else {
ERROR("processes plugin: The `%s' configuration option is not "
"understood and will be ignored.",
plugin_dispatch_values(&vl);
}
- if (report_ctx_switch) {
+ if (ps->num_fd > 0) {
+ sstrncpy(vl.type, "file_handles", sizeof(vl.type));
+ vl.values[0].gauge = ps->num_fd;
+ vl.values_len = 1;
+ plugin_dispatch_values(&vl);
+ }
+
+ if ((ps->cswitch_vol != -1) && (ps->cswitch_invol != -1)) {
sstrncpy(vl.type, "contextswitch", sizeof(vl.type));
sstrncpy(vl.type_instance, "voluntary", sizeof(vl.type_instance));
vl.values[0].derive = ps->cswitch_vol;
plugin_dispatch_values(&vl);
}
- DEBUG("name = %s; num_proc = %lu; num_lwp = %lu; "
+ DEBUG("name = %s; num_proc = %lu; num_lwp = %lu; num_fd = %lu; "
"vmem_size = %lu; vmem_rss = %lu; vmem_data = %lu; "
"vmem_code = %lu; "
"vmem_minflt_counter = %" PRIi64 "; vmem_majflt_counter = %" PRIi64 "; "
"io_rchar = %" PRIi64 "; io_wchar = %" PRIi64 "; "
"io_syscr = %" PRIi64 "; io_syscw = %" PRIi64 "; "
"cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 ";",
- ps->name, ps->num_proc, ps->num_lwp, ps->vmem_size, ps->vmem_rss,
- ps->vmem_data, ps->vmem_code, ps->vmem_minflt_counter,
+ ps->name, ps->num_proc, ps->num_lwp, ps->num_fd, ps->vmem_size,
+ ps->vmem_rss, ps->vmem_data, ps->vmem_code, ps->vmem_minflt_counter,
ps->vmem_majflt_counter, ps->cpu_user_counter, ps->cpu_system_counter,
ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw, ps->cswitch_vol,
ps->cswitch_invol);
/* ------- additional functions for KERNEL_LINUX/HAVE_THREAD_INFO ------- */
#if KERNEL_LINUX
-static int ps_read_tasks_status(procstat_entry_t *ps) {
+static int ps_read_tasks_status(process_entry_t *ps) {
char dirname[64];
DIR *dh;
char filename[64];
} /* int *ps_read_tasks_status */
/* Read data from /proc/pid/status */
-static procstat_t *ps_read_status(long pid, procstat_t *ps) {
+static int ps_read_status(long pid, process_entry_t *ps) {
FILE *fh;
char buffer[1024];
char filename[64];
ssnprintf(filename, sizeof(filename), "/proc/%li/status", pid);
if ((fh = fopen(filename, "r")) == NULL)
- return (NULL);
+ return (-1);
while (fgets(buffer, sizeof(buffer), fh) != NULL) {
unsigned long tmp;
if (threads != 0)
ps->num_lwp = threads;
- return (ps);
-} /* procstat_t *ps_read_vmem */
+ return (0);
+} /* int *ps_read_status */
-static int ps_read_io(procstat_entry_t *ps) {
+static int ps_read_io(process_entry_t *ps) {
FILE *fh;
char buffer[1024];
char filename[64];
int numfields;
ssnprintf(filename, sizeof(filename), "/proc/%li/io", ps->id);
- if ((fh = fopen(filename, "r")) == NULL)
+ if ((fh = fopen(filename, "r")) == NULL) {
+ DEBUG("ps_read_io: Failed to open file `%s'", filename);
return (-1);
+ }
while (fgets(buffer, sizeof(buffer), fh) != NULL) {
derive_t *val = NULL;
return (0);
} /* int ps_read_io (...) */
-static void ps_fill_details(const procstat_t *ps, procstat_entry_t *entry) {
- if (entry->has_io == 0 && ps_read_io(entry) != 0) {
- /* no io data */
- entry->io_rchar = -1;
- entry->io_wchar = -1;
- entry->io_syscr = -1;
- entry->io_syscw = -1;
+static int ps_count_fd(int pid) {
+ char dirname[64];
+ DIR *dh;
+ struct dirent *ent;
+ int count = 0;
+
+ ssnprintf(dirname, sizeof(dirname), "/proc/%i/fd", pid);
- DEBUG("ps_read_process: not get io data for pid %li", entry->id);
+ if ((dh = opendir(dirname)) == NULL) {
+ DEBUG("Failed to open directory `%s'", dirname);
+ return (-1);
}
- entry->has_io = 1;
+ while ((ent = readdir(dh)) != NULL) {
+ if (!isdigit((int)ent->d_name[0]))
+ continue;
+ else
+ count++;
+ }
+ closedir(dh);
- if (report_ctx_switch) {
- if (entry->has_cswitch == 0 && ps_read_tasks_status(entry) != 0) {
- entry->cswitch_vol = -1;
- entry->cswitch_invol = -1;
+ return ((count >= 1) ? count : 1);
+} /* int ps_count_fd (pid) */
- DEBUG("ps_read_tasks_status: not get context "
- "switch data for pid %li",
- entry->id);
+static void ps_fill_details(const procstat_t *ps, process_entry_t *entry) {
+ if (entry->has_io == 0) {
+ ps_read_io(entry);
+ entry->has_io = 1;
+ }
+
+ if (ps->report_ctx_switch) {
+ if (entry->has_cswitch == 0) {
+ ps_read_tasks_status(entry);
+ entry->has_cswitch = 1;
+ }
+ }
+
+ if (ps->report_fd_num) {
+ int num_fd;
+ if (entry->has_fd == 0 && (num_fd = ps_count_fd(entry->id)) > 0) {
+ entry->num_fd = num_fd;
}
- entry->has_cswitch = 1;
+ entry->has_fd = 1;
}
} /* void ps_fill_details (...) */
-static int ps_read_process(long pid, procstat_t *ps, char *state) {
+static int ps_read_process(long pid, process_entry_t *ps, char *state) {
char filename[64];
char buffer[1024];
ssize_t status;
- memset(ps, 0, sizeof(procstat_t));
-
ssnprintf(filename, sizeof(filename), "/proc/%li/stat", pid);
status = read_file_contents(filename, buffer, sizeof(buffer) - 1);
ps->num_proc = 0;
} else {
ps->num_lwp = strtoul(fields[17], /* endptr = */ NULL, /* base = */ 10);
- if ((ps_read_status(pid, ps)) == NULL) {
+ if ((ps_read_status(pid, ps)) != 0) {
/* No VMem data */
ps->vmem_data = -1;
ps->vmem_code = -1;
ps->vmem_rss = (unsigned long)vmem_rss;
ps->stack_size = (unsigned long)stack_size;
+ /* no data by default. May be filled by ps_fill_details () */
+ ps->io_rchar = -1;
+ ps->io_wchar = -1;
+ ps->io_syscr = -1;
+ ps->io_syscw = -1;
+
+ ps->cswitch_vol = -1;
+ ps->cswitch_invol = -1;
+
/* success */
return (0);
} /* int ps_read_process (...) */
* The values for input and ouput chars are calculated "by hand"
* Added a few "solaris" specific process states as well
*/
-static int ps_read_process(long pid, procstat_t *ps, char *state) {
+static int ps_read_process(long pid, process_entry_t *ps, char *state) {
char filename[64];
char f_psinfo[64], f_usage[64];
char *buffer;
ps->stack_size = myStatus->pr_stksize;
/*
+ * TODO: File descriptor count for Solaris
+ */
+ ps->num_fd = 0;
+
+ /*
* Calculating input/ouput chars
* Formula used is total chars / total blocks => chars/block
* then convert input/output blocks to chars
int blocked = 0;
procstat_t *ps;
- procstat_entry_t pse;
+ process_entry_t pse;
ps_list_reset();
pse.vmem_data = 0;
pse.vmem_code = 0;
+ pse.io_rchar = -1;
+ pse.io_wchar = -1;
+ pse.io_syscr = -1;
+ pse.io_syscw = -1;
+
+ /* File descriptor count not implemented */
+ pse.num_fd = 0;
+
pse.vmem_minflt_counter = task_events_info.cow_faults;
pse.vmem_majflt_counter = task_events_info.faults;
char cmdline[CMDLINE_BUFFER_SIZE];
int status;
- procstat_t ps;
- procstat_entry_t pse;
+ process_entry_t pse;
char state;
running = sleeping = zombies = stopped = paging = blocked = 0;
if ((pid = atol(ent->d_name)) < 1)
continue;
- status = ps_read_process(pid, &ps, &state);
+ memset(&pse, 0, sizeof(pse));
+ pse.id = pid;
+
+ status = ps_read_process(pid, &pse, &state);
if (status != 0) {
DEBUG("ps_read_process failed: %i", status);
continue;
}
- memset(&pse, 0, sizeof(pse));
- pse.id = pid;
- pse.age = 0;
-
- pse.num_proc = ps.num_proc;
- pse.num_lwp = ps.num_lwp;
- pse.vmem_size = ps.vmem_size;
- pse.vmem_rss = ps.vmem_rss;
- pse.vmem_data = ps.vmem_data;
- pse.vmem_code = ps.vmem_code;
- pse.stack_size = ps.stack_size;
-
- pse.vmem_minflt_counter = ps.vmem_minflt_counter;
- pse.vmem_majflt_counter = ps.vmem_majflt_counter;
-
- pse.cpu_user_counter = ps.cpu_user_counter;
- pse.cpu_system_counter = ps.cpu_system_counter;
-
- pse.io_rchar = ps.io_rchar;
- pse.io_wchar = ps.io_wchar;
- pse.io_syscr = ps.io_syscr;
- pse.io_syscw = ps.io_syscw;
-
- pse.cswitch_vol = ps.cswitch_vol;
- pse.cswitch_invol = ps.cswitch_invol;
-
switch (state) {
case 'R':
running++;
break;
}
- ps_list_add(ps.name, ps_get_cmdline(pid, ps.name, cmdline, sizeof(cmdline)),
- &pse);
+ ps_list_add(pse.name,
+ ps_get_cmdline(pid, pse.name, cmdline, sizeof(cmdline)), &pse);
}
closedir(proc);
struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
- procstat_entry_t pse;
+ process_entry_t pse;
ps_list_reset();
}
} /* if (process has argument list) */
+ memset(&pse, 0, sizeof(pse));
pse.id = procs[i].ki_pid;
- pse.age = 0;
pse.num_proc = 1;
pse.num_lwp = procs[i].ki_numthreads;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ /* file descriptor count not implemented */
+ pse.num_fd = 0;
+
/* context switch counters not implemented */
pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
struct kinfo_proc *proc_ptr = NULL;
int count; /* returns number of processes */
- procstat_entry_t pse;
+ process_entry_t pse;
ps_list_reset();
memset(&pse, 0, sizeof(pse));
pse.id = procs[i].p_pid;
- pse.age = 0;
pse.num_proc = 1;
pse.num_lwp = 1; /* XXX: accumulate p_tid values for a single p_pid ? */
pse.io_syscr = -1;
pse.io_syscw = -1;
+ /* file descriptor count not implemented */
+ pse.num_fd = 0;
+
/* context switch counters not implemented */
pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
pid_t pindex = 0;
int nprocs;
- procstat_entry_t pse;
+ process_entry_t pse;
ps_list_reset();
while ((nprocs = getprocs64(procentry, sizeof(struct procentry64),
}
}
+ memset(&pse, 0, sizeof(pse));
+
pse.id = procentry[i].pi_pid;
- pse.age = 0;
pse.num_lwp = procentry[i].pi_thcount;
pse.num_proc = 1;
pse.cpu_user_counter = procentry[i].pi_ru.ru_utime.tv_sec * 1000000 +
procentry[i].pi_ru.ru_utime.tv_usec / 1000;
- pse.cpu_system = 0;
/* tv_usec is nanosec ??? */
pse.cpu_system_counter = procentry[i].pi_ru.ru_stime.tv_sec * 1000000 +
procentry[i].pi_ru.ru_stime.tv_usec / 1000;
pse.vmem_size = procentry[i].pi_tsize + procentry[i].pi_dvm * pagesize;
pse.vmem_rss = (procentry[i].pi_drss + procentry[i].pi_trss) * pagesize;
- /* Not supported */
+ /* Not supported/implemented */
pse.vmem_data = 0;
pse.vmem_code = 0;
pse.stack_size = 0;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.num_fd = 0;
+
pse.cswitch_vol = -1;
pse.cswitch_invol = -1;
while ((ent = readdir(proc)) != NULL) {
long pid;
- struct procstat ps;
- procstat_entry_t pse;
+ process_entry_t pse;
char *endptr;
if (!isdigit((int)ent->d_name[0]))
if (*endptr != 0) /* value didn't completely parse as a number */
continue;
- status = ps_read_process(pid, &ps, &state);
+ memset(&pse, 0, sizeof(pse));
+ pse.id = pid;
+
+ status = ps_read_process(pid, &pse, &state);
if (status != 0) {
DEBUG("ps_read_process failed: %i", status);
continue;
}
- memset(&pse, 0, sizeof(pse));
- pse.id = pid;
- pse.age = 0;
-
- pse.num_proc = ps.num_proc;
- pse.num_lwp = ps.num_lwp;
- pse.vmem_size = ps.vmem_size;
- pse.vmem_rss = ps.vmem_rss;
- pse.vmem_data = ps.vmem_data;
- pse.vmem_code = ps.vmem_code;
- pse.stack_size = ps.stack_size;
-
- pse.vmem_minflt_counter = ps.vmem_minflt_counter;
- pse.vmem_majflt_counter = ps.vmem_majflt_counter;
-
- pse.cpu_user_counter = ps.cpu_user_counter;
- pse.cpu_system_counter = ps.cpu_system_counter;
-
- pse.io_rchar = ps.io_rchar;
- pse.io_wchar = ps.io_wchar;
- pse.io_syscr = ps.io_syscr;
- pse.io_syscw = ps.io_syscw;
-
- pse.cswitch_vol = -1;
- pse.cswitch_invol = -1;
-
switch (state) {
case 'R':
running++;
break;
}
- ps_list_add(ps.name, ps_get_cmdline(pid, ps.name, cmdline, sizeof(cmdline)),
- &pse);
+ ps_list_add(pse.name,
+ ps_get_cmdline(pid, pse.name, cmdline, sizeof(cmdline)), &pse);
} /* while(readdir) */
closedir(proc);
static int value_list_to_kairosdb(char *buffer, size_t buffer_size, /* {{{ */
const data_set_t *ds, const value_list_t *vl,
- int store_rates) {
+ int store_rates,
+ char const *const *http_attrs,
+ size_t http_attrs_num) {
char temp[512];
size_t offset = 0;
int status;
BUFFER_ADD(", \"tags\":\{");
BUFFER_ADD("\"host\": \"%s\"", vl->host);
+ for (size_t j = 0; j < http_attrs_num; j += 2) {
+ BUFFER_ADD(", \"%s\":", http_attrs[j]);
+ BUFFER_ADD(" \"%s\"", http_attrs[j + 1]);
+ }
+
if (strlen(vl->plugin_instance))
BUFFER_ADD_KEYVAL("plugin_instance", vl->plugin_instance);
BUFFER_ADD_KEYVAL("type", vl->type);
static int format_kairosdb_value_list_nocheck(
char *buffer, /* {{{ */
size_t *ret_buffer_fill, size_t *ret_buffer_free, const data_set_t *ds,
- const value_list_t *vl, int store_rates, size_t temp_size) {
+ const value_list_t *vl, int store_rates, size_t temp_size,
+ char const *const *http_attrs, size_t http_attrs_num) {
char temp[temp_size];
int status;
- status = value_list_to_kairosdb(temp, sizeof(temp), ds, vl, store_rates);
+ status = value_list_to_kairosdb(temp, sizeof(temp), ds, vl, store_rates,
+ http_attrs, http_attrs_num);
if (status != 0)
return (status);
temp_size = strlen(temp);
int format_kairosdb_value_list(char *buffer, /* {{{ */
size_t *ret_buffer_fill, size_t *ret_buffer_free,
const data_set_t *ds, const value_list_t *vl,
- int store_rates) {
+ int store_rates, char const *const *http_attrs,
+ size_t http_attrs_num) {
if ((buffer == NULL) || (ret_buffer_fill == NULL) ||
(ret_buffer_free == NULL) || (ds == NULL) || (vl == NULL))
return (-EINVAL);
return (format_kairosdb_value_list_nocheck(
buffer, ret_buffer_fill, ret_buffer_free, ds, vl, store_rates,
- (*ret_buffer_free) - 2));
+ (*ret_buffer_free) - 2, http_attrs, http_attrs_num));
} /* }}} int format_kairosdb_value_list */
+
+/* vim: set sw=2 sts=2 et fdm=marker : */
size_t *ret_buffer_free);
int format_kairosdb_value_list(char *buffer, size_t *ret_buffer_fill,
size_t *ret_buffer_free, const data_set_t *ds,
- const value_list_t *vl, int store_rates);
+ const value_list_t *vl, int store_rates,
+ char const *const *http_attrs,
+ size_t http_attrs_num);
int format_kairosdb_finalize(char *buffer, size_t *ret_buffer_fill,
size_t *ret_buffer_free);
--- /dev/null
+/**
+ * collectd - src/utils_ignorelist.c
+ * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+ * Copyright (C) 2008 Florian Forster <octo at collectd.org>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public 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:
+ * Lubos Stanek <lubek at users.sourceforge.net>
+ * Florian Forster <octo at collectd.org>
+ **/
+/**
+ * ignorelist handles plugin's list of configured collectable
+ * entries with global ignore action
+ **/
+/**
+ * Usage:
+ *
+ * Define plugin's global pointer variable of type ignorelist_t:
+ * ignorelist_t *myconfig_ignore;
+ * If you know the state of the global ignore (IgnoreSelected),
+ * allocate the variable with:
+ * myconfig_ignore = ignorelist_create (YourKnownIgnore);
+ * If you do not know the state of the global ignore,
+ * initialize the global variable and set the ignore flag later:
+ * myconfig_ignore = ignorelist_init ();
+ * Append single entries in your cf_register'ed callback function:
+ * ignorelist_add (myconfig_ignore, newentry);
+ * When you hit the IgnoreSelected config option,
+ * offer it to the list:
+ * ignorelist_ignore (myconfig_ignore, instantly_got_value_of_ignore);
+ * That is all for the ignorelist initialization.
+ * Later during read and write (plugin's registered functions) get
+ * the information whether this entry would be collected or not:
+ * if (ignorelist_match (myconfig_ignore, thisentry))
+ * return;
+ **/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "common.h"
+#include "plugin.h"
+#include "utils_ignorelist.h"
+
+/*
+ * private prototypes
+ */
+struct ignorelist_item_s {
+#if HAVE_REGEX_H
+ regex_t *rmatch; /* regular expression entry identification */
+#endif
+ char *smatch; /* string entry identification */
+ struct ignorelist_item_s *next;
+};
+typedef struct ignorelist_item_s ignorelist_item_t;
+
+struct ignorelist_s {
+ int ignore; /* ignore entries */
+ ignorelist_item_t *head; /* pointer to the first entry */
+};
+
+/* *** *** *** ********************************************* *** *** *** */
+/* *** *** *** *** *** *** private functions *** *** *** *** *** *** */
+/* *** *** *** ********************************************* *** *** *** */
+
+static inline void ignorelist_append(ignorelist_t *il,
+ ignorelist_item_t *item) {
+ assert((il != NULL) && (item != NULL));
+
+ item->next = il->head;
+ il->head = item;
+}
+
+#if HAVE_REGEX_H
+static int ignorelist_append_regex(ignorelist_t *il, const char *re_str) {
+ regex_t *re;
+ ignorelist_item_t *entry;
+ int status;
+
+ re = calloc(1, sizeof(*re));
+ if (re == NULL) {
+ ERROR("ignorelist_append_regex: calloc failed.");
+ return (ENOMEM);
+ }
+
+ status = regcomp(re, re_str, REG_EXTENDED);
+ if (status != 0) {
+ char errbuf[1024];
+ (void)regerror(status, re, errbuf, sizeof(errbuf));
+ ERROR("utils_ignorelist: regcomp failed: %s", errbuf);
+ ERROR("ignorelist_append_regex: Compiling regular expression \"%s\" "
+ "failed: %s",
+ re_str, errbuf);
+ sfree(re);
+ return (status);
+ }
+
+ entry = calloc(1, sizeof(*entry));
+ if (entry == NULL) {
+ ERROR("ignorelist_append_regex: calloc failed.");
+ regfree(re);
+ sfree(re);
+ return (ENOMEM);
+ }
+ entry->rmatch = re;
+
+ ignorelist_append(il, entry);
+ return (0);
+} /* int ignorelist_append_regex */
+#endif
+
+static int ignorelist_append_string(ignorelist_t *il, const char *entry) {
+ ignorelist_item_t *new;
+
+ /* create new entry */
+ if ((new = calloc(1, sizeof(*new))) == NULL) {
+ ERROR("cannot allocate new entry");
+ return (1);
+ }
+ new->smatch = sstrdup(entry);
+
+ /* append new entry */
+ ignorelist_append(il, new);
+
+ return (0);
+} /* int ignorelist_append_string(ignorelist_t *il, const char *entry) */
+
+#if HAVE_REGEX_H
+/*
+ * check list for entry regex match
+ * return 1 if found
+ */
+static int ignorelist_match_regex(ignorelist_item_t *item, const char *entry) {
+ assert((item != NULL) && (item->rmatch != NULL) && (entry != NULL) &&
+ (strlen(entry) > 0));
+
+ /* match regex */
+ if (regexec(item->rmatch, entry, 0, NULL, 0) == 0)
+ return (1);
+
+ return (0);
+} /* int ignorelist_match_regex (ignorelist_item_t *item, const char *entry) */
+#endif
+
+/*
+ * check list for entry string match
+ * return 1 if found
+ */
+static int ignorelist_match_string(ignorelist_item_t *item, const char *entry) {
+ assert((item != NULL) && (item->smatch != NULL) && (entry != NULL) &&
+ (strlen(entry) > 0));
+
+ if (strcmp(entry, item->smatch) == 0)
+ return (1);
+
+ return (0);
+} /* int ignorelist_match_string (ignorelist_item_t *item, const char *entry) */
+
+/* *** *** *** ******************************************** *** *** *** */
+/* *** *** *** *** *** *** public functions *** *** *** *** *** *** */
+/* *** *** *** ******************************************** *** *** *** */
+
+/*
+ * create the ignorelist_t with known ignore state
+ * return pointer to ignorelist_t
+ */
+ignorelist_t *ignorelist_create(int invert) {
+ ignorelist_t *il;
+
+ il = calloc(1, sizeof(*il));
+ if (il == NULL)
+ return NULL;
+
+ /*
+ * ->ignore == 0 => collect
+ * ->ignore == 1 => ignore
+ */
+ il->ignore = invert ? 0 : 1;
+
+ return (il);
+} /* ignorelist_t *ignorelist_create (int ignore) */
+
+/*
+ * free memory used by ignorelist_t
+ */
+void ignorelist_free(ignorelist_t *il) {
+ ignorelist_item_t *this;
+ ignorelist_item_t *next;
+
+ if (il == NULL)
+ return;
+
+ for (this = il->head; this != NULL; this = next) {
+ next = this->next;
+#if HAVE_REGEX_H
+ if (this->rmatch != NULL) {
+ regfree(this->rmatch);
+ sfree(this->rmatch);
+ this->rmatch = NULL;
+ }
+#endif
+ if (this->smatch != NULL) {
+ sfree(this->smatch);
+ this->smatch = NULL;
+ }
+ sfree(this);
+ }
+
+ sfree(il);
+} /* void ignorelist_destroy (ignorelist_t *il) */
+
+/*
+ * set ignore state of the ignorelist_t
+ */
+void ignorelist_set_invert(ignorelist_t *il, int invert) {
+ if (il == NULL) {
+ DEBUG("ignore call with ignorelist_t == NULL");
+ return;
+ }
+
+ il->ignore = invert ? 0 : 1;
+} /* void ignorelist_set_invert (ignorelist_t *il, int ignore) */
+
+/*
+ * append entry into ignorelist_t
+ * return 0 for success
+ */
+int ignorelist_add(ignorelist_t *il, const char *entry) {
+ size_t len;
+
+ if (il == NULL) {
+ DEBUG("add called with ignorelist_t == NULL");
+ return (1);
+ }
+
+ len = strlen(entry);
+
+ /* append nothing */
+ if (len == 0) {
+ DEBUG("not appending: empty entry");
+ return (1);
+ }
+
+#if HAVE_REGEX_H
+ /* regex string is enclosed in "/.../" */
+ if ((len > 2) && (entry[0] == '/') && entry[len - 1] == '/') {
+ char *copy;
+ int status;
+
+ /* skip leading slash */
+ copy = strdup(entry + 1);
+ if (copy == NULL)
+ return ENOMEM;
+
+ /* trim trailing slash */
+ copy[strlen(copy) - 1] = 0;
+
+ status = ignorelist_append_regex(il, copy);
+ sfree(copy);
+ return status;
+ }
+#endif
+
+ return ignorelist_append_string(il, entry);
+} /* int ignorelist_add (ignorelist_t *il, const char *entry) */
+
+/*
+ * check list for entry
+ * return 1 for ignored entry
+ */
+int ignorelist_match(ignorelist_t *il, const char *entry) {
+ /* if no entries, collect all */
+ if ((il == NULL) || (il->head == NULL))
+ return (0);
+
+ if ((entry == NULL) || (strlen(entry) == 0))
+ return (0);
+
+ /* traverse list and check entries */
+ for (ignorelist_item_t *traverse = il->head; traverse != NULL;
+ traverse = traverse->next) {
+#if HAVE_REGEX_H
+ if (traverse->rmatch != NULL) {
+ if (ignorelist_match_regex(traverse, entry))
+ return (il->ignore);
+ } else
+#endif
+ {
+ if (ignorelist_match_string(traverse, entry))
+ return (il->ignore);
+ }
+ } /* for traverse */
+
+ return (1 - il->ignore);
+} /* int ignorelist_match (ignorelist_t *il, const char *entry) */
--- /dev/null
+/**
+ * collectd - src/utils_ignorelist.h
+ * Copyright (C) 2006 Lubos Stanek <lubek at users.sourceforge.net>
+ *
+ * This program is free software; you can redistribute it and/
+ * or modify it under the terms of the GNU General Public Li-
+ * cence as published by the Free Software Foundation; either
+ * version 2 of the Licence, or any later version.
+ *
+ * This program is distributed in the hope that it will be use-
+ * ful, but WITHOUT ANY WARRANTY; without even the implied war-
+ * ranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU General Public Licence for more details.
+ *
+ * You should have received a copy of the GNU General Public 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:
+ * Lubos Stanek <lubek at users.sourceforge.net>
+ **/
+/**
+ * ignorelist handles plugin's list of configured collectable
+ * entries with global ignore action
+ **/
+
+#ifndef UTILS_IGNORELIST_H
+#define UTILS_IGNORELIST_H 1
+
+#include "collectd.h"
+
+#if HAVE_REGEX_H
+#include <regex.h>
+#endif
+
+/* public prototypes */
+
+struct ignorelist_s;
+typedef struct ignorelist_s ignorelist_t;
+
+/*
+ * create the ignorelist_t with known ignore state
+ * return pointer to ignorelist_t
+ */
+ignorelist_t *ignorelist_create(int invert);
+
+/*
+ * free memory used by ignorelist_t
+ */
+void ignorelist_free(ignorelist_t *il);
+
+/*
+ * set ignore state of the ignorelist_t
+ */
+void ignorelist_set_invert(ignorelist_t *il, int invert);
+
+/*
+ * append entry to ignorelist_t
+ * returns zero on success, non-zero upon failure.
+ */
+int ignorelist_add(ignorelist_t *il, const char *entry);
+
+/*
+ * check list for entry
+ * return 1 for ignored entry
+ */
+int ignorelist_match(ignorelist_t *il, const char *entry);
+
+#endif /* UTILS_IGNORELIST_H */
size_t obj_len = 0;
yajl_gen_status yajl_gen_ret = yajl_gen_status_ok;
+ if (jval == NULL)
+ return yajl_gen_generation_complete;
+
if (YAJL_IS_STRING(jval))
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, YAJL_GET_STRING(jval));
else if (YAJL_IS_DOUBLE(jval))
/* get method name */
if ((jval = yajl_tree_get(jnode, method_path, yajl_t_string)) != NULL) {
- method = YAJL_GET_STRING(jval);
+ if ((method = YAJL_GET_STRING(jval)) == NULL) {
+ yajl_tree_free(jnode);
+ sfree(sjson);
+ return (-1);
+ }
if (strcmp("echo", method) == 0) {
/* echo request from the server */
if (ovs_db_table_echo_cb(pdb, jnode) < 0)
return 0;
}
+/*
+ virConnectListAllDomains() appeared in 0.10.2
+ Note that LIBVIR_CHECK_VERSION appeared a year later, so
+ in some systems which actually have virConnectListAllDomains()
+ we can't detect this.
+ */
+#ifdef LIBVIR_CHECK_VERSION
+# if LIBVIR_CHECK_VERSION(0,10,2)
+# define HAVE_LIST_ALL_DOMAINS 1
+# endif
+#endif
+
static int refresh_lists(struct lv_read_instance *inst) {
struct lv_read_state *state = &inst->read_state;
int n;
lv_clean_read_state(state);
if (n > 0) {
+#ifdef HAVE_LIST_ALL_DOMAINS
+ virDomainPtr *domains;
+ n = virConnectListAllDomains (conn, &domains, VIR_CONNECT_LIST_DOMAINS_ACTIVE);
+#else
int *domids;
/* Get list of domains. */
}
n = virConnectListDomains(conn, domids, n);
+#endif
+
if (n < 0) {
VIRT_ERROR(conn, "reading list of domains");
+#ifndef HAVE_LIST_ALL_DOMAINS
sfree(domids);
+#endif
return -1;
}
/* Fetch each domain and add it to the list, unless ignore. */
for (int i = 0; i < n; ++i) {
- virDomainPtr dom = NULL;
const char *name;
char *xml = NULL;
xmlDocPtr xml_doc = NULL;
virDomainInfo info;
int status;
+#ifdef HAVE_LIST_ALL_DOMAINS
+ virDomainPtr dom = domains[i];
+#else
+ virDomainPtr dom = NULL;
dom = virDomainLookupByID(conn, domids[i]);
if (dom == NULL) {
VIRT_ERROR(conn, "virDomainLookupByID");
/* Could be that the domain went away -- ignore it anyway. */
continue;
}
+#endif
name = virDomainGetName(dom);
if (name == NULL) {
sfree(xml);
}
+#ifdef HAVE_LIST_ALL_DOMAINS
+ sfree (domains);
+#else
sfree(domids);
+#endif
}
DEBUG(PLUGIN_NAME " plugin#%s: refreshing"
};
typedef struct wh_callback_s wh_callback_t;
+static char **http_attrs;
+static size_t http_attrs_num;
+
static void wh_log_http_error(wh_callback_t *cb) {
if (!cb->log_http_error)
return;
}
}
- status = format_kairosdb_value_list(cb->send_buffer, &cb->send_buffer_fill,
- &cb->send_buffer_free, ds, vl,
- cb->store_rates);
+ status = format_kairosdb_value_list(
+ cb->send_buffer, &cb->send_buffer_fill, &cb->send_buffer_free, ds, vl,
+ cb->store_rates, (char const *const *)http_attrs, http_attrs_num);
if (status == -ENOMEM) {
status = wh_flush_nolock(/* timeout = */ 0, cb);
if (status != 0) {
return (status);
}
- status = format_kairosdb_value_list(cb->send_buffer, &cb->send_buffer_fill,
- &cb->send_buffer_free, ds, vl,
- cb->store_rates);
+ status = format_kairosdb_value_list(
+ cb->send_buffer, &cb->send_buffer_fill, &cb->send_buffer_free, ds, vl,
+ cb->store_rates, (char const *const *)http_attrs, http_attrs_num);
}
if (status != 0) {
pthread_mutex_unlock(&cb->send_lock);
status = cf_util_get_boolean(child, &cb->log_http_error);
else if (strcasecmp("Header", child->key) == 0)
status = wh_config_append_string("Header", &cb->headers, child);
- else {
+ else if (strcasecmp("Attribute", child->key) == 0) {
+ char *key = NULL;
+ char *val = NULL;
+
+ if (child->values_num != 2) {
+ WARNING("write_http plugin: Attribute need both a key and a value.");
+ break;
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("write_http plugin: Attribute needs string arguments.");
+ break;
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
+ break;
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ sfree(key);
+ break;
+ }
+ strarray_add(&http_attrs, &http_attrs_num, key);
+ strarray_add(&http_attrs, &http_attrs_num, val);
+ DEBUG("write_http plugin: got attribute: %s => %s", key, val);
+ sfree(key);
+ sfree(val);
+ } else {
ERROR("write_http plugin: Invalid configuration "
"option: %s.",
child->key);
* Copyright (C) 2010-2013 Florian Forster
* Copyright (C) 2010 Akkarit Sangpetch
* Copyright (C) 2012 Chris Lundquist
+ * Copyright (C) 2017 Saikrishna Arcot
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Florian Forster <octo at collectd.org>
* Akkarit Sangpetch <asangpet at andrew.cmu.edu>
* Chris Lundquist <clundquist at bluebox.net>
+ * Saikrishna Arcot <saiarcot895 at gmail.com>
**/
#include "collectd.h"
#include "plugin.h"
#include "utils_cache.h"
-#define MONGO_HAVE_STDINT 1
-#include <mongo.h>
-
-#if (MONGO_MAJOR == 0) && (MONGO_MINOR < 8)
-#define bson_alloc() bson_create()
-#define bson_dealloc(b) bson_dispose(b)
-#endif
+#include <mongoc.h>
struct wm_node_s {
char name[DATA_MAX_NAME_LEN];
char *passwd;
_Bool store_rates;
+ _Bool connected;
- mongo conn[1];
+ mongoc_client_t *client;
+ mongoc_database_t *database;
pthread_mutex_t lock;
};
typedef struct wm_node_s wm_node_t;
/*
* Functions
*/
-static bson *wm_create_bson(const data_set_t *ds, /* {{{ */
- const value_list_t *vl, _Bool store_rates) {
- bson *ret;
+static bson_t *wm_create_bson(const data_set_t *ds, /* {{{ */
+ const value_list_t *vl, _Bool store_rates) {
+ bson_t *ret;
+ bson_t subarray;
gauge_t *rates;
- ret = bson_alloc(); /* matched by bson_dealloc() */
- if (ret == NULL) {
- ERROR("write_mongodb plugin: bson_create failed.");
- return (NULL);
+ ret = bson_new();
+ if (!ret) {
+ ERROR("write_mongodb plugin: bson_new failed.");
+ return NULL;
}
if (store_rates) {
rates = uc_get_rate(ds, vl);
if (rates == NULL) {
ERROR("write_mongodb plugin: uc_get_rate() failed.");
- return (NULL);
+ bson_free(ret);
+ return NULL;
}
} else {
rates = NULL;
}
- bson_init(ret); /* matched by bson_destroy() */
- bson_append_date(ret, "time", (bson_date_t)CDTIME_T_TO_MS(vl->time));
- bson_append_string(ret, "host", vl->host);
- bson_append_string(ret, "plugin", vl->plugin);
- bson_append_string(ret, "plugin_instance", vl->plugin_instance);
- bson_append_string(ret, "type", vl->type);
- bson_append_string(ret, "type_instance", vl->type_instance);
+ BSON_APPEND_DATE_TIME(ret, "timestamp", CDTIME_T_TO_MS(vl->time));
+ BSON_APPEND_UTF8(ret, "host", vl->host);
+ BSON_APPEND_UTF8(ret, "plugin", vl->plugin);
+ BSON_APPEND_UTF8(ret, "plugin_instance", vl->plugin_instance);
+ BSON_APPEND_UTF8(ret, "type", vl->type);
+ BSON_APPEND_UTF8(ret, "type_instance", vl->type_instance);
- bson_append_start_array(ret, "values"); /* {{{ */
+ BSON_APPEND_ARRAY_BEGIN(ret, "values", &subarray); /* {{{ */
for (int i = 0; i < ds->ds_num; i++) {
char key[16];
ssnprintf(key, sizeof(key), "%i", i);
if (ds->ds[i].type == DS_TYPE_GAUGE)
- bson_append_double(ret, key, vl->values[i].gauge);
+ BSON_APPEND_DOUBLE(&subarray, key, vl->values[i].gauge);
else if (store_rates)
- bson_append_double(ret, key, (double)rates[i]);
+ BSON_APPEND_DOUBLE(&subarray, key, (double)rates[i]);
else if (ds->ds[i].type == DS_TYPE_COUNTER)
- bson_append_long(ret, key, vl->values[i].counter);
+ BSON_APPEND_INT64(&subarray, key, vl->values[i].counter);
else if (ds->ds[i].type == DS_TYPE_DERIVE)
- bson_append_long(ret, key, vl->values[i].derive);
+ BSON_APPEND_INT64(&subarray, key, vl->values[i].derive);
else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
- bson_append_long(ret, key, vl->values[i].absolute);
- else
- assert(23 == 42);
+ BSON_APPEND_INT64(&subarray, key, vl->values[i].absolute);
+ else {
+ ERROR("write_mongodb plugin: Unknown ds_type %d for index %d",
+ ds->ds[i].type, i);
+ bson_free(ret);
+ return NULL;
+ }
}
- bson_append_finish_array(ret); /* }}} values */
+ bson_append_array_end(ret, &subarray); /* }}} values */
- bson_append_start_array(ret, "dstypes"); /* {{{ */
+ BSON_APPEND_ARRAY_BEGIN(ret, "dstypes", &subarray); /* {{{ */
for (int i = 0; i < ds->ds_num; i++) {
char key[16];
ssnprintf(key, sizeof(key), "%i", i);
if (store_rates)
- bson_append_string(ret, key, "gauge");
+ BSON_APPEND_UTF8(&subarray, key, "gauge");
else
- bson_append_string(ret, key, DS_TYPE_TO_STRING(ds->ds[i].type));
+ BSON_APPEND_UTF8(&subarray, key, DS_TYPE_TO_STRING(ds->ds[i].type));
}
- bson_append_finish_array(ret); /* }}} dstypes */
+ bson_append_array_end(ret, &subarray); /* }}} dstypes */
- bson_append_start_array(ret, "dsnames"); /* {{{ */
+ BSON_APPEND_ARRAY_BEGIN(ret, "dsnames", &subarray); /* {{{ */
for (int i = 0; i < ds->ds_num; i++) {
char key[16];
ssnprintf(key, sizeof(key), "%i", i);
- bson_append_string(ret, key, ds->ds[i].name);
+ BSON_APPEND_UTF8(&subarray, key, ds->ds[i].name);
}
- bson_append_finish_array(ret); /* }}} dsnames */
-
- bson_finish(ret);
+ bson_append_array_end(ret, &subarray); /* }}} dsnames */
sfree(rates);
- return (ret);
+
+ size_t error_location;
+ if (!bson_validate(ret, BSON_VALIDATE_UTF8, &error_location)) {
+ ERROR("write_mongodb plugin: Error in generated BSON document "
+ "at byte %zu", error_location);
+ bson_free(ret);
+ return NULL;
+ }
+
+ return ret;
} /* }}} bson *wm_create_bson */
-static int wm_write(const data_set_t *ds, /* {{{ */
- const value_list_t *vl, user_data_t *ud) {
- wm_node_t *node = ud->data;
- char collection_name[512];
- bson *bson_record;
- int status;
+static int wm_initialize(wm_node_t *node) /* {{{ */
+{
+ char *uri;
+ size_t uri_length;
+ char const *format_string;
- ssnprintf(collection_name, sizeof(collection_name), "collectd.%s",
- vl->plugin);
+ if (node->connected) {
+ return 0;
+ }
- bson_record = wm_create_bson(ds, vl, node->store_rates);
- if (bson_record == NULL)
- return (ENOMEM);
+ INFO("write_mongodb plugin: Connecting to [%s]:%i",
+ (node->host != NULL) ? node->host : "localhost",
+ (node->port != 0) ? node->port : MONGOC_DEFAULT_PORT);
+
+ if ((node->db != NULL) && (node->user != NULL) && (node->passwd != NULL)) {
+ format_string = "mongodb://%s:%s@%s:%d/?authSource=%s";
+ uri_length = strlen(format_string) + strlen(node->user) +
+ strlen(node->passwd) + strlen(node->host) + 5 +
+ strlen(node->db) + 1;
+ if ((uri = calloc(sizeof(char), uri_length)) == NULL) {
+ ERROR("write_mongodb plugin: Not enough memory to assemble "
+ "authentication string.");
+ mongoc_client_destroy(node->client);
+ node->client = NULL;
+ node->connected = 0;
+ return -1;
+ }
+ ssnprintf(uri, uri_length, format_string, node->user, node->passwd,
+ node->host, node->port, node->db);
- pthread_mutex_lock(&node->lock);
+ node->client = mongoc_client_new(uri);
+ if (!node->client) {
+ ERROR("write_mongodb plugin: Authenticating to [%s]%i for database "
+ "\"%s\" as user \"%s\" failed.",
+ (node->host != NULL) ? node->host : "localhost",
+ (node->port != 0) ? node->port : MONGOC_DEFAULT_PORT, node->db,
+ node->user);
+ node->connected = 0;
+ sfree(uri);
+ return -1;
+ }
+ } else {
+ format_string = "mongodb://%s:%d";
+ uri_length = strlen(format_string) + strlen(node->host) + 5 + 1;
+ if ((uri = calloc(sizeof(char), uri_length)) == NULL) {
+ ERROR("write_mongodb plugin: Not enough memory to assemble "
+ "authentication string.");
+ mongoc_client_destroy(node->client);
+ node->client = NULL;
+ node->connected = 0;
+ return -1;
+ }
+ snprintf(uri, uri_length, format_string, node->host, node->port);
- if (!mongo_is_connected(node->conn)) {
- INFO("write_mongodb plugin: Connecting to [%s]:%i",
- (node->host != NULL) ? node->host : "localhost",
- (node->port != 0) ? node->port : MONGO_DEFAULT_PORT);
- status = mongo_connect(node->conn, node->host, node->port);
- if (status != MONGO_OK) {
+ node->client = mongoc_client_new(uri);
+ if (!node->client) {
ERROR("write_mongodb plugin: Connecting to [%s]:%i failed.",
(node->host != NULL) ? node->host : "localhost",
- (node->port != 0) ? node->port : MONGO_DEFAULT_PORT);
- mongo_destroy(node->conn);
- pthread_mutex_unlock(&node->lock);
- return (-1);
+ (node->port != 0) ? node->port : MONGOC_DEFAULT_PORT);
+ node->connected = 0;
+ sfree(uri);
+ return -1;
}
+ }
+ sfree(uri);
+
+ node->database = mongoc_client_get_database(node->client, "collectd");
+ if (!node->database) {
+ ERROR("write_mongodb plugin: error creating/getting database");
+ mongoc_client_destroy(node->client);
+ node->client = NULL;
+ node->connected = 0;
+ return -1;
+ }
- if ((node->db != NULL) && (node->user != NULL) && (node->passwd != NULL)) {
- status = mongo_cmd_authenticate(node->conn, node->db, node->user,
- node->passwd);
- if (status != MONGO_OK) {
- ERROR("write_mongodb plugin: Authenticating to [%s]%i for database "
- "\"%s\" as user \"%s\" failed.",
- (node->host != NULL) ? node->host : "localhost",
- (node->port != 0) ? node->port : MONGO_DEFAULT_PORT, node->db,
- node->user);
- mongo_destroy(node->conn);
- pthread_mutex_unlock(&node->lock);
- return (-1);
- }
- }
+ node->connected = 1;
+ return 0;
+} /* }}} int wm_initialize */
- if (node->timeout > 0) {
- status = mongo_set_op_timeout(node->conn, node->timeout);
- if (status != MONGO_OK) {
- WARNING("write_mongodb plugin: mongo_set_op_timeout(%i) failed: %s",
- node->timeout, node->conn->errstr);
- }
- }
+static int wm_write(const data_set_t *ds, /* {{{ */
+ const value_list_t *vl, user_data_t *ud) {
+ wm_node_t *node = ud->data;
+ mongoc_collection_t *collection = NULL;
+ bson_t *bson_record;
+ bson_error_t error;
+ int status;
+
+ bson_record = wm_create_bson(ds, vl, node->store_rates);
+ if (!bson_record) {
+ ERROR("write_mongodb plugin: error making insert bson");
+ return -1;
}
- /* Assert if the connection has been established */
- assert(mongo_is_connected(node->conn));
-
-#if MONGO_MINOR >= 6
- /* There was an API change in 0.6.0 as linked below */
- /* https://github.com/mongodb/mongo-c-driver/blob/master/HISTORY.md */
- status = mongo_insert(node->conn, collection_name, bson_record, NULL);
-#else
- status = mongo_insert(node->conn, collection_name, bson_record);
-#endif
-
- if (status != MONGO_OK) {
- ERROR("write_mongodb plugin: error inserting record: %d", node->conn->err);
- if (node->conn->err != MONGO_BSON_INVALID)
- ERROR("write_mongodb plugin: %s", node->conn->errstr);
- else
- ERROR("write_mongodb plugin: Invalid BSON structure, error = %#x",
- (unsigned int)bson_record->err);
+ pthread_mutex_lock(&node->lock);
+ if (wm_initialize(node) < 0) {
+ ERROR("write_mongodb plugin: error making connection to server");
+ pthread_mutex_unlock(&node->lock);
+ bson_free(bson_record);
+ return -1;
+ }
- /* Disconnect except on data errors. */
- if ((node->conn->err != MONGO_BSON_INVALID) &&
- (node->conn->err != MONGO_BSON_NOT_FINISHED))
- mongo_destroy(node->conn);
+ collection =
+ mongoc_client_get_collection(node->client, "collectd", vl->plugin);
+ if (!collection) {
+ ERROR("write_mongodb plugin: error creating/getting collection");
+ mongoc_database_destroy(node->database);
+ mongoc_client_destroy(node->client);
+ node->database = NULL;
+ node->client = NULL;
+ node->connected = 0;
+ pthread_mutex_unlock(&node->lock);
+ bson_free(bson_record);
+ return -1;
}
- pthread_mutex_unlock(&node->lock);
+ status = mongoc_collection_insert(collection, MONGOC_INSERT_NONE, bson_record,
+ NULL, &error);
+
+ if (!status) {
+ ERROR("write_mongodb plugin: error inserting record: %s", error.message);
+ mongoc_database_destroy(node->database);
+ mongoc_client_destroy(node->client);
+ node->database = NULL;
+ node->client = NULL;
+ node->connected = 0;
+ pthread_mutex_unlock(&node->lock);
+ bson_free(bson_record);
+ mongoc_collection_destroy(collection);
+ return -1;
+ }
/* free our resource as not to leak memory */
- bson_destroy(bson_record); /* matches bson_init() */
- bson_dealloc(bson_record); /* matches bson_alloc() */
+ mongoc_collection_destroy(collection);
- return (0);
+ pthread_mutex_unlock(&node->lock);
+
+ bson_free(bson_record);
+
+ return 0;
} /* }}} int wm_write */
static void wm_config_free(void *ptr) /* {{{ */
if (node == NULL)
return;
- if (mongo_is_connected(node->conn))
- mongo_destroy(node->conn);
+ mongoc_database_destroy(node->database);
+ mongoc_client_destroy(node->client);
+ node->database = NULL;
+ node->client = NULL;
+ node->connected = 0;
sfree(node->host);
sfree(node);
node = calloc(1, sizeof(*node));
if (node == NULL)
return (ENOMEM);
- mongo_init(node->conn);
+ mongoc_init();
node->host = NULL;
node->store_rates = 1;
pthread_mutex_init(&node->lock, /* attr = */ NULL);