fi
if test "x$have_capability" = "xyes"; then
+ AC_CHECK_DECL([CAP_IS_SUPPORTED],
+ [have_capability="yes"],
+ [have_capability="no (CAP_IS_SUPPORTED not found)"],
+ [[#include <sys/capability.h>]]
+ )
+ fi
+
+ if test "x$have_capability" = "xyes"; then
AC_DEFINE([HAVE_CAPABILITY], [1], [Define to 1 if you have cap_get_proc() (-lcap).])
fi
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
%define with_openldap 0%{!?_without_openldap:1}
%define with_openvpn 0%{!?_without_openvpn:1}
%define with_ovs_events 0%{!?_without_ovs_events:1}
+%define with_ovs_stats 0%{!?_without_ovs_stats:1}
%define with_perl 0%{!?_without_perl:1}
%define with_pinba 0%{!?_without_pinba:1}
%define with_ping 0%{!?_without_ping:1}
%define with_aquaero 0%{!?_without_aquaero:0}
# plugin barometer disabled, requires a libi2c
%define with_barometer 0%{!?_without_barometer:0}
-# plugin grpc disabled, requires protobuf-compiler >= 3.0
-%define with_grpc 0%{!?_without_grpc:0}
+# plugin dpdkevents disabled, requires libdpdk
+%define with_dpdkevents 0%{!?_without_dpdkevents:0}
# plugin dpdkstat disabled, requires libdpdk
%define with_dpdkstat 0%{!?_without_dpdkstat:0}
+# plugin grpc disabled, requires protobuf-compiler >= 3.0
+%define with_grpc 0%{!?_without_grpc:0}
# plugin lpar disabled, requires AIX
%define with_lpar 0%{!?_without_lpar:0}
# plugin intel_rdt disabled, requires intel-cmt-cat
%define with_gps 0
%define with_mqtt 0
%define with_ovs_events 0
+%define with_ovs_stats 0
%define with_redis 0
%define with_rrdcached 0
%define with_write_redis 0
Summary: Statistics collection and monitoring daemon
Name: collectd
Version: 5.7.1
-Release: 2%{?dist}
+Release: 6%{?dist}
URL: https://collectd.org
Source: https://collectd.org/files/%{name}-%{version}.tar.bz2
License: GPLv2
Group: System Environment/Daemons
BuildRoot: %{_tmppath}/%{name}-%{version}-root
-BuildRequires: libgcrypt-devel, kernel-headers, libcap-devel, which, xfsprogs-devel
+BuildRequires: libgcrypt-devel, kernel-headers, libcap-devel, which
Vendor: collectd development team <collectd@verplant.org>
%if 0%{?fedora} || 0%{?rhel} >= 7
+BuildRequires: xfsprogs-devel
%{?systemd_requires}
BuildRequires: systemd
%else
whenever a link state change occurs in the OVS database.
%endif
+%if %{with_ovs_stats}
+%package ovs_stats
+Summary: Open vSwitch statistics plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: yajl-devel
+%description ovs_stats
+This plugin collects statictics of OVS connected bridges and
+interfaces.
+%endif
+
%if %{with_perl}
%package perl
Summary: Perl plugin for collectd
%define _with_drbd --disable-drbd
%endif
+%if %{with_dpdkevents}
+%define _with_dpdkevents --enable-dpdkevents
+%else
+%define _with_dpdkevents --disable-dpdkevents
+%endif
+
%if %{with_dpdkstat}
%define _with_dpdkstat --enable-dpdkstat
%else
%define _with_ovs_events --disable-ovs_events
%endif
+%if %{with_ovs_stats}
+%define _with_ovs_stats --enable-ovs_stats
+%else
+%define _with_ovs_stats --disable-ovs_stats
+%endif
+
%if %{with_perl}
%define _with_perl --enable-perl --with-perl-bindings="INSTALLDIRS=vendor"
%else
%{?_with_disk} \
%{?_with_dns} \
%{?_with_drbd} \
+ %{?_with_dpdkevents} \
%{?_with_dpdkstat} \
%{?_with_email} \
%{?_with_entropy} \
%{?_with_openvpn} \
%{?_with_oracle} \
%{?_with_ovs_events} \
+ %{?_with_ovs_stats} \
%{?_with_perl} \
%{?_with_pf} \
%{?_with_pinba} \
%if %{with_drbd}
%{_libdir}/%{name}/drbd.so
%endif
-%if %{with_dpdkstat}
-%{_libdir}/%{name}/dpdkstat.so
-%endif
%if %{with_ethstat}
%{_libdir}/%{name}/ethstat.so
%endif
%if %{with_olsrd}
%{_libdir}/%{name}/olsrd.so
%endif
-%if %{with_ovs_events}
-%{_libdir}/%{name}/ovs_events.so
-%endif
%if %{with_powerdns}
%{_libdir}/%{name}/powerdns.so
%endif
%{_libdir}/%{name}/dbi.so
%endif
+%if %{with_dpdkevents}
+%files dpdkevents
+%{_libdir}/%{name}/dpdkevents.so
+%endif
+
+%if %{with_dpdkstat}
+%files dpdkstat
+%{_libdir}/%{name}/dpdkstat.so
+%endif
+
%if %{with_email}
%files email
%{_libdir}/%{name}/email.so
%{_libdir}/%{name}/openldap.so
%endif
+%if %{with_ovs_events}
+%files ovs_events
+%{_libdir}/%{name}/ovs_events.so
+%endif
+
+%if %{with_ovs_stats}
+%files ovs_stats
+%{_libdir}/%{name}/ovs_stats.so
+%endif
+
%if %{with_perl}
%files perl
%{perl_vendorlib}/Collectd.pm
%doc contrib/
%changelog
+* Sun Mar 05 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-6
+- Move recently added plugins to subpackages
+
+* Sun Mar 05 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-5
+- Add new ovs_stats plugin
+
+* Sun Mar 05 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-4
+- Don't enable XFS support on RHEL6, it is missing for i386
+
+* Sun Mar 05 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-3
+- Add dpdkevents plugin, disabled by default
+
* Wed Feb 22 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-2
- Enable XFS support in df plugin
- Fix bogus date in changelog
* 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>.
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) {
.ovs_db_serv = "6640", /* use default OVS DB service */
};
-static const iface_counter ovs_stats_counter_name_to_type(const char *counter) {
+static iface_counter ovs_stats_counter_name_to_type(const char *counter) {
iface_counter index = not_supported;
if (counter == NULL)
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 (int 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]));
}
yajl_val bridges = yajl_tree_get(jupdates, path, yajl_t_object);
if (bridges && YAJL_IS_OBJECT(bridges)) {
- for (int i = 0; i < YAJL_GET_OBJECT(bridges)->len; i++) {
+ for (size_t i = 0; i < YAJL_GET_OBJECT(bridges)->len; i++) {
yajl_val bridge = YAJL_GET_OBJECT(bridges)->values[i];
ovs_stats_update_bridge(bridge);
}
yajl_val bridge;
if (bridges && YAJL_IS_OBJECT(bridges)) {
pthread_mutex_lock(&g_stats_lock);
- for (int i = 0; i < YAJL_GET_OBJECT(bridges)->len; i++) {
+ for (size_t i = 0; i < YAJL_GET_OBJECT(bridges)->len; i++) {
bridge = YAJL_GET_OBJECT(bridges)->values[i];
ovs_stats_del_bridge(bridge);
}
yajl_val ports = yajl_tree_get(jupdates, path, yajl_t_object);
yajl_val port;
if (ports && YAJL_IS_OBJECT(ports)) {
- for (int i = 0; i < YAJL_GET_OBJECT(ports)->len; i++) {
+ for (size_t i = 0; i < YAJL_GET_OBJECT(ports)->len; i++) {
port = YAJL_GET_OBJECT(ports)->values[i];
ovs_stats_update_port(YAJL_GET_OBJECT(ports)->keys[i], port);
}
yajl_val ports = yajl_tree_get(jupdates, path, yajl_t_object);
pthread_mutex_lock(&g_stats_lock);
if (ports && YAJL_IS_OBJECT(ports))
- for (int i = 0; i < YAJL_GET_OBJECT(ports)->len; i++) {
+ for (size_t i = 0; i < YAJL_GET_OBJECT(ports)->len; i++) {
ovs_stats_del_port(YAJL_GET_OBJECT(ports)->keys[i]);
}
pthread_mutex_unlock(&g_stats_lock);
char *counter_name = NULL;
int64_t counter_value = 0;
if (stats && YAJL_IS_ARRAY(stats))
- for (int i = 0; i < YAJL_GET_ARRAY(stats)->len; i++) {
+ 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]);
char *value;
if (ext_ids && YAJL_IS_ARRAY(ext_ids))
- for (int i = 0; i < YAJL_GET_ARRAY(ext_ids)->len; i++) {
+ 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) {
yajl_val ports = yajl_tree_get(jupdates, path, yajl_t_object);
pthread_mutex_lock(&g_stats_lock);
if (ports && YAJL_IS_OBJECT(ports))
- for (int i = 0; i < YAJL_GET_OBJECT(ports)->len; i++)
+ for (size_t i = 0; i < YAJL_GET_OBJECT(ports)->len; i++)
ovs_stats_update_iface(YAJL_GET_OBJECT(ports)->values[i]);
pthread_mutex_unlock(&g_stats_lock);
return;
static int ovs_stats_plugin_read(__attribute__((unused)) user_data_t *ud) {
bridge_list_t *bridge;
port_list_t *port;
- char devname[PORT_NAME_SIZE_MAX];
+ char devname[PORT_NAME_SIZE_MAX * 2];
pthread_mutex_lock(&g_stats_lock);
for (bridge = g_bridge_list_head; bridge != NULL; bridge = bridge->next) {
* 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);
for (size_t j = 0; (j == 0) || (j < cmd.cmd.flush.identifiers_num); j++) {
char *identifier = NULL;
- char buffer[1024];
- int status;
+ char buf[1024];
if (cmd.cmd.flush.identifiers_num != 0) {
identifier_t *id = cmd.cmd.flush.identifiers + j;
- if (format_name(buffer, sizeof(buffer), id->host, id->plugin,
+ if (format_name(buf, sizeof(buf), id->host, id->plugin,
id->plugin_instance, id->type,
id->type_instance) != 0) {
error++;
continue;
}
- identifier = buffer;
+ identifier = buf;
}
- status = plugin_flush(plugin, DOUBLE_TO_CDTIME_T(cmd.cmd.flush.timeout),
- identifier);
- if (status == 0)
+ if (plugin_flush(plugin, DOUBLE_TO_CDTIME_T(cmd.cmd.flush.timeout),
+ identifier) == 0)
success++;
else
error++;
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);
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)
"minor_fault", "unused", "available",
"actual_balloon", "rss"};
- if ((tag_index < 0) || (tag_index >= STATIC_ARRAY_SIZE(tags))) {
+ if ((tag_index < 0) || (tag_index >= (int)STATIC_ARRAY_SIZE(tags))) {
ERROR("virt plugin: Array index out of bounds: tag_index = %d", tag_index);
return;
}
};
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);