Sebastien Pahl <sebastien.pahl at dotcloud.com>
- AMQP plugin.
+Serhiy Pshyk <serhiyx.pshyk at intel.com>
+ - intel_pmu plugin
+ - intel_rdt plugin
+ - snmp_agent plugin
+
Simon Kuhnle <simon at blarzwurst.de>
- OpenBSD code for the cpu and memory plugins.
pkginclude_HEADERS = \
src/libcollectdclient/collectd/client.h \
- src/libcollectdclient/collectd/network.h \
+ src/libcollectdclient/collectd/lcc_features.h \
src/libcollectdclient/collectd/network_buffer.h \
- src/libcollectdclient/collectd/lcc_features.h
+ src/libcollectdclient/collectd/network.h \
+ src/libcollectdclient/collectd/network_parse.h \
+ src/libcollectdclient/collectd/server.h \
+ src/libcollectdclient/collectd/types.h
lib_LTLIBRARIES = libcollectdclient.la
test_utils_mount \
test_utils_subst \
test_utils_time \
- test_utils_vl_lookup
+ test_utils_vl_lookup \
+ test_libcollectd_network_parse
TESTS = $(check_PROGRAMS)
collectd_nagios_SOURCES = src/collectd-nagios.c
collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) \
- -I$(srcdir)/src/libcollectdclient/collectd \
- -I$(top_builddir)/src/libcollectdclient/collectd
+ -I$(srcdir)/src/libcollectdclient \
+ -I$(top_builddir)/src/libcollectdclient
collectd_nagios_LDADD = libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectd_nagios_LDADD += -lsocket
collectdctl_SOURCES = src/collectdctl.c
collectdctl_CPPFLAGS = $(AM_CPPFLAGS) \
- -I$(srcdir)/src/libcollectdclient/collectd \
- -I$(top_builddir)/src/libcollectdclient/collectd
+ -I$(srcdir)/src/libcollectdclient \
+ -I$(top_builddir)/src/libcollectdclient
collectdctl_LDADD = libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectdctl_LDADD += -lsocket
collectd_tg_SOURCES = src/collectd-tg.c
collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
- -I$(srcdir)/src/libcollectdclient/collectd \
- -I$(top_builddir)/src/libcollectdclient/collectd
+ -I$(srcdir)/src/libcollectdclient \
+ -I$(top_builddir)/src/libcollectdclient
collectd_tg_LDADD = \
$(PTHREAD_LIBS) \
libheap.la \
libcollectdclient_la_SOURCES = \
src/libcollectdclient/client.c \
src/libcollectdclient/network.c \
- src/libcollectdclient/network_buffer.c
+ src/libcollectdclient/network_buffer.c \
+ src/libcollectdclient/network_parse.c \
+ src/libcollectdclient/server.c
libcollectdclient_la_CPPFLAGS = \
$(AM_CPPFLAGS) \
- -I$(srcdir)/src/libcollectdclient/collectd \
- -I$(top_builddir)/src/libcollectdclient/collectd \
+ -I$(srcdir)/src/libcollectdclient \
+ -I$(top_builddir)/src/libcollectdclient \
-I$(srcdir)/src/daemon
-libcollectdclient_la_LDFLAGS = -version-info 1:0:0
-libcollectdclient_la_LIBADD =
+libcollectdclient_la_LDFLAGS = -version-info 2:0:1
+libcollectdclient_la_LIBADD = -lm
if BUILD_WITH_LIBGCRYPT
libcollectdclient_la_CPPFLAGS += $(GCRYPT_CPPFLAGS)
libcollectdclient_la_LDFLAGS += $(GCRYPT_LDFLAGS)
libcollectdclient_la_LIBADD += $(GCRYPT_LIBS)
endif
+# network_parse_test.c includes network_parse.c, so no need to link with
+# libcollectdclient.so.
+test_libcollectd_network_parse_SOURCES = src/libcollectdclient/network_parse_test.c
+test_libcollectd_network_parse_CPPFLAGS = \
+ $(AM_CPPFLAGS) \
+ -I$(srcdir)/src/libcollectdclient \
+ -I$(top_builddir)/src/libcollectdclient
+if BUILD_WITH_LIBGCRYPT
+test_libcollectd_network_parse_CPPFLAGS += $(GCRYPT_CPPFLAGS)
+test_libcollectd_network_parse_LDFLAGS = $(GCRYPT_LDFLAGS)
+test_libcollectd_network_parse_LDADD = $(GCRYPT_LIBS)
+endif
liboconfig_la_SOURCES = \
src/liboconfig/oconfig.c \
pkglib_LTLIBRARIES += dpdkevents.la
dpdkevents_la_SOURCES = src/dpdkevents.c src/utils_dpdk.c src/utils_dpdk.h
dpdkevents_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDPDK_CPPFLAGS)
+dpdkevents_la_CFLAGS = $(AM_CFLAGS) $(LIBDPDK_CFLAGS)
dpdkevents_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBDPDK_LDFLAGS)
-dpdkevents_la_LIBADD = -ldpdk
+dpdkevents_la_LIBADD = $(LIBDPDK_LIBS)
endif
if BUILD_PLUGIN_DPDKSTAT
pkglib_LTLIBRARIES += dpdkstat.la
dpdkstat_la_SOURCES = src/dpdkstat.c src/utils_dpdk.c src/utils_dpdk.h
dpdkstat_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBDPDK_CPPFLAGS)
+dpdkstat_la_CFLAGS = $(AM_CFLAGS) $(LIBDPDK_CFLAGS)
dpdkstat_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBDPDK_LDFLAGS)
-dpdkstat_la_LIBADD = -ldpdk
+dpdkstat_la_LIBADD = $(LIBDPDK_LIBS)
endif
if BUILD_PLUGIN_DRBD
hugepages_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
+if BUILD_PLUGIN_INTEL_PMU
+pkglib_LTLIBRARIES += intel_pmu.la
+intel_pmu_la_SOURCES = src/intel_pmu.c
+intel_pmu_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBJEVENTS_CPPFLAGS)
+intel_pmu_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBJEVENTS_LDFLAGS)
+intel_pmu_la_LIBADD = $(BUILD_WITH_LIBJEVENTS_LIBS)
+endif
+
if BUILD_PLUGIN_INTEL_RDT
pkglib_LTLIBRARIES += intel_rdt.la
intel_rdt_la_SOURCES = src/intel_rdt.c
endif
+if BUILD_PLUGIN_SYNPROXY
+pkglib_LTLIBRARIES += synproxy.la
+synproxy_la_SOURCES = src/synproxy.c
+synproxy_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
if BUILD_PLUGIN_SYSLOG
pkglib_LTLIBRARIES += syslog.la
syslog_la_SOURCES = src/syslog.c
if BUILD_PLUGIN_TURBOSTAT
pkglib_LTLIBRARIES += turbostat.la
-turbostat_la_SOURCES = src/turbostat.c
+turbostat_la_SOURCES = \
+ src/turbostat.c \
+ src/msr-index.h
turbostat_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
hugepages can be found here:
https://www.kernel.org/doc/Documentation/vm/hugetlbpage.txt.
+ - intel_pmu
+ The intel_pmu plugin reads performance counters provided by the Linux
+ kernel perf interface. The plugin uses jevents library to resolve named
+ events to perf events and access perf interface.
+
- intel_rdt
The intel_rdt plugin collects information provided by monitoring features
of Intel Resource Director Technology (Intel(R) RDT) like Cache Monitoring
- netapp
Plugin to query performance values from a NetApp storage system using the
- “Manage ONTAP” SDK provided by NetApp.
+ “Manage ONTAP” SDK provided by NetApp.
- netlink
Very detailed Linux network interface and routing statistics. You can get
plugin of choice for that.
- nfs
- NFS Procedures: Which NFS command were called how often. Only NFSv2 and
- NFSv3 right now.
+ NFS Procedures: Which NFS command were called how often.
- nginx
Collects statistics from `nginx' (speak: engine X), a HTTP and mail
For querying iptables counters.
<http://netfilter.org/>
+ * libjevents (optional)
+ The jevents library is used by the `intel_pmu' plugin to access the Linux
+ kernel perf interface.
+ Note: the library should be build with -fPIC flag to be linked with
+ intel_pmu shared object correctly.
+ <https://github.com/andikleen/pmu-tools>
+
* libjvm (optional)
Library that encapsulates the `Java Virtual Machine' (JVM). This library is
used by the `java' plugin to execute Java bytecode.
pthread_np.h \
pwd.h \
regex.h \
+ sys/endian.h \
sys/fs_types.h \
sys/fstyp.h \
sys/ioctl.h \
]]
)
# For the turbostat plugin
- AC_CHECK_HEADERS([asm/msr-index.h],
- [have_asm_msrindex_h="yes"],
- [have_asm_msrindex_h="no"]
- )
-
- if test "x$have_asm_msrindex_h" = "xyes"; then
- AC_CACHE_CHECK([whether asm/msr-index.h has MSR_PKG_C10_RESIDENCY],
- [c_cv_have_usable_asm_msrindex_h],
- [
- AC_COMPILE_IFELSE(
- [
- AC_LANG_PROGRAM(
- [[#include<asm/msr-index.h>]],
- [[
- int y = MSR_PKG_C10_RESIDENCY;
- return(y);
- ]]
- )
- ],
- [c_cv_have_usable_asm_msrindex_h="yes"],
- [c_cv_have_usable_asm_msrindex_h="no"],
- )
- ]
- )
- fi
-
AC_CHECK_HEADERS([cpuid.h],
[have_cpuid_h="yes"],
[have_cpuid_h="no (cpuid.h not found)"]
# --with-libdpdk {{{
AC_ARG_VAR([LIBDPDK_CPPFLAGS], [Preprocessor flags for libdpdk])
+AC_ARG_VAR([LIBDPDK_CFLAGS], [Compiler flags for libdpdk])
AC_ARG_VAR([LIBDPDK_LDFLAGS], [Linker flags for libdpdk])
+AC_ARG_VAR([LIBDPDK_LIBS], [Libraries to link for libdpdk])
AC_ARG_WITH([libdpdk],
[AS_HELP_STRING([--without-libdpdk], [Disable libdpdk.])],
)
if test "x$with_libdpdk" != "xno"; then
+ PKG_CHECK_MODULES([DPDK], [libdpdk], [],
+ [AC_MSG_NOTICE([no DPDK pkg-config, using defaults])])
if test "x$LIBDPDK_CPPFLAGS" = "x"; then
LIBDPDK_CPPFLAGS="-I/usr/include/dpdk"
fi
+ if test "x$LIBDPDK_CFLAGS" = "x"; then
+ LIBDPDK_CFLAGS="$DPDK_CFLAGS"
+ LIBDPDK_CPPFLAGS="$LIBDPDK_CPPFLAGS $DPDK_CFLAGS"
+ fi
+ if test "x$LIBDPDK_LIBS" = "x"; then
+ if test "x$DPDK_LIBS" != "x"; then
+ LIBDPDK_LIBS="$DPDK_LIBS"
+ else
+ LIBDPDK_LIBS="-ldpdk"
+ fi
+ fi
SAVE_CPPFLAGS="$CPPFLAGS"
CPPFLAGS="$LIBDPDK_CPPFLAGS $CPPFLAGS"
+ SAVE_CFLAGS="$CFLAGS"
+ CFLAGS="$LIBDPDK_CFLAGS $CFLAGS"
AC_CHECK_HEADERS([rte_config.h],
[
with_libdpdk="yes"
[with_libdpdk="no (rte_config.h not found)"]
)
CPPFLAGS="$SAVE_CPPFLAGS"
+ CFLAGS="$SAVE_CFLAGS"
fi
if test "x$with_libdpdk" = "xyes"; then
AC_SUBST([BUILD_WITH_LIBPQOS_LIBS])
# }}}
+# --with-libjevents {{{
+with_libjevents_cppflags=""
+with_libjevents_ldflags=""
+AC_ARG_WITH([libjevents],
+ [AS_HELP_STRING([--with-libjevents@<:@=PREFIX@:>@], [Path to libjevents.])],
+ [
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"; then
+ with_libjevents_cppflags="-I$withval/include"
+ with_libjevents_ldflags="-L$withval/lib"
+ with_libjevents="yes"
+ else
+ with_libjevents="$withval"
+ fi
+ ],
+ [with_libjevents="yes"]
+)
+
+if test "x$with_libjevents" = "xyes"; then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libjevents_cppflags"
+
+ AC_CHECK_HEADERS([jevents.h], [with_libjevents="yes"], [with_libjevents="no (jevents.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libjevents" = "xyes"; then
+ SAVE_LDFLAGS="$LDFLAGS"
+ LDFLAGS="$LDFLAGS $with_libjevents_ldflags"
+
+ AC_CHECK_LIB([jevents], [json_events], [with_libjevents="yes"], [with_libjevents="no (Can't find libjevents)"])
+
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libjevents" = "xyes"; then
+ BUILD_WITH_LIBJEVENTS_CPPFLAGS="$with_libjevents_cppflags"
+ BUILD_WITH_LIBJEVENTS_LDFLAGS="$with_libjevents_ldflags"
+ BUILD_WITH_LIBJEVENTS_LIBS="-ljevents"
+fi
+AC_SUBST([BUILD_WITH_LIBJEVENTS_CPPFLAGS])
+AC_SUBST([BUILD_WITH_LIBJEVENTS_LDFLAGS])
+AC_SUBST([BUILD_WITH_LIBJEVENTS_LIBS])
+# }}}
+
# --with-libprotobuf {{{
with_libprotobuf_cppflags=""
with_libprotobuf_ldflags=""
[AC_DEFINE([HAVE_UPSCLI_INIT], [1], [Define when upscli_init() (since version 2-7) is available.])]
)
+ AC_CHECK_LIB([upsclient], [upscli_tryconnect],
+ [AC_DEFINE([HAVE_UPSCLI_TRYCONNECT], [1], [Define when upscli_tryconnect() (since version 2.6.2) is available.])]
+ )
+
LDFLAGS="$SAVE_LDFLAGS"
fi
plugin_gps="no"
plugin_grpc="no"
plugin_hugepages="no"
+plugin_intel_pmu="no"
plugin_intel_rdt="no"
plugin_interface="no"
plugin_ipc="no"
plugin_serial="no"
plugin_smart="no"
plugin_swap="no"
+plugin_synproxy="no"
plugin_tape="no"
plugin_tcpconns="no"
plugin_ted="no"
plugin_protocols="yes"
plugin_serial="yes"
plugin_swap="yes"
+ plugin_synproxy="yes"
plugin_tcpconns="yes"
plugin_thermal="yes"
plugin_uptime="yes"
plugin_ipvs="yes"
fi
- if test "x$c_cv_have_usable_asm_msrindex_h" = "xyes" && test "x$have_cpuid_h" = "xyes"; then
+ if test "x$have_cpuid_h" = "xyes"; then
plugin_turbostat="yes"
fi
plugin_xencpu="yes"
fi
-if test "x$with_libdpdk" = "xyes"
-then
+if test "x$with_libdpdk" = "xyes"; then
plugin_dpdkevents="$dpdk_keepalive"
plugin_dpdkstat="yes"
fi
AC_PLUGIN([grpc], [$plugin_grpc], [gRPC plugin])
AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
AC_PLUGIN([hugepages], [$plugin_hugepages], [Hugepages statistics])
+AC_PLUGIN([intel_pmu], [$with_libjevents], [Intel performance monitor plugin])
AC_PLUGIN([intel_rdt], [$with_libpqos], [Intel RDT monitor plugin])
AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
AC_PLUGIN([ipc], [$plugin_ipc], [IPC statistics])
AC_PLUGIN([snmp_agent], [$with_libnetsnmpagent], [SNMP agent plugin])
AC_PLUGIN([statsd], [yes], [StatsD plugin])
AC_PLUGIN([swap], [$plugin_swap], [Swap usage statistics])
+AC_PLUGIN([synproxy], [$plugin_synproxy], [Synproxy stats plugin])
AC_PLUGIN([syslog], [$have_syslog], [Syslog logging plugin])
AC_PLUGIN([table], [yes], [Parsing of tabular data])
AC_PLUGIN([tail], [yes], [Parsing of logfiles])
AC_MSG_RESULT([ libi2c-dev . . . . . $with_libi2c])
AC_MSG_RESULT([ libiokit . . . . . . $with_libiokit])
AC_MSG_RESULT([ libiptc . . . . . . . $with_libiptc])
+AC_MSG_RESULT([ libjevents . . . . . $with_libjevents])
AC_MSG_RESULT([ libjvm . . . . . . . $with_java])
AC_MSG_RESULT([ libkstat . . . . . . $with_kstat])
AC_MSG_RESULT([ libkvm . . . . . . . $with_libkvm])
AC_MSG_RESULT([ grpc . . . . . . . . $enable_grpc])
AC_MSG_RESULT([ hddtemp . . . . . . . $enable_hddtemp])
AC_MSG_RESULT([ hugepages . . . . . . $enable_hugepages])
+AC_MSG_RESULT([ intel_pmu . . . . . . $enable_intel_pmu])
AC_MSG_RESULT([ intel_rdt . . . . . . $enable_intel_rdt])
AC_MSG_RESULT([ interface . . . . . . $enable_interface])
AC_MSG_RESULT([ ipc . . . . . . . . . $enable_ipc])
AC_MSG_RESULT([ snmp_agent . . . . . $enable_snmp_agent])
AC_MSG_RESULT([ statsd . . . . . . . $enable_statsd])
AC_MSG_RESULT([ swap . . . . . . . . $enable_swap])
+AC_MSG_RESULT([ synproxy . . . . . . $enable_synproxy])
AC_MSG_RESULT([ syslog . . . . . . . $enable_syslog])
AC_MSG_RESULT([ table . . . . . . . . $enable_table])
AC_MSG_RESULT([ tail_csv . . . . . . $enable_tail_csv])
--- /dev/null
+# Example configuration for PHP-FPM
+<Plugin "curl_json">
+ <URL "http://nginx-status/php-fpm-status?json">
+ Plugin "phpfpm"
+ Instance "main"
+ <Key "accepted conn">
+ Type "total_requests"
+ Instance "accepted"
+ </Key>
+ <Key "slow requests">
+ Type "total_requests"
+ Instance "slow"
+ </Key>
+ <Key "listen queue">
+ Type "queue_length"
+ Instance "listen"
+ </Key>
+ <Key "active processes">
+ Type "vs_processes"
+ Instance "active"
+ </Key>
+ <Key "total processes">
+ Type "vs_processes"
+ Instance "total"
+ </Key>
+ </URL>
+</Plugin>
%define with_grpc 0%{!?_without_grpc:0}
# plugin lpar disabled, requires AIX
%define with_lpar 0%{!?_without_lpar:0}
+# plugin intel_pmu disabled, requires libjevents
+%define with_intel_pmu 0%{!?_without_intel_pmu:0}
# plugin intel_rdt disabled, requires intel-cmt-cat
%define with_intel_rdt 0%{!?_without_intel_rdt:0}
# plugin mic disabled, requires Mic
Summary: Statistics collection and monitoring daemon
Name: collectd
Version: 5.7.1
-Release: 6%{?dist}
+Release: 7%{?dist}
URL: https://collectd.org
Source: https://collectd.org/files/%{name}-%{version}.tar.bz2
License: GPLv2
provided via SMART and queried by the external hddtemp daemon.
%endif
+%if %{with_intel_pmu}
+%package intel_pmu
+Summary: Intel PMU plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+%description intel_pmu
+The intel_pmu plugin reads performance counters provided by the Linux
+kernel perf interface.
+%endif
+
%if %{with_intel_rdt}
%package intel_rdt
Summary: Intel RDT plugin for collectd
Summary: Java plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: java-devel, jpackage-utils
-Requires: java, jpackage-utils
+BuildRequires: java-devel >= 1.6, jpackage-utils >= 1.6
+Requires: java >= 1.6, jpackage-utils >= 1.6
%description java
This plugin for collectd allows plugins to be written in Java and executed
in an embedded JVM.
%define _with_hugepages --disable-hugepages
%endif
+%if %{with_intel_pmu}
+%define _with_intel_pmu --enable-intel_pmu
+%else
+%define _with_intel_pmu --disable-intel_pmu
+%endif
+
%if %{with_intel_rdt}
%define _with_intel_rdt --enable-intel_rdt
%else
%{?_with_grpc} \
%{?_with_hddtemp} \
%{?_with_hugepages} \
+ %{?_with_intel_pmu} \
%{?_with_intel_rdt} \
%{?_with_interface} \
%{?_with_ipc} \
%{_libdir}/%{name}/hddtemp.so
%endif
+%if %{with_intel_pmu}
+%files intel_pmu
+%{_libdir}/%{name}/intel_pmu.so
+%endif
+
%if %{with_intel_rdt}
%files intel_rdt
%{_libdir}/%{name}/intel_rdt.so
%doc contrib/
%changelog
+* Fri Aug 18 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-7
+- Add new intel_pmu plugin
+
* Sun Mar 05 2017 Ruben Kerkhof <ruben@rubenkerkhof.com> - 5.7.1-6
- Move recently added plugins to subpackages
# dns CAP_NET_RAW
# exec CAP_SETUID CAP_SETGID
# intel_rdt CAP_SYS_RAWIO
+# intel_pmu CAP_SYS_ADMIN
# iptables CAP_NET_ADMIN
# ping CAP_NET_RAW
# smart CAP_SYS_RAWIO
# By default, drop all capabilities:
CapabilityBoundingSet=
-NoNewPrivileges=true
-
# Tell systemd it will receive a notification from collectd over its control
# socket once the daemon is ready. See systemd.service(5) for more details.
Type=notify
string type_instance = 5;
}
+message MetadataValue {
+ oneof value {
+ string string_value = 1;
+ int64 int64_value = 2;
+ uint64 uint64_value = 3;
+ double double_value = 4;
+ bool bool_value = 5;
+ };
+}
+
message Value {
oneof value {
uint64 counter = 1;
Identifier identifier = 4;
repeated string ds_names = 5;
-}
+ map<string, MetadataValue> meta_data = 6;
+}
\ No newline at end of file
sstrncpy(inst->ident.plugin_instance, AGG_FUNC_PLACEHOLDER,
sizeof(inst->ident.plugin_instance));
else if (strcmp("", tmp_plugin) != 0)
- ssnprintf(inst->ident.plugin_instance,
- sizeof(inst->ident.plugin_instance), "%s-%s", tmp_plugin,
- AGG_FUNC_PLACEHOLDER);
+ snprintf(inst->ident.plugin_instance, sizeof(inst->ident.plugin_instance),
+ "%s-%s", tmp_plugin, AGG_FUNC_PLACEHOLDER);
else if (strcmp("", tmp_plugin_instance) != 0)
- ssnprintf(inst->ident.plugin_instance,
- sizeof(inst->ident.plugin_instance), "%s-%s",
- tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
+ snprintf(inst->ident.plugin_instance, sizeof(inst->ident.plugin_instance),
+ "%s-%s", tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
else
- ssnprintf(inst->ident.plugin_instance,
- sizeof(inst->ident.plugin_instance), "%s-%s-%s", tmp_plugin,
- tmp_plugin_instance, AGG_FUNC_PLACEHOLDER);
+ snprintf(inst->ident.plugin_instance, sizeof(inst->ident.plugin_instance),
+ "%s-%s-%s", tmp_plugin, tmp_plugin_instance,
+ AGG_FUNC_PLACEHOLDER);
}
/* Type */
if (r.reply.id == AMQP_CONNECTION_CLOSE_METHOD) {
amqp_connection_close_t *m = r.reply.decoded;
char *tmp = camqp_bytes_cstring(&m->reply_text);
- ssnprintf(buffer, buffer_size, "Server connection error %d: %s",
- m->reply_code, tmp);
+ snprintf(buffer, buffer_size, "Server connection error %d: %s",
+ m->reply_code, tmp);
sfree(tmp);
} else if (r.reply.id == AMQP_CHANNEL_CLOSE_METHOD) {
amqp_channel_close_t *m = r.reply.decoded;
char *tmp = camqp_bytes_cstring(&m->reply_text);
- ssnprintf(buffer, buffer_size, "Server channel error %d: %s",
- m->reply_code, tmp);
+ snprintf(buffer, buffer_size, "Server channel error %d: %s",
+ m->reply_code, tmp);
sfree(tmp);
} else {
- ssnprintf(buffer, buffer_size, "Server error method %#" PRIx32,
- r.reply.id);
+ snprintf(buffer, buffer_size, "Server error method %#" PRIx32,
+ r.reply.id);
}
break;
default:
- ssnprintf(buffer, buffer_size, "Unknown reply type %i", (int)r.reply_type);
+ snprintf(buffer, buffer_size, "Unknown reply type %i", (int)r.reply_type);
}
return buffer;
if (conf->routing_key != NULL) {
sstrncpy(routing_key, conf->routing_key, sizeof(routing_key));
} else {
- ssnprintf(routing_key, sizeof(routing_key), "collectd/%s/%s/%s/%s/%s",
- vl->host, vl->plugin, vl->plugin_instance, vl->type,
- vl->type_instance);
+ snprintf(routing_key, sizeof(routing_key), "collectd/%s/%s/%s/%s/%s",
+ vl->host, vl->plugin, vl->plugin_instance, vl->type,
+ vl->type_instance);
/* Switch slashes (the only character forbidden by collectd) and dots
* (the separation character used by AMQP). */
if (publish) {
char cbname[128];
- ssnprintf(cbname, sizeof(cbname), "amqp/%s", conf->name);
+ snprintf(cbname, sizeof(cbname), "amqp/%s", conf->name);
status = plugin_register_write(
cbname, camqp_write, &(user_data_t){
status = -1;
}
- if (status == 0) {
- char callback_name[3 * DATA_MAX_NAME_LEN];
-
- ssnprintf(callback_name, sizeof(callback_name), "apache/%s/%s",
- (st->host != NULL) ? st->host : hostname_g,
- (st->name != NULL) ? st->name : "default");
-
- status = plugin_register_complex_read(
- /* group = */ NULL,
- /* name = */ callback_name,
- /* callback = */ apache_read_host,
- /* interval = */ 0, &(user_data_t){
- .data = st, .free_func = apache_free,
- });
- }
-
if (status != 0) {
apache_free(st);
return -1;
}
- return 0;
+ char callback_name[3 * DATA_MAX_NAME_LEN];
+
+ snprintf(callback_name, sizeof(callback_name), "apache/%s/%s",
+ (st->host != NULL) ? st->host : hostname_g,
+ (st->name != NULL) ? st->name : "default");
+
+ return plugin_register_complex_read(
+ /* group = */ NULL,
+ /* name = */ callback_name,
+ /* callback = */ apache_read_host,
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = st, .free_func = apache_free,
+ });
} /* int config_add */
static int config(oconfig_item_t *ci) {
static char credentials[1024];
int status;
- status = ssnprintf(credentials, sizeof(credentials), "%s:%s", st->user,
- (st->pass == NULL) ? "" : st->pass);
+ status = snprintf(credentials, sizeof(credentials), "%s:%s", st->user,
+ (st->pass == NULL) ? "" : st->pass);
if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
ERROR("apache plugin: init_host: Returning an error "
"because the credentials have been "
static char credentials[1024];
int status;
- status = ssnprintf(credentials, sizeof(credentials), "%s:%s", user,
- (pass == NULL) ? "" : pass);
+ status = snprintf(credentials, sizeof(credentials), "%s:%s", user,
+ (pass == NULL) ? "" : pass);
if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
ERROR("ascent plugin: ascent_init: Returning an error because the "
"credentials have been truncated.");
char filename[PATH_MAX];
int status;
- ssnprintf(filename, sizeof(filename), "%s/%s/%s", dir, power_supply,
- basename);
+ snprintf(filename, sizeof(filename), "%s/%s/%s", dir, power_supply, basename);
status = (int)read_file_contents(filename, buffer, buffer_size - 1);
if (status < 0)
FILE *fh;
- ssnprintf(filename, sizeof(filename), "%s/%s/info", dir, power_supply);
+ snprintf(filename, sizeof(filename), "%s/%s/info", dir, power_supply);
fh = fopen(filename, "r");
if (fh == NULL)
return errno;
FILE *fh;
- ssnprintf(filename, sizeof(filename), "%s/%s/state", dir, power_supply);
+ snprintf(filename, sizeof(filename), "%s/%s/state", dir, power_supply);
fh = fopen(filename, "r");
if (fh == NULL) {
if ((errno == EAGAIN) || (errno == EINTR) || (errno == ENOENT))
gauge_t voltage = NAN;
gauge_t charge = NAN;
- ssnprintf(filename, sizeof(filename), PROC_PMU_PATH_FORMAT, i);
+ snprintf(filename, sizeof(filename), PROC_PMU_PATH_FORMAT, i);
if (access(filename, R_OK) != 0)
break;
- ssnprintf(plugin_instance, sizeof(plugin_instance), "%i", i);
+ snprintf(plugin_instance, sizeof(plugin_instance), "%i", i);
fh = fopen(filename, "r");
if (fh == NULL) {
nsstats_translation_table_length,
plugin_instance};
- ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-zone-%s",
- view->name, zone_name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "%s-zone-%s", view->name,
+ zone_name);
if (version == 3) {
list_info_ptr_t list_info = {plugin_instance,
list_info_ptr_t list_info = {plugin_instance,
/* type = */ "dns_qtype"};
- ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-qtypes",
- view->name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "%s-qtypes", view->name);
if (version == 3) {
bind_parse_generic_name_attr_value_list(
/* xpath = */ "counters[@type='resqtype']",
resstats_translation_table_length,
plugin_instance};
- ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-resolver_stats",
- view->name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "%s-resolver_stats",
+ view->name);
if (version == 3) {
bind_parse_generic_name_attr_value_list(
"counters[@type='resstats']",
list_info_ptr_t list_info = {plugin_instance,
/* type = */ "dns_qtype_cached"};
- ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-cache_rr_sets",
- view->name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "%s-cache_rr_sets",
+ view->name);
bind_parse_generic_name_value(/* xpath = */ "cache/rrset",
/* callback = */ bind_xml_list_callback,
if (ignorelist_match(il_cgroup, cgroup_name))
return 0;
- ssnprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, cgroup_name);
+ snprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, cgroup_name);
status = lstat(abs_path, &statbuf);
if (status != 0) {
if (!S_ISDIR(statbuf.st_mode))
return 0;
- ssnprintf(abs_path, sizeof(abs_path), "%s/%s/cpuacct.stat", dirname,
- cgroup_name);
+ snprintf(abs_path, sizeof(abs_path), "%s/%s/cpuacct.stat", dirname,
+ cgroup_name);
fh = fopen(abs_path, "r");
if (fh == NULL) {
char errbuf[1024];
struct stat statbuf;
int status;
- ssnprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename);
+ snprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename);
status = lstat(abs_path, &statbuf);
if (status != 0) {
#endif
#endif /* NAN_ZERO_ZERO */
-#include "libcollectdclient/collectd/client.h"
+#include "collectd/client.h"
#define RET_OKAY 0
#define RET_WARNING 1
#include "utils_heap.h"
-#include "libcollectdclient/collectd/client.h"
-#include "libcollectdclient/collectd/network.h"
+#include "collectd/client.h"
+#include "collectd/network.h"
#define DEF_NUM_HOSTS 1000
#define DEF_NUM_PLUGINS 20
#@BUILD_PLUGIN_GRPC_TRUE@LoadPlugin grpc
#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
#@BUILD_PLUGIN_HUGEPAGES_TRUE@LoadPlugin hugepages
+#@BUILD_PLUGIN_INTEL_PMU_TRUE@LoadPlugin intel_pmu
#@BUILD_PLUGIN_INTEL_RDT_TRUE@LoadPlugin intel_rdt
@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
#@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
# ReportByCpu true
# ReportByState true
# ValuesPercentage false
+# ReportNumCpu false
+# ReportGuestState false
+# SubtractGuestState true
#</Plugin>
#
#<Plugin csv>
#<Plugin filecount>
# <Directory "/path/to/dir">
+# #Plugin "foo"
# Instance "foodir"
# Name "*.conf"
# MTime "-5m"
# Size "+10k"
# Recursive true
# IncludeHidden false
+# #FilesSizeType "bytes"
+# #FilesCountType "files"
+# #TypeInstance "instance"
# </Directory>
#</Plugin>
# ValuesPercentage false
#</Plugin>
+#<Plugin intel_pmu>
+# ReportHardwareCacheEvents true
+# ReportKernelPMUEvents true
+# ReportSoftwareEvents true
+# EventList "/var/cache/pmu/GenuineIntel-6-2D-core.json"
+# HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD"
+#</Plugin>
+
#<Plugin "intel_rdt">
# Cores "0-2"
#</Plugin>
#</Plugin>
#<Plugin mcelog>
-# McelogClientSocket "/var/run/mcelog-client"
-# McelogLogfile "/var/log/mcelog"
+# <Memory>
+# McelogClientSocket "/var/run/mcelog-client"
+# PersistentNotification false
+# </Memory>
+# McelogLogfile "/var/log/mcelog"
#</Plugin>
#<Plugin md>
# QoS 2
# Topic "collectd/#"
# CleanSession true
+# CACert "/etc/ssl/ca.crt"
+# CertificateFile "/etc/ssl/client.crt"
+# CertificateKeyFile "/etc/ssl/client.pem"
+# TLSProtocol "tlsv1.2"
+# CipherSuite "ciphers"
# </Subscribe>
#</Plugin>
# CacheFlush 1800
@LOAD_PLUGIN_NETWORK@</Plugin>
+#<Plugin nfs>
+# ReportV2 false
+# #ReportV3 false
+# #ReportV4 false
+#</Plugin>
+
#<Plugin nginx>
# URL "http://localhost/status?auto"
# User "www-user"
# ForceSSL true
# VerifyPeer true
# CAPath "/path/to/folder"
+# #ConnectTimeout 5000
#</Plugin>
#<Plugin olsrd>
# ReportBytes true
# ValuesAbsolute true
# ValuesPercentage false
+# ReportIO true
#</Plugin>
#<Plugin table>
# <Table "/proc/slabinfo">
+# #Plugin "table"
# Instance "slabinfo"
# Separator " "
# <Result>
# Bucket 0.5 1.0 # -> bucket-latency-foo-0.5_1
# Bucket 1.0 2.0 # -> bucket-latency-foo-1_2
# Bucket 2.0 0 # -> bucket-latency-foo-2_inf
+# #BucketType "bucket"
# </DSType>
# Type "latency"
# Instance "foo"
# SystemManagementInterrupt true
# DigitalTemperatureSensor true
# PackageThermalManagement true
-# RunningAveragePowerLimit "7"
+# RunningAveragePowerLimit "7"
#</Plugin>
#<Plugin unixsock>
# CollectPurge false # Varnish 2 only
# CollectSession false
# CollectSHM true
-# CollectSMA false # Varnish 2 only
+# CollectSMA false # Varnish 2 & 4 only
# CollectSMS false
# CollectSM false # Varnish 2 only
# CollectStruct false
# CollectVCL false
# CollectVSM false # Varnish 4 only
# CollectWorkers false
+# CollectLock false # Varnish 4 only
+# CollectMempool false # Varnish 4 only
+# CollectManagement false # Varnish 4 only
+# CollectSMF false # Varnish 4 only
+# CollectVBE false # Varnish 4 only
# </Instance>
#</Plugin>
When set to B<true>, reports the number of available CPUs.
Defaults to B<false>.
+=item B<ReportGuestState> B<false>|B<true>
+
+When set to B<true>, reports the "guest" and "guest_nice" CPU states.
+Defaults to B<false>.
+
+=item B<SubtractGuestState> B<false>|B<true>
+
+This option is only considered when B<ReportGuestState> is set to B<true>.
+"guest" and "guest_nice" are included in respectively "user" and "nice".
+If set to B<true>, "guest" will be subtracted from "user" and "guest_nice"
+will be subtracted from "nice".
+Defaults to B<true>.
+
=back
=head2 Plugin C<cpufreq>
<Plugin curl>
<Page "stock_quotes">
+ Plugin "quotes"
URL "http://finance.google.com/finance?q=NYSE%3AAMD"
User "foo"
Password "bar"
=over 4
+=item B<Plugin> I<Plugin>
+
+Use I<Plugin> as the plugin name when submitting values.
+Defaults to C<curl>.
+
=item B<URL> I<URL>
URL of the web site to retrieve. Since a regular expression will be used to
Use I<Name> as the host name when submitting values. Defaults to the global
host name setting.
+=item B<Plugin> I<Plugin>
+
+Use I<Plugin> as the plugin name when submitting values.
+Defaults to C<curl_json>.
+
=item B<Instance> I<Instance>
Sets the plugin instance to I<Instance>.
=over 4
+=item B<Plugin> I<Plugin>
+
+Use I<Plugin> as the plugin name when submitting values.
+Defaults to B<filecount>.
+
=item B<Instance> I<Instance>
-Sets the plugin instance to I<Instance>. That instance name must be unique, but
-it's your responsibility, the plugin doesn't check for that. If not given, the
-instance is set to the directory name with all slashes replaced by underscores
-and all leading underscores removed.
+Sets the plugin instance to I<Instance>. If not given, the instance is set to
+the directory name with all slashes replaced by underscores and all leading
+underscores removed. Empty value is allowed.
=item B<Name> I<Pattern>
"Hidden" files and directories are those, whose name begins with a dot.
Defaults to I<false>, i.e. by default hidden files and directories are ignored.
+=item B<FilesSizeType> I<Type>
+
+Sets the type used to dispatch files combined size. Empty value ("") disables
+reporting. Defaults to B<bytes>.
+
+=item B<FilesCountType> I<Type>
+
+Sets the type used to dispatch number of files. Empty value ("") disables
+reporting. Defaults to B<files>.
+
+=item B<TypeInstance> I<Instance>
+
+Sets the I<type instance> used to dispatch values. Defaults to an empty string
+(no plugin instance).
+
=back
=head2 Plugin C<GenericJMX>
=back
+=head2 Plugin C<intel_pmu>
+
+The I<intel_pmu> plugin collects performance counters data on Intel CPUs using
+Linux perf interface. All events are reported on a per core basis.
+
+B<Synopsis:>
+
+ <Plugin intel_pmu>
+ ReportHardwareCacheEvents true
+ ReportKernelPMUEvents true
+ ReportSoftwareEvents true
+ EventList "/var/cache/pmu/GenuineIntel-6-2D-core.json"
+ HardwareEvents "L2_RQSTS.CODE_RD_HIT,L2_RQSTS.CODE_RD_MISS" "L2_RQSTS.ALL_CODE_RD"
+ </Plugin>
+
+B<Options:>
+
+=over 4
+
+=item B<ReportHardwareCacheEvents> B<false>|B<true>
+
+Enable or disable measuring of hardware CPU cache events:
+ - L1-dcache-loads
+ - L1-dcache-load-misses
+ - L1-dcache-stores
+ - L1-dcache-store-misses
+ - L1-dcache-prefetches
+ - L1-dcache-prefetch-misses
+ - L1-icache-loads
+ - L1-icache-load-misses
+ - L1-icache-prefetches
+ - L1-icache-prefetch-misses
+ - LLC-loads
+ - LLC-load-misses
+ - LLC-stores
+ - LLC-store-misses
+ - LLC-prefetches
+ - LLC-prefetch-misses
+ - dTLB-loads
+ - dTLB-load-misses
+ - dTLB-stores
+ - dTLB-store-misses
+ - dTLB-prefetches
+ - dTLB-prefetch-misses
+ - iTLB-loads
+ - iTLB-load-misses
+ - branch-loads
+ - branch-load-misses
+
+=item B<ReportKernelPMUEvents> B<false>|B<true>
+
+Enable or disable measuring of the following events:
+ - cpu-cycles
+ - instructions
+ - cache-references
+ - cache-misses
+ - branches
+ - branch-misses
+ - bus-cycles
+
+=item B<ReportSoftwareEvents> B<false>|B<true>
+
+Enable or disable measuring of software events provided by kernel:
+ - cpu-clock
+ - task-clock
+ - context-switches
+ - cpu-migrations
+ - page-faults
+ - minor-faults
+ - major-faults
+ - alignment-faults
+ - emulation-faults
+
+=item B<EventList> I<filename>
+
+JSON performance counter event list file name. To be able to monitor all Intel
+CPU specific events JSON event list file should be downloaded. Use the pmu-tools
+event_download.py script to download event list for current CPU.
+
+=item B<HardwareEvents> I<events>
+
+This field is a list of event names or groups of comma separated event names.
+This option requires B<EventList> option to be configured.
+
+=back
+
=head2 Plugin C<intel_rdt>
The I<intel_rdt> plugin collects information provided by monitoring features of
mcelog server is running. When the server is running, the plugin will tail the
specified logfile to retrieve machine check exception information and send a
notification with the details from the logfile. The plugin will use the mcelog
-client protocol to retrieve memory related machine check exceptions.
+client protocol to retrieve memory related machine check exceptions. Note that
+for memory exceptions, notifications are only sent when there is a change in
+the number of corrected/uncorrected memory errors.
-=over 4
+=head3 The Memory block
+
+Note: these options cannot be used in conjunction with the logfile options, they are mutually
+exclusive.
+
+=over 3
=item B<McelogClientSocket> I<Path>
Connect to the mcelog client socket using the UNIX domain socket at I<Path>.
Defaults to B<"/var/run/mcelog-client">.
+=item B<PersistentNotification> B<true>|B<false>
+Override default configuration to only send notifications when sent when there
+is a change in the number of corrected/uncorrected memory errors. When set to
+true notifications will be sent for every read cycle. Default is false. Does
+not affect the stats being dispatched.
+
+=back
+
+=over 4
+
=item B<McelogLogfile> I<Path>
-The mcelog file to parse. Defaults to B<"/var/log/mcelog">.
+The mcelog file to parse. Defaults to B<"/var/log/mcelog">. Note: this option
+cannot be used in conjunction with the memory block options, they are mutually
+exclusive.
=back
<Page "plugin_instance">
Server "localhost"
Key "page_key"
+ Plugin "plugin_name"
<Match>
Regex "(\\d+) bytes sent"
DSType CounterAdd
When connected to the memcached server, asks for the page I<Key>.
+=item B<Plugin> I<Plugin>
+
+Use I<Plugin> as the plugin name when submitting values.
+Defaults to C<memcachec>.
+
=item E<lt>B<Match>E<gt>
Match blocks define which strings to look for and how matches substrings are
Path to the PEM-encoded CA certificate file. Setting this option enables TLS
communication with the MQTT broker, and as such, B<Port> should be the TLS-enabled
port of the MQTT broker.
-A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+This option enables the use of TLS.
=item B<CertificateFile> I<file>
Path to the PEM-encoded certificate file to use as client certificate when
connecting to the MQTT broker.
-A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+Only valid if B<CACert> and B<CertificateKeyFile> are also set.
=item B<CertificateKeyFile> I<file>
Path to the unencrypted PEM-encoded key file corresponding to B<CertificateFile>.
-A valid TLS configuration requires B<CACert>, B<CertificateFile> and B<CertificateKeyFile>.
+Only valid if B<CACert> and B<CertificateFile> are also set.
=item B<TLSProtocol> I<protocol>
C<tlsv1.2>) to use for the TLS connection to the broker. If not set a default
version is used which depends on the version of OpenSSL the Mosquitto library
was linked against.
+Only valid if B<CACert> is set.
=item B<CipherSuite> I<ciphersuite>
A string describing the ciphers available for use. See L<ciphers(1)> and the
C<openssl ciphers> utility for more information. If unset, the default ciphers
will be used.
-
+Only valid if B<CACert> is set.
=back
or SQL threads are not running. Defaults to B<false>.
=item B<WsrepStats> I<true|false>
-
+
Enable the collection of wsrep plugin statistics, used in Master-Master
replication setups like in MySQL Galera/Percona XtraDB Cluster.
User needs only privileges to execute 'SHOW GLOBAL STATUS'
-
+
=item B<ConnectTimeout> I<Seconds>
Sets the connect timeout for the MySQL client.
=back
+=head2 Plugin C<nfs>
+
+The I<nfs plugin> collects information about the usage of the Network File
+System (NFS). It counts the number of procedure calls for each procedure,
+grouped by version and whether the system runs as server or client.
+
+It is possibly to omit metrics for a specific NFS version by setting one or
+more of the following options to B<false> (all of them default to B<true>).
+
+=over 4
+
+=item B<ReportV2> B<true>|B<false>
+
+=item B<ReportV3> B<true>|B<false>
+
+=item B<ReportV4> B<true>|B<false>
+
+=back
+
=head2 Plugin C<nginx>
This plugin collects the number of connections and requests handled by the
Example usage:
C<c_rehash /path/to/certs/folder>
+=item B<ConnectTimeout> I<Milliseconds>
+
+The B<ConnectTimeout> option sets the connect timeout, in milliseconds.
+By default, the configured B<Interval> is used to set the timeout.
+
=back
=head2 Plugin C<olsrd>
traffic statistics about connected clients.
To set up OpenVPN to write to the status file periodically, use the
-B<--status> option of OpenVPN. Since OpenVPN can write two different formats,
-you need to set the required format, too. This is done by setting
-B<--status-version> to B<2>.
+B<--status> option of OpenVPN.
So, in a nutshell you need:
openvpn $OTHER_OPTIONS \
- --status "/var/run/openvpn-status" 10 \
- --status-version 2
+ --status "/var/run/openvpn-status" 10
Available options:
enable the interface, OVS DB daemon should be running with C<--remote=ptcp:>
option. See L<ovsdb-server(1)> for more details. The option may be either
network hostname, IPv4 numbers-and-dots notation or IPv6 hexadecimal string
-format. Defaults to B<'localhost'>.
+format. Defaults to C<localhost>.
=item B<Port> I<service>
enable the interface, OVS DB daemon should be running with C<--remote=ptcp:>
option. See L<ovsdb-server(1)> for more details. The option may be either
network hostname, IPv4 numbers-and-dots notation or IPv6 hexadecimal string
-format. Defaults to B<'localhost'>.
+format. Defaults to C<localhost>.
=item B<Port> I<service>
When the C<rrdtool> plugin uses a cache (by setting B<CacheTimeout>, see below)
it writes all values for a certain RRD-file if the oldest value is older than
-(or equal to) the number of seconds specified. If some RRD-file is not updated
+(or equal to) the number of seconds specified by B<CacheTimeout>.
+That check happens on new values arriwal. If some RRD-file is not updated
anymore for some reason (the computer was shut down, the network is broken,
-etc.) some values may still be in the cache. If B<CacheFlush> is set, then the
-entire cache is searched for entries older than B<CacheTimeout> seconds and
-written to disk every I<Seconds> seconds. Since this is kind of expensive and
-does nothing under normal circumstances, this value should not be too small.
-900 seconds might be a good value, though setting this to 7200 seconds doesn't
-normally do much harm either.
+etc.) some values may still be in the cache. If B<CacheFlush> is set, then
+every I<Seconds> seconds the entire cache is searched for entries older than
+B<CacheTimeout> + B<RandomTimeout> seconds. The entries found are written to
+disk. Since scanning the entire cache is kind of expensive and does nothing
+under normal circumstances, this value should not be too small. 900 seconds
+might be a good value, though setting this to 7200 seconds doesn't normally
+do much harm either.
+
+Defaults to 10x B<CacheTimeout>.
+B<CacheFlush> must be larger than or equal to B<CacheTimeout>, otherwise the
+above default is used.
=item B<CacheTimeout> I<Seconds>
<Plugin snmp_agent>
<Data "memAvailReal">
Plugin "memory"
+ #PluginInstance "some"
Type "memory"
TypeInstance "free"
OIDs "1.3.6.1.4.1.2021.4.6.0"
Read plugin name whose collected data will be mapped to specified OIDs.
+=item B<PluginInstance> I<String>
+
+Read plugin instance whose collected data will be mapped to specified OIDs.
+The field is optional and by default there is no plugin instance check.
+Allowed only if B<Data> block defines scalar data type.
+
=item B<Type> I<String>
Collectd's type that is to be used for specified OID, e.E<nbsp>g. "if_octets"
=item B<OIDs> I<OID> [I<OID> ...]
Configures the OIDs to be handled by I<snmp_agent> plugin. Values for these OIDs
-are taken from collectd data type specified by B<Plugin>, B<Type>,
-B<TypeInstance> fields of this B<Data> block. Number of the OIDs configured
-should correspond to number of values in specified B<Type>.
+are taken from collectd data type specified by B<Plugin>, B<PluginInstance>,
+B<Type>, B<TypeInstance> fields of this B<Data> block. Number of the OIDs
+configured should correspond to number of values in specified B<Type>.
For example two OIDs "IF-MIB::ifInOctets" "IF-MIB::ifOutOctets" can be mapped to
"rx" and "tx" values of "if_octets" type.
This is useful for deploying I<collectd> in a heterogeneous environment, where
swap sizes differ and you want to specify generic thresholds or similar.
+=item B<ReportIO> B<true>|B<false>
+
+Enables or disables reporting swap IO. Defaults to B<true>.
+
+This is useful for the cases when swap IO is not neccessary, is not available,
+or is not reliable.
+
=back
=head2 Plugin C<syslog>
<Plugin table>
<Table "/proc/slabinfo">
+ #Plugin "slab"
Instance "slabinfo"
Separator " "
<Result>
=over 4
+=item B<Plugin> I<Plugin>
+
+If specified, I<Plugin> is used as the plugin name when submitting values.
+Defaults to B<table>.
+
=item B<Instance> I<instance>
-If specified, I<instance> is used as the plugin instance. So, in the above
-example, the plugin name C<table-slabinfo> would be used. If omitted, the
+If specified, I<instance> is used as the plugin instance. If omitted, the
filename of the table is used instead, with all special characters replaced
with an underscore (C<_>).
<Plugin "tail">
<File "/var/log/exim4/mainlog">
+ Plugin "mail"
Instance "exim"
Interval 60
<Match>
<DSType "Distribution">
Percentile 99
Bucket 0 100
+ #BucketType "bucket"
</DSType>
Type "latency"
Instance "foo"
logfile to parse. Within each B<File> block, there are one or more B<Match>
blocks, which configure a regular expression to search for.
-The B<Instance> option in the B<File> block may be used to set the plugin
-instance. So in the above example the plugin name C<tail-foo> would be used.
-This plugin instance is for all B<Match> blocks that B<follow> it, until the
-next B<Instance> option. This way you can extract several plugin instances from
-one logfile, handy when parsing syslog and the like.
+The B<Plugin> and B<Instance> options in the B<File> block may be used to set
+the plugin name and instance respectively. So in the above example the plugin name
+C<mail-exim> would be used.
+
+These options are applied for all B<Match> blocks that B<follow> it, until the
+next B<Plugin> or B<Instance> option. This way you can extract several plugin
+instances from one logfile, handy when parsing syslog and the like.
The B<Interval> option allows you to define the length of time between reads. If
this is not set, the default Interval will be used.
<DSType "Distribution">
Percentile 99
Bucket 0 100
+ BucketType "bucket"
</DSType>
=over 4
Bucket 20 50
Bucket 50 0
-Metrics are reported with the I<type> C<bucket> and the I<type instance>
+Metrics are reported with the I<type> set by B<BucketType> option (C<bucket>
+by default) and the I<type instance>
C<E<lt>TypeE<gt>[-E<lt>InstanceE<gt>]-E<lt>lower_boundE<gt>_E<lt>upper_boundE<gt>>.
This option may be repeated to calculate more than one rate.
+=item B<BucketType> I<Type>
+
+Sets the type used to dispatch B<Bucket> metrics.
+Optional, by default C<bucket> will be used.
+
=back
=back
Index 1
</Metric>
<File "/var/log/snort/snort.stats">
- Instance "snort-eth0"
+ Plugin "snortstats"
+ Instance "eth0"
Interval 600
Collect "snort-dropped"
</File>
=over 4
+=item B<Plugin> I<Plugin>
+
+Use I<Plugin> as the plugin name when submitting values.
+Defaults to C<tail_csv>.
+
=item B<Instance> I<PluginInstance>
Sets the I<plugin instance> used when dispatching the values.
Boolean enabling the use of logical core numbering for per core statistics.
When enabled, C<cpuE<lt>nE<gt>> is used as plugin instance, where I<n> is a
-sequential number assigned by the kernel. Otherwise, C<coreE<lt>nE<gt>> is used
-where I<n> is the n-th core of the socket, causing name conflicts when there is
-more than one socket.
+dynamic number assigned by the kernel. Otherwise, C<coreE<lt>nE<gt>> is used
+if there is only one package and C<pkgE<lt>nE<gt>-coreE<lt>mE<gt>> if there is
+more than one, where I<n> is the n-th core of package I<m>.
=back
CollectVCL false
CollectVSM false
CollectWorkers false
+ CollectLock false
+ CollectMempool false
+ CollectManagement false
+ CollectSMF false
+ CollectVBE false
</Instance>
</Plugin>
=item B<CollectSMA> B<true>|B<false>
malloc or umem (umem_alloc(3MALLOC) based) storage statistics. The umem storage
-component is Solaris specific. Only available with Varnish 2.x. False by
+component is Solaris specific.
+Note: SMA and SMF share counters, enable only the one used by the Varnish
+instance.
+Only available with Varnish 2.x. False by
default.
=item B<CollectSMS> B<true>|B<false>
=item B<CollectSM> B<true>|B<false>
-file (memory mapped file) storage statistics. Only available with Varnish 2.x.
+file (memory mapped file) storage statistics. Only available with Varnish 2.x.,
+in varnish 4.x. use CollectSMF.
False by default.
=item B<CollectStruct> B<true>|B<false>
Collect statistics about worker threads. False by default.
+=item B<CollectVBE> B<true>|B<false>
+
+Backend counters. Only available with Varnish 4.x. False by default.
+
+=item B<CollectSMF> B<true>|B<false>
+
+file (memory mapped file) storage statistics. Only available with Varnish 4.x.
+Note: SMA and SMF share counters, enable only the one used by the Varnish
+instance.
+Used to be called SM in Varnish 2.x. False by default.
+
+=item B<CollectManagement> B<true>|B<false>
+
+Management process counters. Only available with Varnish 4.x. False by default.
+
+=item B<CollectLock> B<true>|B<false>
+
+Lock counters. Only available with Varnish 4.x. False by default.
+
+=item B<CollectMempool> B<true>|B<false>
+
+Memory pool counters. Only available with Varnish 4.x. False by default.
+
=back
=head2 Plugin C<virt>
=item B<BlockDeviceFormat> B<target>|B<source>
If I<BlockDeviceFormat> is set to B<target>, the default, then the device name
-seen by the guest will be used for reporting metrics.
+seen by the guest will be used for reporting metrics.
This corresponds to the C<E<lt>targetE<gt>> node in the XML definition of the
domain.
Prefix "collectd/"
Database 1
MaxSetSize -1
+ MaxSetDuration -1
StoreRates true
</Node>
</Plugin>
The B<MaxSetSize> option limits the number of items that the I<Sorted Sets> can
hold. Negative values for I<Items> sets no limit, which is the default behavior.
+=item B<MaxSetDuration> I<Seconds>
+
+The B<MaxSetDuration> option limits the duration of items that the
+I<Sorted Sets> can hold. Negative values for I<Items> sets no duration, which
+is the default behavior.
+
=item B<StoreRates> B<true>|B<false>
If set to B<true> (the default), convert counter values to rates. If set to
=item B<-P> I<E<lt>pid-fileE<gt>>
-Specify an alternative pid file. This overwrites any settings in the config
+Specify an alternative pid file. This overwrites any settings in the config
file. This is thought for init-scripts that require the PID-file in a certain
directory to work correctly. For everyday-usage use the B<PIDFile>
config-option.
+=item B<-B>
+
+If set, collectd will I<not> try to create its base directory. If the base
+directory does not exist, it will exit rather than trying to create the
+directory.
+
=item B<-f>
Don't fork to the background. I<collectd> will also B<not> close standard file
#endif
#endif /* NAN_ZERO_ZERO */
-#include "libcollectdclient/collectd/client.h"
+#include "collectd/client.h"
#ifndef PREFIX
#define PREFIX "/opt/" PACKAGE_NAME
#define COLLECTD_CPU_STATE_INTERRUPT 5
#define COLLECTD_CPU_STATE_SOFTIRQ 6
#define COLLECTD_CPU_STATE_STEAL 7
-#define COLLECTD_CPU_STATE_IDLE 8
-#define COLLECTD_CPU_STATE_ACTIVE 9 /* sum of (!idle) */
-#define COLLECTD_CPU_STATE_MAX 10 /* #states */
+#define COLLECTD_CPU_STATE_GUEST 8
+#define COLLECTD_CPU_STATE_GUEST_NICE 9
+#define COLLECTD_CPU_STATE_IDLE 10
+#define COLLECTD_CPU_STATE_ACTIVE 11 /* sum of (!idle) */
+#define COLLECTD_CPU_STATE_MAX 12 /* #states */
#if HAVE_STATGRAB_H
#include <statgrab.h>
static const char *cpu_state_names[] = {"user", "system", "wait", "nice",
"swap", "interrupt", "softirq", "steal",
- "idle", "active"};
+ "guest", "guest_nice", "idle", "active"};
#ifdef PROCESSOR_CPU_LOAD_INFO
static mach_port_t port_host;
static _Bool report_by_state = 1;
static _Bool report_percent = 0;
static _Bool report_num_cpu = 0;
+static _Bool report_guest = 0;
+static _Bool subtract_guest = 1;
static const char *config_keys[] = {"ReportByCpu", "ReportByState",
- "ReportNumCpu", "ValuesPercentage"};
+ "ReportNumCpu", "ValuesPercentage",
+ "ReportGuestState", "SubtractGuestState"};
static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
static int cpu_config(char const *key, char const *value) /* {{{ */
report_by_state = IS_TRUE(value) ? 1 : 0;
else if (strcasecmp(key, "ReportNumCpu") == 0)
report_num_cpu = IS_TRUE(value) ? 1 : 0;
+ else if (strcasecmp(key, "ReportGuestState") == 0)
+ report_guest = IS_TRUE(value) ? 1 : 0;
+ else if (strcasecmp(key, "SubtractGuestState") == 0)
+ subtract_guest = IS_TRUE(value) ? 1 : 0;
else
return -1;
sizeof(vl.type_instance));
if (cpu_num >= 0) {
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", cpu_num);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", cpu_num);
}
plugin_dispatch_values(&vl);
}
static void cpu_commit(void) /* {{{ */
{
gauge_t global_rates[COLLECTD_CPU_STATE_MAX] = {
- NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN /* Batman! */
+ NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN /* Batman! */
};
if (report_num_cpu)
for (size_t cpu_num = 0; cpu_num < global_cpu_num; cpu_num++) {
cpu_state_t *this_cpu_states = get_cpu_state(cpu_num, 0);
gauge_t local_rates[COLLECTD_CPU_STATE_MAX] = {NAN, NAN, NAN, NAN, NAN,
- NAN, NAN, NAN, NAN, NAN};
+ NAN, NAN, NAN, NAN, NAN,
+ NAN, NAN };
for (size_t state = 0; state < COLLECTD_CPU_STATE_MAX; state++)
if (this_cpu_states[state].has_value)
FILE *fh;
char buf[1024];
- char *fields[9];
+ char *fields[11];
int numfields;
if ((fh = fopen("/proc/stat", "r")) == NULL) {
if ((buf[3] < '0') || (buf[3] > '9'))
continue;
- numfields = strsplit(buf, fields, 9);
+ numfields = strsplit(buf, fields, STATIC_ARRAY_SIZE(fields));
if (numfields < 5)
continue;
cpu = atoi(fields[0] + 3);
- cpu_stage(cpu, COLLECTD_CPU_STATE_USER, (derive_t)atoll(fields[1]), now);
- cpu_stage(cpu, COLLECTD_CPU_STATE_NICE, (derive_t)atoll(fields[2]), now);
+ /* Do not stage User and Nice immediately: we may need to alter them later: */
+ long long user_value = atoll(fields[1]);
+ long long nice_value = atoll(fields[2]);
cpu_stage(cpu, COLLECTD_CPU_STATE_SYSTEM, (derive_t)atoll(fields[3]), now);
cpu_stage(cpu, COLLECTD_CPU_STATE_IDLE, (derive_t)atoll(fields[4]), now);
now);
cpu_stage(cpu, COLLECTD_CPU_STATE_SOFTIRQ, (derive_t)atoll(fields[7]),
now);
+ }
- if (numfields >= 9)
- cpu_stage(cpu, COLLECTD_CPU_STATE_STEAL, (derive_t)atoll(fields[8]),
- now);
+ if (numfields >= 9) { /* Steal (since Linux 2.6.11) */
+ cpu_stage(cpu, COLLECTD_CPU_STATE_STEAL, (derive_t)atoll(fields[8]), now);
}
+
+ if (numfields >= 10) { /* Guest (since Linux 2.6.24) */
+ if (report_guest) {
+ long long value = atoll(fields[9]);
+ cpu_stage(cpu, COLLECTD_CPU_STATE_GUEST, (derive_t)value, now);
+ /* Guest is included in User; optionally subtract Guest from User: */
+ if (subtract_guest) {
+ user_value -= value;
+ if (user_value < 0) user_value = 0;
+ }
+ }
+ }
+
+ if (numfields >= 11) { /* Guest_nice (since Linux 2.6.33) */
+ if (report_guest) {
+ long long value = atoll(fields[10]);
+ cpu_stage(cpu, COLLECTD_CPU_STATE_GUEST_NICE, (derive_t)value, now);
+ /* Guest_nice is included in Nice; optionally subtract Guest_nice from
+ Nice: */
+ if (subtract_guest) {
+ nice_value -= value;
+ if (nice_value < 0) nice_value = 0;
+ }
+ }
+ }
+
+ /* Eventually stage User and Nice: */
+ cpu_stage(cpu, COLLECTD_CPU_STATE_USER, (derive_t)user_value, now);
+ cpu_stage(cpu, COLLECTD_CPU_STATE_NICE, (derive_t)nice_value, now);
}
fclose(fh);
/* }}} #endif defined(KERNEL_LINUX) */
num_cpu = 0;
while (1) {
- status = ssnprintf(filename, sizeof(filename),
- "/sys/devices/system/cpu/cpu%d/cpufreq/"
- "scaling_cur_freq",
- num_cpu);
+ status = snprintf(filename, sizeof(filename),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/"
+ "scaling_cur_freq",
+ num_cpu);
if ((status < 1) || ((unsigned int)status >= sizeof(filename)))
break;
vl.values_len = 1;
sstrncpy(vl.plugin, "cpufreq", sizeof(vl.plugin));
sstrncpy(vl.type, "cpufreq", sizeof(vl.type));
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%i", cpu_num);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%i", cpu_num);
plugin_dispatch_values(&vl);
}
static int cpufreq_read(void) {
for (int i = 0; i < num_cpu; i++) {
char filename[PATH_MAX];
- ssnprintf(filename, sizeof(filename),
- "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
+ snprintf(filename, sizeof(filename),
+ "/sys/devices/system/cpu/cpu%d/cpufreq/scaling_cur_freq", i);
value_t v;
if (parse_value_file(filename, &v, DS_TYPE_GAUGE) != 0) {
memset(buffer, '\0', buffer_len);
- status = ssnprintf(buffer, buffer_len, "%.3f", CDTIME_T_TO_DOUBLE(vl->time));
+ status = snprintf(buffer, buffer_len, "%.3f", CDTIME_T_TO_DOUBLE(vl->time));
if ((status < 1) || (status >= buffer_len))
return -1;
offset = status;
}
if (ds->ds[i].type == DS_TYPE_GAUGE) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ",%lf",
- vl->values[i].gauge);
+ status = snprintf(buffer + offset, buffer_len - offset, ",%lf",
+ vl->values[i].gauge);
} else if (store_rates != 0) {
if (rates == NULL)
rates = uc_get_rate(ds, vl);
"uc_get_rate failed.");
return -1;
}
- status =
- ssnprintf(buffer + offset, buffer_len - offset, ",%lf", rates[i]);
+ status = snprintf(buffer + offset, buffer_len - offset, ",%lf", rates[i]);
} else if (ds->ds[i].type == DS_TYPE_COUNTER) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ",%llu",
- vl->values[i].counter);
+ status = snprintf(buffer + offset, buffer_len - offset, ",%llu",
+ vl->values[i].counter);
} else if (ds->ds[i].type == DS_TYPE_DERIVE) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ",%" PRIi64,
- vl->values[i].derive);
+ status = snprintf(buffer + offset, buffer_len - offset, ",%" PRIi64,
+ vl->values[i].derive);
} else if (ds->ds[i].type == DS_TYPE_ABSOLUTE) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ",%" PRIu64,
- vl->values[i].absolute);
+ status = snprintf(buffer + offset, buffer_len - offset, ",%" PRIu64,
+ vl->values[i].absolute);
}
if ((status < 1) || (status >= (buffer_len - offset))) {
typedef struct web_page_s web_page_t;
struct web_page_s /* {{{ */
{
+ char *plugin_name;
char *instance;
char *url;
curl_easy_cleanup(wp->curl);
wp->curl = NULL;
+ sfree(wp->plugin_name);
sfree(wp->instance);
sfree(wp->url);
return -1;
}
- ssnprintf(wp->credentials, credentials_size, "%s:%s", wp->user,
- (wp->pass == NULL) ? "" : wp->pass);
+ snprintf(wp->credentials, credentials_size, "%s:%s", wp->user,
+ (wp->pass == NULL) ? "" : wp->pass);
curl_easy_setopt(wp->curl, CURLOPT_USERPWD, wp->credentials);
#endif
ERROR("curl plugin: calloc failed.");
return -1;
}
+ page->plugin_name = NULL;
page->url = NULL;
page->user = NULL;
page->pass = NULL;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
- if (strcasecmp("URL", child->key) == 0)
+ if (strcasecmp("Plugin", child->key) == 0)
+ status = cf_util_get_string(child, &page->plugin_name);
+ else if (strcasecmp("URL", child->key) == 0)
status = cf_util_get_string(child, &page->url);
else if (strcasecmp("User", child->key) == 0)
status = cf_util_get_string(child, &page->user);
vl.values = &value;
vl.values_len = 1;
- sstrncpy(vl.plugin, "curl", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (wp->plugin_name != NULL) ? wp->plugin_name : "curl",
+ sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, wp->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, wm->type, sizeof(vl.type));
if (wm->instance != NULL)
vl.values = &(value_t){.gauge = (gauge_t)code};
vl.values_len = 1;
- sstrncpy(vl.plugin, "curl", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (wp->plugin_name != NULL) ? wp->plugin_name : "curl",
+ sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, wp->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, "response_code", sizeof(vl.type));
vl.values = &(value_t){.gauge = response_time};
vl.values_len = 1;
- sstrncpy(vl.plugin, "curl", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (wp->plugin_name != NULL) ? wp->plugin_name : "curl",
+ sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, wp->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, "response_time", sizeof(vl.type));
if (wp->response_time)
cc_submit_response_time(wp, CDTIME_T_TO_DOUBLE(cdtime() - start));
if (wp->stats != NULL)
- curl_stats_dispatch(wp->stats, wp->curl, hostname_g, "curl", wp->instance);
+ curl_stats_dispatch(wp->stats, wp->curl, NULL, "curl", wp->instance);
if (wp->response_code) {
long response_code = 0;
struct cj_s /* {{{ */
{
char *instance;
+ char *plugin_name;
char *host;
char *sock;
db->state[db->depth].index++;
char name[DATA_MAX_NAME_LEN];
- ssnprintf(name, sizeof(name), "%d", db->state[db->depth].index);
+ snprintf(name, sizeof(name), "%d", db->state[db->depth].index);
cj_load_key(db, name);
}
db->tree = NULL;
sfree(db->instance);
+ sfree(db->plugin_name);
sfree(db->host);
sfree(db->sock);
return -1;
}
- ssnprintf(db->credentials, credentials_size, "%s:%s", db->user,
- (db->pass == NULL) ? "" : db->pass);
+ snprintf(db->credentials, credentials_size, "%s:%s", db->user,
+ (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt(db->curl, CURLOPT_USERPWD, db->credentials);
#endif
if (strcasecmp("Instance", child->key) == 0)
status = cf_util_get_string(child, &db->instance);
+ else if (strcasecmp("Plugin", child->key) == 0)
+ status = cf_util_get_string(child, &db->plugin_name);
else if (strcasecmp("Host", child->key) == 0)
status = cf_util_get_string(child, &db->host);
else if (db->url && strcasecmp("User", child->key) == 0)
if (key->instance == NULL) {
int len = 0;
for (int i = 0; i < db->depth; i++)
- len += ssnprintf(vl.type_instance + len, sizeof(vl.type_instance) - len,
- i ? "-%s" : "%s", db->state[i + 1].name);
+ len += snprintf(vl.type_instance + len, sizeof(vl.type_instance) - len,
+ i ? "-%s" : "%s", db->state[i + 1].name);
} else
sstrncpy(vl.type_instance, key->instance, sizeof(vl.type_instance));
sstrncpy(vl.host, cj_host(db), sizeof(vl.host));
- sstrncpy(vl.plugin, "curl_json", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (db->plugin_name != NULL) ? db->plugin_name : "curl_json",
+ sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, db->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, key->type, sizeof(vl.type));
status = cx_handle_single_value_xpath(xpath_ctx, xpath, ds, vl, i);
if (status != 0)
return -1; /* An error has been printed. */
- } /* for (i = 0; i < xpath->values_len; i++) */
+ } /* for (i = 0; i < xpath->values_len; i++) */
plugin_dispatch_values(vl);
vl->values = NULL;
if (xpath->instance_prefix != NULL) {
if (instance_node != NULL) {
char *node_value = (char *)xmlNodeGetContent(instance_node->nodeTab[0]);
- ssnprintf(vl->type_instance, sizeof(vl->type_instance), "%s%s",
- xpath->instance_prefix, node_value);
+ snprintf(vl->type_instance, sizeof(vl->type_instance), "%s%s",
+ xpath->instance_prefix, node_value);
sfree(node_value);
} else
sstrncpy(vl->type_instance, xpath->instance_prefix,
return -1;
}
- ssnprintf(db->credentials, credentials_size, "%s:%s", db->user,
- (db->pass == NULL) ? "" : db->pass);
+ snprintf(db->credentials, credentials_size, "%s:%s", db->user,
+ (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt(db->curl, CURLOPT_USERPWD, db->credentials);
#endif
return 0;
} /* int init_global_variables */
-static int change_basedir(const char *orig_dir) {
+static int change_basedir(const char *orig_dir, _Bool create) {
char *dir;
size_t dirlen;
int status;
if (status == 0) {
free(dir);
return 0;
- } else if (errno != ENOENT) {
+ } else if (!create || (errno != ENOENT)) {
char errbuf[1024];
ERROR("change_basedir: chdir (%s): %s", dir,
sstrerror(errno, errbuf, sizeof(errbuf)));
#if COLLECT_DAEMON
" -f Don't fork to the background.\n"
#endif
+ " -B Don't create the BaseDir\n"
" -h Display help (this message)\n"
"\nBuiltin defaults:\n"
" Config file " CONFIGFILE "\n"
int test_config = 0;
int test_readall = 0;
const char *basedir;
+ _Bool opt_create_basedir = 1;
#if COLLECT_DAEMON
pid_t pid;
int daemonize = 1;
while (1) {
int c;
- c = getopt(argc, argv, "htTC:"
+ c = getopt(argc, argv, "BhtTC:"
#if COLLECT_DAEMON
"fP:"
#endif
break;
switch (c) {
+ case 'B':
+ opt_create_basedir = 0;
+ break;
case 'C':
configfile = optarg;
break;
fprintf(stderr,
"Don't have a basedir to use. This should not happen. Ever.");
return 1;
- } else if (change_basedir(basedir)) {
+ } else if (change_basedir(basedir, opt_create_basedir)) {
fprintf(stderr, "Error: Unable to change to directory `%s'.\n", basedir);
return 1;
}
return dest;
} /* char *sstrncpy */
-int ssnprintf(char *dest, size_t n, const char *format, ...) {
- int ret = 0;
- va_list ap;
-
- va_start(ap, format);
- ret = vsnprintf(dest, n, format, ap);
- dest[n - 1] = '\0';
- va_end(ap);
-
- return ret;
-} /* int ssnprintf */
-
char *ssnprintf_alloc(char const *format, ...) /* {{{ */
{
char static_buffer[1024] = "";
#else
if (strerror_r(errnum, buf, buflen) != 0) {
- ssnprintf(buf, buflen, "Error #%i; "
- "Additionally, strerror_r failed.",
- errnum);
+ snprintf(buf, buflen, "Error #%i; "
+ "Additionally, strerror_r failed.",
+ errnum);
}
#endif /* STRERROR_R_CHAR_P */
if (recv(fd, buffer, sizeof(buffer), MSG_PEEK | MSG_DONTWAIT) == 0) {
/* if recv returns zero (even though poll() said there is data to be
* read), that means the connection has been closed */
- return errno ? errno : -1;
+ errno = ECONNRESET;
+ return -1;
}
}
if (kc == NULL)
return -1;
- ssnprintf(ident, sizeof(ident), "%s,%i,%s", module, instance, name);
+ snprintf(ident, sizeof(ident), "%s,%i,%s", module, instance, name);
*ksp_ptr = kstat_lookup(kc, module, instance, name);
if (*ksp_ptr == NULL) {
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(ret + offset, ret_len - offset, __VA_ARGS__); \
+ status = snprintf(ret + offset, ret_len - offset, __VA_ARGS__); \
if (status < 1) { \
sfree(rates); \
return -1; \
char *sstrncpy(char *dest, const char *src, size_t n);
-__attribute__((format(printf, 3, 4))) int ssnprintf(char *dest, size_t n,
- const char *format, ...);
-
__attribute__((format(printf, 1, 2))) char *ssnprintf_alloc(char const *format,
...);
return 0;
}
-DEF_TEST(ssnprintf) {
- char buffer[16] = "";
- char *ptr = &buffer[4];
- int status;
-
- buffer[0] = buffer[1] = buffer[2] = buffer[3] = 0xff;
- buffer[12] = buffer[13] = buffer[14] = buffer[15] = 0xff;
-
- status = ssnprintf(ptr, 8, "%i", 1337);
- OK(status == 4);
- EXPECT_EQ_STR("1337", ptr);
-
- status = ssnprintf(ptr, 8, "%s", "collectd");
- OK(status == 8);
- OK(ptr[7] == 0);
- EXPECT_EQ_STR("collect", ptr);
- OK(buffer[3] == buffer[12]);
-
- return 0;
-}
-
DEF_TEST(sstrdup) {
char *ptr;
int main(void) {
RUN_TEST(sstrncpy);
- RUN_TEST(ssnprintf);
RUN_TEST(sstrdup);
RUN_TEST(strsplit);
RUN_TEST(strjoin);
return global_option_set(ci->key, ci->values[0].value.string, 0);
else if (ci->values[0].type == OCONFIG_TYPE_NUMBER) {
char tmp[128];
- ssnprintf(tmp, sizeof(tmp), "%lf", ci->values[0].value.number);
+ snprintf(tmp, sizeof(tmp), "%lf", ci->values[0].value.number);
return global_option_set(ci->key, tmp, 0);
} else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN) {
if (ci->values[0].value.boolean)
if (ci->values[i].type == OCONFIG_TYPE_STRING)
status =
- ssnprintf(buffer_ptr, buffer_free, " %s", ci->values[i].value.string);
+ snprintf(buffer_ptr, buffer_free, " %s", ci->values[i].value.string);
else if (ci->values[i].type == OCONFIG_TYPE_NUMBER)
- status = ssnprintf(buffer_ptr, buffer_free, " %lf",
- ci->values[i].value.number);
+ status =
+ snprintf(buffer_ptr, buffer_free, " %lf", ci->values[i].value.number);
else if (ci->values[i].type == OCONFIG_TYPE_BOOLEAN)
- status = ssnprintf(buffer_ptr, buffer_free, " %s",
- ci->values[i].value.boolean ? "true" : "false");
+ status = snprintf(buffer_ptr, buffer_free, " %s",
+ ci->values[i].value.boolean ? "true" : "false");
if ((status < 0) || (status >= buffer_free))
return -1;
if ((de->d_name[0] == '.') || (de->d_name[0] == 0))
continue;
- status = ssnprintf(name, sizeof(name), "%s/%s", dir, de->d_name);
+ status = snprintf(name, sizeof(name), "%s/%s", dir, de->d_name);
if ((status < 0) || ((size_t)status >= sizeof(name))) {
ERROR("configfile: Not including `%s/%s' because its"
" name is too long.",
ERROR("cf_util_get_service: Out of memory.");
return -1;
}
- ssnprintf(service, 6, "%i", port);
+ snprintf(service, 6, "%i", port);
sfree(*ret_string);
*ret_string = service;
if (ci->values_num == 1) {
sstrncpy(rule->name, ci->values[0].value.string, sizeof(rule->name));
- ssnprintf(rule_name, sizeof(rule_name), "Rule \"%s\"",
- ci->values[0].value.string);
+ snprintf(rule_name, sizeof(rule_name), "Rule \"%s\"",
+ ci->values[0].value.string);
}
for (int i = 0; i < ci->children_num; i++) {
actual = e->value.mv_string;
break;
case MD_TYPE_SIGNED_INT:
- ssnprintf(buffer, sizeof(buffer), "%" PRIi64, e->value.mv_signed_int);
+ snprintf(buffer, sizeof(buffer), "%" PRIi64, e->value.mv_signed_int);
actual = buffer;
break;
case MD_TYPE_UNSIGNED_INT:
- ssnprintf(buffer, sizeof(buffer), "%" PRIu64, e->value.mv_unsigned_int);
+ snprintf(buffer, sizeof(buffer), "%" PRIu64, e->value.mv_unsigned_int);
actual = buffer;
break;
case MD_TYPE_DOUBLE:
- ssnprintf(buffer, sizeof(buffer), GAUGE_FORMAT, e->value.mv_double);
+ snprintf(buffer, sizeof(buffer), GAUGE_FORMAT, e->value.mv_double);
actual = buffer;
break;
case MD_TYPE_BOOLEAN:
return 0;
} /* }}} int plugin_update_internal_statistics */
-static void destroy_callback(callback_func_t *cf) /* {{{ */
+static void free_userdata(user_data_t const *ud) /* {{{ */
{
- if (cf == NULL)
+ if (ud == NULL)
return;
- if ((cf->cf_udata.data != NULL) && (cf->cf_udata.free_func != NULL)) {
- cf->cf_udata.free_func(cf->cf_udata.data);
- cf->cf_udata.data = NULL;
- cf->cf_udata.free_func = NULL;
+ if ((ud->data != NULL) && (ud->free_func != NULL)) {
+ ud->free_func(ud->data);
}
+} /* }}} void free_userdata */
+
+static void destroy_callback(callback_func_t *cf) /* {{{ */
+{
+ if (cf == NULL)
+ return;
+ free_userdata(&cf->cf_udata);
sfree(cf);
} /* }}} void destroy_callback */
cf = calloc(1, sizeof(*cf));
if (cf == NULL) {
+ free_userdata(ud);
ERROR("plugin: create_register_callback: calloc failed.");
return -1;
}
if (dlh == NULL) {
char errbuf[1024] = "";
- ssnprintf(errbuf, sizeof(errbuf),
- "dlopen (\"%s\") failed: %s. "
- "The most common cause for this problem is "
- "missing dependencies. Use ldd(1) to check "
- "the dependencies of the plugin "
- "/ shared object.",
- file, dlerror());
+ snprintf(errbuf, sizeof(errbuf),
+ "dlopen (\"%s\") failed: %s. "
+ "The most common cause for this problem is "
+ "missing dependencies. Use ldd(1) to check "
+ "the dependencies of the plugin "
+ "/ shared object.",
+ file, dlerror());
ERROR("%s", errbuf);
/* Make sure this is printed to STDERR in any case, but also
}
char name[THREAD_NAME_MAX];
- ssnprintf(name, sizeof(name), "reader#%zu", read_threads_num);
+ snprintf(name, sizeof(name), "reader#%zu", read_threads_num);
set_thread_name(read_threads[read_threads_num], name);
read_threads_num++;
}
char name[THREAD_NAME_MAX];
- ssnprintf(name, sizeof(name), "writer#%zu", write_threads_num);
+ snprintf(name, sizeof(name), "writer#%zu", write_threads_num);
set_thread_name(write_threads[write_threads_num], name);
write_threads_num++;
/* `cpu' should not match `cpufreq'. To solve this we add `.so' to the
* type when matching the filename */
- status = ssnprintf(typename, sizeof(typename), "%s.so", plugin_name);
+ status = snprintf(typename, sizeof(typename), "%s.so", plugin_name);
if ((status < 0) || ((size_t)status >= sizeof(typename))) {
WARNING("plugin_load: Filename too long: \"%s.so\"", plugin_name);
return -1;
if (strcasecmp(de->d_name, typename))
continue;
- status = ssnprintf(filename, sizeof(filename), "%s/%s", dir, de->d_name);
+ status = snprintf(filename, sizeof(filename), "%s/%s", dir, de->d_name);
if ((status < 0) || ((size_t)status >= sizeof(filename))) {
WARNING("plugin_load: Filename too long: \"%s/%s\"", dir, de->d_name);
continue;
if (le != NULL) {
pthread_mutex_unlock(&read_lock);
WARNING("The read function \"%s\" is already registered. "
- "Check for duplicate \"LoadPlugin\" lines "
- "in your configuration!",
+ "Check for duplicates in your configuration!",
rf->rf_name);
return EINVAL;
}
rf = calloc(1, sizeof(*rf));
if (rf == NULL) {
+ free_userdata(user_data);
ERROR("plugin_register_complex_read: calloc failed.");
return ENOMEM;
}
status = plugin_insert_read(rf);
if (status != 0) {
+ free_userdata(&rf->rf_udata);
sfree(rf->rf_name);
sfree(rf);
}
});
sfree(flush_name);
- if (status != 0) {
- sfree(cb->name);
- sfree(cb);
- return status;
- }
+ return status;
}
return 0;
return 0;
} /* int uc_iterator_get_name */
+int uc_iterator_get_meta(uc_iter_t *iter, meta_data_t **ret_meta) {
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_meta == NULL))
+ return -1;
+
+ *ret_meta = meta_data_clone(iter->entry->meta);
+
+ return 0;
+} /* int uc_iterator_get_meta */
+
/*
* Meta data interface
*/
size_t *ret_num);
/* Return the interval of the value at the current position. */
int uc_iterator_get_interval(uc_iter_t *iter, cdtime_t *ret_interval);
+/* Return the metadata for the value at the current position. */
+int uc_iterator_get_meta(uc_iter_t *iter, meta_data_t **ret_meta);
/*
* Meta data interface
size_left -= len;
if (print_nano) {
- if ((len = ssnprintf(pos, size_left, ".%09ld", nsec)) == 0)
+ if ((len = snprintf(pos, size_left, ".%09ld", nsec)) == 0)
return ENOMEM;
pos += len;
size_left -= len;
msg = NULL;
status = dbi_conn_error(conn, &msg);
if ((status >= 0) && (msg != NULL))
- ssnprintf(buffer, buffer_size, "%s (status %i)", msg, status);
+ snprintf(buffer, buffer_size, "%s (status %i)", msg, status);
else
- ssnprintf(buffer, buffer_size, "dbi_conn_error failed with status %i",
- status);
+ snprintf(buffer, buffer_size, "dbi_conn_error failed with status %i",
+ status);
return buffer;
} /* }}} const char *cdbi_conn_error */
long long value;
value = dbi_result_get_longlong_idx(res, index);
- ssnprintf(buffer, buffer_size, "%lli", value);
+ snprintf(buffer, buffer_size, "%lli", value);
} else if (src_type == DBI_TYPE_DECIMAL) {
double value;
value = dbi_result_get_double_idx(res, index);
- ssnprintf(buffer, buffer_size, "%63.15g", value);
+ snprintf(buffer, buffer_size, "%63.15g", value);
} else if (src_type == DBI_TYPE_STRING) {
const char *value;
/* Get the list of all disk objects. */
if (IOServiceGetMatchingServices(
- io_master_port, IOServiceMatching(kIOBlockStorageDriverClass),
- &disk_list) != kIOReturnSuccess) {
+ io_master_port, IOServiceMatching(kIOBlockStorageDriverClass),
+ &disk_list) != kIOReturnSuccess) {
ERROR("disk plugin: IOServiceGetMatchingServices failed.");
return -1;
}
sstrncpy(disk_name, props_disk_name_bsd, sizeof(disk_name));
else {
ERROR("disk plugin: can't find bsd disk name.");
- ssnprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major,
- disk_minor);
+ snprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
}
} else
- ssnprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
+ snprintf(disk_name, sizeof(disk_name), "%i-%i", disk_major, disk_minor);
DEBUG("disk plugin: disk_name = \"%s\"", disk_name);
.plugin = DPDK_EVENTS_PLUGIN,
.type = "gauge",
.meta = NULL};
- sstrncpy(vl.host, hostname_g, sizeof(vl.host));
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
plugin_dispatch_values(&vl);
char dev_name[DATA_MAX_NAME_LEN];
if (ec->config.link_status.port_name[i][0] != 0) {
- ssnprintf(dev_name, sizeof(dev_name), "%s",
- ec->config.link_status.port_name[i]);
+ snprintf(dev_name, sizeof(dev_name), "%s",
+ ec->config.link_status.port_name[i]);
} else {
- ssnprintf(dev_name, sizeof(dev_name), "port.%d", i);
+ snprintf(dev_name, sizeof(dev_name), "port.%d", i);
}
if (ec->config.link_status.notify) {
int sev = ec->link_info[i].link_status ? NOTIF_OKAY : NOTIF_WARNING;
char msg[DATA_MAX_NAME_LEN];
- ssnprintf(msg, sizeof(msg), "Link Status: %s",
- ec->link_info[i].link_status ? "UP" : "DOWN");
+ snprintf(msg, sizeof(msg), "Link Status: %s",
+ ec->link_info[i].link_status ? "UP" : "DOWN");
dpdk_events_notification_dispatch(sev, dev_name,
ec->link_info[i].read_time, msg);
} else {
}
char core_name[DATA_MAX_NAME_LEN];
- ssnprintf(core_name, sizeof(core_name), "lcore%u", i);
+ snprintf(core_name, sizeof(core_name), "lcore%u", i);
if (!ec->config.keep_alive.send_updated ||
(ec->core_info[i].lcore_state !=
switch (ec->config.keep_alive.shm->core_state[i]) {
case RTE_KA_STATE_ALIVE:
sev = NOTIF_OKAY;
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: ALIVE", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: ALIVE", i);
break;
case RTE_KA_STATE_MISSING:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: MISSING", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: MISSING", i);
sev = NOTIF_WARNING;
break;
case RTE_KA_STATE_DEAD:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DEAD", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DEAD", i);
sev = NOTIF_FAILURE;
break;
case RTE_KA_STATE_UNUSED:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNUSED", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNUSED", i);
sev = NOTIF_OKAY;
break;
case RTE_KA_STATE_GONE:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: GONE", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: GONE", i);
sev = NOTIF_FAILURE;
break;
case RTE_KA_STATE_DOZING:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DOZING", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: DOZING", i);
sev = NOTIF_OKAY;
break;
case RTE_KA_STATE_SLEEP:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: SLEEP", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: SLEEP", i);
sev = NOTIF_OKAY;
break;
default:
- ssnprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNKNOWN", i);
+ snprintf(msg, sizeof(msg), "lcore %u Keep Alive Status: UNKNOWN", i);
sev = NOTIF_FAILURE;
}
vl.values = &(value_t){.derive = value};
vl.values_len = 1;
vl.time = port_read_time;
- sstrncpy(vl.host, hostname_g, sizeof(vl.host));
sstrncpy(vl.plugin, DPDK_STATS_PLUGIN, sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
dpdk_stats_resolve_cnt_type(vl.type, sizeof(vl.type), cnt_name);
char dev_name[64];
if (ctx->config.port_name[i][0] != 0) {
- ssnprintf(dev_name, sizeof(dev_name), "%s", ctx->config.port_name[i]);
+ snprintf(dev_name, sizeof(dev_name), "%s", ctx->config.port_name[i]);
} else {
- ssnprintf(dev_name, sizeof(dev_name), "port.%d", i);
+ snprintf(dev_name, sizeof(dev_name), "port.%d", i);
}
DEBUG(" === Dispatch stats for port %d (name=%s; stats_count=%d)", i,
return EINVAL;
}
- ssnprintf(plugin_instance, sizeof(plugin_instance), "r%ld", resource);
+ snprintf(plugin_instance, sizeof(plugin_instance), "r%ld", resource);
for (size_t i = 0; i < drbd_names_num; i++) {
char *data;
pl->argv[i] = strdup(ci->values[i + 1].value.string);
} else {
if (ci->values[i + 1].type == OCONFIG_TYPE_NUMBER) {
- ssnprintf(buffer, sizeof(buffer), "%lf",
- ci->values[i + 1].value.number);
+ snprintf(buffer, sizeof(buffer), "%lf", ci->values[i + 1].value.number);
} else {
if (ci->values[i + 1].value.boolean)
sstrncpy(buffer, "true", sizeof(buffer));
char buffer[1024];
#ifdef HAVE_SETENV
- ssnprintf(buffer, sizeof(buffer), "%.3f",
- CDTIME_T_TO_DOUBLE(plugin_get_interval()));
+ snprintf(buffer, sizeof(buffer), "%.3f",
+ CDTIME_T_TO_DOUBLE(plugin_get_interval()));
setenv("COLLECTD_INTERVAL", buffer, /* overwrite = */ 1);
sstrncpy(buffer, hostname_g, sizeof(buffer));
setenv("COLLECTD_HOSTNAME", buffer, /* overwrite = */ 1);
#else
- ssnprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f",
- CDTIME_T_TO_DOUBLE(plugin_get_interval()));
+ snprintf(buffer, sizeof(buffer), "COLLECTD_INTERVAL=%.3f",
+ CDTIME_T_TO_DOUBLE(plugin_get_interval()));
putenv(buffer);
- ssnprintf(buffer, sizeof(buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
+ snprintf(buffer, sizeof(buffer), "COLLECTD_HOSTNAME=%s", hostname_g);
putenv(buffer);
#endif
} /* }}} void set_environment */
struct fc_directory_conf_s {
char *path;
+ char *plugin_name;
char *instance;
+ char *files_size_type;
+ char *files_num_type;
+ char *type_instance;
int options;
static fc_directory_conf_t **directories = NULL;
static size_t directories_num = 0;
+void fc_free_dir(fc_directory_conf_t *dir) {
+ sfree(dir->path);
+ sfree(dir->plugin_name);
+ sfree(dir->instance);
+ sfree(dir->files_size_type);
+ sfree(dir->files_num_type);
+ sfree(dir->type_instance);
+ sfree(dir->name);
+
+ sfree(dir);
+} /* void fc_free_dir */
+
static void fc_submit_dir(const fc_directory_conf_t *dir) {
value_list_t vl = VALUE_LIST_INIT;
- vl.values = &(value_t){.gauge = (gauge_t)dir->files_num};
- vl.values_len = 1;
- sstrncpy(vl.plugin, "filecount", sizeof(vl.plugin));
- sstrncpy(vl.plugin_instance, dir->instance, sizeof(vl.plugin_instance));
- sstrncpy(vl.type, "files", sizeof(vl.type));
+ sstrncpy(vl.plugin, dir->plugin_name, sizeof(vl.plugin));
+ if (dir->instance != NULL)
+ sstrncpy(vl.plugin_instance, dir->instance, sizeof(vl.plugin_instance));
+ if (dir->type_instance != NULL)
+ sstrncpy(vl.type_instance, dir->type_instance, sizeof(vl.type_instance));
- plugin_dispatch_values(&vl);
+ vl.values_len = 1;
- vl.values = &(value_t){.gauge = (gauge_t)dir->files_size};
- sstrncpy(vl.type, "bytes", sizeof(vl.type));
+ if (dir->files_num_type != NULL) {
+ vl.values = &(value_t){.gauge = (gauge_t)dir->files_num};
+ sstrncpy(vl.type, dir->files_num_type, sizeof(vl.type));
+ plugin_dispatch_values(&vl);
+ }
- plugin_dispatch_values(&vl);
+ if (dir->files_size_type != NULL) {
+ vl.values = &(value_t){.gauge = (gauge_t)dir->files_size};
+ sstrncpy(vl.type, dir->files_size_type, sizeof(vl.type));
+ plugin_dispatch_values(&vl);
+ }
} /* void fc_submit_dir */
/*
* Config:
* <Plugin filecount>
* <Directory /path/to/dir>
+ * Plugin "foo"
* Instance "foobar"
* Name "*.conf"
* MTime -3600
* Size "+10M"
+ * Recursive true
+ * IncludeHidden false
+ * FilesSizeType "bytes"
+ * FilesCountType "files"
+ * TypeInstance "instance"
* </Directory>
* </Plugin>
*
static int fc_config_set_instance(fc_directory_conf_t *dir, const char *str) {
char buffer[1024];
char *ptr;
- char *copy;
sstrncpy(buffer, str, sizeof(buffer));
for (ptr = buffer; *ptr != 0; ptr++)
for (ptr = buffer; *ptr == '_'; ptr++)
/* do nothing */;
- if (*ptr == 0)
- return -1;
-
- copy = strdup(ptr);
+ char *copy = strdup(ptr);
if (copy == NULL)
return -1;
static int fc_config_add_dir_name(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
- char *temp;
-
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("filecount plugin: The `Name' config option needs exactly one "
"string argument.");
return -1;
}
- temp = strdup(ci->values[0].value.string);
+ char *temp = strdup(ci->values[0].value.string);
if (temp == NULL) {
ERROR("filecount plugin: strdup failed.");
return -1;
static int fc_config_add_dir_mtime(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
- char *endptr;
- double temp;
-
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
(ci->values[0].type != OCONFIG_TYPE_NUMBER))) {
WARNING("filecount plugin: The `MTime' config option needs exactly one "
}
errno = 0;
- endptr = NULL;
- temp = strtod(ci->values[0].value.string, &endptr);
+ char *endptr = NULL;
+ double temp = strtod(ci->values[0].value.string, &endptr);
if ((errno != 0) || (endptr == NULL) ||
(endptr == ci->values[0].value.string)) {
WARNING("filecount plugin: Converting `%s' to a number failed.",
static int fc_config_add_dir_size(fc_directory_conf_t *dir,
oconfig_item_t *ci) {
- char *endptr;
- double temp;
-
if ((ci->values_num != 1) || ((ci->values[0].type != OCONFIG_TYPE_STRING) &&
(ci->values[0].type != OCONFIG_TYPE_NUMBER))) {
WARNING("filecount plugin: The `Size' config option needs exactly one "
}
errno = 0;
- endptr = NULL;
- temp = strtod(ci->values[0].value.string, &endptr);
+ char *endptr = NULL;
+ double temp = strtod(ci->values[0].value.string, &endptr);
if ((errno != 0) || (endptr == NULL) ||
(endptr == ci->values[0].value.string)) {
WARNING("filecount plugin: Converting `%s' to a number failed.",
} /* int fc_config_add_dir_option */
static int fc_config_add_dir(oconfig_item_t *ci) {
- fc_directory_conf_t *dir;
- int status;
-
if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING)) {
WARNING("filecount plugin: `Directory' needs exactly one string "
"argument.");
}
/* Initialize `dir' */
- dir = calloc(1, sizeof(*dir));
+ fc_directory_conf_t *dir = calloc(1, sizeof(*dir));
if (dir == NULL) {
ERROR("filecount plugin: calloc failed.");
return -1;
dir->path = strdup(ci->values[0].value.string);
if (dir->path == NULL) {
ERROR("filecount plugin: strdup failed.");
- sfree(dir);
+ fc_free_dir(dir);
return -1;
}
- fc_config_set_instance(dir, dir->path);
-
dir->options = FC_RECURSIVE;
dir->name = NULL;
+ dir->plugin_name = strdup("filecount");
+ dir->instance = NULL;
+ dir->type_instance = NULL;
dir->mtime = 0;
dir->size = 0;
- status = 0;
+ dir->files_size_type = strdup("bytes");
+ dir->files_num_type = strdup("files");
+
+ if (dir->plugin_name == NULL || dir->files_size_type == NULL ||
+ dir->files_num_type == NULL) {
+ ERROR("filecount plugin: strdup failed.");
+ fc_free_dir(dir);
+ return -1;
+ }
+
+ int status = 0;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *option = ci->children + i;
- if (strcasecmp("Instance", option->key) == 0)
+ if (strcasecmp("Plugin", option->key) == 0)
+ status = cf_util_get_string(option, &dir->plugin_name);
+ else if (strcasecmp("Instance", option->key) == 0)
status = fc_config_add_dir_instance(dir, option);
else if (strcasecmp("Name", option->key) == 0)
status = fc_config_add_dir_name(dir, option);
status = fc_config_add_dir_option(dir, option, FC_RECURSIVE);
else if (strcasecmp("IncludeHidden", option->key) == 0)
status = fc_config_add_dir_option(dir, option, FC_HIDDEN);
+ else if (strcasecmp("FilesSizeType", option->key) == 0)
+ status = cf_util_get_string(option, &dir->files_size_type);
+ else if (strcasecmp("FilesCountType", option->key) == 0)
+ status = cf_util_get_string(option, &dir->files_num_type);
+ else if (strcasecmp("TypeInstance", option->key) == 0)
+ status = cf_util_get_string(option, &dir->type_instance);
else {
WARNING("filecount plugin: fc_config_add_dir: "
"Option `%s' not allowed here.",
break;
} /* for (ci->children) */
- if (status == 0) {
- fc_directory_conf_t **temp;
+ if (status != 0) {
+ fc_free_dir(dir);
+ return -1;
+ }
- temp = realloc(directories, sizeof(*directories) * (directories_num + 1));
- if (temp == NULL) {
- ERROR("filecount plugin: realloc failed.");
- status = -1;
- } else {
- directories = temp;
- directories[directories_num] = dir;
- directories_num++;
+ /* Set default plugin instance */
+ if (dir->instance == NULL) {
+ fc_config_set_instance(dir, dir->path);
+ if (dir->instance == NULL || strlen(dir->instance) == 0) {
+ ERROR("filecount plugin: failed to build plugin instance name.");
+ fc_free_dir(dir);
+ return -1;
}
}
- if (status != 0) {
- sfree(dir->name);
+ /* Handle disabled types */
+ if (strlen(dir->instance) == 0)
sfree(dir->instance);
- sfree(dir->path);
- sfree(dir);
+
+ if (strlen(dir->files_size_type) == 0)
+ sfree(dir->files_size_type);
+
+ if (strlen(dir->files_num_type) == 0)
+ sfree(dir->files_num_type);
+
+ if (dir->files_size_type == NULL && dir->files_num_type == NULL) {
+ WARNING("filecount plugin: Both `FilesSizeType' and `FilesCountType ' "
+ "are disabled for '%s'. There's no types to report.",
+ dir->path);
+ fc_free_dir(dir);
+ return -1;
+ }
+
+ /* Ready to add it to list */
+ fc_directory_conf_t **temp =
+ realloc(directories, sizeof(*directories) * (directories_num + 1));
+ if (temp == NULL) {
+ ERROR("filecount plugin: realloc failed.");
+ fc_free_dir(dir);
return -1;
}
+ directories = temp;
+ directories[directories_num] = dir;
+ directories_num++;
+
return 0;
} /* int fc_config_add_dir */
fc_directory_conf_t *dir = user_data;
char abs_path[PATH_MAX];
struct stat statbuf;
- int status;
if (dir == NULL)
return -1;
- ssnprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename);
+ snprintf(abs_path, sizeof(abs_path), "%s/%s", dirname, filename);
- status = lstat(abs_path, &statbuf);
+ int status = lstat(abs_path, &statbuf);
if (status != 0) {
ERROR("filecount plugin: stat (%s) failed.", abs_path);
return -1;
} /* int fc_read_dir_callback */
static int fc_read_dir(fc_directory_conf_t *dir) {
- int status;
-
dir->files_num = 0;
dir->files_size = 0;
if (dir->mtime != 0)
dir->now = time(NULL);
- status =
+ int status =
walk_directory(dir->path, fc_read_dir_callback, dir,
/* include hidden */ (dir->options & FC_HIDDEN) ? 1 : 0);
if (status != 0) {
if (staging_tree == NULL)
return NULL;
- ssnprintf(key, sizeof(key), "%s/%s/%s", host, type,
- (type_instance != NULL) ? type_instance : "");
+ snprintf(key, sizeof(key), "%s/%s/%s", host, type,
+ (type_instance != NULL) ? type_instance : "");
se = NULL;
status = c_avl_get(staging_tree, key, (void *)&se);
using google::protobuf::util::TimeUtil;
+typedef google::protobuf::Map<grpc::string, collectd::types::MetadataValue> grpcMetadata;
+
/*
* private types
*/
return grpc::Status::OK;
} /* unmarshal_ident() */
+static grpc::Status marshal_meta_data(meta_data_t *meta,
+ grpcMetadata *mutable_meta_data) {
+ char **meta_data_keys = nullptr;
+ int meta_data_keys_len = meta_data_toc(meta, &meta_data_keys);
+ if (meta_data_keys_len < 0) {
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("error getting metadata keys"));
+ }
+
+ for (int i = 0; i < meta_data_keys_len; i++) {
+ char *key = meta_data_keys[i];
+ int md_type = meta_data_type(meta, key);
+
+ collectd::types::MetadataValue md_value;
+ md_value.Clear();
+
+ switch (md_type) {
+ case MD_TYPE_STRING:
+ char *md_string;
+ if (meta_data_get_string(meta, key, &md_string) != 0 || md_string == nullptr) {
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("missing metadata"));
+ }
+ md_value.set_string_value(md_string);
+ free(md_string);
+ break;
+ case MD_TYPE_SIGNED_INT:
+ int64_t int64_value;
+ if (meta_data_get_signed_int(meta, key, &int64_value) != 0) {
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("missing metadata"));
+ }
+ md_value.set_int64_value(int64_value);
+ break;
+ case MD_TYPE_UNSIGNED_INT:
+ uint64_t uint64_value;
+ if (meta_data_get_unsigned_int(meta, key, &uint64_value) != 0) {
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("missing metadata"));
+ }
+ md_value.set_uint64_value(uint64_value);
+ break;
+ case MD_TYPE_DOUBLE:
+ double double_value;
+ if (meta_data_get_double(meta, key, &double_value) != 0) {
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("missing metadata"));
+ }
+ md_value.set_double_value(double_value);
+ break;
+ case MD_TYPE_BOOLEAN:
+ bool bool_value;
+ if (meta_data_get_boolean(meta, key, &bool_value) != 0) {
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("missing metadata"));
+ }
+ md_value.set_bool_value(bool_value);
+ break;
+ default:
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ ERROR("grpc: invalid metadata type (%d)", md_type);
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("unknown metadata type"));
+ }
+
+ (*mutable_meta_data)[grpc::string(key)] = md_value;
+
+ strarray_free(meta_data_keys, meta_data_keys_len);
+ }
+
+ return grpc::Status::OK;
+}
+
+static grpc::Status unmarshal_meta_data(const grpcMetadata &rpc_metadata,
+ meta_data_t **md_out) {
+ *md_out = meta_data_create();
+ if (*md_out == nullptr) {
+ return grpc::Status(grpc::StatusCode::RESOURCE_EXHAUSTED,
+ grpc::string("failed to metadata list"));
+ }
+ for (auto kv: rpc_metadata) {
+ auto k = kv.first.c_str();
+ auto v = kv.second;
+
+ // The meta_data collection individually allocates copies of the keys and
+ // string values for each entry, so it's safe for us to pass a reference
+ // to our short-lived strings.
+
+ switch (v.value_case()) {
+ case collectd::types::MetadataValue::ValueCase::kStringValue:
+ meta_data_add_string(*md_out, k, v.string_value().c_str());
+ break;
+ case collectd::types::MetadataValue::ValueCase::kInt64Value:
+ meta_data_add_signed_int(*md_out, k, v.int64_value());
+ break;
+ case collectd::types::MetadataValue::ValueCase::kUint64Value:
+ meta_data_add_unsigned_int(*md_out, k, v.uint64_value());
+ break;
+ case collectd::types::MetadataValue::ValueCase::kDoubleValue:
+ meta_data_add_double(*md_out, k, v.double_value());
+ break;
+ case collectd::types::MetadataValue::ValueCase::kBoolValue:
+ meta_data_add_boolean(*md_out, k, v.bool_value());
+ break;
+ default:
+ meta_data_destroy(*md_out);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("Metadata of unknown type"));
+ }
+ }
+ return grpc::Status::OK;
+}
+
static grpc::Status marshal_value_list(const value_list_t *vl,
collectd::types::ValueList *msg) {
auto id = msg->mutable_identifier();
msg->set_allocated_time(new google::protobuf::Timestamp(t));
msg->set_allocated_interval(new google::protobuf::Duration(d));
+ msg->clear_meta_data();
+ if (vl->meta != nullptr) {
+ grpc::Status status = marshal_meta_data(vl->meta, msg->mutable_meta_data());
+ if (!status.ok()) {
+ return status;
+ }
+ }
+
for (size_t i = 0; i < vl->values_len; ++i) {
auto v = msg->add_values();
- switch (ds->ds[i].type) {
+ int value_type = ds->ds[i].type;
+ switch (value_type) {
case DS_TYPE_COUNTER:
v->set_counter(vl->values[i].counter);
break;
v->set_absolute(vl->values[i].absolute);
break;
default:
+ ERROR("grpc: invalid value type (%d)", value_type);
return grpc::Status(grpc::StatusCode::INTERNAL,
grpc::string("unknown value type"));
}
if (!status.ok())
return status;
+ status = unmarshal_meta_data(msg.meta_data(), &vl->meta);
+ if (!status.ok())
+ return status;
+
value_t *values = NULL;
size_t values_len = 0;
if (status.ok()) {
vl->values = values;
vl->values_len = values_len;
- } else if (values) {
+ } else {
+ meta_data_destroy(vl->meta);
free(values);
}
auto vl = value_lists.front();
value_lists.pop();
sfree(vl.values);
+ meta_data_destroy(vl.meta);
}
return status;
if (!ident_matches(&vl, match))
continue;
-
if (uc_iterator_get_time(iter, &vl.time) < 0) {
status =
grpc::Status(grpc::StatusCode::INTERNAL,
grpc::string("failed to retrieve values"));
break;
}
+ if (uc_iterator_get_meta(iter, &vl.meta) < 0) {
+ status = grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve value metadata"));
+ }
value_lists->push(vl);
} // while (uc_iterator_next(iter, &name) == 0)
} else if (strcasecmp(key, "Port") == 0) {
int port = (int)(atof(value));
if ((port > 0) && (port <= 65535))
- ssnprintf(hddtemp_port, sizeof(hddtemp_port), "%i", port);
+ snprintf(hddtemp_port, sizeof(hddtemp_port), "%i", port);
else
sstrncpy(hddtemp_port, value, sizeof(hddtemp_port));
} else {
sstrncpy(vl.plugin, g_plugin_name, sizeof(vl.plugin));
if (info->node) {
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%zuKb",
- info->node, info->page_size_kb);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%zuKb",
+ info->node, info->page_size_kb);
} else {
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%zuKb",
- info->page_size_kb);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%zuKb",
+ info->page_size_kb);
}
/* ensure all metrics have the same timestamp */
struct entry_info *info = e_info;
double value;
- ssnprintf(path2, sizeof(path2), "%s/%s", path, entry);
+ snprintf(path2, sizeof(path2), "%s/%s", path, entry);
FILE *fh = fopen(path2, "rt");
if (fh == NULL) {
}
/* /sys/devices/system/node/node?/hugepages/ */
- ssnprintf(path2, sizeof(path2), "%s/%s", path, result->d_name);
+ snprintf(path2, sizeof(path2), "%s/%s", path, result->d_name);
walk_directory(path2, read_hugepage_entry,
&(struct entry_info){
continue;
}
- ssnprintf(path, sizeof(path), sys_node_hugepages, result->d_name);
+ snprintf(path, sizeof(path), sys_node_hugepages, result->d_name);
read_syshugepages(path, result->d_name);
errno = 0;
}
--- /dev/null
+/**
+ * collectd - src/intel_pmu.c
+ *
+ * Copyright(c) 2017 Intel Corporation. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Serhiy Pshyk <serhiyx.pshyk@intel.com>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+
+#include <jevents.h>
+#include <jsession.h>
+
+#define PMU_PLUGIN "intel_pmu"
+
+#define HW_CACHE_READ_ACCESS \
+ (((PERF_COUNT_HW_CACHE_OP_READ) << 8) | \
+ ((PERF_COUNT_HW_CACHE_RESULT_ACCESS) << 16))
+
+#define HW_CACHE_WRITE_ACCESS \
+ (((PERF_COUNT_HW_CACHE_OP_WRITE) << 8) | \
+ ((PERF_COUNT_HW_CACHE_RESULT_ACCESS) << 16))
+
+#define HW_CACHE_PREFETCH_ACCESS \
+ (((PERF_COUNT_HW_CACHE_OP_PREFETCH) << 8) | \
+ ((PERF_COUNT_HW_CACHE_RESULT_ACCESS) << 16))
+
+#define HW_CACHE_READ_MISS \
+ (((PERF_COUNT_HW_CACHE_OP_READ) << 8) | \
+ ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))
+
+#define HW_CACHE_WRITE_MISS \
+ (((PERF_COUNT_HW_CACHE_OP_WRITE) << 8) | \
+ ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))
+
+#define HW_CACHE_PREFETCH_MISS \
+ (((PERF_COUNT_HW_CACHE_OP_PREFETCH) << 8) | \
+ ((PERF_COUNT_HW_CACHE_RESULT_MISS) << 16))
+
+struct event_info {
+ char *name;
+ uint64_t config;
+};
+typedef struct event_info event_info_t;
+
+struct intel_pmu_ctx_s {
+ _Bool hw_cache_events;
+ _Bool kernel_pmu_events;
+ _Bool sw_events;
+ char event_list_fn[PATH_MAX];
+ char **hw_events;
+ size_t hw_events_count;
+ struct eventlist *event_list;
+};
+typedef struct intel_pmu_ctx_s intel_pmu_ctx_t;
+
+event_info_t g_kernel_pmu_events[] = {
+ {.name = "cpu-cycles", .config = PERF_COUNT_HW_CPU_CYCLES},
+ {.name = "instructions", .config = PERF_COUNT_HW_INSTRUCTIONS},
+ {.name = "cache-references", .config = PERF_COUNT_HW_CACHE_REFERENCES},
+ {.name = "cache-misses", .config = PERF_COUNT_HW_CACHE_MISSES},
+ {.name = "branches", .config = PERF_COUNT_HW_BRANCH_INSTRUCTIONS},
+ {.name = "branch-misses", .config = PERF_COUNT_HW_BRANCH_MISSES},
+ {.name = "bus-cycles", .config = PERF_COUNT_HW_BUS_CYCLES},
+};
+
+event_info_t g_hw_cache_events[] = {
+
+ {.name = "L1-dcache-loads",
+ .config = (PERF_COUNT_HW_CACHE_L1D | HW_CACHE_READ_ACCESS)},
+ {.name = "L1-dcache-load-misses",
+ .config = (PERF_COUNT_HW_CACHE_L1D | HW_CACHE_READ_MISS)},
+ {.name = "L1-dcache-stores",
+ .config = (PERF_COUNT_HW_CACHE_L1D | HW_CACHE_WRITE_ACCESS)},
+ {.name = "L1-dcache-store-misses",
+ .config = (PERF_COUNT_HW_CACHE_L1D | HW_CACHE_WRITE_MISS)},
+ {.name = "L1-dcache-prefetches",
+ .config = (PERF_COUNT_HW_CACHE_L1D | HW_CACHE_PREFETCH_ACCESS)},
+ {.name = "L1-dcache-prefetch-misses",
+ .config = (PERF_COUNT_HW_CACHE_L1D | HW_CACHE_PREFETCH_MISS)},
+
+ {.name = "L1-icache-loads",
+ .config = (PERF_COUNT_HW_CACHE_L1I | HW_CACHE_READ_ACCESS)},
+ {.name = "L1-icache-load-misses",
+ .config = (PERF_COUNT_HW_CACHE_L1I | HW_CACHE_READ_MISS)},
+ {.name = "L1-icache-prefetches",
+ .config = (PERF_COUNT_HW_CACHE_L1I | HW_CACHE_PREFETCH_ACCESS)},
+ {.name = "L1-icache-prefetch-misses",
+ .config = (PERF_COUNT_HW_CACHE_L1I | HW_CACHE_PREFETCH_MISS)},
+
+ {.name = "LLC-loads",
+ .config = (PERF_COUNT_HW_CACHE_LL | HW_CACHE_READ_ACCESS)},
+ {.name = "LLC-load-misses",
+ .config = (PERF_COUNT_HW_CACHE_LL | HW_CACHE_READ_MISS)},
+ {.name = "LLC-stores",
+ .config = (PERF_COUNT_HW_CACHE_LL | HW_CACHE_WRITE_ACCESS)},
+ {.name = "LLC-store-misses",
+ .config = (PERF_COUNT_HW_CACHE_LL | HW_CACHE_WRITE_MISS)},
+ {.name = "LLC-prefetches",
+ .config = (PERF_COUNT_HW_CACHE_LL | HW_CACHE_PREFETCH_ACCESS)},
+ {.name = "LLC-prefetch-misses",
+ .config = (PERF_COUNT_HW_CACHE_LL | HW_CACHE_PREFETCH_MISS)},
+
+ {.name = "dTLB-loads",
+ .config = (PERF_COUNT_HW_CACHE_DTLB | HW_CACHE_READ_ACCESS)},
+ {.name = "dTLB-load-misses",
+ .config = (PERF_COUNT_HW_CACHE_DTLB | HW_CACHE_READ_MISS)},
+ {.name = "dTLB-stores",
+ .config = (PERF_COUNT_HW_CACHE_DTLB | HW_CACHE_WRITE_ACCESS)},
+ {.name = "dTLB-store-misses",
+ .config = (PERF_COUNT_HW_CACHE_DTLB | HW_CACHE_WRITE_MISS)},
+ {.name = "dTLB-prefetches",
+ .config = (PERF_COUNT_HW_CACHE_DTLB | HW_CACHE_PREFETCH_ACCESS)},
+ {.name = "dTLB-prefetch-misses",
+ .config = (PERF_COUNT_HW_CACHE_DTLB | HW_CACHE_PREFETCH_MISS)},
+
+ {.name = "iTLB-loads",
+ .config = (PERF_COUNT_HW_CACHE_ITLB | HW_CACHE_READ_ACCESS)},
+ {.name = "iTLB-load-misses",
+ .config = (PERF_COUNT_HW_CACHE_ITLB | HW_CACHE_READ_MISS)},
+
+ {.name = "branch-loads",
+ .config = (PERF_COUNT_HW_CACHE_BPU | HW_CACHE_READ_ACCESS)},
+ {.name = "branch-load-misses",
+ .config = (PERF_COUNT_HW_CACHE_BPU | HW_CACHE_READ_MISS)},
+};
+
+event_info_t g_sw_events[] = {
+ {.name = "cpu-clock", .config = PERF_COUNT_SW_CPU_CLOCK},
+
+ {.name = "task-clock", .config = PERF_COUNT_SW_TASK_CLOCK},
+
+ {.name = "context-switches", .config = PERF_COUNT_SW_CONTEXT_SWITCHES},
+
+ {.name = "cpu-migrations", .config = PERF_COUNT_SW_CPU_MIGRATIONS},
+
+ {.name = "page-faults", .config = PERF_COUNT_SW_PAGE_FAULTS},
+
+ {.name = "minor-faults", .config = PERF_COUNT_SW_PAGE_FAULTS_MIN},
+
+ {.name = "major-faults", .config = PERF_COUNT_SW_PAGE_FAULTS_MAJ},
+
+ {.name = "alignment-faults", .config = PERF_COUNT_SW_ALIGNMENT_FAULTS},
+
+ {.name = "emulation-faults", .config = PERF_COUNT_SW_EMULATION_FAULTS},
+};
+
+static intel_pmu_ctx_t g_ctx;
+
+#if COLLECT_DEBUG
+static void pmu_dump_events() {
+
+ DEBUG(PMU_PLUGIN ": Events:");
+
+ struct event *e;
+
+ for (e = g_ctx.event_list->eventlist; e; e = e->next) {
+ DEBUG(PMU_PLUGIN ": event : %s", e->event);
+ DEBUG(PMU_PLUGIN ": group_lead: %d", e->group_leader);
+ DEBUG(PMU_PLUGIN ": end_group : %d", e->end_group);
+ DEBUG(PMU_PLUGIN ": type : %#x", e->attr.type);
+ DEBUG(PMU_PLUGIN ": config : %#x", (unsigned)e->attr.config);
+ DEBUG(PMU_PLUGIN ": size : %d", e->attr.size);
+ }
+}
+
+static void pmu_dump_config(void) {
+
+ DEBUG(PMU_PLUGIN ": Config:");
+ DEBUG(PMU_PLUGIN ": hw_cache_events : %d", g_ctx.hw_cache_events);
+ DEBUG(PMU_PLUGIN ": kernel_pmu_events : %d", g_ctx.kernel_pmu_events);
+ DEBUG(PMU_PLUGIN ": software_events : %d", g_ctx.sw_events);
+
+ for (size_t i = 0; i < g_ctx.hw_events_count; i++) {
+ DEBUG(PMU_PLUGIN ": hardware_events[%zu]: %s", i, g_ctx.hw_events[i]);
+ }
+}
+
+#endif /* COLLECT_DEBUG */
+
+static int pmu_config_hw_events(oconfig_item_t *ci) {
+
+ if (strcasecmp("HardwareEvents", ci->key) != 0) {
+ return -EINVAL;
+ }
+
+ g_ctx.hw_events = calloc(ci->values_num, sizeof(char *));
+ if (g_ctx.hw_events == NULL) {
+ ERROR(PMU_PLUGIN ": Failed to allocate hw events.");
+ return -ENOMEM;
+ }
+
+ for (int i = 0; i < ci->values_num; i++) {
+ if (ci->values[i].type != OCONFIG_TYPE_STRING) {
+ WARNING(PMU_PLUGIN ": The %s option requires string arguments.", ci->key);
+ continue;
+ }
+
+ g_ctx.hw_events[g_ctx.hw_events_count] = strdup(ci->values[i].value.string);
+ if (g_ctx.hw_events[g_ctx.hw_events_count] == NULL) {
+ ERROR(PMU_PLUGIN ": Failed to allocate hw events entry.");
+ return -ENOMEM;
+ }
+
+ g_ctx.hw_events_count++;
+ }
+
+ return 0;
+}
+
+static int pmu_config(oconfig_item_t *ci) {
+
+ DEBUG(PMU_PLUGIN ": %s:%d", __FUNCTION__, __LINE__);
+
+ for (int i = 0; i < ci->children_num; i++) {
+ int ret = 0;
+ oconfig_item_t *child = ci->children + i;
+
+ if (strcasecmp("ReportHardwareCacheEvents", child->key) == 0) {
+ ret = cf_util_get_boolean(child, &g_ctx.hw_cache_events);
+ } else if (strcasecmp("ReportKernelPMUEvents", child->key) == 0) {
+ ret = cf_util_get_boolean(child, &g_ctx.kernel_pmu_events);
+ } else if (strcasecmp("EventList", child->key) == 0) {
+ ret = cf_util_get_string_buffer(child, g_ctx.event_list_fn,
+ sizeof(g_ctx.event_list_fn));
+ } else if (strcasecmp("HardwareEvents", child->key) == 0) {
+ ret = pmu_config_hw_events(child);
+ } else if (strcasecmp("ReportSoftwareEvents", child->key) == 0) {
+ ret = cf_util_get_boolean(child, &g_ctx.sw_events);
+ } else {
+ ERROR(PMU_PLUGIN ": Unknown configuration parameter \"%s\".", child->key);
+ ret = -1;
+ }
+
+ if (ret != 0) {
+ DEBUG(PMU_PLUGIN ": %s:%d ret=%d", __FUNCTION__, __LINE__, ret);
+ return ret;
+ }
+ }
+
+#if COLLECT_DEBUG
+ pmu_dump_config();
+#endif
+
+ return 0;
+}
+
+static void pmu_submit_counter(int cpu, char *event, counter_t value) {
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = &(value_t){.counter = value};
+ vl.values_len = 1;
+
+ sstrncpy(vl.plugin, PMU_PLUGIN, sizeof(vl.plugin));
+ if (cpu == -1) {
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "all");
+ } else {
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%d", cpu);
+ }
+ sstrncpy(vl.type, "counter", sizeof(vl.type));
+ sstrncpy(vl.type_instance, event, sizeof(vl.type_instance));
+
+ plugin_dispatch_values(&vl);
+}
+
+static void pmu_dispatch_data(void) {
+
+ struct event *e;
+
+ for (e = g_ctx.event_list->eventlist; e; e = e->next) {
+ uint64_t all_value = 0;
+ int event_enabled = 0;
+ for (int i = 0; i < g_ctx.event_list->num_cpus; i++) {
+
+ if (e->efd[i].fd < 0)
+ continue;
+
+ event_enabled++;
+
+ uint64_t value = event_scaled_value(e, i);
+ all_value += value;
+
+ /* dispatch per CPU value */
+ pmu_submit_counter(i, e->event, value);
+ }
+
+ if (event_enabled > 0) {
+ DEBUG(PMU_PLUGIN ": %-20s %'10lu", e->event, all_value);
+ /* dispatch all CPU value */
+ pmu_submit_counter(-1, e->event, all_value);
+ }
+ }
+}
+
+static int pmu_read(__attribute__((unused)) user_data_t *ud) {
+ int ret;
+
+ DEBUG(PMU_PLUGIN ": %s:%d", __FUNCTION__, __LINE__);
+
+ ret = read_all_events(g_ctx.event_list);
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to read values of all events.");
+ return ret;
+ }
+
+ pmu_dispatch_data();
+
+ return 0;
+}
+
+static int pmu_add_events(struct eventlist *el, uint32_t type,
+ event_info_t *events, size_t count) {
+
+ for (size_t i = 0; i < count; i++) {
+ /* Allocate memory for event struct that contains array of efd structs
+ for all cores */
+ struct event *e =
+ calloc(sizeof(struct event) + sizeof(struct efd) * el->num_cpus, 1);
+ if (e == NULL) {
+ ERROR(PMU_PLUGIN ": Failed to allocate event structure");
+ return -ENOMEM;
+ }
+
+ e->attr.type = type;
+ e->attr.config = events[i].config;
+ e->attr.size = PERF_ATTR_SIZE_VER0;
+ if (!el->eventlist)
+ el->eventlist = e;
+ if (el->eventlist_last)
+ el->eventlist_last->next = e;
+ el->eventlist_last = e;
+ e->event = strdup(events[i].name);
+ }
+
+ return 0;
+}
+
+static int pmu_add_hw_events(struct eventlist *el, char **e, size_t count) {
+
+ for (size_t i = 0; i < count; i++) {
+
+ size_t group_events_count = 0;
+
+ char *events = strdup(e[i]);
+ if (!events)
+ return -1;
+
+ char *s, *tmp;
+ for (s = strtok_r(events, ",", &tmp); s; s = strtok_r(NULL, ",", &tmp)) {
+
+ /* Multiple events parsed in one entry */
+ if (group_events_count == 1) {
+ /* Mark previously added event as group leader */
+ el->eventlist_last->group_leader = 1;
+ }
+
+ /* Allocate memory for event struct that contains array of efd structs
+ for all cores */
+ struct event *e =
+ calloc(sizeof(struct event) + sizeof(struct efd) * el->num_cpus, 1);
+ if (e == NULL) {
+ free(events);
+ return -ENOMEM;
+ }
+
+ if (resolve_event(s, &e->attr) == 0) {
+ e->next = NULL;
+ if (!el->eventlist)
+ el->eventlist = e;
+ if (el->eventlist_last)
+ el->eventlist_last->next = e;
+ el->eventlist_last = e;
+ e->event = strdup(s);
+ } else {
+ DEBUG(PMU_PLUGIN ": Cannot resolve %s", s);
+ sfree(e);
+ }
+
+ group_events_count++;
+ }
+
+ /* Multiple events parsed in one entry */
+ if (group_events_count > 1) {
+ /* Mark last added event as group end */
+ el->eventlist_last->end_group = 1;
+ }
+
+ free(events);
+ }
+
+ return 0;
+}
+
+static void pmu_free_events(struct eventlist *el) {
+
+ if (el == NULL)
+ return;
+
+ struct event *e = el->eventlist;
+
+ while (e) {
+ struct event *next = e->next;
+ sfree(e);
+ e = next;
+ }
+
+ el->eventlist = NULL;
+}
+
+static int pmu_setup_events(struct eventlist *el, bool measure_all,
+ int measure_pid) {
+ struct event *e, *leader = NULL;
+ int ret = -1;
+
+ for (e = el->eventlist; e; e = e->next) {
+
+ for (int i = 0; i < el->num_cpus; i++) {
+ if (setup_event(e, i, leader, measure_all, measure_pid) < 0) {
+ WARNING(PMU_PLUGIN ": perf event '%s' is not available (cpu=%d).",
+ e->event, i);
+ } else {
+ /* success if at least one event was set */
+ ret = 0;
+ }
+ }
+
+ if (e->group_leader)
+ leader = e;
+ if (e->end_group)
+ leader = NULL;
+ }
+
+ return ret;
+}
+
+static int pmu_init(void) {
+ int ret;
+
+ DEBUG(PMU_PLUGIN ": %s:%d", __FUNCTION__, __LINE__);
+
+ g_ctx.event_list = alloc_eventlist();
+ if (g_ctx.event_list == NULL) {
+ ERROR(PMU_PLUGIN ": Failed to allocate event list.");
+ return -ENOMEM;
+ }
+
+ if (g_ctx.hw_cache_events) {
+ ret =
+ pmu_add_events(g_ctx.event_list, PERF_TYPE_HW_CACHE, g_hw_cache_events,
+ STATIC_ARRAY_SIZE(g_hw_cache_events));
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to add hw cache events.");
+ goto init_error;
+ }
+ }
+
+ if (g_ctx.kernel_pmu_events) {
+ ret = pmu_add_events(g_ctx.event_list, PERF_TYPE_HARDWARE,
+ g_kernel_pmu_events,
+ STATIC_ARRAY_SIZE(g_kernel_pmu_events));
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to add kernel PMU events.");
+ goto init_error;
+ }
+ }
+
+ /* parse events names if config option is present and is not empty */
+ if (g_ctx.hw_events_count) {
+
+ ret = read_events(g_ctx.event_list_fn);
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to read event list file '%s'.",
+ g_ctx.event_list_fn);
+ return ret;
+ }
+
+ ret = pmu_add_hw_events(g_ctx.event_list, g_ctx.hw_events,
+ g_ctx.hw_events_count);
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to add hardware events.");
+ goto init_error;
+ }
+ }
+
+ if (g_ctx.sw_events) {
+ ret = pmu_add_events(g_ctx.event_list, PERF_TYPE_SOFTWARE, g_sw_events,
+ STATIC_ARRAY_SIZE(g_sw_events));
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to add software events.");
+ goto init_error;
+ }
+ }
+
+#if COLLECT_DEBUG
+ pmu_dump_events();
+#endif
+
+ if (g_ctx.event_list->eventlist != NULL) {
+ /* measure all processes */
+ ret = pmu_setup_events(g_ctx.event_list, true, -1);
+ if (ret != 0) {
+ ERROR(PMU_PLUGIN ": Failed to setup perf events for the event list.");
+ goto init_error;
+ }
+ } else {
+ WARNING(PMU_PLUGIN
+ ": Events list is empty. No events were setup for monitoring.");
+ }
+
+ return 0;
+
+init_error:
+
+ pmu_free_events(g_ctx.event_list);
+ sfree(g_ctx.event_list);
+ for (size_t i = 0; i < g_ctx.hw_events_count; i++) {
+ sfree(g_ctx.hw_events[i]);
+ }
+ sfree(g_ctx.hw_events);
+ g_ctx.hw_events_count = 0;
+
+
+ return ret;
+}
+
+static int pmu_shutdown(void) {
+
+ DEBUG(PMU_PLUGIN ": %s:%d", __FUNCTION__, __LINE__);
+
+ pmu_free_events(g_ctx.event_list);
+ sfree(g_ctx.event_list);
+ for (size_t i = 0; i < g_ctx.hw_events_count; i++) {
+ sfree(g_ctx.hw_events[i]);
+ }
+ sfree(g_ctx.hw_events);
+ g_ctx.hw_events_count = 0;
+
+ return 0;
+}
+
+void module_register(void) {
+ plugin_register_init(PMU_PLUGIN, pmu_init);
+ plugin_register_complex_config(PMU_PLUGIN, pmu_config);
+ plugin_register_complex_read(NULL, PMU_PLUGIN, pmu_read, 0, NULL);
+ plugin_register_shutdown(PMU_PLUGIN, pmu_shutdown);
+}
char desc[DATA_MAX_NAME_LEN];
uint64_t core = i;
- ssnprintf(desc, sizeof(desc), "%d", g_rdt->pqos_cpu->cores[i].lcore);
+ snprintf(desc, sizeof(desc), "%d", g_rdt->pqos_cpu->cores[i].lcore);
/* set core group info */
ret = cgroup_set(&g_rdt->cgroups[i], desc, &core, 1);
static int rdt_init(void) {
int ret;
- if(g_state == CONFIGURATION_ERROR)
+ if (g_state == CONFIGURATION_ERROR)
return -1;
ret = rdt_preinit();
continue;
if (unique_name)
- ssnprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module,
- ksp[i]->ks_instance, ksp[i]->ks_name);
+ snprintf(iname, sizeof(iname), "%s_%d_%s", ksp[i]->ks_module,
+ ksp[i]->ks_instance, ksp[i]->ks_name);
else
sstrncpy(iname, ksp[i]->ks_name, sizeof(iname));
ipcinfo_shm_t *pshm;
unsigned int shm_segments = 0;
size64_t shm_bytes = 0;
- int n;
+ int i, n;
ipcinfo_shm = (ipcinfo_shm_t *)ipc_get_info(
0, GET_IPCINFO_SHM_ALL, IPCINFO_SHM_VERSION, sizeof(ipcinfo_shm_t), &n);
if (ipcinfo_shm == NULL)
return -1;
- for (int i = 0, pshm = ipcinfo_shm; i < n; i++, pshm++) {
+ for (i = 0, pshm = ipcinfo_shm; i < n; i++, pshm++) {
shm_segments++;
shm_bytes += pshm->shm_segsz;
}
}
if (errbuf[0] == 0) {
- ssnprintf(errbuf, sizeof(errbuf), "Unknown error %#x", status);
+ snprintf(errbuf, sizeof(errbuf), "Unknown error %#x", status);
}
errbuf[sizeof(errbuf) - 1] = 0;
sstrncpy(n.type_instance, list_item->sensor_name,
sizeof(n.type_instance));
sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
- ssnprintf(n.message, sizeof(n.message), "sensor %s not present",
- list_item->sensor_name);
+ snprintf(n.message, sizeof(n.message), "sensor %s not present",
+ list_item->sensor_name);
plugin_dispatch_notification(&n);
}
sstrncpy(n.type_instance, list_item->sensor_name,
sizeof(n.type_instance));
sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
- ssnprintf(n.message, sizeof(n.message), "sensor %s present",
- list_item->sensor_name);
+ snprintf(n.message, sizeof(n.message), "sensor %s present",
+ list_item->sensor_name);
plugin_dispatch_notification(&n);
}
if (entity_id_string == NULL)
sstrncpy(sensor_name, buffer, sizeof(sensor_name));
else
- ssnprintf(sensor_name, sizeof(sensor_name), "%s %s", buffer,
- entity_id_string);
+ snprintf(sensor_name, sizeof(sensor_name), "%s %s", buffer,
+ entity_id_string);
sstrncpy(buffer, sensor_name, sizeof(buffer));
sensor_name_ptr = strstr(buffer, ").");
sensor_id_ptr = strstr(buffer, "(");
if (sensor_id_ptr != NULL) {
/* `sensor_id_ptr' now points to "(123)". */
- ssnprintf(sensor_name, sizeof(sensor_name), "%s %s", sensor_name_ptr,
- sensor_id_ptr);
+ snprintf(sensor_name, sizeof(sensor_name), "%s %s", sensor_name_ptr,
+ sensor_id_ptr);
}
/* else: don't touch sensor_name. */
}
sstrncpy(n.host, hostname_g, sizeof(n.host));
sstrncpy(n.type_instance, list_item->sensor_name, sizeof(n.type_instance));
sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
- ssnprintf(n.message, sizeof(n.message), "sensor %s added",
- list_item->sensor_name);
+ snprintf(n.message, sizeof(n.message), "sensor %s added",
+ list_item->sensor_name);
plugin_dispatch_notification(&n);
}
sstrncpy(n.host, hostname_g, sizeof(n.host));
sstrncpy(n.type_instance, list_item->sensor_name, sizeof(n.type_instance));
sstrncpy(n.type, list_item->sensor_type, sizeof(n.type));
- ssnprintf(n.message, sizeof(n.message), "sensor %s removed",
- list_item->sensor_name);
+ snprintf(n.message, sizeof(n.message), "sensor %s removed",
+ list_item->sensor_name);
plugin_dispatch_notification(&n);
}
return 1;
ip_chain_t temp = {0};
- ip_chain_t * final, **list;
+ ip_chain_t *final, **list;
char *table;
int table_len;
char *chain;
}
chain_list = list;
- final = malloc(sizeof(* final));
+ final = malloc(sizeof(*final));
if (final == NULL) {
char errbuf[1024];
ERROR("malloc failed: %s", sstrerror(errno, errbuf, sizeof(errbuf)));
sstrncpy(vl.plugin, "ip6tables", sizeof(vl.plugin));
- status = ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
- chain->table, chain->chain);
+ status = snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
+ chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof(vl.plugin_instance)))
return 0;
sstrncpy(vl.type_instance, chain->name, sizeof(vl.type_instance));
} else {
if (chain->rule_type == RTYPE_NUM)
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
- chain->rule.num);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
+ chain->rule.num);
else
sstrncpy(vl.type_instance, (char *)match->data, sizeof(vl.type_instance));
}
sstrncpy(vl.plugin, "iptables", sizeof(vl.plugin));
- status = ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
- chain->table, chain->chain);
+ status = snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
+ chain->table, chain->chain);
if ((status < 1) || ((unsigned int)status >= sizeof(vl.plugin_instance)))
return 0;
sstrncpy(vl.type_instance, chain->name, sizeof(vl.type_instance));
} else {
if (chain->rule_type == RTYPE_NUM)
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
- chain->rule.num);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%i",
+ chain->rule.num);
else
sstrncpy(vl.type_instance, (char *)match->data, sizeof(vl.type_instance));
}
struct in_addr addr = {.s_addr = se->addr};
int len =
- ssnprintf(pi, size, "%s_%s%u", inet_ntoa(addr),
- (se->protocol == IPPROTO_TCP) ? "TCP" : "UDP", ntohs(se->port));
+ snprintf(pi, size, "%s_%s%u", inet_ntoa(addr),
+ (se->protocol == IPPROTO_TCP) ? "TCP" : "UDP", ntohs(se->port));
if ((len < 0) || (size <= ((size_t)len))) {
log_err("plugin instance truncated: %s", pi);
struct in_addr addr = {.s_addr = de->addr};
- int len = ssnprintf(ti, size, "%s_%u", inet_ntoa(addr), ntohs(de->port));
+ int len = snprintf(ti, size, "%s_%u", inet_ntoa(addr), ntohs(de->port));
if ((len < 0) || (size <= ((size_t)len))) {
log_err("type instance truncated: %s", ti);
return 0;
} /* }}} int jtoc_notification */
- /*
- * Functions accessible from Java
- */
+/*
+ * Functions accessible from Java
+ */
static jint JNICALL cjni_api_dispatch_values(JNIEnv *jvm_env, /* {{{ */
jobject this, jobject java_vl) {
value_list_t vl = VALUE_LIST_INIT;
* Florian octo Forster <octo at collectd.org>
**/
-#if HAVE_CONFIG_H
#include "config.h"
-#endif
#if !defined(__GNUC__) || !__GNUC__
#define __attribute__(x) /**/
#define LCC_SET_ERRSTR(c, ...) \
do { \
snprintf((c)->errbuf, sizeof((c)->errbuf), __VA_ARGS__); \
- (c)->errbuf[sizeof((c)->errbuf) - 1] = 0; \
} while (0)
/*
*/
struct lcc_connection_s {
FILE *fh;
- char errbuf[1024];
+ char errbuf[2048];
};
struct lcc_response_s {
#ifndef LIBCOLLECTD_COLLECTDCLIENT_H
#define LIBCOLLECTD_COLLECTDCLIENT_H 1
-#include "lcc_features.h"
+#include "collectd/lcc_features.h"
+#include "collectd/types.h"
/* COLLECTD_TRACE is the environment variable used to control trace output. When
* set to something non-zero, all lines sent to / received from the daemon are
/*
* Includes (for data types)
*/
-#include <stdint.h>
#include <inttypes.h>
+#include <stdint.h>
#include <time.h>
-/*
- * Defines
- */
-#define LCC_NAME_LEN 64
-#define LCC_DEFAULT_PORT "25826"
-
-/*
- * Types
- */
-#define LCC_TYPE_COUNTER 0
-#define LCC_TYPE_GAUGE 1
-#define LCC_TYPE_DERIVE 2
-#define LCC_TYPE_ABSOLUTE 3
-
LCC_BEGIN_DECLS
-typedef uint64_t counter_t;
-typedef double gauge_t;
-typedef uint64_t derive_t;
-typedef uint64_t absolute_t;
-
-union value_u {
- counter_t counter;
- gauge_t gauge;
- derive_t derive;
- absolute_t absolute;
-};
-typedef union value_u value_t;
-
-struct lcc_identifier_s {
- char host[LCC_NAME_LEN];
- char plugin[LCC_NAME_LEN];
- char plugin_instance[LCC_NAME_LEN];
- char type[LCC_NAME_LEN];
- char type_instance[LCC_NAME_LEN];
-};
-typedef struct lcc_identifier_s lcc_identifier_t;
-#define LCC_IDENTIFIER_INIT \
- { "localhost", "", "", "", "" }
-
-struct lcc_value_list_s {
- value_t *values;
- int *values_types;
- size_t values_len;
- double time;
- double interval;
- lcc_identifier_t identifier;
-};
-typedef struct lcc_value_list_s lcc_value_list_t;
-#define LCC_VALUE_LIST_INIT \
- { NULL, NULL, 0, 0, 0, LCC_IDENTIFIER_INIT }
-
struct lcc_connection_s;
typedef struct lcc_connection_s lcc_connection_t;
#ifndef LIBCOLLECTDCLIENT_NETWORK_H
#define LIBCOLLECTDCLIENT_NETWORK_H 1
+#include "collectd/client.h"
+
#include <inttypes.h>
#include <stdint.h>
-#include "client.h"
-
#define NET_DEFAULT_V4_ADDR "239.192.74.66"
#define NET_DEFAULT_V6_ADDR "ff18::efc0:4a42"
#define NET_DEFAULT_PORT "25826"
#ifndef LIBCOLLECTDCLIENT_NETWORK_BUFFER_H
#define LIBCOLLECTDCLIENT_NETWORK_BUFFER_H 1
-/* FIXME */
-#include "client.h"
-#include "network.h"
+#include "collectd/network.h" /* for lcc_security_level_t */
+#include "collectd/types.h"
/* Ethernet frame - (IPv6 header + UDP header) */
#define LCC_NETWORK_BUFFER_SIZE_DEFAULT 1452
--- /dev/null
+/**
+ * Copyright 2017 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef LIBCOLLECTD_NETWORK_PARSE_H
+#define LIBCOLLECTD_NETWORK_PARSE_H 1
+
+#include "collectd/lcc_features.h"
+
+#include "collectd/network.h" /* for lcc_security_level_t */
+#include "collectd/types.h"
+
+#include <stdint.h>
+
+LCC_BEGIN_DECLS
+
+typedef struct {
+ /* writer is the callback used to send incoming lcc_value_list_t to. */
+ lcc_value_list_writer_t writer;
+
+ /* password_lookup is used to look up the password for a given username. */
+ lcc_password_lookup_t password_lookup;
+
+ /* security_level is the minimal required security level. */
+ lcc_security_level_t security_level;
+} lcc_network_parse_options_t;
+
+/* lcc_network_parse parses data received from the network and calls "w" with
+ * the parsed lcc_value_list_ts. */
+int lcc_network_parse(void *buffer, size_t buffer_size,
+ lcc_network_parse_options_t opts);
+
+LCC_END_DECLS
+
+#endif /* LIBCOLLECTD_NETWORK_PARSE_H */
--- /dev/null
+/**
+ * Copyright 2017 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef LIBCOLLECTD_SERVER_H
+#define LIBCOLLECTD_SERVER_H 1
+
+#include "collectd/lcc_features.h"
+
+#include "collectd/network.h" /* for lcc_security_level_t */
+#include "collectd/network_parse.h" /* for lcc_network_parse_options_t */
+#include "collectd/types.h"
+
+#include <stdint.h>
+
+#ifndef LCC_NETWORK_BUFFER_SIZE
+#define LCC_NETWORK_BUFFER_SIZE 1452
+#endif
+
+LCC_BEGIN_DECLS
+
+/* lcc_network_parser_t is a callback that parses received network packets. It
+ * is expected to call lcc_network_parse_options_t.writer with each
+ * lcc_value_list_t it parses that has the required security level. */
+typedef int (*lcc_network_parser_t)(void *payload, size_t payload_size,
+ lcc_network_parse_options_t opts);
+
+/* lcc_listener_t holds parameters for running a collectd server. */
+typedef struct {
+ /* conn is a UDP socket for the server to listen on. If set to <0 node and
+ * service will be used to open a new UDP socket. If >=0, it is the caller's
+ * job to clean up the socket. */
+ int conn;
+
+ /* node is the local address to listen on if conn is <0. Defaults to "::" (any
+ * address). */
+ char *node;
+
+ /* service is the local address to listen on if conn is <0. Defaults to
+ * LCC_DEFAULT_PORT. */
+ char *service;
+
+ /* parser is the callback used to parse incoming network packets. Defaults to
+ * lcc_network_parse() if set to NULL. */
+ lcc_network_parser_t parser;
+
+ /* parse_options contains options for parser and is passed on verbatimely. */
+ lcc_network_parse_options_t parse_options;
+
+ /* buffer_size determines the maximum packet size to accept. Defaults to
+ * LCC_NETWORK_BUFFER_SIZE if set to zero. */
+ uint16_t buffer_size;
+
+ /* interface is the name of the interface to use when subscribing to a
+ * multicast group. Has no effect when using unicast. */
+ char *interface;
+} lcc_listener_t;
+
+/* lcc_listen_and_write listens on the provided UDP socket (or opens one using
+ * srv.addr if srv.conn is less than zero), parses the received packets and
+ * writes them to the provided lcc_value_list_writer_t. Returns non-zero on
+ * failure and does not return otherwise. */
+int lcc_listen_and_write(lcc_listener_t srv);
+
+LCC_END_DECLS
+
+#endif /* LIBCOLLECTD_SERVER_H */
--- /dev/null
+/**
+ * libcollectdclient - src/libcollectdclient/collectd/types.h
+ * Copyright (C) 2008-2017 Florian octo Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#ifndef LIBCOLLECTD_COLLECTD_TYPES_H
+#define LIBCOLLECTD_COLLECTD_TYPES_H 1
+
+#include "collectd/lcc_features.h"
+
+#include <stdint.h> /* for uint64_t */
+#include <sys/types.h> /* for size_t */
+
+/*
+ * Defines
+ */
+#define LCC_NAME_LEN 64
+#define LCC_DEFAULT_PORT "25826"
+
+/*
+ * Types
+ */
+#define LCC_TYPE_COUNTER 0
+#define LCC_TYPE_GAUGE 1
+#define LCC_TYPE_DERIVE 2
+#define LCC_TYPE_ABSOLUTE 3
+
+LCC_BEGIN_DECLS
+
+typedef uint64_t counter_t;
+typedef double gauge_t;
+typedef uint64_t derive_t;
+typedef uint64_t absolute_t;
+
+union value_u {
+ counter_t counter;
+ gauge_t gauge;
+ derive_t derive;
+ absolute_t absolute;
+};
+typedef union value_u value_t;
+
+struct lcc_identifier_s {
+ char host[LCC_NAME_LEN];
+ char plugin[LCC_NAME_LEN];
+ char plugin_instance[LCC_NAME_LEN];
+ char type[LCC_NAME_LEN];
+ char type_instance[LCC_NAME_LEN];
+};
+typedef struct lcc_identifier_s lcc_identifier_t;
+#define LCC_IDENTIFIER_INIT \
+ { "localhost", "", "", "", "" }
+
+struct lcc_value_list_s {
+ value_t *values;
+ int *values_types;
+ size_t values_len;
+ double time;
+ double interval;
+ lcc_identifier_t identifier;
+};
+typedef struct lcc_value_list_s lcc_value_list_t;
+#define LCC_VALUE_LIST_INIT \
+ { NULL, NULL, 0, 0, 0, LCC_IDENTIFIER_INIT }
+
+/* lcc_value_list_writer_t is a write callback to which value lists are
+ * dispatched. */
+typedef int (*lcc_value_list_writer_t)(lcc_value_list_t const *);
+
+/* lcc_password_lookup_t is a callback for looking up the password for a given
+ * user. Must return NULL if the user is not known. */
+typedef char const *(*lcc_password_lookup_t)(char const *);
+
+LCC_END_DECLS
+
+#endif /* LIBCOLLECTD_COLLECTD_TYPES_H */
--- /dev/null
+/**
+ * Copyright 2017 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "config.h"
+
+#if !defined(__GNUC__) || !__GNUC__
+#define __attribute__(x) /**/
+#endif
+
+#include "collectd/lcc_features.h"
+#include "collectd/network_parse.h"
+
+#include <errno.h>
+#include <math.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* for be{16,64}toh */
+#if HAVE_ENDIAN_H
+#include <endian.h>
+#elif HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+
+#if HAVE_GCRYPT_H
+#define GCRYPT_NO_DEPRECATED
+#include <gcrypt.h>
+#endif
+
+#include <stdio.h>
+#define DEBUG(...) printf(__VA_ARGS__)
+
+#if HAVE_GCRYPT_H
+#if GCRYPT_VERSION_NUMBER < 0x010600
+GCRY_THREAD_OPTION_PTHREAD_IMPL;
+#endif
+#endif
+
+/* forward declaration because parse_sign_sha256()/parse_encrypt_aes256() and
+ * network_parse() need to call each other. */
+static int network_parse(void *data, size_t data_size, lcc_security_level_t sl,
+ lcc_network_parse_options_t const *opts);
+
+#if HAVE_GCRYPT_H
+static int init_gcrypt() {
+ /* http://lists.gnupg.org/pipermail/gcrypt-devel/2003-August/000458.html
+ * Because you can't know in a library whether another library has
+ * already initialized the library */
+ if (gcry_control(GCRYCTL_ANY_INITIALIZATION_P))
+ return (0);
+
+/* http://www.gnupg.org/documentation/manuals/gcrypt/Multi_002dThreading.html
+ * To ensure thread-safety, it's important to set GCRYCTL_SET_THREAD_CBS
+ * *before* initalizing Libgcrypt with gcry_check_version(), which itself must
+ * be called before any other gcry_* function. GCRYCTL_ANY_INITIALIZATION_P
+ * above doesn't count, as it doesn't implicitly initalize Libgcrypt.
+ *
+ * tl;dr: keep all these gry_* statements in this exact order please. */
+#if GCRYPT_VERSION_NUMBER < 0x010600
+ if (gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread)) {
+ return -1;
+ }
+#endif
+
+ gcry_check_version(NULL);
+
+ if (gcry_control(GCRYCTL_INIT_SECMEM, 32768)) {
+ return -1;
+ }
+
+ gcry_control(GCRYCTL_INITIALIZATION_FINISHED);
+ return 0;
+}
+#endif
+
+typedef struct {
+ uint8_t *data;
+ size_t len;
+} buffer_t;
+
+static int buffer_next(buffer_t *b, void *out, size_t n) {
+ if (b->len < n) {
+ return -1;
+ }
+ memmove(out, b->data, n);
+
+ b->data += n;
+ b->len -= n;
+
+ return 0;
+}
+
+static int buffer_uint16(buffer_t *b, uint16_t *out) {
+ uint16_t tmp;
+ if (buffer_next(b, &tmp, sizeof(tmp)) != 0)
+ return -1;
+
+ *out = be16toh(tmp);
+ return 0;
+}
+
+#define TYPE_HOST 0x0000
+#define TYPE_TIME 0x0001
+#define TYPE_TIME_HR 0x0008
+#define TYPE_PLUGIN 0x0002
+#define TYPE_PLUGIN_INSTANCE 0x0003
+#define TYPE_TYPE 0x0004
+#define TYPE_TYPE_INSTANCE 0x0005
+#define TYPE_VALUES 0x0006
+#define TYPE_INTERVAL 0x0007
+#define TYPE_INTERVAL_HR 0x0009
+#define TYPE_SIGN_SHA256 0x0200
+#define TYPE_ENCR_AES256 0x0210
+
+static int parse_int(void *payload, size_t payload_size, uint64_t *out) {
+ uint64_t tmp;
+
+ if (payload_size != sizeof(tmp))
+ return EINVAL;
+
+ memmove(&tmp, payload, sizeof(tmp));
+ *out = be64toh(tmp);
+ return 0;
+}
+
+static int parse_string(void *payload, size_t payload_size, char *out,
+ size_t out_size) {
+ char *in = payload;
+
+ if ((payload_size < 1) || (in[payload_size - 1] != 0) ||
+ (payload_size > out_size))
+ return EINVAL;
+
+ strncpy(out, in, out_size);
+ return 0;
+}
+
+static int parse_identifier(uint16_t type, void *payload, size_t payload_size,
+ lcc_value_list_t *state) {
+ char buf[LCC_NAME_LEN];
+
+ if (parse_string(payload, payload_size, buf, sizeof(buf)) != 0)
+ return EINVAL;
+
+ switch (type) {
+ case TYPE_HOST:
+ memmove(state->identifier.host, buf, LCC_NAME_LEN);
+ break;
+ case TYPE_PLUGIN:
+ memmove(state->identifier.plugin, buf, LCC_NAME_LEN);
+ break;
+ case TYPE_PLUGIN_INSTANCE:
+ memmove(state->identifier.plugin_instance, buf, LCC_NAME_LEN);
+ break;
+ case TYPE_TYPE:
+ memmove(state->identifier.type, buf, LCC_NAME_LEN);
+ break;
+ case TYPE_TYPE_INSTANCE:
+ memmove(state->identifier.type_instance, buf, LCC_NAME_LEN);
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+static int parse_time(uint16_t type, void *payload, size_t payload_size,
+ lcc_value_list_t *state) {
+ uint64_t tmp = 0;
+ if (parse_int(payload, payload_size, &tmp))
+ return EINVAL;
+
+ double t = (double)tmp;
+ switch (type) {
+ case TYPE_INTERVAL:
+ state->interval = t;
+ break;
+ case TYPE_INTERVAL_HR:
+ state->interval = t / 1073741824.0;
+ break;
+ case TYPE_TIME:
+ state->time = t;
+ break;
+ case TYPE_TIME_HR:
+ state->time = t / 1073741824.0;
+ break;
+ default:
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+static double ntohd(double val) /* {{{ */
+{
+ static int config = 0;
+
+ union {
+ uint8_t byte[8];
+ double floating;
+ } in = {
+ .floating = val,
+ };
+ union {
+ uint8_t byte[8];
+ double floating;
+ } out = {
+ .byte = {0},
+ };
+
+ if (config == 0) {
+ double d = 8.642135e130;
+ uint8_t b[8];
+
+ memcpy(b, &d, sizeof(b));
+
+ if ((b[0] == 0x2f) && (b[1] == 0x25) && (b[2] == 0xc0) && (b[3] == 0xc7) &&
+ (b[4] == 0x43) && (b[5] == 0x2b) && (b[6] == 0x1f) && (b[7] == 0x5b))
+ config = 1; /* need nothing */
+ else if ((b[7] == 0x2f) && (b[6] == 0x25) && (b[5] == 0xc0) &&
+ (b[4] == 0xc7) && (b[3] == 0x43) && (b[2] == 0x2b) &&
+ (b[1] == 0x1f) && (b[0] == 0x5b))
+ config = 2; /* endian flip */
+ else if ((b[4] == 0x2f) && (b[5] == 0x25) && (b[6] == 0xc0) &&
+ (b[7] == 0xc7) && (b[0] == 0x43) && (b[1] == 0x2b) &&
+ (b[2] == 0x1f) && (b[3] == 0x5b))
+ config = 3; /* int swap */
+ else
+ config = 4;
+ }
+
+ if (memcmp((char[]){0, 0, 0, 0, 0, 0, 0xf8, 0x7f}, in.byte, 8) == 0) {
+ return NAN;
+ } else if (config == 1) {
+ return val;
+ } else if (config == 2) {
+ in.floating = val;
+ out.byte[0] = in.byte[7];
+ out.byte[1] = in.byte[6];
+ out.byte[2] = in.byte[5];
+ out.byte[3] = in.byte[4];
+ out.byte[4] = in.byte[3];
+ out.byte[5] = in.byte[2];
+ out.byte[6] = in.byte[1];
+ out.byte[7] = in.byte[0];
+ return (out.floating);
+ } else if (config == 3) {
+ in.floating = val;
+ out.byte[0] = in.byte[4];
+ out.byte[1] = in.byte[5];
+ out.byte[2] = in.byte[6];
+ out.byte[3] = in.byte[7];
+ out.byte[4] = in.byte[0];
+ out.byte[5] = in.byte[1];
+ out.byte[6] = in.byte[2];
+ out.byte[7] = in.byte[3];
+ return out.floating;
+ } else {
+ /* If in doubt, just copy the value back to the caller. */
+ return val;
+ }
+} /* }}} double ntohd */
+
+static int parse_values(void *payload, size_t payload_size,
+ lcc_value_list_t *state) {
+ buffer_t *b = &(buffer_t){
+ .data = payload, .len = payload_size,
+ };
+
+ uint16_t n;
+ if (buffer_uint16(b, &n))
+ return EINVAL;
+
+ if (((size_t)n * 9) != b->len)
+ return EINVAL;
+
+ state->values_len = (size_t)n;
+ state->values = calloc(sizeof(*state->values), state->values_len);
+ state->values_types = calloc(sizeof(*state->values_types), state->values_len);
+ if ((state->values == NULL) || (state->values_types == NULL)) {
+ free(state->values);
+ free(state->values_types);
+ return ENOMEM;
+ }
+
+ for (uint16_t i = 0; i < n; i++) {
+ uint8_t tmp;
+ if (buffer_next(b, &tmp, sizeof(tmp)))
+ return EINVAL;
+ state->values_types[i] = (int)tmp;
+ }
+
+ for (uint16_t i = 0; i < n; i++) {
+ uint64_t tmp;
+ if (buffer_next(b, &tmp, sizeof(tmp)))
+ return EINVAL;
+
+ if (state->values_types[i] == LCC_TYPE_GAUGE) {
+ union {
+ uint64_t i;
+ double d;
+ } conv = {.i = tmp};
+ state->values[i].gauge = ntohd(conv.d);
+ continue;
+ }
+
+ tmp = be64toh(tmp);
+ switch (state->values_types[i]) {
+ case LCC_TYPE_COUNTER:
+ state->values[i].counter = (counter_t)tmp;
+ break;
+ case LCC_TYPE_DERIVE:
+ state->values[i].derive = (derive_t)tmp;
+ break;
+ case LCC_TYPE_ABSOLUTE:
+ state->values[i].absolute = (absolute_t)tmp;
+ break;
+ default:
+ return EINVAL;
+ }
+ }
+
+ return 0;
+}
+
+#if HAVE_GCRYPT_H
+static int verify_sha256(void *payload, size_t payload_size,
+ char const *username, char const *password,
+ uint8_t hash_provided[32]) {
+ gcry_md_hd_t hd = NULL;
+
+ gcry_error_t err = gcry_md_open(&hd, GCRY_MD_SHA256, GCRY_MD_FLAG_HMAC);
+ if (err != 0) {
+ return (int)err;
+ }
+
+ err = gcry_md_setkey(hd, password, strlen(password));
+ if (err != 0) {
+ gcry_md_close(hd);
+ return (int)err;
+ }
+
+ gcry_md_write(hd, username, strlen(username));
+ gcry_md_write(hd, payload, payload_size);
+
+ unsigned char *hash_calculated = gcry_md_read(hd, GCRY_MD_SHA256);
+ if (!hash_calculated) {
+ gcry_md_close(hd);
+ return -1;
+ }
+
+ int ret = memcmp(hash_provided, hash_calculated, 32);
+
+ gcry_md_close(hd);
+ hash_calculated = NULL;
+
+ return !!ret;
+}
+#else /* !HAVE_GCRYPT_H */
+static int verify_sha256(void *payload, size_t payload_size,
+ char const *username, char const *password,
+ uint8_t hash_provided[32]) {
+ return ENOTSUP;
+}
+#endif
+
+static int parse_sign_sha256(void *signature, size_t signature_len,
+ void *payload, size_t payload_size,
+ lcc_network_parse_options_t const *opts) {
+ if (opts->password_lookup == NULL) {
+ /* The sender signed the packet but we can't verify it. Handle it as if it
+ * were unsigned, i.e. security level NONE. */
+ return network_parse(payload, payload_size, NONE, opts);
+ }
+
+ buffer_t *b = &(buffer_t){
+ .data = signature, .len = signature_len,
+ };
+
+ uint8_t hash[32];
+ if (buffer_next(b, hash, sizeof(hash)))
+ return EINVAL;
+
+ char username[b->len + 1];
+ memset(username, 0, sizeof(username));
+ if (buffer_next(b, username, sizeof(username) - 1)) {
+ return EINVAL;
+ }
+
+ char const *password = opts->password_lookup(username);
+ if (!password)
+ return network_parse(payload, payload_size, NONE, opts);
+
+ int status = verify_sha256(payload, payload_size, username, password, hash);
+ if (status != 0)
+ return status;
+
+ return network_parse(payload, payload_size, SIGN, opts);
+}
+
+#if HAVE_GCRYPT_H
+static int decrypt_aes256(buffer_t *b, void *iv, size_t iv_size,
+ char const *password) {
+ gcry_cipher_hd_t cipher = NULL;
+
+ if (gcry_cipher_open(&cipher, GCRY_CIPHER_AES256, GCRY_CIPHER_MODE_OFB,
+ /* flags = */ 0))
+ return -1;
+
+ uint8_t pwhash[32] = {0};
+ gcry_md_hash_buffer(GCRY_MD_SHA256, pwhash, password, strlen(password));
+
+ fprintf(stderr, "sizeof(iv) = %zu\n", sizeof(iv));
+ if (gcry_cipher_setkey(cipher, pwhash, sizeof(pwhash)) ||
+ gcry_cipher_setiv(cipher, iv, iv_size) ||
+ gcry_cipher_decrypt(cipher, b->data, b->len, /* in = */ NULL,
+ /* in_size = */ 0)) {
+ gcry_cipher_close(cipher);
+ return -1;
+ }
+
+ gcry_cipher_close(cipher);
+ return 0;
+}
+
+static int parse_encrypt_aes256(void *data, size_t data_size,
+ lcc_network_parse_options_t const *opts) {
+ if (opts->password_lookup == NULL) {
+ /* Without a password source it's (hopefully) impossible to decrypt the
+ * network packet. */
+ return ENOENT;
+ }
+
+ buffer_t *b = &(buffer_t){
+ .data = data, .len = data_size,
+ };
+
+ uint16_t username_len;
+ if (buffer_uint16(b, &username_len))
+ return EINVAL;
+ if ((size_t)username_len > data_size)
+ return ENOMEM;
+ char username[((size_t)username_len) + 1];
+ memset(username, 0, sizeof(username));
+ if (buffer_next(b, username, (size_t)username_len))
+ return EINVAL;
+
+ char const *password = opts->password_lookup(username);
+ if (!password)
+ return ENOENT;
+
+ uint8_t iv[16];
+ if (buffer_next(b, iv, sizeof(iv)))
+ return EINVAL;
+
+ int status = decrypt_aes256(b, iv, sizeof(iv), password);
+ if (status != 0)
+ return status;
+
+ uint8_t hash_provided[20];
+ if (buffer_next(b, hash_provided, sizeof(hash_provided))) {
+ return -1;
+ }
+
+ uint8_t hash_calculated[20];
+ gcry_md_hash_buffer(GCRY_MD_SHA1, hash_calculated, b->data, b->len);
+
+ if (memcmp(hash_provided, hash_calculated, sizeof(hash_provided)) != 0) {
+ return -1;
+ }
+
+ return network_parse(b->data, b->len, ENCRYPT, opts);
+}
+#else /* !HAVE_GCRYPT_H */
+static int parse_encrypt_aes256(void *data, size_t data_size,
+ lcc_network_parse_options_t const *opts) {
+ return ENOTSUP;
+}
+#endif
+
+static int network_parse(void *data, size_t data_size, lcc_security_level_t sl,
+ lcc_network_parse_options_t const *opts) {
+ buffer_t *b = &(buffer_t){
+ .data = data, .len = data_size,
+ };
+
+ lcc_value_list_t state = {0};
+
+ while (b->len > 0) {
+ uint16_t type = 0, sz = 0;
+ if (buffer_uint16(b, &type) || buffer_uint16(b, &sz)) {
+ DEBUG("lcc_network_parse(): reading type and/or length failed.\n");
+ return EINVAL;
+ }
+
+ if ((sz < 5) || (((size_t)sz - 4) > b->len)) {
+ DEBUG("lcc_network_parse(): invalid 'sz' field: sz = %" PRIu16
+ ", b->len = %zu\n",
+ sz, b->len);
+ return EINVAL;
+ }
+ sz -= 4;
+
+ uint8_t payload[sz];
+ if (buffer_next(b, payload, sizeof(payload)))
+ return EINVAL;
+
+ switch (type) {
+ case TYPE_HOST:
+ case TYPE_PLUGIN:
+ case TYPE_PLUGIN_INSTANCE:
+ case TYPE_TYPE:
+ case TYPE_TYPE_INSTANCE: {
+ if (parse_identifier(type, payload, sizeof(payload), &state)) {
+ DEBUG("lcc_network_parse(): parse_identifier failed.\n");
+ return EINVAL;
+ }
+ break;
+ }
+
+ case TYPE_INTERVAL:
+ case TYPE_INTERVAL_HR:
+ case TYPE_TIME:
+ case TYPE_TIME_HR: {
+ if (parse_time(type, payload, sizeof(payload), &state)) {
+ DEBUG("lcc_network_parse(): parse_time failed.\n");
+ return EINVAL;
+ }
+ break;
+ }
+
+ case TYPE_VALUES: {
+ lcc_value_list_t vl = state;
+ if (parse_values(payload, sizeof(payload), &vl)) {
+ DEBUG("lcc_network_parse(): parse_values failed.\n");
+ return EINVAL;
+ }
+
+ int status = 0;
+
+ /* Write metrics if they have the required security level. */
+ if (sl >= opts->security_level)
+ status = opts->writer(&vl);
+
+ free(vl.values);
+ free(vl.values_types);
+
+ if (status != 0)
+ return status;
+ break;
+ }
+
+ case TYPE_SIGN_SHA256: {
+ int status =
+ parse_sign_sha256(payload, sizeof(payload), b->data, b->len, opts);
+ if (status != 0) {
+ DEBUG("lcc_network_parse(): parse_sign_sha256() = %d\n", status);
+ return -1;
+ }
+ /* parse_sign_sha256, if successful, consumes all remaining data. */
+ b->data = NULL;
+ b->len = 0;
+ break;
+ }
+
+ case TYPE_ENCR_AES256: {
+ int status = parse_encrypt_aes256(payload, sizeof(payload), opts);
+ if (status != 0) {
+ DEBUG("lcc_network_parse(): parse_encrypt_aes256() = %d\n", status);
+ return -1;
+ }
+ break;
+ }
+
+ default: {
+ DEBUG("lcc_network_parse(): ignoring unknown type %" PRIu16 "\n", type);
+ return EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
+int lcc_network_parse(void *data, size_t data_size,
+ lcc_network_parse_options_t opts) {
+ if (opts.password_lookup) {
+#if HAVE_GCRYPT_H
+ int status;
+ if ((status = init_gcrypt())) {
+ return status;
+ }
+#else
+ return ENOTSUP;
+#endif
+ }
+
+ return network_parse(data, data_size, NONE, &opts);
+}
--- /dev/null
+/**
+ * Copyright 2017 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "collectd/lcc_features.h"
+
+#include "collectd/network_buffer.h" /* for LCC_NETWORK_BUFFER_SIZE_DEFAULT */
+
+#include <assert.h>
+
+#include "network_parse.c" /* sic */
+
+char *raw_packet_data[] = {
+ "0000000e6c6f63616c686f7374000008000c1513676ac3a6e0970009000c00000002800000"
+ "000002000973776170000004000973776170000005000966726565000006000f0001010000"
+ "0080ff610f420008000c1513676ac3a8fc120004000c737761705f696f0000050007696e00"
+ "0006000f00010200000000000000000008000c1513676ac3a9077d000500086f7574000006"
+ "000f00010200000000000000000008000c1513676ac3bd2a8c0002000e696e746572666163"
+ "65000003000965746830000004000e69665f6f637465747300000500050000060018000202"
+ "02000000000000000000000000000000000008000c1513676ac3bd5a970004000e69665f65"
+ "72726f7273000006001800020202000000000000000000000000000000000008000c151367"
+ "6ac3bd7fea000300076c6f000004000e69665f6f6374657473000006001800020202000000"
+ "000009e79c000000000009e79c0008000c1513676ac3bdaae60003000a776c616e30000006"
+ "001800020202000000001009fa5400000000011cf6670008000c1513676ac3bdb0e0000400"
+ "0e69665f6572726f7273000006001800020202000000000000000000000000000000000008"
+ "000c1513676ac3bd3d6d0003000965746830000004000f69665f7061636b65747300000600"
+ "1800020202000000000000000000000000000000000008000c1513676ac3bdae290003000a"
+ "776c616e300000060018000202020000000000032f8f00000000000205e50008000c151367"
+ "6ac3bdbb7b0003000c646f636b657230000006001800020202000000000000000000000000"
+ "000000000008000c1513676ac3bda0db000300076c6f000004000e69665f6572726f727300"
+ "0006001800020202000000000000000000000000000000000008000c1513676ac3bdbde800"
+ "03000c646f636b657230000006001800020202000000000000000000000000000000000008"
+ "000c1513676ac3bd8d8e000300076c6f000004000f69665f7061636b657473000006001800"
+ "0202020000000000000c9c0000000000000c9c0008000c1513676ac3bdb90b0003000c646f"
+ "636b657230000004000e69665f6f6374657473000006001800020202000000000000000000"
+ "000000000000000008000c1513676ac469b10f0002000e70726f6365737365730000030005"
+ "000004000d70735f7374617465000005000c7a6f6d62696573000006000f00010100000000"
+ "000000000008000c1513676ac469a4a30005000d736c656570696e67000006000f00010100"
+ "00000000006e400008000c1513676ac469c6320005000b706167696e67000006000f000101"
+ "00000000000000000008000c1513676ac469f06e0005000c626c6f636b6564000006000f00"
+ "010100000000000000000008000c1513676ac4698af40005000c72756e6e696e6700000600"
+ "0f00010100000000000000000008000c1513676ac469bbe10005000c73746f707065640000"
+ "06000f00010100000000000000000008000c1513676ac46b8e710004000e666f726b5f7261"
+ "74650000050005000006000f0001020000000000001bcf0008000c1513676d437f12960002"
+ "00086370750000030006300000040008637075000005000b73797374656d000006000f0001"
+ "0200000000000021870008000c1513676d437f36020005000969646c65000006000f000102"
+ "000000000005847a0008000c1513676d437f979b0005000977616974000006000f00010200"
+ "000000000005210008000c1513676d43802ff60005000c736f6674697271000006000f0001"
+ "02000000000000001f0008000c1513676d43803b3a0005000a737465616c000006000f0001"
+ "020000000000000000",
+ "0000000e6c6f63616c686f7374000008000c1513676d4380551f0009000c00000002800000"
+ "00000200086370750000030006310000040008637075000005000975736572000006000f00"
+ "01020000000000007cad0008000c1513676d43805dbe000500096e696365000006000f0001"
+ "0200000000000001de0008000c1513676d4380697d0005000b73797374656d000006000f00"
+ "01020000000000001ce80008000c1513676d438072bd0005000969646c65000006000f0001"
+ "02000000000005931c0008000c1513676d43807c430005000977616974000006000f000102"
+ "000000000000094b0008000c1513676d43808cee0005000c736f6674697271000006000f00"
+ "010200000000000000120008000c1513676d4380843a0005000e696e746572727570740000"
+ "06000f00010200000000000000000008000c1513676d438096230005000a737465616c0000"
+ "06000f00010200000000000000000008000c1513676d4380aa9c0003000632000005000975"
+ "736572000006000f00010200000000000089580008000c1513676d4380b29f000500096e69"
+ "6365000006000f00010200000000000003610008000c1513676d4380c44c0005000969646c"
+ "65000006000f000102000000000005873d0008000c1513676d4380bc0f0005000b73797374"
+ "656d000006000f000102000000000000201d0008000c1513676d4380cea400050009776169"
+ "74000006000f00010200000000000005810008000c1513676d4380d7370005000e696e7465"
+ "7272757074000006000f00010200000000000000000008000c1513676d4380ea830005000a"
+ "737465616c000006000f00010200000000000000000008000c1513676d437eef6200030006"
+ "3000000500096e696365000006000f00010200000000000003920008000c1513676d4380e0"
+ "260003000632000005000c736f6674697271000006000f0001020000000000000016000800"
+ "0c1513676d438101410003000633000005000975736572000006000f000102000000000000"
+ "7d8a0008000c1513676d438109f5000500096e696365000006000f00010200000000000004"
+ "350008000c1513676d4380244b0003000630000005000e696e74657272757074000006000f"
+ "00010200000000000000000008000c1513676d438122070003000633000005000969646c65"
+ "000006000f0001020000000000058eb60008000c1513676d43812e83000500097761697400"
+ "0006000f0001020000000000000ca80008000c1513676d438141480005000c736f66746972"
+ "71000006000f000102000000000000001e0008000c1513676d43814a5d0005000a73746561"
+ "6c000006000f00010200000000000000000008000c1513676d4381149e0005000b73797374"
+ "656d000006000f0001020000000000001b9a0008000c1513676d437ea86000030006300000"
+ "05000975736572000006000f00010200000000000089a80008000c1513676d438138190003"
+ "000633000005000e696e74657272757074000006000f00010200000000000000000008000c"
+ "1513676d438a9ca00002000e696e74657266616365000003000965746830000004000e6966"
+ "5f6f6374657473000005000500000600180002020200000000000000000000000000000000"
+ "0008000c1513676d438aea760004000f69665f7061636b6574730000060018000202020000"
+ "00000000000000000000000000000008000c1513676d438b214d0004000e69665f6572726f"
+ "727300000600180002020200000000000000000000000000000000",
+ "0000000e6c6f63616c686f7374000008000c1513676d438aac590009000c00000002800000"
+ "000002000764660000030009726f6f74000004000f64665f636f6d706c6578000005000966"
+ "726565000006000f0001010000004c077e57420008000c1513676d438b6ada0005000d7265"
+ "736572766564000006000f00010100000000338116420008000c1513676d438b7a17000200"
+ "0e696e7465726661636500000300076c6f000004000e69665f6f6374657473000005000500"
+ "0006001800020202000000000009ecf5000000000009ecf50008000c1513676d438b757800"
+ "02000764660000030009726f6f74000004000f64665f636f6d706c65780000050009757365"
+ "64000006000f000101000000e0a41b26420008000c1513676d438b8ed20002000e696e7465"
+ "726661636500000300076c6f000004000e69665f6572726f72730000050005000006001800"
+ "020202000000000000000000000000000000000008000c1513676d438b86bf0004000f6966"
+ "5f7061636b6574730000060018000202020000000000000c9d0000000000000c9d0008000c"
+ "1513676d438bb3e60003000a776c616e300000060018000202020000000000032fab000000"
+ "00000205ed0008000c1513676d438bd62e0003000c646f636b657230000004000e69665f6f"
+ "6374657473000006001800020202000000000000000000000000000000000008000c151367"
+ "6d438bbc8f0003000a776c616e30000004000e69665f6572726f7273000006001800020202"
+ "000000000000000000000000000000000008000c1513676d438bdf030003000c646f636b65"
+ "7230000004000f69665f7061636b6574730000060018000202020000000000000000000000"
+ "00000000000008000c1513676d438baaf10003000a776c616e30000004000e69665f6f6374"
+ "65747300000600180002020200000000100a042300000000011cfa460008000c1513676d43"
+ "8c5f100002000764660000030009626f6f74000004000f64665f636f6d706c657800000500"
+ "0966726565000006000f0001010000000010e198410008000c1513676d438c689c0005000d"
+ "7265736572766564000006000f00010100000000804c68410008000c1513676d438c70ce00"
+ "05000975736564000006000f0001010000000020ea9e410008000c1513676d438be7bc0002"
+ "000e696e74657266616365000003000c646f636b657230000004000e69665f6572726f7273"
+ "0000050005000006001800020202000000000000000000000000000000000008000c151367"
+ "6d43beca8c0002000c656e74726f70790000030005000004000c656e74726f707900000600"
+ "0f0001010000000000088f400008000c1513676d43bf1d13000200096c6f61640000040009"
+ "6c6f6164000006002100030101019a9999999999a93f666666666666d63f5c8fc2f5285cdf"
+ "3f0008000c1513676d43c02b85000200096469736b00000300087364610000040010646973"
+ "6b5f6f63746574730000060018000202020000000075887800000000005b6f3c000008000c"
+ "1513676d43c06d1f0004000d6469736b5f6f7073000006001800020202000000000003cbbd"
+ "000000000001c0510008000c1513676d43c08b6a0004000e6469736b5f74696d6500000600"
+ "1800020202000000000000003f00000000000001720008000c1513676d43c0a5fb00040010"
+ "6469736b5f6d65726765640000060018000202020000000000001285000000000000f80100"
+ "08000c1513676d43c0c8b4000300097364613100000400106469736b5f6f63746574730000"
+ "060018000202020000000001107c000000000000003c00",
+ "0000000e6c6f63616c686f7374000008000c1513676d43c0d00a0009000c00000002800000"
+ "00000200096469736b000003000973646131000004000d6469736b5f6f7073000006001800"
+ "020202000000000000029b00000000000000080008000c1513676d43c0d7b20004000e6469"
+ "736b5f74696d650000060018000202020000000000000004000000000000000f0008000c15"
+ "13676d43c0df73000400106469736b5f6d6572676564000006001800020202000000000000"
+ "0fb400000000000000010008000c1513676d43c0f87c000300097364613200000400106469"
+ "736b5f6f637465747300000600180002020200000000000008000000000000000000000800"
+ "0c1513676d43c1003e0004000d6469736b5f6f707300000600180002020200000000000000"
+ "0200000000000000000008000c1513676d43c107bf000400106469736b5f6d657267656400"
+ "0006001800020202000000000000000000000000000000000008000c1513676d43c12fa400"
+ "03000973646135000004000d6469736b5f6f7073000006001800020202000000000003c867"
+ "000000000001aef20008000c1513676d43c13d5e000400106469736b5f6d65726765640000"
+ "0600180002020200000000000002d1000000000000f8000008000c1513676d43c136a90004"
+ "000e6469736b5f74696d65000006001800020202000000000000003f000000000000011c00"
+ "08000c1513676d43c1740500030009646d2d3000000400106469736b5f6f63746574730000"
+ "060018000202020000000074596400000000005b6f00000008000c1513676d43c179c70004"
+ "000d6469736b5f6f7073000006001800020202000000000003cae4000000000002b0f30008"
+ "000c1513676d43c18abe000400106469736b5f6d6572676564000006001800020202000000"
+ "000000000000000000000000000008000c1513676d43c181b90004000e6469736b5f74696d"
+ "650000060018000202020000000000000040000000000000013e0008000c1513676d43c1a9"
+ "5e00030009646d2d3100000400106469736b5f6f6374657473000006001800020202000000"
+ "00000e000000000000000000000008000c1513676d43c1b7ea0004000e6469736b5f74696d"
+ "65000006001800020202000000000000000200000000000000000008000c1513676d43c1b0"
+ "3e0004000d6469736b5f6f707300000600180002020200000000000000e000000000000000"
+ "000008000c1513676d43c1c00d000400106469736b5f6d6572676564000006001800020202"
+ "000000000000000000000000000000000008000c1513676d43c12818000300097364613500"
+ "000400106469736b5f6f637465747300000600180002020200000000746c6400000000005b"
+ "6f00000008000c1513676d43d320a80002000c62617474657279000003000630000004000b"
+ "636861726765000006000f0001018fc2f5285c2f58400008000c1513676d43d36fd6000400"
+ "0c63757272656e74000006000f00010100000000000000800008000c1513676d43d3cdb600"
+ "04000c766f6c74616765000006000f000101736891ed7cbf28400008000c1513676d43d59d"
+ "d60002000869727100000300050000040008697271000005000630000006000f0001020000"
+ "0000000000110008000c1513676d43d5d2cf0005000631000006000f000102000000000000"
+ "00100008000c1513676d43d5fe820005000638000006000f00010200000000000000010008"
+ "000c1513676d43d635440005000639000006000f00010200000000000035210008000c1513"
+ "676d43d66265000500073132000006000f0001020000000000000790",
+ "0000000e6c6f63616c686f7374000008000c1513676d43d68e940009000c00000002800000"
+ "0000020008697271000004000869727100000500073136000006000f000102000000000000"
+ "00210008000c1513676d43d69be20002000a7573657273000004000a757365727300000500"
+ "05000006000f00010100000000000010400008000c1513676d43d6aa5d0002000869727100"
+ "0004000869727100000500073233000006000f00010200000000000000250008000c151367"
+ "6d43d6c7dc000500073431000006000f000102000000000000ff7d0008000c1513676d43d6"
+ "e23d000500073432000006000f00010200000000000008070008000c1513676d43d9aa3a00"
+ "0500073437000006000f0001020000000000079a260008000c1513676d43d9cca900050007"
+ "3438000006000f00010200000000000000c70008000c1513676d43d9ea5d00050007343900"
+ "0006000f00010200000000000004c20008000c1513676d43da050e00050007353000000600"
+ "0f000102000000000000001c0008000c1513676d43da1efa000500084e4d49000006000f00"
+ "010200000000000000000008000c1513676d43da3c82000500084c4f43000006000f000102"
+ "000000000018d3080008000c1513676d43da544e00050008535055000006000f0001020000"
+ "0000000000000008000c1513676d43da6cca00050008504d49000006000f00010200000000"
+ "000000000008000c1513676d43da885400050008495749000006000f000102000000000000"
+ "a9da0008000c1513676d43daa23a00050008525452000006000f0001020000000000000003"
+ "0008000c1513676d43dabaed00050008524553000006000f00010200000000000ac8360008"
+ "000c1513676d43dad4150005000843414c000006000f000102000000000000191f0008000c"
+ "1513676d43daeef300050008544c42000006000f000102000000000003dbdc0008000c1513"
+ "676d43db11410005000854524d000006000f00010200000000000000000008000c1513676d"
+ "43db292c00050008544852000006000f00010200000000000000000008000c1513676d43db"
+ "411d000500084d4345000006000f00010200000000000000000008000c1513676d43db5b59"
+ "000500084d4350000006000f000102000000000000003c0008000c1513676d43db68010005"
+ "0008455252000006000f00010200000000000000000008000c1513676d43db758a00050008"
+ "4d4953000006000f00010200000000000000000008000c1513676d43dd2e800002000b6d65"
+ "6d6f7279000004000b6d656d6f7279000005000975736564000006000f00010100000000fe"
+ "bbe0410008000c1513676d43dd3f4b0005000d6275666665726564000006000f0001010000"
+ "000070fbc8410008000c1513676d43dd48700005000b636163686564000006000f00010100"
+ "000000c008df410008000c1513676d43dd51c60005000966726565000006000f0001010000"
+ "0080481d05420008000c1513676d43dec7e300020009737761700000040009737761700000"
+ "05000975736564000006000f00010100000000000000000008000c1513676d43ded4490005"
+ "000966726565000006000f00010100000080ff610f420008000c1513676d43dedcfd000500"
+ "0b636163686564000006000f00010100000000000000000008000c1513676d43d715e30002"
+ "0008697271000004000869727100000500073434000006000f0001020000000000031b6100"
+ "08000c1513676d43d73116000500073435000006000f00010200000000000000180008000c"
+ "1513676d43ee00150002000973776170000004000c737761705f696f0000050007696e0000"
+ "06000f0001020000000000000000",
+};
+
+static int decode_string(char const *in, uint8_t *out, size_t *out_size) {
+ size_t in_size = strlen(in);
+ if (*out_size < (in_size / 2))
+ return -1;
+ *out_size = in_size / 2;
+
+ for (size_t i = 0; i < *out_size; i++) {
+ char tmp[] = {in[2 * i], in[2 * i + 1], 0};
+ out[i] = (uint8_t)strtoul(tmp, NULL, 16);
+ }
+
+ return 0;
+}
+
+static int nop_writer(lcc_value_list_t const *vl) {
+ if (!strlen(vl->identifier.host) || !strlen(vl->identifier.plugin) ||
+ !strlen(vl->identifier.type)) {
+ return EINVAL;
+ }
+ return 0;
+}
+
+static int test_network_parse() {
+ int ret = 0;
+
+ for (size_t i = 0; i < sizeof(raw_packet_data) / sizeof(raw_packet_data[0]);
+ i++) {
+ uint8_t buffer[LCC_NETWORK_BUFFER_SIZE_DEFAULT];
+ size_t buffer_size = sizeof(buffer);
+ if (decode_string(raw_packet_data[i], buffer, &buffer_size)) {
+ fprintf(
+ stderr,
+ "lcc_network_parse(raw_packet_data[%zu]): decoding string failed\n",
+ i);
+ return -1;
+ }
+
+ int status =
+ lcc_network_parse(buffer, buffer_size, (lcc_network_parse_options_t){
+ .writer = nop_writer,
+ });
+ if (status != 0) {
+ fprintf(stderr, "lcc_network_parse(raw_packet_data[%zu]) = %d, want 0\n",
+ i, status);
+ ret = status;
+ }
+
+ printf("ok - lcc_network_parse(raw_packet_data[%zu])\n", i);
+ }
+
+ return ret;
+}
+
+static int test_parse_time() {
+ int ret = 0;
+
+ struct {
+ uint64_t in;
+ double want;
+ } cases[] = {
+ {1439980823, 1439980823.0},
+ {1439981005, 1439981005.0},
+ {1439981150, 1439981150.0},
+ };
+
+ for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
+ lcc_value_list_t vl = LCC_VALUE_LIST_INIT;
+
+ uint64_t be = htobe64(cases[i].in);
+ int status = parse_time(TYPE_TIME, &be, sizeof(be), &vl);
+ if ((status != 0) || (vl.time != cases[i].want)) {
+ fprintf(stderr, "parse_time(%" PRIu64 ") = (%.0f, %d), want (%.0f, 0)\n",
+ cases[i].in, vl.time, status, cases[i].want);
+ ret = -1;
+ }
+ }
+
+ struct {
+ uint64_t in;
+ double want;
+ } cases_hr[] = {
+ {1546167635576736987, 1439980823.152453627},
+ {1546167831554815222, 1439981005.671262017},
+ {1546167986577716567, 1439981150.047589622},
+ };
+
+ for (size_t i = 0; i < sizeof(cases_hr) / sizeof(cases_hr[0]); i++) {
+ lcc_value_list_t vl = LCC_VALUE_LIST_INIT;
+
+ uint64_t be = htobe64(cases_hr[i].in);
+ int status = parse_time(TYPE_TIME_HR, &be, sizeof(be), &vl);
+ if ((status != 0) || (vl.time != cases_hr[i].want)) {
+ fprintf(stderr, "parse_time(%" PRIu64 ") = (%.9f, %d), want (%.9f, 0)\n",
+ cases_hr[i].in, vl.time, status, cases_hr[i].want);
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
+
+static int test_parse_string() {
+ int ret = 0;
+
+ struct {
+ uint8_t *in;
+ size_t in_len;
+ char *want;
+ } cases[] = {
+ {(uint8_t[]){0}, 1, ""},
+ {(uint8_t[]){'t', 'e', 's', 't', 0}, 5, "test"},
+ {(uint8_t[]){'t', 'e', 's', 't'}, 4, NULL}, // null byte missing
+ {(uint8_t[]){'t', 'e', 's', 't', 'x', 0}, 6,
+ NULL}, // output buffer too small
+ };
+
+ for (size_t i = 0; i < sizeof(cases) / sizeof(cases[0]); i++) {
+ char got[5] = {0};
+
+ int status = parse_string(cases[i].in, cases[i].in_len, got, sizeof(got));
+ if (cases[i].want == NULL) {
+ if (status == 0) {
+ fprintf(stderr, "parse_string() = (\"%s\", 0), want error\n", got);
+ ret = -1;
+ }
+ } else /* if cases[i].want != NULL */ {
+ if (status != 0) {
+ fprintf(stderr, "parse_string() = %d, want 0\n", status);
+ ret = -1;
+ } else if (strcmp(got, cases[i].want) != 0) {
+ fprintf(stderr, "parse_string() = (\"%s\", 0), want (\"%s\", 0)\n", got,
+ cases[i].want);
+ ret = -1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+static int test_parse_values() {
+ int ret = 0;
+
+ uint8_t testcase[] = {
+ // 0, 6, // pkg type
+ // 0, 33, // pkg len
+ 0, 3, // num values
+ 1, 2, 1, // gauge, derive, gauge
+ 0, 0, 0, 0, 0, 0, 0x45, 0x40, // 42.0
+ 0, 0, 0, 0, 0, 0, 0x7a, 0x69, // 31337
+ 0, 0, 0, 0, 0, 0, 0xf8, 0x7f, // NaN
+ };
+
+ lcc_value_list_t vl = LCC_VALUE_LIST_INIT;
+ int status = parse_values(testcase, sizeof(testcase), &vl);
+ if (status != 0) {
+ fprintf(stderr, "parse_values() = %d, want 0\n", status);
+ return -1;
+ }
+
+ if (vl.values_len != 3) {
+ fprintf(stderr, "parse_values(): vl.values_len = %zu, want 3\n",
+ vl.values_len);
+ return -1;
+ }
+
+ int want_types[] = {LCC_TYPE_GAUGE, LCC_TYPE_DERIVE, LCC_TYPE_GAUGE};
+ for (size_t i = 0; i < sizeof(want_types) / sizeof(want_types[0]); i++) {
+ if (vl.values_types[i] != want_types[i]) {
+ fprintf(stderr, "parse_values(): vl.values_types[%zu] = %d, want %d\n", i,
+ vl.values_types[i], want_types[i]);
+ ret = -1;
+ }
+ }
+
+ if (vl.values[0].gauge != 42.0) {
+ fprintf(stderr, "parse_values(): vl.values[0] = %g, want 42\n",
+ vl.values[0].gauge);
+ ret = -1;
+ }
+ if (vl.values[1].derive != 31337) {
+ fprintf(stderr, "parse_values(): vl.values[1] = %" PRIu64 ", want 31337\n",
+ vl.values[1].derive);
+ ret = -1;
+ }
+ if (!isnan(vl.values[2].gauge)) {
+ fprintf(stderr, "parse_values(): vl.values[2] = %g, want NaN\n",
+ vl.values[2].gauge);
+ ret = -1;
+ }
+
+ free(vl.values);
+ free(vl.values_types);
+
+ return ret;
+}
+
+static int test_verify_sha256() {
+ int ret = 0;
+
+ int status = verify_sha256(
+ (char[]){'c', 'o', 'l', 'l', 'e', 'c', 't', 'd'}, 8, "admin", "admin",
+ (uint8_t[]){
+ 0xcd, 0xa5, 0x9a, 0x37, 0xb0, 0x81, 0xc2, 0x31, 0x24, 0x2a, 0x6d,
+ 0xbd, 0xfb, 0x44, 0xdb, 0xd7, 0x41, 0x2a, 0xf4, 0x29, 0x83, 0xde,
+ 0xa5, 0x11, 0x96, 0xd2, 0xe9, 0x30, 0x21, 0xae, 0xc5, 0x45,
+ });
+ if (status != 0) {
+ fprintf(stderr, "verify_sha256() = %d, want 0\n", status);
+ ret = -1;
+ }
+
+ status = verify_sha256(
+ (char[]){'c', 'o', 'l', 'l', 'E', 'c', 't', 'd'}, 8, "admin", "admin",
+ (uint8_t[]){
+ 0xcd, 0xa5, 0x9a, 0x37, 0xb0, 0x81, 0xc2, 0x31, 0x24, 0x2a, 0x6d,
+ 0xbd, 0xfb, 0x44, 0xdb, 0xd7, 0x41, 0x2a, 0xf4, 0x29, 0x83, 0xde,
+ 0xa5, 0x11, 0x96, 0xd2, 0xe9, 0x30, 0x21, 0xae, 0xc5, 0x45,
+ });
+ if (status != 1) {
+ fprintf(stderr, "verify_sha256() = %d, want 1\n", status);
+ ret = -1;
+ }
+
+ return ret;
+}
+
+static int test_decrypt_aes256() {
+ char const *iv_str = "4cbe2a747c9f9dcfa0e66f0c2fa74875";
+ uint8_t iv[16] = {0};
+ size_t iv_len = sizeof(iv);
+
+ char const *ciphertext_str =
+ "8f023b0b15178f8428da1221a5f653e840f065db4aff032c22e5a3df";
+ uint8_t ciphertext[28] = {0};
+ size_t ciphertext_len = sizeof(ciphertext);
+
+ if (decode_string(iv_str, iv, &iv_len) ||
+ decode_string(ciphertext_str, ciphertext, &ciphertext_len)) {
+ fprintf(stderr, "test_decrypt_aes256: decode_string failed.\n");
+ return -1;
+ }
+ assert(iv_len == sizeof(iv));
+ assert(ciphertext_len == sizeof(ciphertext));
+
+ int status = decrypt_aes256(
+ &(buffer_t){
+ .data = ciphertext, .len = ciphertext_len,
+ },
+ iv, iv_len, "admin");
+ if (status != 0) {
+ fprintf(stderr, "decrypt_aes256() = %d, want 0\n", status);
+ return -1;
+ }
+
+ char const *want = "collectd";
+ char got[9] = {0};
+ memmove(got, &ciphertext[20], sizeof(got) - 1);
+ if (strcmp(got, want) != 0) {
+ fprintf(stderr, "decrypt_aes256() = \"%s\", want \"%s\"\n", got, want);
+ return -1;
+ }
+
+ return 0;
+}
+
+int main(void) {
+ int ret = 0;
+
+ printf("libcollectdclient/server_test.c\n");
+
+ int status;
+ if ((status = test_network_parse())) {
+ ret = status;
+ }
+ if ((status = test_parse_time())) {
+ ret = status;
+ }
+ if ((status = test_parse_string())) {
+ ret = status;
+ }
+ if ((status = test_parse_values())) {
+ ret = status;
+ }
+
+ if ((status = test_verify_sha256())) {
+ ret = status;
+ }
+ if ((status = test_decrypt_aes256())) {
+ ret = status;
+ }
+
+ return ret;
+}
--- /dev/null
+/**
+ * Copyright 2017 Florian Forster
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ * Authors:
+ * Florian octo Forster <octo at collectd.org>
+ **/
+
+#include "config.h"
+
+#if !defined(__GNUC__) || !__GNUC__
+#define __attribute__(x) /**/
+#endif
+
+#include "collectd/lcc_features.h"
+#include "collectd/network_parse.h" /* for lcc_network_parse_options_t */
+#include "collectd/server.h"
+
+#include <errno.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <stdio.h>
+#define DEBUG(...) printf(__VA_ARGS__)
+
+static _Bool is_multicast(struct addrinfo const *ai) {
+ if (ai->ai_family == AF_INET) {
+ struct sockaddr_in *addr = (struct sockaddr_in *)ai->ai_addr;
+ return IN_MULTICAST(ntohl(addr->sin_addr.s_addr));
+ } else if (ai->ai_family == AF_INET6) {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *)ai->ai_addr;
+ return IN6_IS_ADDR_MULTICAST(&addr->sin6_addr);
+ }
+ return 0;
+}
+
+static int server_multicast_join(lcc_listener_t *srv,
+ struct sockaddr_storage *group, int loop_back,
+ int ttl) {
+ if (group->ss_family == AF_INET) {
+ struct sockaddr_in *sa = (struct sockaddr_in *)group;
+
+ int status = setsockopt(srv->conn, IPPROTO_IP, IP_MULTICAST_LOOP,
+ &loop_back, sizeof(loop_back));
+ if (status == -1) {
+ DEBUG("setsockopt(IP_MULTICAST_LOOP, %d) = %d\n", loop_back, errno);
+ return errno;
+ }
+
+ status =
+ setsockopt(srv->conn, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl));
+ if (status == -1)
+ return errno;
+
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+ struct ip_mreqn mreq = {
+ .imr_address.s_addr = INADDR_ANY,
+ .imr_multiaddr.s_addr = sa->sin_addr.s_addr,
+ .imr_ifindex = if_nametoindex(srv->interface),
+ };
+#else
+ struct ip_mreq mreq = {
+ .imr_address.s_addr = INADDR_ANY, .imr_multiaddr.s_addr = sa->s_addr,
+ };
+#endif
+ status = setsockopt(srv->conn, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq,
+ sizeof(mreq));
+ if (status == -1)
+ return errno;
+ } else if (group->ss_family == AF_INET6) {
+ struct sockaddr_in6 *sa = (struct sockaddr_in6 *)group;
+
+ int status = setsockopt(srv->conn, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
+ &loop_back, sizeof(loop_back));
+ if (status == -1)
+ return errno;
+
+ status = setsockopt(srv->conn, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl,
+ sizeof(ttl));
+ if (status == -1)
+ return errno;
+
+ struct ipv6_mreq mreq6 = {
+ .ipv6mr_interface = if_nametoindex(srv->interface),
+ };
+ memmove(&mreq6.ipv6mr_multiaddr, &sa->sin6_addr, sizeof(struct in6_addr));
+
+ status = setsockopt(srv->conn, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq6,
+ sizeof(mreq6));
+ if (status == -1)
+ return errno;
+ } else {
+ return EINVAL;
+ }
+
+ return 0;
+}
+
+static int server_bind_socket(lcc_listener_t *srv, struct addrinfo const *ai) {
+ /* allow multiple sockets to use the same PORT number */
+ if (setsockopt(srv->conn, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) ==
+ -1) {
+ return errno;
+ }
+
+ if (bind(srv->conn, ai->ai_addr, ai->ai_addrlen) == -1) {
+ return -1;
+ }
+
+ if (is_multicast(ai)) {
+ int status = server_multicast_join(srv, (void *)ai->ai_addr, /* loop = */ 1,
+ /* ttl = */ 16);
+ if (status != 0)
+ return status;
+ }
+
+ return 0;
+}
+
+static int server_open(lcc_listener_t *srv) {
+ struct addrinfo *res = NULL;
+ int status = getaddrinfo(srv->node ? srv->node : "::",
+ srv->service ? srv->service : LCC_DEFAULT_PORT,
+ &(struct addrinfo){
+ .ai_flags = AI_ADDRCONFIG,
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM,
+ },
+ &res);
+ if (status != 0)
+ return status;
+
+ for (struct addrinfo *ai = res; ai != NULL; ai = ai->ai_next) {
+ srv->conn = socket(ai->ai_family, ai->ai_socktype, 0);
+ if (srv->conn == -1)
+ continue;
+
+ status = server_bind_socket(srv, ai);
+ if (status != 0) {
+ close(srv->conn);
+ srv->conn = -1;
+ continue;
+ }
+
+ break;
+ }
+
+ freeaddrinfo(res);
+
+ if (srv->conn >= 0)
+ return 0;
+ return status != 0 ? status : -1;
+}
+
+int lcc_listen_and_write(lcc_listener_t srv) {
+ _Bool close_socket = 0;
+
+ if (srv.conn < 0) {
+ int status = server_open(&srv);
+ if (status != 0)
+ return status;
+ close_socket = 1;
+ }
+
+ if (srv.buffer_size == 0)
+ srv.buffer_size = LCC_NETWORK_BUFFER_SIZE;
+
+ if (srv.parser == NULL)
+ srv.parser = lcc_network_parse;
+
+ int ret = 0;
+ while (42) {
+ char buffer[srv.buffer_size];
+ ssize_t len = recv(srv.conn, buffer, sizeof(buffer), /* flags = */ 0);
+ if (len == -1) {
+ ret = errno;
+ break;
+ } else if (len == 0) {
+ break;
+ }
+
+ (void)srv.parser(buffer, (size_t)len, srv.parse_options);
+ }
+
+ if (close_socket) {
+ close(srv.conn);
+ srv.conn = -1;
+ }
+
+ return ret;
+}
int buf_len = sizeof(buf);
int status;
- status = ssnprintf(
+ status = snprintf(
buf_ptr, buf_len, "Notification: severity = %s",
(n->severity == NOTIF_FAILURE)
? "FAILURE"
#define APPEND(bufptr, buflen, key, value) \
if ((buflen > 0) && (strlen(value) > 0)) { \
- status = ssnprintf(bufptr, buflen, ", %s = %s", key, value); \
+ status = snprintf(bufptr, buflen, ", %s = %s", key, value); \
if (status > 0) { \
bufptr += status; \
buflen -= status; \
if (pool_busy_cpus < 0.0)
pool_busy_cpus = 0.0;
- ssnprintf(typinst, sizeof(typinst), "pool-%X-busy", lparstats.pool_id);
+ snprintf(typinst, sizeof(typinst), "pool-%X-busy", lparstats.pool_id);
lpar_submit(typinst, pool_busy_cpus);
- ssnprintf(typinst, sizeof(typinst), "pool-%X-idle", lparstats.pool_id);
+ snprintf(typinst, sizeof(typinst), "pool-%X-idle", lparstats.pool_id);
lpar_submit(typinst, pool_idle_cpus);
}
luaL_checktype(L, 1, LUA_TFUNCTION);
char function_name[DATA_MAX_NAME_LEN];
- ssnprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1));
+ snprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1));
int callback_id = clua_store_callback(L, 1);
if (callback_id < 0)
int status = plugin_register_complex_read(/* group = */ "lua",
/* name = */ function_name,
/* callback = */ clua_read,
- /* interval = */ 0, &(user_data_t){
- .data = cb,
- });
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = cb,
+ });
if (status != 0)
return luaL_error(L, "%s", "plugin_register_complex_read failed");
luaL_checktype(L, 1, LUA_TFUNCTION);
char function_name[DATA_MAX_NAME_LEN] = "";
- ssnprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1));
+ snprintf(function_name, sizeof(function_name), "lua/%s", lua_tostring(L, 1));
int callback_id = clua_store_callback(L, 1);
if (callback_id < 0)
cb->lua_function_name = strdup(function_name);
pthread_mutex_init(&cb->lock, NULL);
- int status =
- plugin_register_write(/* name = */ function_name,
- /* callback = */ clua_write, &(user_data_t){
- .data = cb,
- });
+ int status = plugin_register_write(/* name = */ function_name,
+ /* callback = */ clua_write,
+ &(user_data_t){
+ .data = cb,
+ });
if (status != 0)
return luaL_error(L, "%s", "plugin_register_write failed");
if (base_path[0] == '\0')
sstrncpy(abs_path, rel_path, sizeof(abs_path));
else
- ssnprintf(abs_path, sizeof(abs_path), "%s/%s", base_path, rel_path);
+ snprintf(abs_path, sizeof(abs_path), "%s/%s", base_path, rel_path);
DEBUG("Lua plugin: abs_path = \"%s\";", abs_path);
return;
used_bytes = lv_size * (used_percent_unscaled * PERCENT_SCALE_FACTOR);
- ssnprintf(plugin_instance, sizeof(plugin_instance), "%s-%s", vg_name,
- lv_name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "%s-%s", vg_name, lv_name);
lvm_submit(plugin_instance, "used", used_bytes);
lvm_submit(plugin_instance, "free", lv_size - used_bytes);
}
sstrncpy(vl.type, type, sizeof(vl.type));
if ((ti1 != NULL) && (ti2 != NULL))
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s", ti1, ti2);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s", ti1, ti2);
else if ((ti1 != NULL) && (ti2 == NULL))
sstrncpy(vl.type_instance, ti1, sizeof(vl.type_instance));
if (vals[i] == 0)
continue;
- ssnprintf(ti2, sizeof(ti2), "%i", i);
+ snprintf(ti2, sizeof(ti2), "%i", i);
submit_derive(dev, "ath_stat", name, ti2, (derive_t)vals[i]);
}
}
static inline void macaddr_to_str(char *buf, size_t bufsize,
const uint8_t mac[IEEE80211_ADDR_LEN]) {
- ssnprintf(buf, bufsize, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1],
- mac[2], mac[3], mac[4], mac[5]);
+ snprintf(buf, bufsize, "%02x:%02x:%02x:%02x:%02x:%02x", mac[0], mac[1],
+ mac[2], mac[3], mac[4], mac[5]);
}
static void process_stat_struct(int which, const void *ptr, const char *dev,
if (dev[0] == '.')
return 0;
- ssnprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver", dev);
+ snprintf(buf, sizeof(buf), "/sys/class/net/%s/device/driver", dev);
buf[sizeof(buf) - 1] = '\0';
i = readlink(buf, buf2, sizeof(buf2) - 1);
llist_append(*meta, entry);
}
- ssnprintf(buffer, sizeof(buffer), "%s `%s'", ci->key, meta_key);
+ snprintf(buffer, sizeof(buffer), "%s `%s'", ci->key, meta_key);
/* Can't pass &entry->value into mr_add_regex, so copy in/out. */
re_head = entry->value;
status = mr_add_regex(&re_head, ci->values[1].value.string, buffer);
* collectd - src/mcelog.c
* MIT License
*
- * Copyright(c) 2016 Intel Corporation. All rights reserved.
+ * Copyright(c) 2016-2017 Intel Corporation. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* Krzysztof Matczak <krzysztofx.matczak@intel.com>
*/
-#include "common.h"
#include "collectd.h"
+#include "common.h"
+#include "utils_llist.h"
+
#include <poll.h>
#include <sys/socket.h>
#include <sys/un.h>
#define MCELOG_DIMM_NAME "DMI_NAME"
#define MCELOG_CORRECTED_ERR "corrected memory errors"
#define MCELOG_UNCORRECTED_ERR "uncorrected memory errors"
+#define MCELOG_CORRECTED_ERR_TIMED "corrected memory timed errors"
+#define MCELOG_UNCORRECTED_ERR_TIMED "uncorrected memory timed errors"
+#define MCELOG_CORRECTED_ERR_TYPE_INS "corrected_memory_errors"
+#define MCELOG_UNCORRECTED_ERR_TYPE_INS "uncorrected_memory_errors"
typedef struct mcelog_config_s {
char logfile[PATH_MAX]; /* mcelog logfile */
pthread_t tid; /* poll thread id */
+ llist_t *dimms_list; /* DIMMs list */
+ pthread_mutex_t dimms_lock; /* lock for dimms cache */
+ _Bool persist;
} mcelog_config_t;
typedef struct socket_adapter_s socket_adapter_t;
static int socket_reinit(socket_adapter_t *self);
static int socket_receive(socket_adapter_t *self, FILE **p_file);
-static mcelog_config_t g_mcelog_config = {.logfile = "/var/log/mcelog"};
+static mcelog_config_t g_mcelog_config = {
+ .logfile = "/var/log/mcelog", .persist = 0,
+};
static socket_adapter_t socket_adapter = {
.sock_fd = -1,
};
static _Bool mcelog_thread_running;
+static _Bool mcelog_apply_defaults;
+
+static void mcelog_free_dimms_list_records(llist_t *dimms_list) {
+
+ for (llentry_t *e = llist_head(dimms_list); e != NULL; e = e->next) {
+ sfree(e->key);
+ sfree(e->value);
+ }
+}
+
+/* Create or get dimm by dimm name/location */
+static llentry_t *mcelog_dimm(const mcelog_memory_rec_t *rec,
+ llist_t *dimms_list) {
+
+ char dimm_name[DATA_MAX_NAME_LEN];
+
+ if (strlen(rec->dimm_name) > 0) {
+ snprintf(dimm_name, sizeof(dimm_name), "%s_%s", rec->location,
+ rec->dimm_name);
+ } else
+ sstrncpy(dimm_name, rec->location, sizeof(dimm_name));
+
+ llentry_t *dimm_le = llist_search(g_mcelog_config.dimms_list, dimm_name);
+
+ if (dimm_le != NULL)
+ return dimm_le;
+
+ /* allocate new linked list entry */
+ mcelog_memory_rec_t *dimm_mr = calloc(1, sizeof(*dimm_mr));
+ if (dimm_mr == NULL) {
+ ERROR(MCELOG_PLUGIN ": Error allocating dimm memory item");
+ return NULL;
+ }
+ char *p_name = strdup(dimm_name);
+ if (p_name == NULL) {
+ ERROR(MCELOG_PLUGIN ": strdup: error");
+ free(dimm_mr);
+ return NULL;
+ }
+
+ /* add new dimm */
+ dimm_le = llentry_create(p_name, dimm_mr);
+ if (dimm_le == NULL) {
+ ERROR(MCELOG_PLUGIN ": llentry_create(): error");
+ free(dimm_mr);
+ free(p_name);
+ return NULL;
+ }
+ pthread_mutex_lock(&g_mcelog_config.dimms_lock);
+ llist_append(g_mcelog_config.dimms_list, dimm_le);
+ pthread_mutex_unlock(&g_mcelog_config.dimms_lock);
+
+ return dimm_le;
+}
+
+static void mcelog_update_dimm_stats(llentry_t *dimm,
+ const mcelog_memory_rec_t *rec) {
+ pthread_mutex_lock(&g_mcelog_config.dimms_lock);
+ memcpy(dimm->value, rec, sizeof(mcelog_memory_rec_t));
+ pthread_mutex_unlock(&g_mcelog_config.dimms_lock);
+}
static int mcelog_config(oconfig_item_t *ci) {
+ int use_logfile = 0, use_memory = 0;
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
- if (strcasecmp("McelogClientSocket", child->key) == 0) {
- if (cf_util_get_string_buffer(child, socket_adapter.unix_sock.sun_path,
- sizeof(socket_adapter.unix_sock.sun_path)) <
- 0) {
- ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\".",
+ if (strcasecmp("McelogLogfile", child->key) == 0) {
+ use_logfile = 1;
+ if (use_memory) {
+ ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\", Memory "
+ "option is already configured.",
child->key);
return -1;
}
- } else if (strcasecmp("McelogLogfile", child->key) == 0) {
if (cf_util_get_string_buffer(child, g_mcelog_config.logfile,
sizeof(g_mcelog_config.logfile)) < 0) {
ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\".",
child->key);
return -1;
}
+ memset(socket_adapter.unix_sock.sun_path, 0,
+ sizeof(socket_adapter.unix_sock.sun_path));
+ } else if (strcasecmp("Memory", child->key) == 0) {
+ if (use_logfile) {
+ ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\", Logfile "
+ "option is already configured.",
+ child->key);
+ return -1;
+ }
+ use_memory = 1;
+ for (int j = 0; j < child->children_num; j++) {
+ oconfig_item_t *mem_child = child->children + j;
+ if (strcasecmp("McelogClientSocket", mem_child->key) == 0) {
+ if (cf_util_get_string_buffer(
+ mem_child, socket_adapter.unix_sock.sun_path,
+ sizeof(socket_adapter.unix_sock.sun_path)) < 0) {
+ ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\".",
+ mem_child->key);
+ return -1;
+ }
+ } else if (strcasecmp("PersistentNotification", mem_child->key) == 0) {
+ if (cf_util_get_boolean(mem_child, &g_mcelog_config.persist) < 0) {
+ ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\".",
+ mem_child->key);
+ return -1;
+ }
+ } else {
+ ERROR(MCELOG_PLUGIN ": Invalid Memory configuration option: \"%s\".",
+ mem_child->key);
+ return -1;
+ }
+ }
+ memset(g_mcelog_config.logfile, 0, sizeof(g_mcelog_config.logfile));
} else {
ERROR(MCELOG_PLUGIN ": Invalid configuration option: \"%s\".",
child->key);
return -1;
}
}
+
+ if (!use_logfile && !use_memory)
+ mcelog_apply_defaults = 1;
+
return 0;
}
return ret;
}
-static int mcelog_prepare_notification(notification_t *n,
- const mcelog_memory_rec_t *mr) {
- if (n == NULL || mr == NULL)
- return -1;
+static int mcelog_dispatch_mem_notifications(const mcelog_memory_rec_t *mr) {
+ notification_t n = {.severity = NOTIF_WARNING,
+ .time = cdtime(),
+ .plugin = MCELOG_PLUGIN,
+ .type = "errors"};
- if ((mr->location[0] != '\0') &&
- (plugin_notification_meta_add_string(n, MCELOG_SOCKET_STR, mr->location) <
- 0)) {
- ERROR(MCELOG_PLUGIN ": add memory location meta data failed");
- return -1;
- }
- if ((mr->dimm_name[0] != '\0') &&
- (plugin_notification_meta_add_string(n, MCELOG_DIMM_NAME, mr->dimm_name) <
- 0)) {
- ERROR(MCELOG_PLUGIN ": add DIMM name meta data failed");
- plugin_notification_meta_free(n->meta);
- return -1;
- }
- if (plugin_notification_meta_add_signed_int(n, MCELOG_CORRECTED_ERR,
- mr->corrected_err_total) < 0) {
- ERROR(MCELOG_PLUGIN ": add corrected errors meta data failed");
- plugin_notification_meta_free(n->meta);
- return -1;
- }
- if (plugin_notification_meta_add_signed_int(
- n, "corrected memory timed errors", mr->corrected_err_timed) < 0) {
- ERROR(MCELOG_PLUGIN ": add corrected timed errors meta data failed");
- plugin_notification_meta_free(n->meta);
+ int dispatch_corrected_notifs = 0, dispatch_uncorrected_notifs = 0;
+
+ if (mr == NULL)
return -1;
- }
- if ((mr->corrected_err_timed_period[0] != '\0') &&
- (plugin_notification_meta_add_string(n, "corrected errors time period",
- mr->corrected_err_timed_period) <
- 0)) {
- ERROR(MCELOG_PLUGIN ": add corrected errors period meta data failed");
- plugin_notification_meta_free(n->meta);
+
+ llentry_t *dimm = mcelog_dimm(mr, g_mcelog_config.dimms_list);
+ if (dimm == NULL) {
+ ERROR(MCELOG_PLUGIN
+ ": Error adding/getting dimm memory item to/from cache");
return -1;
}
- if (plugin_notification_meta_add_signed_int(n, MCELOG_UNCORRECTED_ERR,
- mr->uncorrected_err_total) < 0) {
- ERROR(MCELOG_PLUGIN ": add corrected errors meta data failed");
- plugin_notification_meta_free(n->meta);
- return -1;
+ mcelog_memory_rec_t *mr_old = dimm->value;
+ if (!g_mcelog_config.persist) {
+
+ if (mr_old->corrected_err_total != mr->corrected_err_total ||
+ mr_old->corrected_err_timed != mr->corrected_err_timed)
+ dispatch_corrected_notifs = 1;
+
+ if (mr_old->uncorrected_err_total != mr->uncorrected_err_total ||
+ mr_old->uncorrected_err_timed != mr->uncorrected_err_timed)
+ dispatch_uncorrected_notifs = 1;
+
+ if (!dispatch_corrected_notifs && !dispatch_uncorrected_notifs) {
+ DEBUG("%s: No new notifications to dispatch", MCELOG_PLUGIN);
+ return 0;
+ }
+ } else {
+ dispatch_corrected_notifs = 1;
+ dispatch_uncorrected_notifs = 1;
}
- if (plugin_notification_meta_add_signed_int(n,
- "uncorrected memory timed errors",
- mr->uncorrected_err_timed) < 0) {
- ERROR(MCELOG_PLUGIN ": add corrected timed errors meta data failed");
- plugin_notification_meta_free(n->meta);
- return -1;
+
+ sstrncpy(n.host, hostname_g, sizeof(n.host));
+
+ if (mr->dimm_name[0] != '\0')
+ snprintf(n.plugin_instance, sizeof(n.plugin_instance), "%s_%s",
+ mr->location, mr->dimm_name);
+ else
+ sstrncpy(n.plugin_instance, mr->location, sizeof(n.plugin_instance));
+
+ if (dispatch_corrected_notifs &&
+ (mr->corrected_err_total > 0 || mr->corrected_err_timed > 0)) {
+ /* Corrected Error Notifications */
+ plugin_notification_meta_add_signed_int(&n, MCELOG_CORRECTED_ERR,
+ mr->corrected_err_total);
+ plugin_notification_meta_add_signed_int(&n, MCELOG_CORRECTED_ERR_TIMED,
+ mr->corrected_err_timed);
+ snprintf(n.message, sizeof(n.message), MCELOG_CORRECTED_ERR);
+ sstrncpy(n.type_instance, MCELOG_CORRECTED_ERR_TYPE_INS,
+ sizeof(n.type_instance));
+ plugin_dispatch_notification(&n);
+ if (n.meta)
+ plugin_notification_meta_free(n.meta);
+ n.meta = NULL;
}
- if ((mr->uncorrected_err_timed_period[0] != '\0') &&
- (plugin_notification_meta_add_string(n, "uncorrected errors time period",
- mr->uncorrected_err_timed_period) <
- 0)) {
- ERROR(MCELOG_PLUGIN ": add corrected errors period meta data failed");
- plugin_notification_meta_free(n->meta);
- return -1;
+
+ if (dispatch_uncorrected_notifs &&
+ (mr->uncorrected_err_total > 0 || mr->uncorrected_err_timed > 0)) {
+ /* Uncorrected Error Notifications */
+ plugin_notification_meta_add_signed_int(&n, MCELOG_UNCORRECTED_ERR,
+ mr->uncorrected_err_total);
+ plugin_notification_meta_add_signed_int(&n, MCELOG_UNCORRECTED_ERR_TIMED,
+ mr->uncorrected_err_timed);
+ snprintf(n.message, sizeof(n.message), MCELOG_UNCORRECTED_ERR);
+ sstrncpy(n.type_instance, MCELOG_UNCORRECTED_ERR_TYPE_INS,
+ sizeof(n.type_instance));
+ n.severity = NOTIF_FAILURE;
+ plugin_dispatch_notification(&n);
+ if (n.meta)
+ plugin_notification_meta_free(n.meta);
+ n.meta = NULL;
}
return 0;
return -1;
}
+ llentry_t *dimm = mcelog_dimm(mr, g_mcelog_config.dimms_list);
+ if (dimm == NULL) {
+ ERROR(MCELOG_PLUGIN
+ ": Error adding/getting dimm memory item to/from cache");
+ return -1;
+ }
+
value_list_t vl = {
.values_len = 1,
.values = &(value_t){.derive = (derive_t)mr->corrected_err_total},
.time = cdtime(),
.plugin = MCELOG_PLUGIN,
.type = "errors",
- .type_instance = "corrected_memory_errors"};
+ .type_instance = MCELOG_CORRECTED_ERR_TYPE_INS};
+
+ mcelog_update_dimm_stats(dimm, mr);
if (mr->dimm_name[0] != '\0')
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s_%s",
- mr->location, mr->dimm_name);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s_%s",
+ mr->location, mr->dimm_name);
else
sstrncpy(vl.plugin_instance, mr->location, sizeof(vl.plugin_instance));
plugin_dispatch_values(&vl);
- ssnprintf(vl.type_instance, sizeof(vl.type_instance),
- "corrected_memory_errors_in_%s", mr->corrected_err_timed_period);
+ snprintf(vl.type_instance, sizeof(vl.type_instance),
+ "corrected_memory_errors_in_%s", mr->corrected_err_timed_period);
vl.values = &(value_t){.derive = (derive_t)mr->corrected_err_timed};
plugin_dispatch_values(&vl);
- sstrncpy(vl.type_instance, "uncorrected_memory_errors",
+ sstrncpy(vl.type_instance, MCELOG_UNCORRECTED_ERR_TYPE_INS,
sizeof(vl.type_instance));
vl.values = &(value_t){.derive = (derive_t)mr->uncorrected_err_total};
plugin_dispatch_values(&vl);
- ssnprintf(vl.type_instance, sizeof(vl.type_instance),
- "uncorrected_memory_errors_in_%s",
- mr->uncorrected_err_timed_period);
+ snprintf(vl.type_instance, sizeof(vl.type_instance),
+ "uncorrected_memory_errors_in_%s", mr->uncorrected_err_timed_period);
vl.values = &(value_t){.derive = (derive_t)mr->uncorrected_err_timed};
plugin_dispatch_values(&vl);
continue;
}
- notification_t n = {.severity = NOTIF_OKAY,
- .time = cdtime(),
- .message = "Got memory errors info.",
- .plugin = MCELOG_PLUGIN,
- .type_instance = "memory_erros"};
-
- if (mcelog_prepare_notification(&n, &memory_record) == 0)
- mcelog_dispatch_notification(&n);
+ if (mcelog_dispatch_mem_notifications(&memory_record) != 0)
+ ERROR(MCELOG_PLUGIN ": Failed to submit memory errors notification");
if (mcelog_submit(&memory_record) != 0)
ERROR(MCELOG_PLUGIN ": Failed to submit memory errors");
memset(&memory_record, 0, sizeof(memory_record));
}
static int mcelog_init(void) {
+ if (mcelog_apply_defaults) {
+ INFO(MCELOG_PLUGIN
+ ": No configuration selected defaulting to memory errors.");
+ memset(g_mcelog_config.logfile, 0, sizeof(g_mcelog_config.logfile));
+ }
+ g_mcelog_config.dimms_list = llist_create();
+ int err = pthread_mutex_init(&g_mcelog_config.dimms_lock, NULL);
+ if (err < 0) {
+ ERROR(MCELOG_PLUGIN ": plugin: failed to initialize cache lock");
+ return -1;
+ }
+
if (socket_adapter.reinit(&socket_adapter) != 0) {
ERROR(MCELOG_PLUGIN ": Cannot connect to client socket");
return -1;
}
- if (plugin_thread_create(&g_mcelog_config.tid, NULL, poll_worker, NULL,
- NULL) != 0) {
- ERROR(MCELOG_PLUGIN ": Error creating poll thread.");
- return -1;
+ if (strlen(socket_adapter.unix_sock.sun_path)) {
+ if (plugin_thread_create(&g_mcelog_config.tid, NULL, poll_worker, NULL,
+ NULL) != 0) {
+ ERROR(MCELOG_PLUGIN ": Error creating poll thread.");
+ return -1;
+ }
}
return 0;
}
ret = -1;
}
}
-
+ pthread_mutex_lock(&g_mcelog_config.dimms_lock);
+ mcelog_free_dimms_list_records(g_mcelog_config.dimms_list);
+ llist_destroy(g_mcelog_config.dimms_list);
+ g_mcelog_config.dimms_list = NULL;
+ pthread_mutex_unlock(&g_mcelog_config.dimms_lock);
+ pthread_mutex_destroy(&g_mcelog_config.dimms_lock);
ret = socket_adapter.close(&socket_adapter) || ret;
pthread_rwlock_destroy(&(socket_adapter.lock));
return -ret;
vl.values = &(value_t){.gauge = value};
vl.values_len = 1;
sstrncpy(vl.plugin, "md", sizeof(vl.plugin));
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", minor);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", minor);
sstrncpy(vl.type, "md_disks", sizeof(vl.type));
sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
* major/minor, but that again can be tricky if the filesystem
* with the device file is mounted using the "nodev" option.
*/
- ssnprintf(path, sizeof(path), "%s/%s", DEV_DIR, name);
+ snprintf(path, sizeof(path), "%s/%s", DEV_DIR, name);
md_process(minor, path);
}
typedef struct web_page_s web_page_t;
struct web_page_s /* {{{ */
{
+ char *plugin_name;
char *instance;
char *server;
memcached_free(wp->memc);
wp->memc = NULL;
+ sfree(wp->plugin_name);
sfree(wp->instance);
sfree(wp->server);
sfree(wp->key);
status = cmc_config_add_string("Server", &page->server, child);
else if (strcasecmp("Key", child->key) == 0)
status = cmc_config_add_string("Key", &page->key, child);
+ else if (strcasecmp("Plugin", child->key) == 0)
+ status = cmc_config_add_string("Plugin", &page->plugin_name, child);
else if (strcasecmp("Match", child->key) == 0)
/* Be liberal with failing matches => don't set `status'. */
cmc_config_add_match(page, child);
vl.values = &value;
vl.values_len = 1;
- sstrncpy(vl.plugin, "memcachec", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (wp->plugin_name != NULL) ? wp->plugin_name : "memcachec",
+ sizeof (vl.plugin));
sstrncpy(vl.plugin_instance, wp->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, wm->type, sizeof(vl.type));
sstrncpy(vl.type_instance, wm->instance, sizeof(vl.type_instance));
* Copyright (C) 2009 Doug MacEachern
* Copyright (C) 2009 Franck Lombardi
* Copyright (C) 2012 Nicolas Szalay
+ * Copyright (C) 2017 Pavel Rochnyak
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
* Doug MacEachern <dougm at hyperic.com>
* Franck Lombardi
* Nicolas Szalay
+ * Pavel Rochnyak <pavel2000 ngs.ru>
**/
#include "collectd.h"
#include <netinet/tcp.h>
#include <sys/un.h>
+#include <poll.h>
+
#define MEMCACHED_DEF_HOST "127.0.0.1"
#define MEMCACHED_DEF_PORT "11211"
+#define MEMCACHED_CONNECT_TIMEOUT 10000
+#define MEMCACHED_IO_TIMEOUT 5000
struct memcached_s {
char *name;
char *socket;
char *connhost;
char *connport;
+ int fd;
};
typedef struct memcached_s memcached_t;
if (st == NULL)
return;
+ if (st->fd >= 0) {
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
+ }
+
sfree(st->name);
sfree(st->host);
sfree(st->socket);
if (status != 0) {
shutdown(fd, SHUT_RDWR);
close(fd);
- fd = -1;
+ return -1;
+ }
+
+ /* switch to non-blocking mode */
+ int flags = fcntl(fd, F_GETFL);
+ status = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (status != 0) {
+ close(fd);
+ return -1;
}
return fd;
continue;
}
+ /* switch socket to non-blocking mode */
+ int flags = fcntl(fd, F_GETFL);
+ status = fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+ if (status != 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+
/* connect to the memcached daemon */
status = (int)connect(fd, ai_ptr->ai_addr, ai_ptr->ai_addrlen);
- if (status != 0) {
+ if (status != 0 && errno != EINPROGRESS) {
shutdown(fd, SHUT_RDWR);
close(fd);
fd = -1;
continue;
}
- /* A socket could be opened and connecting succeeded. We're done. */
+ /* Wait until connection establishes */
+ struct pollfd pollfd = {
+ .fd = fd, .events = POLLOUT,
+ };
+ do
+ status = poll(&pollfd, 1, MEMCACHED_CONNECT_TIMEOUT);
+ while (status < 0 && errno == EINTR);
+ if (status <= 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+
+ /* Check if all is good */
+ int socket_error;
+ status = getsockopt(fd, SOL_SOCKET, SO_ERROR, (void *)&socket_error,
+ &(socklen_t){sizeof(socket_error)});
+ if (status != 0 || socket_error != 0) {
+ close(fd);
+ fd = -1;
+ continue;
+ }
+ /* A socket is opened and connection succeeded. We're done. */
break;
}
return fd;
} /* int memcached_connect_inet */
-static int memcached_connect(memcached_t *st) {
+static void memcached_connect(memcached_t *st) {
+ if (st->fd >= 0)
+ return;
+
if (st->socket != NULL)
- return memcached_connect_unix(st);
+ st->fd = memcached_connect_unix(st);
else
- return memcached_connect_inet(st);
+ st->fd = memcached_connect_inet(st);
+
+ if (st->fd >= 0)
+ INFO("memcached plugin: Instance \"%s\": connection established.",
+ st->name);
}
static int memcached_query_daemon(char *buffer, size_t buffer_size,
memcached_t *st) {
- int fd, status;
+ int status;
size_t buffer_fill;
- fd = memcached_connect(st);
- if (fd < 0) {
+ memcached_connect(st);
+ if (st->fd < 0) {
ERROR("memcached plugin: Instance \"%s\" could not connect to daemon.",
st->name);
return -1;
}
- status = (int)swrite(fd, "stats\r\n", strlen("stats\r\n"));
+ struct pollfd pollfd = {
+ .fd = st->fd, .events = POLLOUT,
+ };
+
+ do
+ status = poll(&pollfd, 1, MEMCACHED_IO_TIMEOUT);
+ while (status < 0 && errno == EINTR);
+
+ if (status <= 0) {
+ ERROR("memcached plugin: poll() failed for write() call.");
+ close(st->fd);
+ st->fd = -1;
+ return -1;
+ }
+
+ status = (int)swrite(st->fd, "stats\r\n", strlen("stats\r\n"));
if (status != 0) {
char errbuf[1024];
- ERROR("memcached plugin: write(2) failed: %s",
+ ERROR("memcached plugin: Instance \"%s\": write(2) failed: %s", st->name,
sstrerror(errno, errbuf, sizeof(errbuf)));
- shutdown(fd, SHUT_RDWR);
- close(fd);
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
return -1;
}
memset(buffer, 0, buffer_size);
buffer_fill = 0;
- while ((status = (int)recv(fd, buffer + buffer_fill,
- buffer_size - buffer_fill, /* flags = */ 0)) !=
- 0) {
+ pollfd.events = POLLIN;
+ while (1) {
+ do
+ status = poll(&pollfd, 1, MEMCACHED_IO_TIMEOUT);
+ while (status < 0 && errno == EINTR);
+
+ if (status <= 0) {
+ ERROR("memcached plugin: Instance \"%s\": Timeout reading from socket",
+ st->name);
+ close(st->fd);
+ st->fd = -1;
+ return -1;
+ }
+
+ do
+ status = (int)recv(st->fd, buffer + buffer_fill,
+ buffer_size - buffer_fill, /* flags = */ 0);
+ while (status < 0 && errno == EINTR);
+
char const end_token[5] = {'E', 'N', 'D', '\r', '\n'};
if (status < 0) {
char errbuf[1024];
- if ((errno == EAGAIN) || (errno == EINTR))
+ if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
continue;
- ERROR("memcached: Error reading from socket: %s",
- sstrerror(errno, errbuf, sizeof(errbuf)));
- shutdown(fd, SHUT_RDWR);
- close(fd);
+ ERROR("memcached plugin: Instance \"%s\": Error reading from socket: %s",
+ st->name, sstrerror(errno, errbuf, sizeof(errbuf)));
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
return -1;
}
buffer_fill += (size_t)status;
if (buffer_fill > buffer_size) {
buffer_fill = buffer_size;
- WARNING("memcached plugin: Message was truncated.");
+ WARNING("memcached plugin: Instance \"%s\": Message was truncated.",
+ st->name);
+ shutdown(st->fd, SHUT_RDWR);
+ close(st->fd);
+ st->fd = -1;
break;
}
status = 0;
if (buffer_fill == 0) {
- WARNING("memcached plugin: No data returned by memcached.");
+ WARNING("memcached plugin: Instance \"%s\": No data returned by memcached.",
+ st->name);
status = -1;
}
- shutdown(fd, SHUT_RDWR);
- close(fd);
return status;
} /* int memcached_query_daemon */
} else if (FIELD_IS("listen_disabled_num")) {
submit_derive("connections", "listen_disabled", atof(fields[2]), st);
}
+ /*
+ * Total number of connections opened since the server started running
+ * Report this as connection rate.
+ */
+ else if (FIELD_IS("total_connections")) {
+ submit_derive("connections", "opened", atof(fields[2]), st);
+ }
/*
* Commands
return 0;
} /* int memcached_read */
-static int memcached_add_read_callback(memcached_t *st) {
- char callback_name[3 * DATA_MAX_NAME_LEN];
- int status;
-
- ssnprintf(callback_name, sizeof(callback_name), "memcached/%s",
- (st->name != NULL) ? st->name : "__legacy__");
-
+static int memcached_set_defaults(memcached_t *st) {
/* If no <Address> used then:
* - Connect to the destination specified by <Host>, if present.
* If not, use the default address.
assert(st->connhost != NULL);
assert(st->connport != NULL);
- status = plugin_register_complex_read(
+ return 0;
+} /* int memcached_set_defaults */
+
+static int memcached_add_read_callback(memcached_t *st) {
+ char callback_name[3 * DATA_MAX_NAME_LEN];
+
+ if (memcached_set_defaults(st) != 0) {
+ memcached_free(st);
+ return -1;
+ }
+
+ snprintf(callback_name, sizeof(callback_name), "memcached/%s",
+ (st->name != NULL) ? st->name : "__legacy__");
+
+ return plugin_register_complex_read(
/* group = */ "memcached",
/* name = */ callback_name,
/* callback = */ memcached_read,
- /* interval = */ 0, &(user_data_t){
- .data = st, .free_func = memcached_free,
- });
-
- return status;
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = st, .free_func = memcached_free,
+ });
} /* int memcached_add_read_callback */
/* Configuration handling functiions
st->connhost = NULL;
st->connport = NULL;
+ st->fd = -1;
+
if (strcasecmp(ci->key, "Instance") == 0)
status = cf_util_get_string(ci, &st->name);
break;
}
- if (status == 0)
- status = memcached_add_read_callback(st);
-
if (status != 0) {
memcached_free(st);
return -1;
}
- return 0;
-}
+ return memcached_add_read_callback(st);
+} /* int config_add_instance */
static int memcached_config(oconfig_item_t *ci) {
- int status = 0;
_Bool have_instance_block = 0;
for (int i = 0; i < ci->children_num; i++) {
child->key);
} /* for (ci->children) */
- return status;
-}
+ return 0;
+} /* int memcached_config */
static int memcached_init(void) {
memcached_t *st;
st->connhost = NULL;
st->connport = NULL;
+ st->fd = -1;
+
status = memcached_add_read_callback(st);
if (status == 0)
memcached_have_instances = 1;
- else
- memcached_free(st);
return status;
} /* int memcached_init */
vl.values_len = 1;
strncpy(vl.plugin, "mic", sizeof(vl.plugin));
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
strncpy(vl.type, "memory", sizeof(vl.type));
strncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
vl.values = &(value_t){.gauge = value};
vl.values_len = 1;
- strncpy(vl.host, hostname_g, sizeof(vl.host));
strncpy(vl.plugin, "mic", sizeof(vl.plugin));
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
strncpy(vl.type, "temperature", sizeof(vl.type));
strncpy(vl.type_instance, type, sizeof(vl.type_instance));
vl.values = &(value_t){.derive = value};
vl.values_len = 1;
- strncpy(vl.host, hostname_g, sizeof(vl.host));
strncpy(vl.plugin, "mic", sizeof(vl.plugin));
if (core < 0) /* global aggregation */
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
else /* per-core statistics */
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i-cpu-%i",
- micnumber, core);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i-cpu-%i",
+ micnumber, core);
strncpy(vl.type, "cpu", sizeof(vl.type));
strncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
vl.values = &(value_t){.gauge = value};
vl.values_len = 1;
- strncpy(vl.host, hostname_g, sizeof(vl.host));
strncpy(vl.plugin, "mic", sizeof(vl.plugin));
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", micnumber);
strncpy(vl.type, type, sizeof(vl.type));
strncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
host->interval = plugin_get_interval();
if (slave->instance[0] == 0)
- ssnprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
+ snprintf(slave->instance, sizeof(slave->instance), "slave_%i", slave->id);
vl.values = &value;
vl.values_len = 1;
if (status == 0) {
char name[1024];
- ssnprintf(name, sizeof(name), "modbus-%s", host->host);
+ snprintf(name, sizeof(name), "modbus-%s", host->host);
plugin_register_complex_read(/* group = */ NULL, name,
/* callback = */ mb_read,
if (status != 0)
return status;
- status = ssnprintf(buf, buf_len, "%s/%s", conf->topic_prefix, name);
+ status = snprintf(buf, buf_len, "%s/%s", conf->topic_prefix, name);
if ((status < 0) || (((size_t)status) >= buf_len))
return ENOMEM;
- while((c = strchr(buf, '#')) || (c = strchr(buf, '+'))) {
- *c = '_';
+ while ((c = strchr(buf, '#')) || (c = strchr(buf, '+'))) {
+ *c = '_';
}
return 0;
* StoreRates true
* Retain false
* QoS 0
- * CACert "ca.pem" Enables TLS if set
- * CertificateFile "client-cert.pem" optional
- * CertificateKeyFile "client-key.pem" optional
- * TLSProtocol "tlsv1.2" optional
+ * CACert "ca.pem" Enables TLS if set
+ * CertificateFile "client-cert.pem" optional
+ * CertificateKeyFile "client-key.pem" optional
+ * TLSProtocol "tlsv1.2" optional
* </Publish>
*/
static int mqtt_config_publisher(oconfig_item_t *ci) {
ERROR("mqtt plugin: Unknown config option: %s", child->key);
}
- ssnprintf(cb_name, sizeof(cb_name), "mqtt/%s", conf->name);
- plugin_register_write(cb_name, mqtt_write, &(user_data_t){
- .data = conf,
- });
+ snprintf(cb_name, sizeof(cb_name), "mqtt/%s", conf->name);
+ plugin_register_write(cb_name, mqtt_write,
+ &(user_data_t){
+ .data = conf,
+ });
return 0;
} /* mqtt_config_publisher */
* User "guest"
* Password "secret"
* Topic "collectd/#"
+ * CACert "ca.pem" Enables TLS if set
+ * CertificateFile "client-cert.pem" optional
+ * CertificateKeyFile "client-key.pem" optional
+ * TLSProtocol "tlsv1.2" optional
* </Subscribe>
*/
static int mqtt_config_subscriber(oconfig_item_t *ci) {
cf_util_get_string(child, &conf->topic);
else if (strcasecmp("CleanSession", child->key) == 0)
cf_util_get_boolean(child, &conf->clean_session);
+ else if (strcasecmp("CACert", child->key) == 0)
+ cf_util_get_string(child, &conf->cacertificatefile);
+ else if (strcasecmp("CertificateFile", child->key) == 0)
+ cf_util_get_string(child, &conf->certificatefile);
+ else if (strcasecmp("CertificateKeyFile", child->key) == 0)
+ cf_util_get_string(child, &conf->certificatekeyfile);
+ else if (strcasecmp("TLSProtocol", child->key) == 0)
+ cf_util_get_string(child, &conf->tlsprotocol);
+ else if (strcasecmp("CipherSuite", child->key) == 0)
+ cf_util_get_string(child, &conf->ciphersuite);
else
ERROR("mqtt plugin: Unknown config option: %s", child->key);
}
--- /dev/null
+/*
+ * Partial header file imported from the linux kernel
+ * (arch/x86/include/asm/msr-index.h)
+ * as it is not provided by the kernel sources anymore
+ *
+ * Only the minimal blocks of macro have been included
+ * ----
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
+ * ----
+ */
+
+#ifndef _ASM_X86_MSR_INDEX_H
+#define _ASM_X86_MSR_INDEX_H
+
+/*
+ * CPU model specific register (MSR) numbers.
+ *
+ * Do not add new entries to this file unless the definitions are shared
+ * between multiple compilation units.
+ */
+
+/* Intel MSRs. Some also available on other CPUs */
+
+/* C-state Residency Counters */
+#define MSR_PKG_C3_RESIDENCY 0x000003f8
+#define MSR_PKG_C6_RESIDENCY 0x000003f9
+#define MSR_ATOM_PKG_C6_RESIDENCY 0x000003fa
+#define MSR_PKG_C7_RESIDENCY 0x000003fa
+#define MSR_CORE_C3_RESIDENCY 0x000003fc
+#define MSR_CORE_C6_RESIDENCY 0x000003fd
+#define MSR_CORE_C7_RESIDENCY 0x000003fe
+#define MSR_KNL_CORE_C6_RESIDENCY 0x000003ff
+#define MSR_PKG_C2_RESIDENCY 0x0000060d
+#define MSR_PKG_C8_RESIDENCY 0x00000630
+#define MSR_PKG_C9_RESIDENCY 0x00000631
+#define MSR_PKG_C10_RESIDENCY 0x00000632
+
+/* Run Time Average Power Limiting (RAPL) Interface */
+
+#define MSR_RAPL_POWER_UNIT 0x00000606
+
+#define MSR_PKG_POWER_LIMIT 0x00000610
+#define MSR_PKG_ENERGY_STATUS 0x00000611
+#define MSR_PKG_PERF_STATUS 0x00000613
+#define MSR_PKG_POWER_INFO 0x00000614
+
+#define MSR_DRAM_POWER_LIMIT 0x00000618
+#define MSR_DRAM_ENERGY_STATUS 0x00000619
+#define MSR_DRAM_PERF_STATUS 0x0000061b
+#define MSR_DRAM_POWER_INFO 0x0000061c
+
+#define MSR_PP0_POWER_LIMIT 0x00000638
+#define MSR_PP0_ENERGY_STATUS 0x00000639
+#define MSR_PP0_POLICY 0x0000063a
+#define MSR_PP0_PERF_STATUS 0x0000063b
+
+#define MSR_PP1_POWER_LIMIT 0x00000640
+#define MSR_PP1_ENERGY_STATUS 0x00000641
+#define MSR_PP1_POLICY 0x00000642
+
+
+
+/* Intel defined MSRs. */
+#define MSR_IA32_TSC 0x00000010
+#define MSR_SMI_COUNT 0x00000034
+
+#define MSR_IA32_MPERF 0x000000e7
+#define MSR_IA32_APERF 0x000000e8
+
+#define MSR_IA32_THERM_STATUS 0x0000019c
+
+#define MSR_IA32_TEMPERATURE_TARGET 0x000001a2
+
+#define MSR_IA32_PACKAGE_THERM_STATUS 0x000001b1
+
+
+#endif /* _ASM_X86_MSR_INDEX_H */
(db->database != NULL) ? db->database : "<default>");
if (db->instance != NULL)
- ssnprintf(cb_name, sizeof(cb_name), "mysql-%s", db->instance);
+ snprintf(cb_name, sizeof(cb_name), "mysql-%s", db->instance);
else
sstrncpy(cb_name, "mysql", sizeof(cb_name));
if (((io == NULL) || (strcasecmp(io, "yes") != 0)) &&
(db->slave_io_running)) {
n.severity = NOTIF_WARNING;
- ssnprintf(n.message, sizeof(n.message),
- "slave I/O thread not started or not connected to master");
+ snprintf(n.message, sizeof(n.message),
+ "slave I/O thread not started or not connected to master");
plugin_dispatch_notification(&n);
db->slave_io_running = 0;
} else if (((io != NULL) && (strcasecmp(io, "yes") == 0)) &&
(!db->slave_io_running)) {
n.severity = NOTIF_OKAY;
- ssnprintf(n.message, sizeof(n.message),
- "slave I/O thread started and connected to master");
+ snprintf(n.message, sizeof(n.message),
+ "slave I/O thread started and connected to master");
plugin_dispatch_notification(&n);
db->slave_io_running = 1;
}
if (((sql == NULL) || (strcasecmp(sql, "yes") != 0)) &&
(db->slave_sql_running)) {
n.severity = NOTIF_WARNING;
- ssnprintf(n.message, sizeof(n.message), "slave SQL thread not started");
+ snprintf(n.message, sizeof(n.message), "slave SQL thread not started");
plugin_dispatch_notification(&n);
db->slave_sql_running = 0;
} else if (((sql != NULL) && (strcasecmp(sql, "yes") == 0)) &&
(!db->slave_sql_running)) {
n.severity = NOTIF_OKAY;
- ssnprintf(n.message, sizeof(n.message), "slave SQL thread started");
+ snprintf(n.message, sizeof(n.message), "slave SQL thread started");
plugin_dispatch_notification(&n);
db->slave_sql_running = 1;
}
const char *type, const char *type_inst,
derive_t counter, cdtime_t timestamp,
cdtime_t interval) {
- return submit_values(host, plugin_inst, type, type_inst, &(value_t){
- .derive=counter,
- }, 1, timestamp, interval);
+ return submit_values(host, plugin_inst, type, type_inst,
+ &(value_t){
+ .derive = counter,
+ },
+ 1, timestamp, interval);
} /* }}} int submit_derive */
static int submit_two_gauge(const char *host, const char *plugin_inst, /* {{{ */
static int submit_double(const char *host, const char *plugin_inst, /* {{{ */
const char *type, const char *type_inst, double d,
cdtime_t timestamp, cdtime_t interval) {
- return submit_values(host, plugin_inst, type, type_inst, &(value_t){
- .gauge=d,
- }, 1, timestamp, interval);
+ return submit_values(host, plugin_inst, type, type_inst,
+ &(value_t){
+ .gauge = d,
+ },
+ 1, timestamp, interval);
} /* }}} int submit_uint64 */
/* Calculate hit ratio from old and new counters and submit the resulting
if ((hostname == NULL) || (old_data == NULL) || (new_data == NULL))
return -1;
- ssnprintf(plugin_instance, sizeof(plugin_instance), "volume-%s",
- old_data->name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "volume-%s",
+ old_data->name);
/* Check for and submit disk-octet values */
if (HAS_ALL_FLAGS(old_data->flags, CFG_VOLUME_PERF_IO) &&
- HAS_ALL_FLAGS(new_data->flags, HAVE_VOLUME_PERF_BYTES_READ |
- HAVE_VOLUME_PERF_BYTES_WRITE)) {
+ HAS_ALL_FLAGS(new_data->flags,
+ HAVE_VOLUME_PERF_BYTES_READ |
+ HAVE_VOLUME_PERF_BYTES_WRITE)) {
submit_two_derive(
hostname, plugin_instance, "disk_octets", /* type instance = */ NULL,
(derive_t)new_data->read_bytes, (derive_t)new_data->write_bytes,
}
/* Check for, calculate and submit disk-latency values */
- if (HAS_ALL_FLAGS(old_data->flags, CFG_VOLUME_PERF_LATENCY |
- HAVE_VOLUME_PERF_OPS_READ |
- HAVE_VOLUME_PERF_OPS_WRITE |
- HAVE_VOLUME_PERF_LATENCY_READ |
- HAVE_VOLUME_PERF_LATENCY_WRITE) &&
- HAS_ALL_FLAGS(new_data->flags, HAVE_VOLUME_PERF_OPS_READ |
- HAVE_VOLUME_PERF_OPS_WRITE |
- HAVE_VOLUME_PERF_LATENCY_READ |
- HAVE_VOLUME_PERF_LATENCY_WRITE)) {
+ if (HAS_ALL_FLAGS(old_data->flags,
+ CFG_VOLUME_PERF_LATENCY | HAVE_VOLUME_PERF_OPS_READ |
+ HAVE_VOLUME_PERF_OPS_WRITE |
+ HAVE_VOLUME_PERF_LATENCY_READ |
+ HAVE_VOLUME_PERF_LATENCY_WRITE) &&
+ HAS_ALL_FLAGS(new_data->flags,
+ HAVE_VOLUME_PERF_OPS_READ | HAVE_VOLUME_PERF_OPS_WRITE |
+ HAVE_VOLUME_PERF_LATENCY_READ |
+ HAVE_VOLUME_PERF_LATENCY_WRITE)) {
gauge_t latency_per_op_read;
gauge_t latency_per_op_write;
uint64_t snap_reserve_free = v->snap_reserved;
uint64_t snap_norm_used = v->snap_used;
- ssnprintf(plugin_instance, sizeof(plugin_instance), "volume-%s", v->name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "volume-%s", v->name);
- if (HAS_ALL_FLAGS(v->flags, HAVE_VOLUME_USAGE_SNAP_USED |
- HAVE_VOLUME_USAGE_SNAP_RSVD)) {
+ if (HAS_ALL_FLAGS(v->flags,
+ HAVE_VOLUME_USAGE_SNAP_USED |
+ HAVE_VOLUME_USAGE_SNAP_RSVD)) {
if (v->snap_reserved > v->snap_used) {
snap_reserve_free = v->snap_reserved - v->snap_used;
snap_reserve_used = v->snap_used;
/* The space used by snapshots but not reserved for them is included in
* both, norm_used and snap_norm_used. If possible, subtract this here. */
- if (HAS_ALL_FLAGS(v->flags, HAVE_VOLUME_USAGE_NORM_USED |
- HAVE_VOLUME_USAGE_SNAP_USED)) {
+ if (HAS_ALL_FLAGS(v->flags,
+ HAVE_VOLUME_USAGE_NORM_USED |
+ HAVE_VOLUME_USAGE_SNAP_USED)) {
if (norm_used >= snap_norm_used)
norm_used -= snap_norm_used;
else {
"df_complex", "snap_reserved", (double)snap_reserve_free,
/* timestamp = */ 0, interval);
- if (HAS_ALL_FLAGS(v->flags, HAVE_VOLUME_USAGE_SNAP_USED |
- HAVE_VOLUME_USAGE_SNAP_RSVD))
+ if (HAS_ALL_FLAGS(v->flags,
+ HAVE_VOLUME_USAGE_SNAP_USED |
+ HAVE_VOLUME_USAGE_SNAP_RSVD))
submit_double(hostname, /* plugin instance = */ plugin_instance,
"df_complex", "snap_reserve_used",
(double)snap_reserve_used, /* timestamp = */ 0, interval);
if ((v->flags & IS_VOLUME_USAGE_OFFLINE) != 0) {
n.severity = NOTIF_OKAY;
- ssnprintf(n.message, sizeof(n.message), "Volume %s is now online.",
- v->name);
+ snprintf(n.message, sizeof(n.message), "Volume %s is now online.", v->name);
v->flags &= ~IS_VOLUME_USAGE_OFFLINE;
} else {
n.severity = NOTIF_WARNING;
- ssnprintf(n.message, sizeof(n.message), "Volume %s is now offline.",
- v->name);
+ snprintf(n.message, sizeof(n.message), "Volume %s is now offline.",
+ v->name);
v->flags |= IS_VOLUME_USAGE_OFFLINE;
}
}
} /* for (elem_volume) */
- return cna_submit_volume_usage_data(host->name, cfg_volume,
- host->cfg_volume_usage->interval.interval);
+ return cna_submit_volume_usage_data(
+ host->name, cfg_volume, host->cfg_volume_usage->interval.interval);
} /* }}} int cna_handle_volume_usage_data */
static int cna_setup_volume_usage(cfg_volume_usage_t *cvu) /* {{{ */
if (volume_name == NULL)
continue;
- ssnprintf(plugin_instance, sizeof(plugin_instance), "quota-%s-%s",
- volume_name, tree_name);
+ snprintf(plugin_instance, sizeof(plugin_instance), "quota-%s-%s",
+ volume_name, tree_name);
value = na_child_get_uint64(elem_quota, "disk-used", UINT64_MAX);
if (value != UINT64_MAX) {
continue;
/* possible TODO: make plugin instance configurable */
- ssnprintf(plugin_instance, sizeof(plugin_instance), "snapvault-%s",
- dest_path);
+ snprintf(plugin_instance, sizeof(plugin_instance), "snapvault-%s",
+ dest_path);
submit_double(hostname, plugin_instance, /* type = */ "delay", NULL,
(double)value, /* timestamp = */ 0, interval);
char cb_name[256];
if (host->vfiler)
- ssnprintf(cb_name, sizeof(cb_name), "netapp-%s-%s", host->name,
- host->vfiler);
+ snprintf(cb_name, sizeof(cb_name), "netapp-%s-%s", host->name,
+ host->vfiler);
else
- ssnprintf(cb_name, sizeof(cb_name), "netapp-%s", host->name);
+ snprintf(cb_name, sizeof(cb_name), "netapp-%s", host->name);
plugin_register_complex_read(
/* group = */ NULL, cb_name,
if (strcmp(tc_type, "filter") == 0)
numberic_id = tm->tcm_parent;
- ssnprintf(tc_inst, sizeof(tc_inst), "%s-%x:%x", kind, numberic_id >> 16,
- numberic_id & 0x0000FFFF);
+ snprintf(tc_inst, sizeof(tc_inst), "%s-%x:%x", kind, numberic_id >> 16,
+ numberic_id & 0x0000FFFF);
}
DEBUG("netlink plugin: qos_filter_cb: got %s for %s (%i).", tc_type, dev,
stats_submitted = 1;
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
- tc_inst);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, tc_inst);
if (q_stats.bs != NULL) {
submit_one(dev, "ipt_bytes", type_instance, q_stats.bs->bytes);
if (!stats_submitted && ts != NULL) {
char type_instance[DATA_MAX_NAME_LEN];
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type,
- tc_inst);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s", tc_type, tc_inst);
submit_one(dev, "ipt_bytes", type_instance, ts->bytes);
submit_one(dev, "ipt_packets", type_instance, ts->packets);
part_size - buffer_offset,
/* in = */ NULL, /* in len = */ 0);
if (err != 0) {
- sfree(pea.username);
ERROR("network plugin: gcry_cipher_decrypt returned: %s. Username: %s",
gcry_strerror(err), pea.username);
+ sfree(pea.username);
return -1;
}
parse_packet(se, buffer + buffer_offset, payload_len, flags | PP_ENCRYPTED,
pea.username);
- /* XXX: Free pea.username?!? */
-
/* Update return values */
*ret_buffer = buffer + part_size;
*ret_buffer_len = buffer_len - part_size;
#include <kstat.h>
#endif
+static const char *config_keys[] = {"ReportV2", "ReportV3", "ReportV4"};
+static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
+static _Bool report_v2 = 1;
+static _Bool report_v3 = 1;
+static _Bool report_v4 = 1;
+
/*
see /proc/net/rpc/nfs
see http://www.missioncriticallinux.com/orph/NFS-Statistics
static kstat_t *nfs4_ksp_server;
#endif
+static int nfs_config(const char *key, const char *value) {
+ if (strcasecmp(key, "ReportV2") == 0)
+ report_v2 = IS_TRUE(value);
+ else if (strcasecmp(key, "ReportV3") == 0)
+ report_v3 = IS_TRUE(value);
+ else if (strcasecmp(key, "ReportV4") == 0)
+ report_v4 = IS_TRUE(value);
+ else
+ return -1;
+
+ return 0;
+}
+
#if KERNEL_LINUX
static int nfs_init(void) { return 0; }
/* #endif KERNEL_LINUX */
char plugin_instance[DATA_MAX_NAME_LEN];
value_t values[fields_num];
- ssnprintf(plugin_instance, sizeof(plugin_instance), "v%i%s", nfs_version,
- instance);
+ snprintf(plugin_instance, sizeof(plugin_instance), "v%i%s", nfs_version,
+ instance);
for (size_t i = 0; i < fields_num; i++)
(void)parse_value(fields[i], &values[i], DS_TYPE_DERIVE);
if (fields_num < 3)
continue;
- if (strcmp(fields[0], "proc2") == 0) {
+ if (strcmp(fields[0], "proc2") == 0 && report_v2) {
nfs_submit_fields_safe(/* version = */ 2, inst, fields + 2,
(size_t)(fields_num - 2), nfs2_procedures_names,
nfs2_procedures_names_num);
- } else if (strncmp(fields[0], "proc3", 5) == 0) {
+ } else if (strncmp(fields[0], "proc3", 5) == 0 && report_v3) {
nfs_submit_fields_safe(/* version = */ 3, inst, fields + 2,
(size_t)(fields_num - 2), nfs3_procedures_names,
nfs3_procedures_names_num);
- } else if (strcmp(fields[0], "proc4ops") == 0) {
+ } else if (strcmp(fields[0], "proc4ops") == 0 && report_v4) {
if (inst[0] == 's')
nfs_submit_nfs4_server(inst, fields + 2, (size_t)(fields_num - 2));
- } else if (strcmp(fields[0], "proc4") == 0) {
+ } else if (strcmp(fields[0], "proc4") == 0 && report_v4) {
if (inst[0] == 'c')
nfs_submit_nfs4_client(inst, fields + 2, (size_t)(fields_num - 2));
}
if (ksp == NULL)
return EINVAL;
- ssnprintf(plugin_instance, sizeof(plugin_instance), "v%i%s", nfs_version,
- inst);
+ snprintf(plugin_instance, sizeof(plugin_instance), "v%i%s", nfs_version,
+ inst);
kstat_read(kc, ksp, NULL);
for (size_t i = 0; i < proc_names_num; i++) {
#elif HAVE_LIBKSTAT
static int nfs_read(void) {
- nfs_read_kstat(nfs2_ksp_client, /* version = */ 2, "client",
- nfs2_procedures_names, nfs2_procedures_names_num);
- nfs_read_kstat(nfs2_ksp_server, /* version = */ 2, "server",
- nfs2_procedures_names, nfs2_procedures_names_num);
- nfs_read_kstat(nfs3_ksp_client, /* version = */ 3, "client",
- nfs3_procedures_names, nfs3_procedures_names_num);
- nfs_read_kstat(nfs3_ksp_server, /* version = */ 3, "server",
- nfs3_procedures_names, nfs3_procedures_names_num);
- nfs_read_kstat(nfs4_ksp_client, /* version = */ 4, "client",
- nfs4_procedures_names, nfs4_procedures_names_num);
- nfs_read_kstat(nfs4_ksp_server, /* version = */ 4, "server",
- nfs4_procedures_names, nfs4_procedures_names_num);
+ if (report_v2) {
+ nfs_read_kstat(nfs2_ksp_client, /* version = */ 2, "client",
+ nfs2_procedures_names, nfs2_procedures_names_num);
+ nfs_read_kstat(nfs2_ksp_server, /* version = */ 2, "server",
+ nfs2_procedures_names, nfs2_procedures_names_num);
+ }
+ if (report_v3) {
+ nfs_read_kstat(nfs3_ksp_client, /* version = */ 3, "client",
+ nfs3_procedures_names, nfs3_procedures_names_num);
+ nfs_read_kstat(nfs3_ksp_server, /* version = */ 3, "server",
+ nfs3_procedures_names, nfs3_procedures_names_num);
+ }
+ if (report_v4) {
+ nfs_read_kstat(nfs4_ksp_client, /* version = */ 4, "client",
+ nfs4_procedures_names, nfs4_procedures_names_num);
+ nfs_read_kstat(nfs4_ksp_server, /* version = */ 4, "server",
+ nfs4_procedures_names, nfs4_procedures_names_num);
+ }
return 0;
}
#endif /* HAVE_LIBKSTAT */
void module_register(void) {
+ plugin_register_config("nfs", nfs_config, config_keys, config_keys_num);
plugin_register_init("nfs", nfs_init);
plugin_register_read("nfs", nfs_read);
} /* void module_register */
curl_easy_setopt(curl, CURLOPT_PASSWORD, (pass == NULL) ? "" : pass);
#else
static char credentials[1024];
- int status = ssnprintf(credentials, sizeof(credentials), "%s:%s", user,
- pass == NULL ? "" : pass);
+ int status = snprintf(credentials, sizeof(credentials), "%s:%s", user,
+ pass == NULL ? "" : pass);
if ((status < 0) || ((size_t)status >= sizeof(credentials))) {
ERROR("nginx plugin: Credentials would have been truncated.");
return -1;
timeout = fail_timeout;
}
- ssnprintf(summary, sizeof(summary), "collectd %s notification",
- (NOTIF_FAILURE == n->severity)
- ? "FAILURE"
- : (NOTIF_WARNING == n->severity)
- ? "WARNING"
- : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
+ snprintf(summary, sizeof(summary), "collectd %s notification",
+ (NOTIF_FAILURE == n->severity)
+ ? "FAILURE"
+ : (NOTIF_WARNING == n->severity)
+ ? "WARNING"
+ : (NOTIF_OKAY == n->severity) ? "OKAY" : "UNKNOWN");
notification = notify_notification_new(summary, n->message, NULL
#if NOTIFY_CHECK_VERSION(0, 7, 0)
static int notify_email_init(void) {
char server[MAXSTRING];
- ssnprintf(server, sizeof(server), "%s:%i",
- (smtp_host == NULL) ? DEFAULT_SMTP_HOST : smtp_host, smtp_port);
+ snprintf(server, sizeof(server), "%s:%i",
+ (smtp_host == NULL) ? DEFAULT_SMTP_HOST : smtp_host, smtp_port);
pthread_mutex_lock(&session_lock);
int buf_len = sizeof(buf);
int i;
- ssnprintf(severity, sizeof(severity), "%s",
- (n->severity == NOTIF_FAILURE)
- ? "FAILURE"
- : ((n->severity == NOTIF_WARNING)
- ? "WARNING"
- : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
+ snprintf(severity, sizeof(severity), "%s",
+ (n->severity == NOTIF_FAILURE)
+ ? "FAILURE"
+ : ((n->severity == NOTIF_WARNING)
+ ? "WARNING"
+ : ((n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN")));
- ssnprintf(subject, sizeof(subject),
- (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject,
- severity, n->host);
+ snprintf(subject, sizeof(subject),
+ (email_subject == NULL) ? DEFAULT_SMTP_SUBJECT : email_subject,
+ severity, n->host);
localtime_r(&CDTIME_T_TO_TIME_T(n->time), ×tamp_tm);
strftime(timestamp_str, sizeof(timestamp_str), "%Y-%m-%d %H:%M:%S",
timestamp_str[sizeof(timestamp_str) - 1] = '\0';
/* Let's make RFC822 message text with \r\n EOLs */
- ssnprintf(buf, buf_len, "MIME-Version: 1.0\r\n"
- "Content-Type: text/plain; charset=\"US-ASCII\"\r\n"
- "Content-Transfer-Encoding: 8bit\r\n"
- "Subject: %s\r\n"
- "\r\n"
- "%s - %s@%s\r\n"
- "\r\n"
- "Message: %s",
- subject, timestamp_str, severity, n->host, n->message);
+ snprintf(buf, buf_len, "MIME-Version: 1.0\r\n"
+ "Content-Type: text/plain; charset=\"US-ASCII\"\r\n"
+ "Content-Transfer-Encoding: 8bit\r\n"
+ "Subject: %s\r\n"
+ "\r\n"
+ "%s - %s@%s\r\n"
+ "\r\n"
+ "Message: %s",
+ subject, timestamp_str, severity, n->host, n->message);
pthread_mutex_lock(&session_lock);
break;
}
- ssnprintf(buffer, sizeof(buffer),
- "[%.0f] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
- CDTIME_T_TO_DOUBLE(n->time), n->host, &svc_description[1], code,
- n->message);
+ snprintf(buffer, sizeof(buffer),
+ "[%.0f] PROCESS_SERVICE_CHECK_RESULT;%s;%s;%d;%s\n",
+ CDTIME_T_TO_DOUBLE(n->time), n->host, &svc_description[1], code,
+ n->message);
return nagios_print(buffer);
} /* }}} int nagios_notify */
} else if (strcasecmp(key, "Port") == 0) {
int port = (int)(atof(value));
if ((port > 0) && (port <= 65535))
- ssnprintf(ntpd_port, sizeof(ntpd_port), "%i", port);
+ snprintf(ntpd_port, sizeof(ntpd_port), "%i", port);
else
sstrncpy(ntpd_port, value, sizeof(ntpd_port));
} else if (strcasecmp(key, "ReverseLookups") == 0) {
return ntpd_get_name_from_address(buffer, buffer_size, peer_info, 0);
if (include_unit_id)
- ssnprintf(buffer, buffer_size, "%s-%" PRIu32, refclock_names[refclock_id],
- unit_id);
+ snprintf(buffer, buffer_size, "%s-%" PRIu32, refclock_names[refclock_id],
+ unit_id);
else
sstrncpy(buffer, refclock_names[refclock_id], buffer_size);
}
/* kerninfo -> estimated error */
- offset_loop = scale_loop * ((gauge_t)ntohl(ik->offset));
+ offset_loop = (gauge_t)((int32_t)ntohl(ik->offset) * scale_loop);
freq_loop = ntpd_read_fp(ik->freq);
- offset_error = scale_error * ((gauge_t)ntohl(ik->esterror));
+ offset_error = (gauge_t)((int32_t)ntohl(ik->esterror) * scale_error);
DEBUG("info_kernel:\n"
" pll offset = %.8g\n"
vl.values_len = 1;
sstrncpy(vl.plugin, "numa", sizeof(vl.plugin));
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "node%i", node);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "node%i", node);
sstrncpy(vl.type, "vmpage_action", sizeof(vl.type));
sstrncpy(vl.type_instance, type_instance, sizeof(vl.type_instance));
int status;
int success;
- ssnprintf(path, sizeof(path), NUMA_ROOT_DIR "/node%i/numastat", node);
+ snprintf(path, sizeof(path), NUMA_ROOT_DIR "/node%i/numastat", node);
fh = fopen(path, "r");
if (fh == NULL) {
struct stat statbuf = {0};
int status;
- ssnprintf(path, sizeof(path), NUMA_ROOT_DIR "/node%i", max_node + 1);
+ snprintf(path, sizeof(path), NUMA_ROOT_DIR "/node%i", max_node + 1);
status = stat(path, &statbuf);
if (status == 0) {
*
* Authors:
* Florian octo Forster <octo at collectd.org>
+ * Pavel Rochnyak <pavel2000 ngs.ru>
**/
#include "collectd.h"
nut_ups_t *next;
};
-static nut_ups_t *upslist_head = NULL;
-
-static pthread_mutex_t read_lock = PTHREAD_MUTEX_INITIALIZER;
-static int read_busy = 0;
-
-static const char *config_keys[] = {"UPS", "FORCESSL", "VERIFYPEER", "CAPATH"};
+static const char *config_keys[] = {"UPS", "FORCESSL", "VERIFYPEER", "CAPATH",
+ "CONNECTTIMEOUT"};
static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
static int force_ssl = 0; // Initialized to default of 0 (false)
static int verify_peer = 0; // Initialized to default of 0 (false)
+static int ssl_flags = UPSCLI_CONN_TRYSSL;
+static int connect_timeout = -1;
static char *ca_path = NULL;
-static void free_nut_ups_t(nut_ups_t *ups) {
+static int nut_read(user_data_t *user_data);
+
+static void free_nut_ups_t(void *arg) {
+ nut_ups_t *ups = arg;
+
if (ups->conn != NULL) {
upscli_disconnect(ups->conn);
sfree(ups->conn);
static int nut_add_ups(const char *name) {
nut_ups_t *ups;
int status;
+ char *cb_name;
DEBUG("nut plugin: nut_add_ups (name = %s);", name);
return 1;
}
- if (upslist_head == NULL)
- upslist_head = ups;
- else {
- nut_ups_t *last = upslist_head;
- while (last->next != NULL)
- last = last->next;
- last->next = ups;
+ cb_name = ssnprintf_alloc("nut/%s", name);
+
+ status = plugin_register_complex_read(
+ /* group = */ "nut",
+ /* name = */ cb_name,
+ /* callback = */ nut_read,
+ /* interval = */ 0,
+ /* user_data = */ &(user_data_t){
+ .data = ups, .free_func = free_nut_ups_t,
+ });
+
+ sfree(cb_name);
+
+ if (status == EINVAL) {
+ WARNING("nut plugin: UPS \"%s\" already added. "
+ "Please check your configuration.",
+ name);
+ return -1;
}
return 0;
return 0;
} /* int nut_ca_path */
+static int nut_set_connect_timeout(const char *value) {
+#if HAVE_UPSCLI_TRYCONNECT
+ long ret;
+
+ errno = 0;
+ ret = strtol(value, /* endptr = */ NULL, /* base = */ 10);
+ if (errno == 0)
+ connect_timeout = ret;
+ else
+ WARNING("nut plugin: The ConnectTimeout option requires numeric argument. "
+ "Setting ignored.");
+#else /* #if HAVE_UPSCLI_TRYCONNECT */
+ WARNING("nut plugin: Dependency libupsclient version insufficient (<2.6.2) "
+ "for ConnectTimeout option support. Setting ignored.");
+#endif
+ return 0;
+} /* int nut_set_connect_timeout */
+
static int nut_config(const char *key, const char *value) {
if (strcasecmp(key, "UPS") == 0)
return nut_add_ups(value);
return nut_verify_peer(value);
else if (strcasecmp(key, "CAPATH") == 0)
return nut_ca_path(value);
+ else if (strcasecmp(key, "CONNECTTIMEOUT") == 0)
+ return nut_set_connect_timeout(value);
else
return -1;
} /* int nut_config */
vl.values = &(value_t){.gauge = value};
vl.values_len = 1;
- sstrncpy(vl.host,
- (strcasecmp(ups->hostname, "localhost") == 0) ? hostname_g
- : ups->hostname,
- sizeof(vl.host));
+ if (strcasecmp(ups->hostname, "localhost") != 0)
+ sstrncpy(vl.host, ups->hostname, sizeof(vl.host));
sstrncpy(vl.plugin, "nut", sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, ups->upsname, sizeof(vl.plugin_instance));
sstrncpy(vl.type, type, sizeof(vl.type));
} /* void nut_submit */
static int nut_connect(nut_ups_t *ups) {
-#if HAVE_UPSCLI_INIT
- int status;
- int ssl_status;
- int ssl_flags;
+ int status, ssl_status;
- if (verify_peer == 1 && force_ssl == 0) {
- WARNING("nut plugin: nut_connect: VerifyPeer true but ForceSSL "
- "false. Setting ForceSSL to true.");
- force_ssl = 1;
- }
-
- if (verify_peer == 1 && ca_path == NULL) {
- ERROR("nut plugin: nut_connect: VerifyPeer true but missing "
- "CAPath value.");
- return -1;
- }
-
- if (verify_peer == 1) {
- status = upscli_init(verify_peer, ca_path, NULL, NULL);
-
- if (status != 1) {
- ERROR("nut plugin: nut_connect: upscli_init (%i, %s) failed: %s",
- verify_peer, ca_path, upscli_strerror(ups->conn));
- upscli_cleanup();
- return -1;
- }
- } /* if (verify_peer == 1) */
-
- if (verify_peer == 1)
- ssl_flags = (UPSCLI_CONN_REQSSL | UPSCLI_CONN_CERTVERIF);
- else if (force_ssl == 1)
- ssl_flags = UPSCLI_CONN_REQSSL;
- else
- ssl_flags = UPSCLI_CONN_TRYSSL;
+#if HAVE_UPSCLI_TRYCONNECT
+ struct timeval tv;
+ tv.tv_sec = connect_timeout / 1000;
+ tv.tv_usec = connect_timeout % 1000;
+ status =
+ upscli_tryconnect(ups->conn, ups->hostname, ups->port, ssl_flags, &tv);
+#else /* #if HAVE_UPSCLI_TRYCONNECT */
status = upscli_connect(ups->conn, ups->hostname, ups->port, ssl_flags);
+#endif
if (status != 0) {
ERROR("nut plugin: nut_connect: upscli_connect (%s, %i) failed: %s",
ups->hostname, ups->port, upscli_strerror(ups->conn));
sfree(ups->conn);
- upscli_cleanup();
return -1;
} /* if (status != 0) */
ERROR("nut plugin: nut_connect: upscli_ssl failed: %s",
upscli_strerror(ups->conn));
sfree(ups->conn);
- upscli_cleanup();
return -1;
} /* if (ssl_status == 1 && verify_peer == 1) */
return 0;
-
-#else /* #if HAVE_UPSCLI_INIT */
- int status;
- int ssl_status;
- int ssl_flags;
-
- if (verify_peer == 1 || ca_path != NULL) {
- WARNING("nut plugin: nut_connect: Dependency libupsclient version "
- "insufficient (<2.7) for VerifyPeer support. Ignoring VerifyPeer "
- "and CAPath.");
- }
-
- if (force_ssl == 1)
- ssl_flags = UPSCLI_CONN_REQSSL;
- else
- ssl_flags = UPSCLI_CONN_TRYSSL;
-
- status = upscli_connect(ups->conn, ups->hostname, ups->port, ssl_flags);
-
- if (status != 0) {
- ERROR("nut plugin: nut_connect: upscli_connect (%s, %i) failed: %s",
- ups->hostname, ups->port, upscli_strerror(ups->conn));
- sfree(ups->conn);
- return -1;
- } /* if (status != 0) */
-
- INFO("nut plugin: Connection to (%s, %i) established.", ups->hostname,
- ups->port);
-
- // Output INFO or WARNING based on SSL
- ssl_status = upscli_ssl(ups->conn); // 1 for SSL, 0 for not, -1 for error
- if (ssl_status == 1) {
- INFO("nut plugin: Connection is secured with SSL with no verification "
- "of server SSL certificate.");
- } else if (ssl_status == 0) {
- WARNING("nut plugin: Connection is unsecured (no SSL).");
- } else {
- ERROR("nut plugin: nut_connect: upscli_ssl failed: %s",
- upscli_strerror(ups->conn));
- sfree(ups->conn);
- return -1;
- } /* if (ssl_status == 1 && verify_peer == 1) */
- return 0;
-#endif
}
-static int nut_read_one(nut_ups_t *ups) {
+static int nut_read(user_data_t *user_data) {
+ nut_ups_t *ups = user_data->data;
const char *query[3] = {"VAR", ups->upsname, NULL};
unsigned int query_num = 2;
char **answer;
* error */
status = upscli_list_start(ups->conn, query_num, query);
if (status != 0) {
- ERROR("nut plugin: nut_read_one: upscli_list_start (%s) failed: %s",
+ ERROR("nut plugin: nut_read: upscli_list_start (%s) failed: %s",
ups->upsname, upscli_strerror(ups->conn));
upscli_disconnect(ups->conn);
sfree(ups->conn);
-#if HAVE_UPSCLI_INIT
- upscli_cleanup();
-#endif
return -1;
}
} /* while (upscli_list_next) */
return 0;
-} /* int nut_read_one */
+} /* int nut_read */
+
+static int nut_init(void) {
+#if HAVE_UPSCLI_INIT
+ if (verify_peer == 1 && force_ssl == 0) {
+ WARNING("nut plugin: nut_connect: VerifyPeer true but ForceSSL "
+ "false. Setting ForceSSL to true.");
+ force_ssl = 1;
+ }
+
+ if (verify_peer == 1 && ca_path == NULL) {
+ ERROR("nut plugin: nut_connect: VerifyPeer true but missing "
+ "CAPath value.");
+ plugin_unregister_read_group("nut");
+ return -1;
+ }
-static int nut_read(void) {
- int success = 0;
+ if (verify_peer == 1 || force_ssl == 1) {
+ int status = upscli_init(verify_peer, ca_path, NULL, NULL);
- pthread_mutex_lock(&read_lock);
- success = read_busy;
- read_busy = 1;
- pthread_mutex_unlock(&read_lock);
+ if (status != 1) {
+ ERROR("nut plugin: upscli_init (%i, %s) failed", verify_peer, ca_path);
+ upscli_cleanup();
+ plugin_unregister_read_group("nut");
+ return -1;
+ }
+ } /* if (verify_peer == 1) */
+
+ if (verify_peer == 1)
+ ssl_flags = (UPSCLI_CONN_REQSSL | UPSCLI_CONN_CERTVERIF);
+ else if (force_ssl == 1)
+ ssl_flags = UPSCLI_CONN_REQSSL;
- if (success != 0)
- return 0;
+#else /* #if HAVE_UPSCLI_INIT */
+ if (verify_peer == 1 || ca_path != NULL) {
+ WARNING("nut plugin: nut_connect: Dependency libupsclient version "
+ "insufficient (<2.7) for VerifyPeer support. Ignoring VerifyPeer "
+ "and CAPath.");
+ verify_peer = 0;
+ }
- for (nut_ups_t *ups = upslist_head; ups != NULL; ups = ups->next)
- if (nut_read_one(ups) == 0)
- success++;
+ if (force_ssl == 1)
+ ssl_flags = UPSCLI_CONN_REQSSL;
+#endif
- pthread_mutex_lock(&read_lock);
- read_busy = 0;
- pthread_mutex_unlock(&read_lock);
+ if (connect_timeout <= 0)
+ connect_timeout = (long)CDTIME_T_TO_MS(plugin_get_interval());
- return (success != 0) ? 0 : -1;
-} /* int nut_read */
+ return 0;
+} /* int nut_init */
static int nut_shutdown(void) {
- nut_ups_t *this;
- nut_ups_t *next;
-
- this = upslist_head;
- while (this != NULL) {
- next = this->next;
- free_nut_ups_t(this);
- this = next;
- }
#if HAVE_UPSCLI_INIT
upscli_cleanup();
#endif
void module_register(void) {
plugin_register_config("nut", nut_config, config_keys, config_keys_num);
- plugin_register_read("nut", nut_read);
+ plugin_register_init("nut", nut_init);
plugin_register_shutdown("nut", nut_shutdown);
} /* void module_register */
if (config_want_links == OLSRD_WANT_DETAIL) {
char type_instance[DATA_MAX_NAME_LEN];
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s-lq", fields[0],
- fields[1]);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s-lq", fields[0],
+ fields[1]);
DEBUG("olsrd plugin: links: type_instance = %s; lq = %g;", type_instance,
lq);
if (config_want_links == OLSRD_WANT_DETAIL) {
char type_instance[DATA_MAX_NAME_LEN];
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s-rx", fields[0],
- fields[1]);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s-rx", fields[0],
+ fields[1]);
DEBUG("olsrd plugin: links: type_instance = %s; nlq = %g;", type_instance,
lq);
if (config_want_topology == OLSRD_WANT_DETAIL) {
char type_instance[DATA_MAX_NAME_LEN] = {0};
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s-lq", fields[0],
- fields[1]);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s-lq", fields[0],
+ fields[1]);
DEBUG("olsrd plugin: type_instance = %s; lq = %g;", type_instance, lq);
olsrd_submit(/* p.-inst = */ "topology", /* type = */ "signal_quality",
type_instance, lq);
} else {
char type_instance[DATA_MAX_NAME_LEN] = {0};
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s-nlq", fields[0],
- fields[1]);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s-nlq", fields[0],
+ fields[1]);
DEBUG("olsrd plugin: type_instance = %s; nlq = %g;", type_instance, nlq);
olsrd_submit(/* p.-inst = */ "topology", /* type = */ "signal_quality",
type_instance, nlq);
char subpath[4096];
int status;
- status = ssnprintf(subpath, sizeof(subpath), "%s/main", path);
+ status = snprintf(subpath, sizeof(subpath), "%s/main", path);
if ((status > 0) && (status < (int)sizeof(subpath)))
cow_read_bus(subpath);
- status = ssnprintf(subpath, sizeof(subpath), "%s/aux", path);
+ status = snprintf(subpath, sizeof(subpath), "%s/aux", path);
if ((status > 0) && (status < (int)sizeof(subpath)))
cow_read_bus(subpath);
dummy = NULL;
if (strcmp("/", path) == 0)
- status = ssnprintf(subpath, sizeof(subpath), "/%s", buffer_ptr);
+ status = snprintf(subpath, sizeof(subpath), "/%s", buffer_ptr);
else
- status = ssnprintf(subpath, sizeof(subpath), "%s/%s", path, buffer_ptr);
+ status = snprintf(subpath, sizeof(subpath), "%s/%s", path, buffer_ptr);
if ((status <= 0) || (status >= (int)sizeof(subpath)))
continue;
char *password;
char *cacert;
char *host;
- int state;
_Bool starttls;
int timeout;
char *url;
};
typedef struct cldap_s cldap_t; /* }}} */
-static cldap_t **databases = NULL;
-static size_t databases_num = 0;
-
-static void cldap_free(cldap_t *st) /* {{{ */
+static void cldap_free(void *arg) /* {{{ */
{
+ cldap_t *st = arg;
+
if (st == NULL)
return;
sfree(st->name);
sfree(st->url);
if (st->ld)
- ldap_memfree(st->ld);
+ ldap_unbind_ext_s(st->ld, NULL, NULL);
+
sfree(st);
} /* }}} void cldap_free */
/* initialize ldap for each host */
static int cldap_init_host(cldap_t *st) /* {{{ */
{
- LDAP *ld;
int rc;
- if (st->state && st->ld) {
+ if (st->ld) {
DEBUG("openldap plugin: Already connected to %s", st->url);
return 0;
}
- rc = ldap_initialize(&ld, st->url);
+ rc = ldap_initialize(&st->ld, st->url);
if (rc != LDAP_SUCCESS) {
ERROR("openldap plugin: ldap_initialize failed: %s", ldap_err2string(rc));
- st->state = 0;
- if (ld != NULL)
- ldap_unbind_ext_s(ld, NULL, NULL);
+ if (st->ld != NULL)
+ ldap_unbind_ext_s(st->ld, NULL, NULL);
+ st->ld = NULL;
return (-1);
}
- st->ld = ld;
-
ldap_set_option(st->ld, LDAP_OPT_PROTOCOL_VERSION, &st->version);
ldap_set_option(st->ld, LDAP_OPT_TIMEOUT,
}
if (st->starttls != 0) {
- rc = ldap_start_tls_s(ld, NULL, NULL);
+ rc = ldap_start_tls_s(st->ld, NULL, NULL);
if (rc != LDAP_SUCCESS) {
ERROR("openldap plugin: Failed to start tls on %s: %s", st->url,
ldap_err2string(rc));
- st->state = 0;
- if (st->ld != NULL)
- ldap_unbind_ext_s(st->ld, NULL, NULL);
+ ldap_unbind_ext_s(st->ld, NULL, NULL);
+ st->ld = NULL;
return (-1);
}
}
if (rc != LDAP_SUCCESS) {
ERROR("openldap plugin: Failed to bind to %s: %s", st->url,
ldap_err2string(rc));
- st->state = 0;
- if (st->ld != NULL)
- ldap_unbind_ext_s(st->ld, NULL, NULL);
+ ldap_unbind_ext_s(st->ld, NULL, NULL);
+ st->ld = NULL;
return (-1);
} else {
DEBUG("openldap plugin: Successfully connected to %s", st->url);
- st->state = 1;
return 0;
}
} /* }}} static cldap_init_host */
if (rc != LDAP_SUCCESS) {
ERROR("openldap plugin: Failed to execute search: %s", ldap_err2string(rc));
ldap_msgfree(result);
- st->state = 0;
- if (st->ld != NULL)
- ldap_unbind_ext_s(st->ld, NULL, NULL);
+ ldap_unbind_ext_s(st->ld, NULL, NULL);
+ st->ld = NULL;
return (-1);
}
if ((olmbdb_list =
ldap_get_values_len(st->ld, e, "olmBDBEntryCache")) != NULL) {
olmbdb_data = *olmbdb_list[0];
- ssnprintf(typeinst, sizeof(typeinst), "bdbentrycache-%s",
- nc_data.bv_val);
+ snprintf(typeinst, sizeof(typeinst), "bdbentrycache-%s",
+ nc_data.bv_val);
cldap_submit_gauge("cache_size", typeinst, atoll(olmbdb_data.bv_val),
st);
ldap_value_free_len(olmbdb_list);
if ((olmbdb_list = ldap_get_values_len(st->ld, e, "olmBDBDNCache")) !=
NULL) {
olmbdb_data = *olmbdb_list[0];
- ssnprintf(typeinst, sizeof(typeinst), "bdbdncache-%s",
- nc_data.bv_val);
+ snprintf(typeinst, sizeof(typeinst), "bdbdncache-%s", nc_data.bv_val);
cldap_submit_gauge("cache_size", typeinst, atoll(olmbdb_data.bv_val),
st);
ldap_value_free_len(olmbdb_list);
if ((olmbdb_list = ldap_get_values_len(st->ld, e, "olmBDBIDLCache")) !=
NULL) {
olmbdb_data = *olmbdb_list[0];
- ssnprintf(typeinst, sizeof(typeinst), "bdbidlcache-%s",
- nc_data.bv_val);
+ snprintf(typeinst, sizeof(typeinst), "bdbidlcache-%s",
+ nc_data.bv_val);
cldap_submit_gauge("cache_size", typeinst, atoll(olmbdb_data.bv_val),
st);
ldap_value_free_len(olmbdb_list);
ldap_free_urldesc(ludpp);
}
- if (status == 0) {
- cldap_t **temp;
-
- temp = (cldap_t **)realloc(databases,
- sizeof(*databases) * (databases_num + 1));
-
- if (temp == NULL) {
- ERROR("openldap plugin: realloc failed");
- status = -1;
- } else {
- char callback_name[3 * DATA_MAX_NAME_LEN] = {0};
-
- databases = temp;
- databases[databases_num] = st;
- databases_num++;
-
- ssnprintf(callback_name, sizeof(callback_name), "openldap/%s/%s",
- (st->host != NULL) ? st->host : hostname_g,
- (st->name != NULL) ? st->name : "default");
-
- status = plugin_register_complex_read(/* group = */ NULL,
- /* name = */ callback_name,
- /* callback = */ cldap_read_host,
- /* interval = */ 0, &(user_data_t){
- .data = st,
- });
- }
- }
-
if (status != 0) {
cldap_free(st);
return -1;
}
- return 0;
+ char callback_name[3 * DATA_MAX_NAME_LEN] = {0};
+
+ snprintf(callback_name, sizeof(callback_name), "openldap/%s/%s",
+ (st->host != NULL) ? st->host : hostname_g,
+ (st->name != NULL) ? st->name : "default");
+
+ return plugin_register_complex_read(/* group = */ NULL,
+ /* name = */ callback_name,
+ /* callback = */ cldap_read_host,
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = st, .free_func = cldap_free,
+ });
} /* }}} int cldap_config_add */
static int cldap_config(oconfig_item_t *ci) /* {{{ */
return 0;
} /* }}} int cldap_init */
-static int cldap_shutdown(void) /* {{{ */
-{
- for (size_t i = 0; i < databases_num; i++)
- if (databases[i]->ld != NULL)
- ldap_unbind_ext_s(databases[i]->ld, NULL, NULL);
- sfree(databases);
- databases_num = 0;
-
- return 0;
-} /* }}} int cldap_shutdown */
-
void module_register(void) /* {{{ */
{
plugin_register_complex_config("openldap", cldap_config);
plugin_register_init("openldap", cldap_init);
- plugin_register_shutdown("openldap", cldap_shutdown);
} /* }}} void module_register */
#if defined(__APPLE__)
* Florian octo Forster <octo at collectd.org>
* Marco Chiappero <marco at absence.it>
* Fabian Schuh <mail at xeroc.org>
+ * Pavel Rochnyak <pavel2000 ngs.ru>
**/
#include "collectd.h"
#include "common.h"
#include "plugin.h"
-#define V1STRING \
+/**
+ * There is two main kinds of OpenVPN status file:
+ * - for 'single' mode (point-to-point or client mode)
+ * - for 'multi' mode (server with multiple clients)
+ *
+ * For 'multi' there is 3 versions of status file format:
+ * - version 1 - First version of status file: without line type tokens,
+ * comma delimited for easy machine parsing. Currently used by default.
+ * Added in openvpn-2.0-beta3.
+ * - version 2 - with line type tokens, with 'HEADER' line type, uses comma
+ * as a delimiter.
+ * Added in openvpn-2.0-beta15.
+ * - version 3 - The only difference from version 2 is delimiter: in version 3
+ * tabs are used instead of commas. Set of fields is the same.
+ * Added in openvpn-2.1_rc14.
+ *
+ * For versions 2/3 there may be different sets of fields in different
+ * OpenVPN versions.
+ *
+ * Versions 2.0, 2.1, 2.2:
+ * Common Name,Real Address,Virtual Address,
+ * Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t)
+ *
+ * Version 2.3:
+ * Common Name,Real Address,Virtual Address,
+ * Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t),Username
+ *
+ * Version 2.4:
+ * Common Name,Real Address,Virtual Address,Virtual IPv6 Address,
+ * Bytes Received,Bytes Sent,Connected Since,Connected Since (time_t),Username,
+ * Client ID,Peer ID
+ *
+ * Current Collectd code tries to handle changes in this field set,
+ * if they are backward-compatible.
+ **/
+
+#define TITLE_SINGLE "OpenVPN STATISTICS\n"
+#define TITLE_V1 "OpenVPN CLIENT LIST\n"
+#define TITLE_V2 "TITLE"
+
+#define V1HEADER \
"Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since\n"
-#define V2STRING \
- "HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Bytes " \
- "Received,Bytes Sent,Connected Since,Connected Since (time_t)\n"
-#define V3STRING \
- "HEADER CLIENT_LIST Common Name Real Address Virtual Address Bytes " \
- "Received Bytes Sent Connected Since Connected Since (time_t)\n"
-#define V4STRING \
- "HEADER,CLIENT_LIST,Common Name,Real Address,Virtual Address,Bytes " \
- "Received,Bytes Sent,Connected Since,Connected Since (time_t),Username\n"
-#define VSSTRING "OpenVPN STATISTICS\n"
struct vpn_status_s {
char *file;
- enum {
- MULTI1 = 1, /* status-version 1 */
- MULTI2, /* status-version 2 */
- MULTI3, /* status-version 3 */
- MULTI4, /* status-version 4 */
- SINGLE = 10 /* currently no versions for single mode, maybe in the future */
- } version;
char *name;
};
typedef struct vpn_status_s vpn_status_t;
-static vpn_status_t **vpn_list = NULL;
-static int vpn_num = 0;
-
static _Bool new_naming_schema = 0;
static _Bool collect_compression = 1;
static _Bool collect_user_count = 0;
static int config_keys_num = STATIC_ARRAY_SIZE(config_keys);
/* Helper function
- * copy-n-pasted from common.c - changed delim to "," */
+ * copy-n-pasted from common.c - changed delim to ",\t" */
static int openvpn_strsplit(char *string, char **fields, size_t size) {
- size_t i;
- char *ptr;
- char *saveptr;
-
- i = 0;
- ptr = string;
- saveptr = NULL;
- while ((fields[i] = strtok_r(ptr, ",", &saveptr)) != NULL) {
+ size_t i = 0;
+ char *ptr = string;
+ char *saveptr = NULL;
+
+ while ((fields[i] = strtok_r(ptr, ",\t", &saveptr)) != NULL) {
ptr = NULL;
i++;
return i;
} /* int openvpn_strsplit */
+static void openvpn_free(void *arg) {
+ vpn_status_t *st = arg;
+
+ sfree(st->file);
+ sfree(st);
+} /* void openvpn_free */
+
/* dispatches number of users */
static void numusers_submit(const char *pinst, const char *tinst,
gauge_t value) {
char buffer[1024];
char *fields[4];
const int max_fields = STATIC_ARRAY_SIZE(fields);
- int fields_num, read = 0;
-
- derive_t link_rx, link_tx;
- derive_t tun_rx, tun_tx;
- derive_t pre_compress, post_compress;
- derive_t pre_decompress, post_decompress;
- derive_t overhead_rx, overhead_tx;
-
- link_rx = 0;
- link_tx = 0;
- tun_rx = 0;
- tun_tx = 0;
- pre_compress = 0;
- post_compress = 0;
- pre_decompress = 0;
- post_decompress = 0;
+
+ derive_t link_rx = 0, link_tx = 0;
+ derive_t tun_rx = 0, tun_tx = 0;
+ derive_t pre_compress = 0, post_compress = 0;
+ derive_t pre_decompress = 0, post_decompress = 0;
while (fgets(buffer, sizeof(buffer), fh) != NULL) {
- fields_num = openvpn_strsplit(buffer, fields, max_fields);
+ int fields_num = openvpn_strsplit(buffer, fields, max_fields);
/* status file is generated by openvpn/sig.c:print_status()
* http://svn.openvpn.net/projects/openvpn/trunk/openvpn/sig.c
iostats_submit(name, "traffic", link_rx, link_tx);
/* we need to force this order to avoid negative values with these unsigned */
- overhead_rx = (((link_rx - pre_decompress) + post_decompress) - tun_rx);
- overhead_tx = (((link_tx - post_compress) + pre_compress) - tun_tx);
+ derive_t overhead_rx =
+ (((link_rx - pre_decompress) + post_decompress) - tun_rx);
+ derive_t overhead_tx = (((link_tx - post_compress) + pre_compress) - tun_tx);
iostats_submit(name, "overhead", overhead_rx, overhead_tx);
compression_submit(name, "data_out", pre_compress, post_compress);
}
- read = 1;
-
- return read;
+ return 0;
} /* int single_read */
/* for reading status version 1 */
static int multi1_read(const char *name, FILE *fh) {
char buffer[1024];
char *fields[10];
- int fields_num, found_header = 0;
+ const int max_fields = STATIC_ARRAY_SIZE(fields);
long long sum_users = 0;
+ _Bool found_header = 0;
/* read the file until the "ROUTING TABLE" line is found (no more info after)
*/
if (strcmp(buffer, "ROUTING TABLE\n") == 0)
break;
- if (strcmp(buffer, V1STRING) == 0) {
+ if (strcmp(buffer, V1HEADER) == 0) {
found_header = 1;
continue;
}
/* we can't start reading data until this string is found */
continue;
- fields_num = openvpn_strsplit(buffer, fields, STATIC_ARRAY_SIZE(fields));
+ int fields_num = openvpn_strsplit(buffer, fields, max_fields);
if (fields_num < 4)
continue;
}
if (ferror(fh))
- return 0;
+ return -1;
+
+ if (found_header == 0) {
+ NOTICE("openvpn plugin: Unknown file format in instance %s, please "
+ "report this as bug. Make sure to include "
+ "your status file, so the plugin can "
+ "be adapted.",
+ name);
+ return -1;
+ }
if (collect_user_count)
numusers_submit(name, name, sum_users);
- return 1;
+ return 0;
} /* int multi1_read */
-/* for reading status version 2 */
+/* for reading status version 2 / version 3
+ * status file is generated by openvpn/multi.c:multi_print_status()
+ * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
+ */
static int multi2_read(const char *name, FILE *fh) {
char buffer[1024];
- char *fields[10];
+ /* OpenVPN-2.4 has 11 fields of data + 2 fields for "HEADER" and "CLIENT_LIST"
+ * So, set array size to 20 elements, to support future extensions.
+ */
+ char *fields[20];
const int max_fields = STATIC_ARRAY_SIZE(fields);
- int fields_num, read = 0;
long long sum_users = 0;
- while (fgets(buffer, sizeof(buffer), fh) != NULL) {
- fields_num = openvpn_strsplit(buffer, fields, max_fields);
-
- /* status file is generated by openvpn/multi.c:multi_print_status()
- * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
- *
- * The line we're expecting has 8 fields. We ignore all lines
- * with more or less fields.
- */
- if (fields_num != 8)
- continue;
-
- if (strcmp(fields[0], "CLIENT_LIST") != 0)
- continue;
-
- if (collect_user_count)
- /* If so, sum all users, ignore the individuals*/
- {
- sum_users += 1;
- }
- if (collect_individual_users) {
- if (new_naming_schema) {
- /* plugin inst = file name, type inst = fields[1] */
- iostats_submit(name, /* vpn instance */
- fields[1], /* "Common Name" */
- atoll(fields[4]), /* "Bytes Received" */
- atoll(fields[5])); /* "Bytes Sent" */
- } else {
- /* plugin inst = fields[1], type inst = "" */
- iostats_submit(fields[1], /* "Common Name" */
- NULL, /* unused when in multimode */
- atoll(fields[4]), /* "Bytes Received" */
- atoll(fields[5])); /* "Bytes Sent" */
- }
- }
-
- read = 1;
- }
-
- if (collect_user_count) {
- numusers_submit(name, name, sum_users);
- read = 1;
- }
-
- return read;
-} /* int multi2_read */
-
-/* for reading status version 3 */
-static int multi3_read(const char *name, FILE *fh) {
- char buffer[1024];
- char *fields[15];
- const int max_fields = STATIC_ARRAY_SIZE(fields);
- int fields_num, read = 0;
- long long sum_users = 0;
+ _Bool found_header = 0;
+ int idx_cname = 0;
+ int idx_bytes_recv = 0;
+ int idx_bytes_sent = 0;
+ int columns = 0;
while (fgets(buffer, sizeof(buffer), fh) != NULL) {
- fields_num = strsplit(buffer, fields, max_fields);
+ int fields_num = openvpn_strsplit(buffer, fields, max_fields);
- /* status file is generated by openvpn/multi.c:multi_print_status()
- * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
- *
- * The line we're expecting has 12 fields. We ignore all lines
- * with more or less fields.
- */
- if (fields_num != 12) {
- continue;
- } else {
- if (strcmp(fields[0], "CLIENT_LIST") != 0)
+ /* Try to find section header */
+ if (found_header == 0) {
+ if (fields_num < 2)
+ continue;
+ if (strcmp(fields[0], "HEADER") != 0)
+ continue;
+ if (strcmp(fields[1], "CLIENT_LIST") != 0)
continue;
- if (collect_user_count)
- /* If so, sum all users, ignore the individuals*/
- {
- sum_users += 1;
- }
-
- if (collect_individual_users) {
- if (new_naming_schema) {
- iostats_submit(name, /* vpn instance */
- fields[1], /* "Common Name" */
- atoll(fields[4]), /* "Bytes Received" */
- atoll(fields[5])); /* "Bytes Sent" */
- } else {
- iostats_submit(fields[1], /* "Common Name" */
- NULL, /* unused when in multimode */
- atoll(fields[4]), /* "Bytes Received" */
- atoll(fields[5])); /* "Bytes Sent" */
+ for (int i = 2; i < fields_num; i++) {
+ if (strcmp(fields[i], "Common Name") == 0) {
+ idx_cname = i - 1;
+ } else if (strcmp(fields[i], "Bytes Received") == 0) {
+ idx_bytes_recv = i - 1;
+ } else if (strcmp(fields[i], "Bytes Sent") == 0) {
+ idx_bytes_sent = i - 1;
}
}
- read = 1;
- }
- }
-
- if (collect_user_count) {
- numusers_submit(name, name, sum_users);
- read = 1;
- }
+ DEBUG("openvpn plugin: found MULTI v2/v3 HEADER. "
+ "Column idx: cname: %d, bytes_recv: %d, bytes_sent: %d",
+ idx_cname, idx_bytes_recv, idx_bytes_sent);
- return read;
-} /* int multi3_read */
+ if (idx_cname == 0 || idx_bytes_recv == 0 || idx_bytes_sent == 0)
+ break;
-/* for reading status version 4 */
-static int multi4_read(const char *name, FILE *fh) {
- char buffer[1024];
- char *fields[11];
- const int max_fields = STATIC_ARRAY_SIZE(fields);
- int fields_num, read = 0;
- long long sum_users = 0;
+ /* Data row has 1 field ("HEADER") less than header row */
+ columns = fields_num - 1;
- while (fgets(buffer, sizeof(buffer), fh) != NULL) {
- fields_num = openvpn_strsplit(buffer, fields, max_fields);
+ found_header = 1;
+ continue;
+ }
- /* status file is generated by openvpn/multi.c:multi_print_status()
- * http://svn.openvpn.net/projects/openvpn/trunk/openvpn/multi.c
- *
- * The line we're expecting has 9 fields. We ignore all lines
- * with more or less fields.
+ /* Header already found. Check if the line is the section data.
+ * If no match, then section was finished and there is no more data.
+ * Empty section is OK too.
*/
- if (fields_num != 9)
- continue;
+ if (fields_num == 0 || strcmp(fields[0], "CLIENT_LIST") != 0)
+ break;
- if (strcmp(fields[0], "CLIENT_LIST") != 0)
- continue;
+ /* Check if the data line fields count matches header line. */
+ if (fields_num != columns) {
+ ERROR("openvpn plugin: File format error in instance %s: Fields count "
+ "mismatch.",
+ name);
+ return -1;
+ }
+
+ DEBUG("openvpn plugin: found MULTI v2/v3 CLIENT_LIST. "
+ "Columns: cname: %s, bytes_recv: %s, bytes_sent: %s",
+ fields[idx_cname], fields[idx_bytes_recv], fields[idx_bytes_sent]);
if (collect_user_count)
- /* If so, sum all users, ignore the individuals*/
- {
sum_users += 1;
- }
+
if (collect_individual_users) {
if (new_naming_schema) {
/* plugin inst = file name, type inst = fields[1] */
- iostats_submit(name, /* vpn instance */
- fields[1], /* "Common Name" */
- atoll(fields[4]), /* "Bytes Received" */
- atoll(fields[5])); /* "Bytes Sent" */
+ iostats_submit(name, /* vpn instance */
+ fields[idx_cname], /* "Common Name" */
+ atoll(fields[idx_bytes_recv]), /* "Bytes Received" */
+ atoll(fields[idx_bytes_sent])); /* "Bytes Sent" */
} else {
- /* plugin inst = fields[1], type inst = "" */
- iostats_submit(fields[1], /* "Common Name" */
- NULL, /* unused when in multimode */
- atoll(fields[4]), /* "Bytes Received" */
- atoll(fields[5])); /* "Bytes Sent" */
+ /* plugin inst = fields[idx_cname], type inst = "" */
+ iostats_submit(fields[idx_cname], /* "Common Name" */
+ NULL, /* unused when in multimode */
+ atoll(fields[idx_bytes_recv]), /* "Bytes Received" */
+ atoll(fields[idx_bytes_sent])); /* "Bytes Sent" */
}
}
+ }
+
+ if (ferror(fh))
+ return -1;
- read = 1;
+ if (found_header == 0) {
+ NOTICE("openvpn plugin: Unknown file format in instance %s, please "
+ "report this as bug. Make sure to include "
+ "your status file, so the plugin can "
+ "be adapted.",
+ name);
+ return -1;
}
if (collect_user_count) {
numusers_submit(name, name, sum_users);
- read = 1;
}
- return read;
-} /* int multi4_read */
+ return 0;
+} /* int multi2_read */
/* read callback */
-static int openvpn_read(void) {
- FILE *fh;
- int read;
-
- read = 0;
-
- if (vpn_num == 0)
- return 0;
-
- /* call the right read function for every status entry in the list */
- for (int i = 0; i < vpn_num; i++) {
- int vpn_read = 0;
-
- fh = fopen(vpn_list[i]->file, "r");
- if (fh == NULL) {
- char errbuf[1024];
- WARNING("openvpn plugin: fopen(%s) failed: %s", vpn_list[i]->file,
- sstrerror(errno, errbuf, sizeof(errbuf)));
-
- continue;
- }
-
- switch (vpn_list[i]->version) {
- case SINGLE:
- vpn_read = single_read(vpn_list[i]->name, fh);
- break;
-
- case MULTI1:
- vpn_read = multi1_read(vpn_list[i]->name, fh);
- break;
-
- case MULTI2:
- vpn_read = multi2_read(vpn_list[i]->name, fh);
- break;
-
- case MULTI3:
- vpn_read = multi3_read(vpn_list[i]->name, fh);
- break;
-
- case MULTI4:
- vpn_read = multi4_read(vpn_list[i]->name, fh);
- break;
- }
-
- fclose(fh);
- read += vpn_read;
- }
-
- return read ? 0 : -1;
-} /* int openvpn_read */
-
-static int version_detect(const char *filename) {
- FILE *fh;
+static int openvpn_read(user_data_t *user_data) {
char buffer[1024];
- int version = 0;
+ int read = 0;
- /* Sanity checking. We're called from the config handling routine, so
- * better play it save. */
- if ((filename == NULL) || (*filename == 0))
- return 0;
+ vpn_status_t *st = user_data->data;
- fh = fopen(filename, "r");
+ FILE *fh = fopen(st->file, "r");
if (fh == NULL) {
char errbuf[1024];
- WARNING("openvpn plugin: Unable to read \"%s\": %s", filename,
+ WARNING("openvpn plugin: fopen(%s) failed: %s", st->file,
sstrerror(errno, errbuf, sizeof(errbuf)));
- return 0;
+
+ return -1;
}
- /* now search for the specific multimode data format */
- while ((fgets(buffer, sizeof(buffer), fh)) != NULL) {
- /* we look at the first line searching for SINGLE mode configuration */
- if (strcmp(buffer, VSSTRING) == 0) {
- DEBUG("openvpn plugin: found status file version SINGLE");
- version = SINGLE;
- break;
- }
- /* searching for multi version 1 */
- else if (strcmp(buffer, V1STRING) == 0) {
- DEBUG("openvpn plugin: found status file version MULTI1");
- version = MULTI1;
- break;
- }
- /* searching for multi version 2 */
- else if (strcmp(buffer, V2STRING) == 0) {
- DEBUG("openvpn plugin: found status file version MULTI2");
- version = MULTI2;
- break;
- }
- /* searching for multi version 3 */
- else if (strcmp(buffer, V3STRING) == 0) {
- DEBUG("openvpn plugin: found status file version MULTI3");
- version = MULTI3;
- break;
- }
- /* searching for multi version 4 */
- else if (strcmp(buffer, V4STRING) == 0) {
- DEBUG("openvpn plugin: found status file version MULTI4");
- version = MULTI4;
- break;
- }
+ // Try to detect file format by its first line
+ if ((fgets(buffer, sizeof(buffer), fh)) == NULL) {
+ WARNING("openvpn plugin: failed to get data from: %s", st->file);
+ fclose(fh);
+ return -1;
}
- if (version == 0) {
- /* This is only reached during configuration, so complaining to
- * the user is in order. */
+ if (strcmp(buffer, TITLE_SINGLE) == 0) { // OpenVPN STATISTICS
+ DEBUG("openvpn plugin: found status file SINGLE");
+ read = single_read(st->name, fh);
+ } else if (strcmp(buffer, TITLE_V1) == 0) { // OpenVPN CLIENT LIST
+ DEBUG("openvpn plugin: found status file MULTI version 1");
+ read = multi1_read(st->name, fh);
+ } else if (strncmp(buffer, TITLE_V2, strlen(TITLE_V2)) == 0) { // TITLE
+ DEBUG("openvpn plugin: found status file MULTI version 2/3");
+ read = multi2_read(st->name, fh);
+ } else {
NOTICE("openvpn plugin: %s: Unknown file format, please "
"report this as bug. Make sure to include "
"your status file, so the plugin can "
"be adapted.",
- filename);
+ st->file);
+ read = -1;
}
-
fclose(fh);
-
- return version;
-} /* int version_detect */
+ return read;
+} /* int openvpn_read */
static int openvpn_config(const char *key, const char *value) {
if (strcasecmp("StatusFile", key) == 0) {
- char *status_file, *status_name, *filename;
- int status_version;
- vpn_status_t *temp;
+ char callback_name[3 * DATA_MAX_NAME_LEN];
+ char *status_name;
- /* try to detect the status file format */
- status_version = version_detect(value);
-
- if (status_version == 0) {
- WARNING("openvpn plugin: unable to detect status version, "
- "discarding status file \"%s\".",
- value);
- return 1;
- }
-
- status_file = sstrdup(value);
+ char *status_file = strdup(value);
if (status_file == NULL) {
char errbuf[1024];
- WARNING("openvpn plugin: sstrdup failed: %s",
- sstrerror(errno, errbuf, sizeof(errbuf)));
+ ERROR("openvpn plugin: strdup failed: %s",
+ sstrerror(errno, errbuf, sizeof(errbuf)));
return 1;
}
/* it determines the file name as string starting at location filename + 1
*/
- filename = strrchr(status_file, (int)'/');
+ char *filename = strrchr(status_file, (int)'/');
if (filename == NULL) {
/* status_file is already the file name only */
status_name = status_file;
status_name = filename + 1;
}
- /* scan the list looking for a clone */
- for (int i = 0; i < vpn_num; i++) {
- if (strcasecmp(vpn_list[i]->name, status_name) == 0) {
- WARNING("openvpn plugin: status filename \"%s\" "
- "already used, please choose a "
- "different one.",
- status_name);
- sfree(status_file);
- return 1;
- }
- }
-
- /* create a new vpn element since file, version and name are ok */
- temp = malloc(sizeof(*temp));
- if (temp == NULL) {
+ /* create a new vpn element */
+ vpn_status_t *instance = calloc(1, sizeof(*instance));
+ if (instance == NULL) {
char errbuf[1024];
ERROR("openvpn plugin: malloc failed: %s",
sstrerror(errno, errbuf, sizeof(errbuf)));
sfree(status_file);
return 1;
}
- temp->file = status_file;
- temp->version = status_version;
- temp->name = status_name;
-
- vpn_status_t **tmp_list =
- realloc(vpn_list, (vpn_num + 1) * sizeof(*vpn_list));
- if (tmp_list == NULL) {
- char errbuf[1024];
- ERROR("openvpn plugin: realloc failed: %s",
- sstrerror(errno, errbuf, sizeof(errbuf)));
-
- sfree(vpn_list);
- sfree(temp->file);
- sfree(temp);
- return 1;
+ instance->file = status_file;
+ instance->name = status_name;
+
+ snprintf(callback_name, sizeof(callback_name), "openvpn/%s", status_name);
+
+ int status = plugin_register_complex_read(
+ /* group = */ "openvpn",
+ /* name = */ callback_name,
+ /* callback = */ openvpn_read,
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = instance, .free_func = openvpn_free,
+ });
+
+ if (status == EINVAL) {
+ WARNING("openvpn plugin: status filename \"%s\" "
+ "already used, please choose a "
+ "different one.",
+ status_name);
+ return -1;
}
- vpn_list = tmp_list;
-
- vpn_list[vpn_num] = temp;
- vpn_num++;
-
- DEBUG("openvpn plugin: status file \"%s\" added", temp->file);
+ DEBUG("openvpn plugin: status file \"%s\" added", instance->file);
} /* if (strcasecmp ("StatusFile", key) == 0) */
else if ((strcasecmp("CollectCompression", key) == 0) ||
(strcasecmp("Compression", key) == 0)) /* old, deprecated name */
return 0;
} /* int openvpn_config */
-/* shutdown callback */
-static int openvpn_shutdown(void) {
- for (int i = 0; i < vpn_num; i++) {
- sfree(vpn_list[i]->file);
- sfree(vpn_list[i]);
- }
-
- sfree(vpn_list);
-
- return 0;
-} /* int openvpn_shutdown */
-
static int openvpn_init(void) {
if (!collect_individual_users && !collect_compression &&
!collect_user_count) {
return -1;
}
- plugin_register_read("openvpn", openvpn_read);
- plugin_register_shutdown("openvpn", openvpn_shutdown);
-
return 0;
} /* int openvpn_init */
column_names[i] = column_names[i - 1] + DATA_MAX_NAME_LEN;
ALLOC_OR_FAIL(column_values, column_num * sizeof(char *));
- ALLOC_OR_FAIL(column_values[0],
- column_num * DATA_MAX_NAME_LEN);
+ ALLOC_OR_FAIL(column_values[0], column_num * DATA_MAX_NAME_LEN);
for (size_t i = 1; i < column_num; i++)
column_values[i] = column_values[i - 1] + DATA_MAX_NAME_LEN;
if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO)) {
char errfunc[256];
- ssnprintf(errfunc, sizeof(errfunc), "OCILogon(\"%s\")", db->connect_id);
+ snprintf(errfunc, sizeof(errfunc), "OCILogon(\"%s\")", db->connect_id);
o_report_error("o_read_database", db->name, NULL, errfunc, oci_error);
DEBUG("oracle plugin: OCILogon (%s): db->oci_service_context = %p;",
*
* Copyright(c) 2016 Intel Corporation. All rights reserved.
*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ *of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
+ * of the Software, and to permit persons to whom the Software is furnished to
+ *do
* so, subject to the following conditions:
*
- * The above copyright notice and this permission notice shall be included in all
+ * The above copyright notice and this permission notice shall be included in
+ *all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
return NULL;
}
opt_buff = new_buff;
- int ret = ssnprintf(opt_buff + buff_off, buff_size - buff_off, option_fmt,
- iface->name);
+ int ret = snprintf(opt_buff + buff_off, buff_size - buff_off, option_fmt,
+ iface->name);
if (ret < 0) {
sfree(opt_buff);
return NULL;
}
/* create OVS DB select params */
- if (ssnprintf(params_buff, params_size, params_fmt, opt_buff) < 0)
+ if (snprintf(params_buff, params_size, params_fmt, opt_buff) < 0)
sfree(params_buff);
sfree(opt_buff);
for (int j = 0; j < ci->values_num; j++) {
/* check interface name type */
if (ci->values[j].type != OCONFIG_TYPE_STRING) {
- ERROR(OVS_EVENTS_PLUGIN
- ": given interface name is not a string [idx=%d]", j);
+ ERROR(OVS_EVENTS_PLUGIN ": given interface name is not a string [idx=%d]",
+ j);
return -1;
}
/* allocate memory for configured interface */
}
/* Check and warn about invalid configuration */
if (!ovs_events_ctx.config.send_notification && !dispatch_values) {
- WARNING(OVS_EVENTS_PLUGIN ": send notification and dispatch values "
- "options are disabled. No information will be dispatched by the "
- "plugin. Please check your configuration");
+ WARNING(OVS_EVENTS_PLUGIN
+ ": send notification and dispatch values "
+ "options are disabled. No information will be dispatched by the "
+ "plugin. Please check your configuration");
}
/* Dispatch link status values if configured */
if (dispatch_values)
}
/* Dispatch OVS interface link status event to collectd */
-static void ovs_events_dispatch_notification(const ovs_events_iface_info_t *ifinfo) {
+static void
+ovs_events_dispatch_notification(const ovs_events_iface_info_t *ifinfo) {
const char *msg_link_status = NULL;
notification_t n = {
NOTIF_FAILURE, cdtime(), "", "", OVS_EVENTS_PLUGIN, "", "", "", NULL};
}
/* fill the notification data */
- ssnprintf(n.message, sizeof(n.message),
- "link state of \"%s\" interface has been changed to \"%s\"",
- ifinfo->name, msg_link_status);
+ snprintf(n.message, sizeof(n.message),
+ "link state of \"%s\" interface has been changed to \"%s\"",
+ ifinfo->name, msg_link_status);
sstrncpy(n.host, hostname_g, sizeof(n.host));
sstrncpy(n.plugin_instance, ifinfo->name, sizeof(n.plugin_instance));
sstrncpy(n.type, "gauge", sizeof(n.type));
}
/* Dispatch OVS interface link status value to collectd */
-static void ovs_events_link_status_submit(const ovs_events_iface_info_t *ifinfo) {
+static void
+ovs_events_link_status_submit(const ovs_events_iface_info_t *ifinfo) {
value_list_t vl = VALUE_LIST_INIT;
meta_data_t *meta = NULL;
*
* Copyright(c) 2016 Intel Corporation. All rights reserved.
*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
+ * of the Software, and to permit persons to whom the Software is furnished to
+ * do
* so, subject to the following conditions:
*
- * The above copyright notice and this permission notice shall be included in all
+ * The above copyright notice and this permission notice shall be included in
+ * all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
"external_ids", NULL};
/* subscribe to a tables */
- ovs_db_table_cb_register(pdb, "Bridge", bridge_columns,
- ovs_stats_bridge_table_change_cb,
+ ovs_db_table_cb_register(
+ pdb, "Bridge", bridge_columns, ovs_stats_bridge_table_change_cb,
ovs_stats_bridge_table_result_cb,
- OVS_DB_TABLE_CB_FLAG_INITIAL |
- OVS_DB_TABLE_CB_FLAG_INSERT |
+ OVS_DB_TABLE_CB_FLAG_INITIAL | OVS_DB_TABLE_CB_FLAG_INSERT |
OVS_DB_TABLE_CB_FLAG_MODIFY);
ovs_db_table_cb_register(pdb, "Bridge", bridge_columns,
ovs_stats_bridge_table_delete_cb, NULL,
OVS_DB_TABLE_CB_FLAG_DELETE);
- ovs_db_table_cb_register(pdb, "Port", port_columns,
- ovs_stats_port_table_change_cb,
+ ovs_db_table_cb_register(
+ pdb, "Port", port_columns, ovs_stats_port_table_change_cb,
ovs_stats_port_table_result_cb,
- OVS_DB_TABLE_CB_FLAG_INITIAL |
- OVS_DB_TABLE_CB_FLAG_INSERT |
+ OVS_DB_TABLE_CB_FLAG_INITIAL | OVS_DB_TABLE_CB_FLAG_INSERT |
OVS_DB_TABLE_CB_FLAG_MODIFY);
ovs_db_table_cb_register(pdb, "Port", port_columns,
ovs_stats_port_table_delete_cb, NULL,
OVS_DB_TABLE_CB_FLAG_DELETE);
- ovs_db_table_cb_register(pdb, "Interface", interface_columns,
- ovs_stats_interface_table_change_cb,
+ ovs_db_table_cb_register(
+ pdb, "Interface", interface_columns, ovs_stats_interface_table_change_cb,
ovs_stats_interface_table_result_cb,
- OVS_DB_TABLE_CB_FLAG_INITIAL |
- OVS_DB_TABLE_CB_FLAG_INSERT |
+ OVS_DB_TABLE_CB_FLAG_INITIAL | OVS_DB_TABLE_CB_FLAG_INSERT |
OVS_DB_TABLE_CB_FLAG_MODIFY);
}
plugin_name, ovs_stats_cfg.ovs_db_node, ovs_stats_cfg.ovs_db_serv,
ovs_stats_cfg.ovs_db_unix);
/* connect to OvS DB */
- if ((g_ovs_db = ovs_db_init (ovs_stats_cfg.ovs_db_node,
- ovs_stats_cfg.ovs_db_serv,
+ if ((g_ovs_db =
+ ovs_db_init(ovs_stats_cfg.ovs_db_node, ovs_stats_cfg.ovs_db_serv,
ovs_stats_cfg.ovs_db_unix, &cb)) == NULL) {
ERROR("%s: plugin: failed to connect to OvS DB server", plugin_name);
return -1;
if (NULL != (tmp = hv_fetch(hash, "host", 4, 0)))
sstrncpy(vl->host, SvPV_nolen(*tmp), sizeof(vl->host));
- else
- sstrncpy(vl->host, hostname_g, sizeof(vl->host));
if (NULL != (tmp = hv_fetch(hash, "plugin", 6, 0)))
sstrncpy(vl->plugin, SvPV_nolen(*tmp), sizeof(vl->plugin));
* meta => [ { name => <name>, value => <value> }, ... ]
* }
*/
-static int av2notification_meta(pTHX_ AV *array, notification_meta_t **ret_meta) {
+static int av2notification_meta(pTHX_ AV *array,
+ notification_meta_t **ret_meta) {
notification_meta_t *tail = NULL;
int len = av_len(array);
static char *get_module_name(char *buf, size_t buf_len, const char *module) {
int status = 0;
if (base_name[0] == '\0')
- status = ssnprintf(buf, buf_len, "%s", module);
+ status = snprintf(buf, buf_len, "%s", module);
else
- status = ssnprintf(buf, buf_len, "%s::%s", base_name, module);
+ status = snprintf(buf, buf_len, "%s::%s", base_name, module);
if ((status < 0) || ((unsigned int)status >= buf_len))
return NULL;
return buf;
ret = plugin_register_flush("perl", perl_flush, /* user_data = */ NULL);
}
- if (0 == ret)
+ if (0 == ret) {
ret = plugin_register_flush(pluginname, perl_flush, &userdata);
+ } else {
+ free(userdata.data);
+ }
} else {
ret = -1;
}
if (0 == ret)
XSRETURN_YES;
- else {
- free(userdata.data);
+ else
XSRETURN_EMPTY;
- }
} /* static void _plugin_register_generic_userdata ( ... ) */
/*
char *plugin;
HV *config;
+ if (NULL == perl_threads) {
+ log_err("A `Plugin' block was encountered but no plugin was loaded yet. "
+ "Put the appropriate `LoadPlugin' option in front of it.");
+ return -1;
+ }
+
dSP;
if ((1 != ci->values_num) || (OCONFIG_TYPE_STRING != ci->values[0].type)) {
* is ignored. */
#define C_PSQL_PAR_APPEND(buf, buf_len, parameter, value) \
if ((0 < (buf_len)) && (NULL != (value)) && ('\0' != *(value))) { \
- int s = ssnprintf(buf, buf_len, " %s = '%s'", parameter, value); \
+ int s = snprintf(buf, buf_len, " %s = '%s'", parameter, value); \
if (0 < s) { \
buf += s; \
buf_len -= s; \
if ((!db) || (!db->database))
return -1;
- status = ssnprintf(buf, buf_len, "dbname = '%s'", db->database);
+ status = snprintf(buf, buf_len, "dbname = '%s'", db->database);
if (0 < status) {
buf += status;
buf_len -= status;
params[i] = db->user;
break;
case C_PSQL_PARAM_INTERVAL:
- ssnprintf(interval, sizeof(interval), "%.3f",
- (db->interval > 0) ? CDTIME_T_TO_DOUBLE(db->interval)
- : plugin_get_interval());
+ snprintf(interval, sizeof(interval), "%.3f",
+ (db->interval > 0) ? CDTIME_T_TO_DOUBLE(db->interval)
+ : plugin_get_interval());
params[i] = interval;
break;
case C_PSQL_PARAM_INSTANCE:
}
return PQexecParams(db->conn, udb_query_get_statement(q), data->params_num,
- NULL, (const char *const*)params, NULL, NULL, 0);
+ NULL, (const char *const *)params, NULL, NULL, 0);
} /* c_psql_exec_query_params */
/* db->db_lock must be locked when calling this function */
str_len = string_len;
for (size_t i = 0; i < ds->ds_num; ++i) {
- int status = ssnprintf(str_ptr, str_len, ",'%s'", ds->ds[i].name);
+ int status = snprintf(str_ptr, str_len, ",'%s'", ds->ds[i].name);
if (status < 1)
return NULL;
int status;
if (store_rates)
- status = ssnprintf(str_ptr, str_len, ",'gauge'");
+ status = snprintf(str_ptr, str_len, ",'gauge'");
else
- status = ssnprintf(str_ptr, str_len, ",'%s'",
- DS_TYPE_TO_STRING(ds->ds[i].type));
+ status = snprintf(str_ptr, str_len, ",'%s'",
+ DS_TYPE_TO_STRING(ds->ds[i].type));
if (status < 1) {
str_len = 0;
if (ds->ds[i].type == DS_TYPE_GAUGE)
status =
- ssnprintf(str_ptr, str_len, "," GAUGE_FORMAT, vl->values[i].gauge);
+ snprintf(str_ptr, str_len, "," GAUGE_FORMAT, vl->values[i].gauge);
else if (store_rates) {
if (rates == NULL)
rates = uc_get_rate(ds, vl);
return NULL;
}
- status = ssnprintf(str_ptr, str_len, ",%lf", rates[i]);
+ status = snprintf(str_ptr, str_len, ",%lf", rates[i]);
} else if (ds->ds[i].type == DS_TYPE_COUNTER)
- status = ssnprintf(str_ptr, str_len, ",%llu", vl->values[i].counter);
+ status = snprintf(str_ptr, str_len, ",%llu", vl->values[i].counter);
else if (ds->ds[i].type == DS_TYPE_DERIVE)
- status = ssnprintf(str_ptr, str_len, ",%" PRIi64, vl->values[i].derive);
+ status = snprintf(str_ptr, str_len, ",%" PRIi64, vl->values[i].derive);
else if (ds->ds[i].type == DS_TYPE_ABSOLUTE)
- status = ssnprintf(str_ptr, str_len, ",%" PRIu64, vl->values[i].absolute);
+ status = snprintf(str_ptr, str_len, ",%" PRIu64, vl->values[i].absolute);
if (status < 1) {
str_len = 0;
if (db->writers_num > 0) {
char cb_name[DATA_MAX_NAME_LEN];
- ssnprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->database);
+ snprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->database);
if (!had_flush) {
plugin_unregister_flush("postgresql");
}
}
- ssnprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->instance);
+ snprintf(cb_name, sizeof(cb_name), "postgresql-%s", db->instance);
user_data_t ud = {.data = db, .free_func = c_psql_database_delete};
derive_t io_wchar;
derive_t io_syscr;
derive_t io_syscw;
+ derive_t io_diskr;
+ derive_t io_diskw;
_Bool has_io;
derive_t cswitch_vol;
derive_t io_wchar;
derive_t io_syscr;
derive_t io_syscw;
+ derive_t io_diskr;
+ derive_t io_diskw;
derive_t cswitch_vol;
derive_t cswitch_invol;
derive_t io_wchar;
derive_t io_syscr;
derive_t io_syscw;
+ derive_t io_diskr;
+ derive_t io_diskw;
derive_t cswitch_vol;
derive_t cswitch_invol;
new->io_wchar = -1;
new->io_syscr = -1;
new->io_syscw = -1;
+ new->io_diskr = -1;
+ new->io_diskw = -1;
new->cswitch_vol = -1;
new->cswitch_invol = -1;
ps_update_counter(&ps->io_syscw, &pse->io_syscw, entry->io_syscw);
}
+ if ((entry->io_diskr != -1) && (entry->io_diskw != -1)) {
+ ps_update_counter(&ps->io_diskr, &pse->io_diskr, entry->io_diskr);
+ ps_update_counter(&ps->io_diskw, &pse->io_diskw, entry->io_diskw);
+ }
+
if ((entry->cswitch_vol != -1) && (entry->cswitch_vol != -1)) {
ps_update_counter(&ps->cswitch_vol, &pse->cswitch_vol,
entry->cswitch_vol);
plugin_dispatch_values(&vl);
if ((ps->io_rchar != -1) && (ps->io_wchar != -1)) {
- sstrncpy(vl.type, "ps_disk_octets", sizeof(vl.type));
+ sstrncpy(vl.type, "io_octets", sizeof(vl.type));
vl.values[0].derive = ps->io_rchar;
vl.values[1].derive = ps->io_wchar;
vl.values_len = 2;
}
if ((ps->io_syscr != -1) && (ps->io_syscw != -1)) {
- sstrncpy(vl.type, "ps_disk_ops", sizeof(vl.type));
+ sstrncpy(vl.type, "io_ops", sizeof(vl.type));
vl.values[0].derive = ps->io_syscr;
vl.values[1].derive = ps->io_syscw;
vl.values_len = 2;
plugin_dispatch_values(&vl);
}
+ if ((ps->io_diskr != -1) && (ps->io_diskw != -1)) {
+ sstrncpy(vl.type, "disk_octets", sizeof(vl.type));
+ vl.values[0].derive = ps->io_diskr;
+ vl.values[1].derive = ps->io_diskw;
+ vl.values_len = 2;
+ plugin_dispatch_values(&vl);
+ }
+
if (ps->num_fd > 0) {
sstrncpy(vl.type, "file_handles", sizeof(vl.type));
vl.values[0].gauge = ps->num_fd;
"cpu_user_counter = %" PRIi64 "; cpu_system_counter = %" PRIi64 "; "
"io_rchar = %" PRIi64 "; io_wchar = %" PRIi64 "; "
"io_syscr = %" PRIi64 "; io_syscw = %" PRIi64 "; "
+ "io_diskr = %" PRIi64 "; io_diskw = %" PRIi64 "; "
"cswitch_vol = %" PRIi64 "; cswitch_invol = %" PRIi64 ";",
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);
+ ps->io_rchar, ps->io_wchar, ps->io_syscr, ps->io_syscw, ps->io_diskr,
+ ps->io_diskw, ps->cswitch_vol, ps->cswitch_invol);
} /* void ps_submit_proc_list */
#if KERNEL_LINUX || KERNEL_SOLARIS
char *fields[8];
int numfields;
- ssnprintf(dirname, sizeof(dirname), "/proc/%li/task", ps->id);
+ snprintf(dirname, sizeof(dirname), "/proc/%li/task", ps->id);
if ((dh = opendir(dirname)) == NULL) {
DEBUG("Failed to open directory `%s'", dirname);
tpid = ent->d_name;
- ssnprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", ps->id,
- tpid);
+ if (snprintf(filename, sizeof(filename), "/proc/%li/task/%s/status", ps->id,
+ tpid) >= sizeof(filename)) {
+ DEBUG("Filename too long: `%s'", filename);
+ continue;
+ }
+
if ((fh = fopen(filename, "r")) == NULL) {
DEBUG("Failed to open file `%s'", filename);
continue;
char *fields[8];
int numfields;
- ssnprintf(filename, sizeof(filename), "/proc/%li/status", pid);
+ snprintf(filename, sizeof(filename), "/proc/%li/status", pid);
if ((fh = fopen(filename, "r")) == NULL)
return -1;
char *fields[8];
int numfields;
- ssnprintf(filename, sizeof(filename), "/proc/%li/io", ps->id);
+ snprintf(filename, sizeof(filename), "/proc/%li/io", ps->id);
if ((fh = fopen(filename, "r")) == NULL) {
DEBUG("ps_read_io: Failed to open file `%s'", filename);
return -1;
val = &(ps->io_syscr);
else if (strncasecmp(buffer, "syscw:", 6) == 0)
val = &(ps->io_syscw);
+ else if (strncasecmp(buffer, "read_bytes:", 11) == 0)
+ val = &(ps->io_diskr);
+ else if (strncasecmp(buffer, "write_bytes:", 12) == 0)
+ val = &(ps->io_diskw);
else
continue;
struct dirent *ent;
int count = 0;
- ssnprintf(dirname, sizeof(dirname), "/proc/%i/fd", pid);
+ snprintf(dirname, sizeof(dirname), "/proc/%i/fd", pid);
if ((dh = opendir(dirname)) == NULL) {
DEBUG("Failed to open directory `%s'", dirname);
ssize_t status;
- ssnprintf(filename, sizeof(filename), "/proc/%li/stat", pid);
+ snprintf(filename, sizeof(filename), "/proc/%li/stat", pid);
status = read_file_contents(filename, buffer, sizeof(buffer) - 1);
if (status <= 0)
ps->io_wchar = -1;
ps->io_syscr = -1;
ps->io_syscw = -1;
+ ps->io_diskr = -1;
+ ps->io_diskw = -1;
ps->cswitch_vol = -1;
ps->cswitch_invol = -1;
if ((pid < 1) || (NULL == buf) || (buf_len < 2))
return NULL;
- ssnprintf(file, sizeof(file), "/proc/%li/cmdline", pid);
+ snprintf(file, sizeof(file), "/proc/%li/cmdline", pid);
errno = 0;
fd = open(file, O_RDONLY);
if (NULL == name)
return NULL;
- ssnprintf(buf, buf_len, "[%s]", name);
+ snprintf(buf, buf_len, "[%s]", name);
return buf;
}
ps->io_wchar = myUsage->pr_oublk * chars_per_block;
ps->io_syscr = myUsage->pr_sysc;
ps->io_syscw = myUsage->pr_sysc;
+ ps->io_diskr = -1;
+ ps->io_diskw = -1;
/*
* TODO: context switch counters for Solaris
pse.io_wchar = -1;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.io_diskr = -1;
+ pse.io_diskw = -1;
/* File descriptor count not implemented */
pse.num_fd = 0;
pse.io_wchar = -1;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.io_diskr = -1;
+ pse.io_diskw = -1;
/* file descriptor count not implemented */
pse.num_fd = 0;
pse.io_wchar = -1;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.io_diskr = -1;
+ pse.io_diskw = -1;
/* file descriptor count not implemented */
pse.num_fd = 0;
pse.io_wchar = -1;
pse.io_syscr = -1;
pse.io_syscw = -1;
+ pse.io_diskr = -1;
+ pse.io_diskw = -1;
pse.num_fd = 0;
if (values_list != NULL) {
char match_name[2 * DATA_MAX_NAME_LEN];
- ssnprintf(match_name, sizeof(match_name), "%s:%s", key_buffer,
- key_fields[i]);
+ snprintf(match_name, sizeof(match_name), "%s:%s", key_buffer,
+ key_fields[i]);
if (ignorelist_match(values_list, match_name))
continue;
static PyObject *cpy_register_notification(PyObject *self, PyObject *args,
PyObject *kwds) {
return cpy_register_generic_userdata((void *)plugin_register_notification,
- (void *)cpy_notification_callback,
- args, kwds);
+ (void *)cpy_notification_callback, args,
+ kwds);
}
static PyObject *cpy_register_flush(PyObject *self, PyObject *args,
}
static PyObject *cpy_unregister_write(PyObject *self, PyObject *arg) {
- return cpy_unregister_generic_userdata(plugin_unregister_write, arg,
- "write");
+ return cpy_unregister_generic_userdata(plugin_unregister_write, arg, "write");
}
static PyObject *cpy_unregister_notification(PyObject *self, PyObject *arg) {
}
static PyObject *cpy_unregister_flush(PyObject *self, PyObject *arg) {
- return cpy_unregister_generic_userdata(plugin_unregister_flush, arg,
- "flush");
+ return cpy_unregister_generic_userdata(plugin_unregister_flush, arg, "flush");
}
static PyObject *cpy_unregister_shutdown(PyObject *self, PyObject *arg) {
char *str;
int i;
- ssnprintf(field_name, sizeof(field_name), "db%d:keys=", db);
+ snprintf(field_name, sizeof(field_name), "db%d:keys=", db);
str = strstr(info_line, field_name);
if (!str)
return -1;
}
- ssnprintf(db_id, sizeof(db_id), "%d", db);
+ snprintf(db_id, sizeof(db_id), "%d", db);
redis_submit(node, "records", db_id, val);
}
return 0;
static int handle_interface(__attribute__((unused))
ros_connection_t *c, /* {{{ */
- const ros_interface_t *i,
- void *user_data) {
+ const ros_interface_t *i, void *user_data) {
if ((i == NULL) || (user_data == NULL))
return EINVAL;
return;
/*** RX ***/
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s-rx", r->interface,
- r->radio_name);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s-rx", r->interface,
+ r->radio_name);
cr_submit_gauge(rd, "bitrate", type_instance,
(gauge_t)(1000000.0 * r->rx_rate));
cr_submit_gauge(rd, "signal_power", type_instance,
cr_submit_gauge(rd, "signal_quality", type_instance, (gauge_t)r->rx_ccq);
/*** TX ***/
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s-tx", r->interface,
- r->radio_name);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s-tx", r->interface,
+ r->radio_name);
cr_submit_gauge(rd, "bitrate", type_instance,
(gauge_t)(1000000.0 * r->tx_rate));
cr_submit_gauge(rd, "signal_power", type_instance,
cr_submit_gauge(rd, "signal_quality", type_instance, (gauge_t)r->tx_ccq);
/*** RX / TX ***/
- ssnprintf(type_instance, sizeof(type_instance), "%s-%s", r->interface,
- r->radio_name);
+ snprintf(type_instance, sizeof(type_instance), "%s-%s", r->interface,
+ r->radio_name);
cr_submit_io(rd, "if_octets", type_instance, (derive_t)r->rx_bytes,
(derive_t)r->tx_bytes);
cr_submit_gauge(rd, "snr", type_instance, (gauge_t)r->signal_to_noise);
static int handle_regtable(__attribute__((unused))
ros_connection_t *c, /* {{{ */
- const ros_registration_table_t *r,
- void *user_data) {
+ const ros_registration_table_t *r, void *user_data) {
if ((r == NULL) || (user_data == NULL))
return EINVAL;
}
}
- ssnprintf(read_name, sizeof(read_name), "routeros/%s", router_data->node);
- if (status == 0)
- status = plugin_register_complex_read(
- /* group = */ NULL, read_name, cr_read, /* interval = */ 0,
- &(user_data_t){
- .data = router_data, .free_func = (void *)cr_free_data,
- });
-
- if (status != 0)
+ if (status != 0) {
cr_free_data(router_data);
+ return status;
+ }
- return status;
+ snprintf(read_name, sizeof(read_name), "routeros/%s", router_data->node);
+ return plugin_register_complex_read(
+ /* group = */ NULL, read_name, cr_read, /* interval = */ 0,
+ &(user_data_t){
+ .data = router_data, .free_func = (void *)cr_free_data,
+ });
} /* }}} int cr_config_router */
static int cr_config(oconfig_item_t *ci) {
memset(buffer, '\0', buffer_len);
t = CDTIME_T_TO_TIME_T(vl->time);
- status = ssnprintf(buffer, buffer_len, "%lu", (unsigned long)t);
+ status = snprintf(buffer, buffer_len, "%lu", (unsigned long)t);
if ((status < 1) || (status >= buffer_len))
return -1;
offset = status;
return -1;
if (ds->ds[i].type == DS_TYPE_COUNTER) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%llu",
- vl->values[i].counter);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%llu",
+ vl->values[i].counter);
} else if (ds->ds[i].type == DS_TYPE_GAUGE) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%f",
- vl->values[i].gauge);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%f",
+ vl->values[i].gauge);
} else if (ds->ds[i].type == DS_TYPE_DERIVE) {
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
- vl->values[i].derive);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
+ vl->values[i].derive);
} else /* if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */ {
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
- vl->values[i].absolute);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+ vl->values[i].absolute);
}
if ((status < 1) || (status >= (buffer_len - offset)))
return EINVAL;
if (datadir != NULL)
- ssnprintf(filename, sizeof(filename), "%s/%s.rrd", datadir, identifier);
+ snprintf(filename, sizeof(filename), "%s/%s.rrd", datadir, identifier);
else
- ssnprintf(filename, sizeof(filename), "%s.rrd", identifier);
+ snprintf(filename, sizeof(filename), "%s.rrd", identifier);
rrd_clear_error();
status = rrdc_connect(daemon_address);
* ALWAYS lock `cache_lock' first! */
static cdtime_t cache_timeout = 0;
static cdtime_t cache_flush_timeout = 0;
-static cdtime_t random_timeout = TIME_T_TO_CDTIME_T_STATIC(1);
+static cdtime_t random_timeout = 0;
static cdtime_t cache_flush_last;
static c_avl_tree_t *cache = NULL;
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
memset(buffer, '\0', buffer_len);
tt = CDTIME_T_TO_TIME_T(vl->time);
- status = ssnprintf(buffer, buffer_len, "%u", (unsigned int)tt);
+ status = snprintf(buffer, buffer_len, "%u", (unsigned int)tt);
if ((status < 1) || (status >= buffer_len))
return -1;
offset = status;
return -1;
if (ds->ds[i].type == DS_TYPE_COUNTER)
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%llu",
- vl->values[i].counter);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%llu",
+ vl->values[i].counter);
else if (ds->ds[i].type == DS_TYPE_GAUGE)
- status = ssnprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT,
- vl->values[i].gauge);
+ status = snprintf(buffer + offset, buffer_len - offset, ":" GAUGE_FORMAT,
+ vl->values[i].gauge);
else if (ds->ds[i].type == DS_TYPE_DERIVE)
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
- vl->values[i].derive);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIi64,
+ vl->values[i].derive);
else /*if (ds->ds[i].type == DS_TYPE_ABSOLUTE) */
- status = ssnprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
- vl->values[i].absolute);
+ status = snprintf(buffer + offset, buffer_len - offset, ":%" PRIu64,
+ vl->values[i].absolute);
if ((status < 1) || (status >= (buffer_len - offset)))
return -1;
tt = CDTIME_T_TO_TIME_T(vl->time);
switch (ds->ds[0].type) {
case DS_TYPE_DERIVE:
- status = ssnprintf(buffer, buffer_len, "%u:%" PRIi64, (unsigned)tt,
- vl->values[0].derive);
+ status = snprintf(buffer, buffer_len, "%u:%" PRIi64, (unsigned)tt,
+ vl->values[0].derive);
break;
case DS_TYPE_GAUGE:
- status = ssnprintf(buffer, buffer_len, "%u:" GAUGE_FORMAT, (unsigned)tt,
- vl->values[0].gauge);
+ status = snprintf(buffer, buffer_len, "%u:" GAUGE_FORMAT, (unsigned)tt,
+ vl->values[0].gauge);
break;
case DS_TYPE_COUNTER:
- status = ssnprintf(buffer, buffer_len, "%u:%llu", (unsigned)tt,
- vl->values[0].counter);
+ status = snprintf(buffer, buffer_len, "%u:%llu", (unsigned)tt,
+ vl->values[0].counter);
break;
case DS_TYPE_ABSOLUTE:
- status = ssnprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
- vl->values[0].absolute);
+ status = snprintf(buffer, buffer_len, "%u:%" PRIu64, (unsigned)tt,
+ vl->values[0].absolute);
break;
default:
return EINVAL;
CDTIME_T_TO_DOUBLE(timeout));
now = cdtime();
- timeout = TIME_T_TO_CDTIME_T(timeout);
/* Build a list of entries to be flushed */
iter = c_avl_get_iterator(cache);
} /* int rrd_cache_flush_identifier */
static int64_t rrd_get_random_variation(void) {
- long min;
- long max;
-
if (random_timeout == 0)
return 0;
- /* Assure that "cache_timeout + random_variation" is never negative. */
- if (random_timeout > cache_timeout) {
- INFO("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.",
- CDTIME_T_TO_DOUBLE(cache_timeout));
- random_timeout = cache_timeout;
- }
-
- max = (long)(random_timeout / 2);
- min = max - ((long)random_timeout);
-
- return (int64_t)cdrand_range(min, max);
+ return (int64_t)cdrand_range(-random_timeout, random_timeout);
} /* int64_t rrd_get_random_variation */
static int rrd_cache_insert(const char *filename, const char *value,
if ((cache_timeout > 0) &&
((cdtime() - cache_flush_last) > cache_flush_timeout))
- rrd_cache_flush(cache_flush_timeout);
+ rrd_cache_flush(cache_timeout + random_timeout);
pthread_mutex_unlock(&cache_lock);
}
cache_timeout = DOUBLE_TO_CDTIME_T(tmp);
} else if (strcasecmp("CacheFlush", key) == 0) {
- int tmp = atoi(value);
+ double tmp = atof(value);
if (tmp < 0) {
fprintf(stderr, "rrdtool: `CacheFlush' must "
"be greater than 0.\n");
"be greater than 0.\n");
return 1;
}
- cache_flush_timeout = tmp;
+ cache_flush_timeout = DOUBLE_TO_CDTIME_T(tmp);
} else if (strcasecmp("DataDir", key) == 0) {
char *tmp;
size_t len;
cache_flush_last = cdtime();
if (cache_timeout == 0) {
+ random_timeout = 0;
cache_flush_timeout = 0;
- } else if (cache_flush_timeout < cache_timeout)
+ } else if (cache_flush_timeout < cache_timeout) {
+ INFO("rrdtool plugin: \"CacheFlush %.3f\" is less than \"CacheTimeout %.3f\". "
+ "Ajusting \"CacheFlush\" to %.3f seconds.",
+ CDTIME_T_TO_DOUBLE(cache_flush_timeout),
+ CDTIME_T_TO_DOUBLE(cache_timeout),
+ CDTIME_T_TO_DOUBLE(cache_timeout * 10));
cache_flush_timeout = 10 * cache_timeout;
+ }
+
+ /* Assure that "cache_timeout + random_variation" is never negative. */
+ if (random_timeout > cache_timeout) {
+ INFO("rrdtool plugin: Adjusting \"RandomTimeout\" to %.3f seconds.",
+ CDTIME_T_TO_DOUBLE(cache_timeout));
+ random_timeout = cache_timeout;
+ }
pthread_mutex_unlock(&cache_lock);
int status = -1;
if (chip->bus == SENSORS_CHIP_NAME_BUS_ISA) {
- status = ssnprintf(buf, buf_size, "%s-isa-%04x", chip->prefix, chip->addr);
+ status = snprintf(buf, buf_size, "%s-isa-%04x", chip->prefix, chip->addr);
} else if (chip->bus == SENSORS_CHIP_NAME_BUS_DUMMY) {
status = snprintf(buf, buf_size, "%s-%s-%04x", chip->prefix, chip->busname,
chip->addr);
value_list_t vl = VALUE_LIST_INIT;
- status = ssnprintf(match_key, sizeof(match_key), "%s/%s-%s", plugin_instance,
- type, type_instance);
+ status = snprintf(match_key, sizeof(match_key), "%s/%s-%s", plugin_instance,
+ type, type_instance);
if (status < 1)
return;
}
cfdev->sdi = devlist->data;
g_slist_free(devlist);
- ssnprintf(hwident, sizeof(hwident), "%s %s %s",
- cfdev->sdi->vendor ? cfdev->sdi->vendor : "",
- cfdev->sdi->model ? cfdev->sdi->model : "",
- cfdev->sdi->version ? cfdev->sdi->version : "");
+ snprintf(hwident, sizeof(hwident), "%s %s %s",
+ cfdev->sdi->vendor ? cfdev->sdi->vendor : "",
+ cfdev->sdi->model ? cfdev->sdi->model : "",
+ cfdev->sdi->version ? cfdev->sdi->version : "");
INFO("sigrok plugin: Device \"%s\" is a %s", cfdev->name, hwident);
if (sr_dev_open(cfdev->sdi) != SR_OK)
sstrncpy(notif.host, hostname_g, sizeof(notif.host));
sstrncpy(notif.plugin_instance, name, sizeof(notif.plugin_instance));
sstrncpy(notif.type_instance, a->name, sizeof(notif.type_instance));
- ssnprintf(notif.message, sizeof(notif.message),
- "attribute %s is below allowed threshold (%d < %d)", a->name,
- a->current_value, a->threshold);
+ snprintf(notif.message, sizeof(notif.message),
+ "attribute %s is below allowed threshold (%d < %d)", a->name,
+ a->current_value, a->threshold);
plugin_dispatch_notification(¬if);
}
}
}
static int csnmp_oid_compare(oid_t const *left, oid_t const *right) {
- return snmp_oid_compare(left->oid, left->oid_len, right->oid,
- right->oid_len);
+ return snmp_oid_compare(left->oid, left->oid_len, right->oid, right->oid_len);
}
static int csnmp_oid_suffix(oid_t *dst, oid_t const *src, oid_t const *root) {
char *oid_str_ptr[MAX_OID_LEN];
for (size_t i = 0; i < o->oid_len; i++) {
- ssnprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
+ snprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
oid_str_ptr[i] = oid_str[i];
}
"= %i }",
hd->name, hd->address, hd->community, hd->version);
- ssnprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
+ snprintf(cb_name, sizeof(cb_name), "snmp-%s", hd->name);
status = plugin_register_complex_read(
/* group = */ NULL, cb_name, csnmp_read_host, hd->interval,
});
if (status != 0) {
ERROR("snmp plugin: Registering complex read function failed.");
- csnmp_host_definition_destroy(hd);
return -1;
}
else if (vb->type == ASN_BIT_STR)
src = (char *)vb->val.bitstring;
else if (vb->type == ASN_IPADDRESS) {
- return ssnprintf(dst, dst_size,
- "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
- (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
- (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
+ return snprintf(dst, dst_size,
+ "%" PRIu8 ".%" PRIu8 ".%" PRIu8 ".%" PRIu8 "",
+ (uint8_t)vb->val.string[0], (uint8_t)vb->val.string[1],
+ (uint8_t)vb->val.string[2], (uint8_t)vb->val.string[3]);
} else {
dst[0] = 0;
return EINVAL;
value_t val = csnmp_value_list_to_value(
vb, DS_TYPE_COUNTER,
/* scale = */ 1.0, /* shift = */ 0.0, hd->name, dd->name);
- ssnprintf(il->instance, sizeof(il->instance), "%llu", val.counter);
+ snprintf(il->instance, sizeof(il->instance), "%llu", val.counter);
}
/* TODO: Debugging output */
if (data->instance_prefix == NULL)
sstrncpy(vl.type_instance, temp, sizeof(vl.type_instance));
else
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
- data->instance_prefix, temp);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s%s",
+ data->instance_prefix, temp);
}
vl.values_len = data->values_len;
status = 0;
while (status == 0) {
- int oid_list_todo_num;
-
req = snmp_pdu_create(SNMP_MSG_GETNEXT);
if (req == NULL) {
ERROR("snmp plugin: snmp_pdu_create failed.");
break;
}
- oid_list_todo_num = 0;
+ size_t oid_list_todo_num = 0;
+ size_t var_idx[oid_list_len];
+ memset(var_idx, 0, sizeof(var_idx));
+
for (i = 0; i < oid_list_len; i++) {
/* Do not rerequest already finished OIDs */
if (!oid_list_todo[i])
continue;
- oid_list_todo_num++;
snmp_add_null_var(req, oid_list[i].oid, oid_list[i].oid_len);
+ var_idx[oid_list_todo_num] = i;
+ oid_list_todo_num++;
}
if (oid_list_todo_num == 0) {
break;
}
+ if (res->errstat != SNMP_ERR_NOERROR) {
+ if (res->errindex != 0) {
+ /* Find the OID which caused error */
+ for (i = 1, vb = res->variables; vb != NULL && i != res->errindex;
+ vb = vb->next_variable, i++)
+ /* do nothing */;
+ }
+
+ if ((res->errindex == 0) || (vb == NULL)) {
+ ERROR("snmp plugin: host %s; data %s: response error: %s (%li) ",
+ host->name, data->name, snmp_errstring(res->errstat),
+ res->errstat);
+ status = -1;
+ break;
+ }
+
+ char oid_buffer[1024] = {0};
+ snprint_objid(oid_buffer, sizeof(oid_buffer) - 1, vb->name,
+ vb->name_length);
+ NOTICE("snmp plugin: host %s; data %s: OID `%s` failed: %s", host->name,
+ data->name, oid_buffer, snmp_errstring(res->errstat));
+
+ /* Get value index from todo list and skip OID found */
+ assert(res->errindex <= oid_list_todo_num);
+ i = var_idx[res->errindex - 1];
+ assert(i < oid_list_len);
+ oid_list_todo[i] = 0;
+
+ snmp_free_pdu(res);
+ res = NULL;
+ continue;
+ }
+
for (vb = res->variables, i = 0; (vb != NULL);
vb = vb->next_variable, i++) {
/* Calculate value index from todo list */
(_dd->type ? !strcmp(_dd->type, _t) : 0) && \
(_dd->type_instance ? !strcmp(_dd->type_instance, _ti) : 1)
+static int snmp_agent_shutdown(void);
static void *snmp_agent_thread_run(void *arg);
static int snmp_agent_register_oid(oid_t *oid, Netsnmp_Node_Handler *handler);
static int snmp_agent_set_vardata(void *dst_buf, size_t *dst_buf_len,
char *oid_str_ptr[MAX_OID_LEN];
for (size_t i = 0; i < o->oid_len; i++) {
- ssnprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
+ snprintf(oid_str[i], sizeof(oid_str[i]), "%lu", (unsigned long)o->oid[i]);
oid_str_ptr[i] = oid_str[i];
}
return 0;
}
-static void snmp_agent_generate_oid2string(oid_t *oid, size_t offset, char *key) {
+static void snmp_agent_generate_oid2string(oid_t *oid, size_t offset,
+ char *key) {
int key_len = oid->oid[offset];
int i;
.severity = NOTIF_WARNING, .time = cdtime(), .plugin = PLUGIN_NAME};
sstrncpy(n.host, hostname_g, sizeof(n.host));
sstrncpy(n.plugin_instance, ins, sizeof(n.plugin_instance));
- ssnprintf(n.message, sizeof(n.message),
- "Removed data row from table %s instance %s index %d", td->name,
- ins, (index != NULL) ? *index : -1);
+ snprintf(n.message, sizeof(n.message),
+ "Removed data row from table %s instance %s index %d", td->name, ins,
+ (index != NULL) ? *index : -1);
plugin_dispatch_notification(&n);
if (td->index_oid.oid_len) {
for (size_t i = 0; i < (*dd)->oids_len; i++)
unregister_mib((*dd)->oids[i].oid, (*dd)->oids[i].oid_len);
}
- if (!(*dd)->table->index_oid.oid_len) {
- char *instance;
-
- c_avl_iterator_t *iter = c_avl_get_iterator((*dd)->table->instance_index);
- while (c_avl_iterator_next(iter, (void *)&instance, (void *)&instance) ==
- 0) {
- for (size_t i = 0; i < (*dd)->oids_len; i++)
- snmp_agent_unregister_oid_string(&(*dd)->oids[i], instance);
- }
- c_avl_iterator_destroy(iter);
- } else {
- /* unregister all table OIDs */
- int *index;
- char *value;
-
- c_avl_iterator_t *iter = c_avl_get_iterator((*dd)->table->index_instance);
- while (c_avl_iterator_next(iter, (void *)&index, (void *)&value) == 0) {
- for (size_t i = 0; i < (*dd)->oids_len; i++)
- snmp_agent_unregister_oid_index(&(*dd)->oids[i], *index);
- }
- c_avl_iterator_destroy(iter);
- }
sfree((*dd)->name);
sfree((*dd)->plugin);
return;
}
+static void snmp_agent_free_table_columns(table_definition_t *td) {
+ if (td->columns == NULL)
+ return;
+
+ for (llentry_t *de = llist_head(td->columns); de != NULL; de = de->next) {
+ data_definition_t *dd = de->value;
+
+ if (td->index_oid.oid_len) {
+ int *index;
+ char *instance;
+
+ c_avl_iterator_t *iter = c_avl_get_iterator(td->index_instance);
+ while (c_avl_iterator_next(iter, (void *)&index, (void *)&instance) ==
+ 0) {
+ for (size_t i = 0; i < dd->oids_len; i++)
+ snmp_agent_unregister_oid_index(&dd->oids[i], *index);
+ }
+ c_avl_iterator_destroy(iter);
+ } else {
+ char *instance;
+
+ c_avl_iterator_t *iter = c_avl_get_iterator(dd->table->instance_index);
+ while (c_avl_iterator_next(iter, (void *)&instance, (void *)&instance) ==
+ 0) {
+ for (size_t i = 0; i < dd->oids_len; i++)
+ snmp_agent_unregister_oid_string(&dd->oids[i], instance);
+ }
+ c_avl_iterator_destroy(iter);
+ }
+
+ snmp_agent_free_data(&dd);
+ }
+
+ llist_destroy(td->columns);
+ td->columns = NULL;
+} /* void snmp_agent_free_table_columns */
+
static void snmp_agent_free_table(table_definition_t **td) {
if (td == NULL || *td == NULL)
if ((*td)->size_oid.oid_len)
unregister_mib((*td)->size_oid.oid, (*td)->size_oid.oid_len);
+ /* Unregister Index OIDs */
if ((*td)->index_oid.oid_len) {
int *index;
- char *value;
+ char *instance;
c_avl_iterator_t *iter = c_avl_get_iterator((*td)->index_instance);
- while (c_avl_iterator_next(iter, (void *)&index, (void *)&value) == 0)
+ while (c_avl_iterator_next(iter, (void *)&index, (void *)&instance) == 0)
snmp_agent_unregister_oid_index(&(*td)->index_oid, *index);
c_avl_iterator_destroy(iter);
}
- for (llentry_t *de = llist_head((*td)->columns); de != NULL; de = de->next) {
- data_definition_t *dd = de->value;
- snmp_agent_free_data(&dd);
- }
-
- llist_destroy((*td)->columns);
+ /* Unregister all table columns and their registered OIDs */
+ snmp_agent_free_table_columns(*td);
void *key = NULL;
void *value = NULL;
if (dd->is_instance) {
requests->requestvb->type = ASN_OCTET_STR;
- snmp_set_var_typed_value(requests->requestvb,
- requests->requestvb->type, (const u_char *)instance,
- strlen((instance)));
+ snmp_set_var_typed_value(
+ requests->requestvb, requests->requestvb->type,
+ (const u_char *)instance, strlen((instance)));
pthread_mutex_unlock(&g_agent->lock);
.severity = NOTIF_OKAY, .time = cdtime(), .plugin = PLUGIN_NAME};
sstrncpy(n.host, hostname_g, sizeof(n.host));
sstrncpy(n.plugin_instance, ins, sizeof(n.plugin_instance));
- ssnprintf(n.message, sizeof(n.message),
- "Data row added to table %s instance %s index %d", td->name, ins,
- (index != NULL) ? *index : -1);
+ snprintf(n.message, sizeof(n.message),
+ "Data row added to table %s instance %s index %d", td->name, ins,
+ (index != NULL) ? *index : -1);
plugin_dispatch_notification(&n);
return 0;
g_agent->tables = llist_create();
g_agent->scalars = llist_create();
+ if (g_agent->tables == NULL || g_agent->scalars == NULL) {
+ ERROR(PLUGIN_NAME ": llist_create() failed");
+ llist_destroy(g_agent->scalars);
+ llist_destroy(g_agent->tables);
+ return -ENOMEM;
+ }
+
int err;
/* make us a agentx client. */
err = netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE,
1);
if (err != 0) {
ERROR(PLUGIN_NAME ": Failed to set agent role (%d)", err);
+ llist_destroy(g_agent->scalars);
+ llist_destroy(g_agent->tables);
return -1;
}
err = init_agent(PLUGIN_NAME);
if (err != 0) {
ERROR(PLUGIN_NAME ": Failed to initialize the agent library (%d)", err);
+ llist_destroy(g_agent->scalars);
+ llist_destroy(g_agent->tables);
return -1;
}
static int snmp_agent_init(void) {
int ret;
- ret = snmp_agent_preinit();
- if (ret != 0)
- return ret;
+ if (g_agent == NULL || ((llist_head(g_agent->scalars) == NULL) &&
+ (llist_head(g_agent->tables) == NULL))) {
+ ERROR(PLUGIN_NAME ": snmp_agent_init: plugin not configured");
+ return -EINVAL;
+ }
+
+ plugin_register_shutdown(PLUGIN_NAME, snmp_agent_shutdown);
ret = snmp_agent_register_scalar_oids();
if (ret != 0)
if (ret != 0)
return ret;
- /* create a second thread to listen for requests from AgentX*/
- ret = pthread_create(&g_agent->thread, NULL, &snmp_agent_thread_run, NULL);
- if (ret != 0) {
- ERROR(PLUGIN_NAME ": Failed to create a separate thread, err %u", ret);
- return ret;
- }
-
ret = pthread_mutex_init(&g_agent->lock, NULL);
if (ret != 0) {
ERROR(PLUGIN_NAME ": Failed to initialize mutex, err %u", ret);
return ret;
}
+ /* create a second thread to listen for requests from AgentX*/
+ ret = pthread_create(&g_agent->thread, NULL, &snmp_agent_thread_run, NULL);
+ if (ret != 0) {
+ ERROR(PLUGIN_NAME ": Failed to create a separate thread, err %u", ret);
+ return ret;
+ }
+
+ if (llist_head(g_agent->tables) != NULL) {
+ plugin_register_write(PLUGIN_NAME, snmp_agent_collect, NULL);
+ plugin_register_missing(PLUGIN_NAME, snmp_agent_clear_missing, NULL);
+ }
+
return 0;
}
void module_register(void) {
plugin_register_init(PLUGIN_NAME, snmp_agent_init);
plugin_register_complex_config(PLUGIN_NAME, snmp_agent_config);
- plugin_register_write(PLUGIN_NAME, snmp_agent_collect, NULL);
- plugin_register_missing(PLUGIN_NAME, snmp_agent_clear_missing, NULL);
- plugin_register_shutdown(PLUGIN_NAME, snmp_agent_shutdown);
}
return ERANGE;
}
- tmp = realloc(conf_timer_percentile, sizeof(*conf_timer_percentile) *
- (conf_timer_percentile_num + 1));
+ tmp =
+ realloc(conf_timer_percentile,
+ sizeof(*conf_timer_percentile) * (conf_timer_percentile_num + 1));
if (tmp == NULL) {
ERROR("statsd plugin: realloc failed.");
return ENOMEM;
/* Make sure all timer metrics share the *same* timestamp. */
vl.time = cdtime();
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-average", name);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-average", name);
vl.values[0].gauge =
have_events
? CDTIME_T_TO_DOUBLE(latency_counter_get_average(metric->latency))
plugin_dispatch_values(&vl);
if (conf_timer_lower) {
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-lower", name);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-lower", name);
vl.values[0].gauge =
have_events
? CDTIME_T_TO_DOUBLE(latency_counter_get_min(metric->latency))
}
if (conf_timer_upper) {
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-upper", name);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-upper", name);
vl.values[0].gauge =
have_events
? CDTIME_T_TO_DOUBLE(latency_counter_get_max(metric->latency))
}
if (conf_timer_sum) {
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-sum", name);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-sum", name);
vl.values[0].gauge =
have_events
? CDTIME_T_TO_DOUBLE(latency_counter_get_sum(metric->latency))
}
for (size_t i = 0; i < conf_timer_percentile_num; i++) {
- ssnprintf(vl.type_instance, sizeof(vl.type_instance),
- "%s-percentile-%.0f", name, conf_timer_percentile[i]);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-percentile-%.0f",
+ name, conf_timer_percentile[i]);
vl.values[0].gauge =
have_events ? CDTIME_T_TO_DOUBLE(latency_counter_get_percentile(
metric->latency, conf_timer_percentile[i]))
* vl.type's above are implicitly set to "latency". */
if (conf_timer_count) {
sstrncpy(vl.type, "gauge", sizeof(vl.type));
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-count", name);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-count", name);
vl.values[0].gauge = latency_counter_get_num(metric->latency);
plugin_dispatch_values(&vl);
}
static _Bool values_absolute = 1;
static _Bool values_percentage = 0;
+static _Bool report_io = 1;
static int swap_config(oconfig_item_t *ci) /* {{{ */
{
cf_util_get_boolean(child, &values_absolute);
else if (strcasecmp("ValuesPercentage", child->key) == 0)
cf_util_get_boolean(child, &values_percentage);
+ else if (strcasecmp("ReportIO", child->key) == 0)
+ cf_util_get_boolean(child, &report_io);
else
WARNING("swap plugin: Unknown config option: \"%s\"", child->key);
}
else
swap_read_combined();
- swap_read_io();
+ if (report_io)
+ swap_read_io();
return 0;
} /* }}} int swap_read */
- /* #endif KERNEL_LINUX */
+/* #endif KERNEL_LINUX */
/*
* Under Solaris, two mechanisms can be used to read swap statistics, swapctl
reserved = (gauge_t)(pmemory.pgsp_rsvd * pagesize);
swap_submit_usage(NULL, total - free, free, "reserved", reserved);
- swap_submit_derive("in", (derive_t)pmemory.pgspins * pagesize);
- swap_submit_derive("out", (derive_t)pmemory.pgspouts * pagesize);
+
+ if (report_io) {
+ swap_submit_derive("in", (derive_t)pmemory.pgspins * pagesize);
+ swap_submit_derive("out", (derive_t)pmemory.pgspouts * pagesize);
+ }
return 0;
} /* }}} int swap_read */
--- /dev/null
+/**
+ * collectd - src/synproxy.c
+ * Copyright (C) 2017 Marek Becka
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; only version 2 of the License is applicable.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Authors:
+ * Marek Becka <https://github.com/marekbecka>
+ **/
+
+#include "collectd.h"
+
+#include "common.h"
+#include "plugin.h"
+
+#if !KERNEL_LINUX
+#error "No applicable input method."
+#endif
+
+#define SYNPROXY_FIELDS 6
+
+static const char *synproxy_stat_path = "/proc/net/stat/synproxy";
+
+static const char *column_names[SYNPROXY_FIELDS] = {
+ "entries", "syn_received", "invalid",
+ "valid", "retransmission", "reopened"};
+static const char *column_types[SYNPROXY_FIELDS] = {
+ "current_connections", "connections", "cookies", "cookies", "cookies",
+ "connections"};
+
+static void synproxy_submit(value_t *results) {
+ value_list_t vl = VALUE_LIST_INIT;
+
+ /* 1st column (entries) is hardcoded to 0 in kernel code */
+ for (size_t n = 1; n < SYNPROXY_FIELDS; n++) {
+ vl.values = &results[n];
+ vl.values_len = 1;
+
+ sstrncpy(vl.plugin, "synproxy", sizeof(vl.plugin));
+ sstrncpy(vl.type, column_types[n], sizeof(vl.type));
+ sstrncpy(vl.type_instance, column_names[n], sizeof(vl.type_instance));
+
+ plugin_dispatch_values(&vl);
+ }
+}
+
+static int synproxy_read(void) {
+ char buf[1024];
+ value_t results[SYNPROXY_FIELDS];
+ int is_header = 1, status = 0;
+
+ FILE *fh = fopen(synproxy_stat_path, "r");
+ if (fh == NULL) {
+ ERROR("synproxy plugin: unable to open %s", synproxy_stat_path);
+ return -1;
+ }
+
+ memset(results, 0, sizeof(results));
+
+ while (fgets(buf, sizeof(buf), fh) != NULL) {
+ char *fields[SYNPROXY_FIELDS], *endprt;
+
+ if (is_header) {
+ is_header = 0;
+ continue;
+ }
+
+ int numfields = strsplit(buf, fields, STATIC_ARRAY_SIZE(fields));
+ if (numfields != SYNPROXY_FIELDS) {
+ ERROR("synproxy plugin: unexpected number of columns in %s",
+ synproxy_stat_path);
+ status = -1;
+ break;
+ }
+
+ /* 1st column (entries) is hardcoded to 0 in kernel code */
+ for (size_t n = 1; n < SYNPROXY_FIELDS; n++) {
+ char *endptr = NULL;
+ errno = 0;
+
+ results[n].derive += strtoull(fields[n], &endprt, 16);
+ if ((endptr == fields[n]) || errno != 0) {
+ ERROR("synproxy plugin: unable to parse value: %s", fields[n]);
+ fclose(fh);
+ return -1;
+ }
+ }
+ }
+
+ fclose(fh);
+
+ if (status == 0) {
+ synproxy_submit(results);
+ }
+
+ return status;
+}
+
+void module_register(void) {
+ plugin_register_read("synproxy", synproxy_read);
+} /* void module_register */
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(&buf[offset], sizeof(buf) - offset, __VA_ARGS__); \
+ status = snprintf(&buf[offset], sizeof(buf) - offset, __VA_ARGS__); \
if (status < 1) \
return -1; \
else if (((size_t)status) >= (sizeof(buf) - offset)) \
typedef struct {
char *file;
char *sep;
+ char *plugin_name;
char *instance;
tbl_result_t *results;
static void tbl_setup(tbl_t *tbl, char *file) {
tbl->file = sstrdup(file);
tbl->sep = NULL;
+ tbl->plugin_name = NULL;
tbl->instance = NULL;
tbl->results = NULL;
static void tbl_clear(tbl_t *tbl) {
sfree(tbl->file);
sfree(tbl->sep);
+ sfree(tbl->plugin_name);
sfree(tbl->instance);
for (size_t i = 0; i < tbl->results_num; ++i)
if (0 == strcasecmp(c->key, "Separator"))
tbl_config_set_s(c->key, &tbl->sep, c);
+ else if (0 == strcasecmp(c->key, "Plugin"))
+ tbl_config_set_s(c->key, &tbl->plugin_name, c);
else if (0 == strcasecmp(c->key, "Instance"))
tbl_config_set_s(c->key, &tbl->instance, c);
else if (0 == strcasecmp(c->key, "Result"))
vl.values = values;
vl.values_len = STATIC_ARRAY_SIZE(values);
- sstrncpy(vl.plugin, "table", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (tbl->plugin_name != NULL) ? tbl->plugin_name : "table",
+ sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, tbl->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, res->type, sizeof(vl.type));
/*
* <Plugin tail>
* <File "/var/log/exim4/mainlog">
- * Instance "exim"
+ * Plugin "mail"
+ * Instance "exim"
* Interval 60
* <Match>
* Regex "S=([1-9][0-9]*)"
} /* int ctail_config_add_match_dstype */
static int ctail_config_add_match(cu_tail_match_t *tm,
+ const char *plugin_name,
const char *plugin_instance,
oconfig_item_t *ci, cdtime_t interval) {
ctail_config_match_t cm = {0};
if (status == 0) {
// TODO(octo): there's nothing "simple" about the latency stuff …
status = tail_match_add_match_simple(
- tm, cm.regex, cm.excluderegex, cm.flags, "tail", plugin_instance,
+ tm, cm.regex, cm.excluderegex, cm.flags,
+ (plugin_name != NULL) ? plugin_name : "tail", plugin_instance,
cm.type, cm.type_instance, cm.latency, interval);
if (status != 0)
static int ctail_config_add_file(oconfig_item_t *ci) {
cu_tail_match_t *tm;
cdtime_t interval = 0;
+ char *plugin_name = NULL;
char *plugin_instance = NULL;
int num_matches = 0;
oconfig_item_t *option = ci->children + i;
int status = 0;
- if (strcasecmp("Instance", option->key) == 0)
+ if (strcasecmp("Plugin", option->key) == 0)
+ status = cf_util_get_string (option, &plugin_name);
+ else if (strcasecmp("Instance", option->key) == 0)
status = cf_util_get_string(option, &plugin_instance);
else if (strcasecmp("Interval", option->key) == 0)
cf_util_get_cdtime(option, &interval);
else if (strcasecmp("Match", option->key) == 0) {
- status = ctail_config_add_match(tm, plugin_instance, option, interval);
+ status = ctail_config_add_match(tm, plugin_name, plugin_instance, option,
+ interval);
if (status == 0)
num_matches++;
/* Be mild with failed matches.. */
break;
} /* for (i = 0; i < ci->children_num; i++) */
+ sfree(plugin_name);
sfree(plugin_instance);
if (num_matches == 0) {
}
for (size_t i = 0; i < tail_match_list_num; i++) {
- ssnprintf(str, sizeof(str), "tail-%zu", i);
+ snprintf(str, sizeof(str), "tail-%zu", i);
plugin_register_complex_read(NULL, str, ctail_read,
tail_match_list_intervals[i],
typedef struct metric_definition_s metric_definition_t;
struct instance_definition_s {
+ char *plugin_name;
char *instance;
char *path;
cu_tail_t *tail;
vl.values_len = 1;
vl.values = &v;
- sstrncpy(vl.plugin, "tail_csv", sizeof(vl.plugin));
+ sstrncpy(vl.plugin, (id->plugin_name != NULL) ? id->plugin_name : "tail_csv",
+ sizeof(vl.plugin));
if (id->instance != NULL)
sstrncpy(vl.plugin_instance, id->instance, sizeof(vl.plugin_instance));
sstrncpy(vl.type, md->type, sizeof(vl.type));
cu_tail_destroy(id->tail);
id->tail = NULL;
+ sfree(id->plugin_name);
sfree(id->instance);
sfree(id->path);
sfree(id->metric_list);
id = calloc(1, sizeof(*id));
if (id == NULL)
return -1;
+ id->plugin_name = NULL;
id->instance = NULL;
id->path = NULL;
id->metric_list = NULL;
cf_util_get_cdtime(option, &id->interval);
else if (strcasecmp("TimeFrom", option->key) == 0)
status = tcsv_config_get_index(option, &id->time_from);
+ else if (strcasecmp("Plugin", option->key) == 0)
+ status = cf_util_get_string(option, &id->plugin_name);
else {
WARNING("tail_csv plugin: Option `%s' not allowed here.", option->key);
status = -1;
return -1;
}
- ssnprintf(cb_name, sizeof(cb_name), "tail_csv/%s", id->path);
+ snprintf(cb_name, sizeof(cb_name), "tail_csv/%s", id->path);
status = plugin_register_complex_read(
NULL, cb_name, tcsv_read, id->interval,
});
if (status != 0) {
ERROR("tail_csv plugin: Registering complex read function failed.");
- tcsv_instance_definition_destroy(id);
return -1;
}
char template[DATA_MAX_NAME_LEN];
char value_str[DATA_MAX_NAME_LEN];
- ssnprintf(template, sizeof(template), "%%{ds:%s}", ds->ds[i].name);
+ snprintf(template, sizeof(template), "%%{ds:%s}", ds->ds[i].name);
if (ds->ds[i].type != DS_TYPE_GAUGE) {
if ((rates == NULL) && (rates_failed == 0)) {
/* If this is a gauge value, use the current value. */
if (ds->ds[i].type == DS_TYPE_GAUGE)
- ssnprintf(value_str, sizeof(value_str), GAUGE_FORMAT,
- (double)vl->values[i].gauge);
+ snprintf(value_str, sizeof(value_str), GAUGE_FORMAT,
+ (double)vl->values[i].gauge);
/* If it's a counter, try to use the current rate. This may fail, if the
* value has been renamed. */
else if (rates != NULL)
- ssnprintf(value_str, sizeof(value_str), GAUGE_FORMAT, (double)rates[i]);
+ snprintf(value_str, sizeof(value_str), GAUGE_FORMAT, (double)rates[i]);
/* Since we don't know any better, use the string `unknown'. */
else
sstrncpy(value_str, "unknown", sizeof(value_str));
curr_counter = (uint64_t)vl->values[dsrc_index].counter;
- ssnprintf(key_prev_counter, sizeof(key_prev_counter),
- "target_scale[%p,%i]:prev_counter", (void *)data, dsrc_index);
- ssnprintf(key_int_counter, sizeof(key_int_counter),
- "target_scale[%p,%i]:int_counter", (void *)data, dsrc_index);
- ssnprintf(key_int_fraction, sizeof(key_int_fraction),
- "target_scale[%p,%i]:int_fraction", (void *)data, dsrc_index);
+ snprintf(key_prev_counter, sizeof(key_prev_counter),
+ "target_scale[%p,%i]:prev_counter", (void *)data, dsrc_index);
+ snprintf(key_int_counter, sizeof(key_int_counter),
+ "target_scale[%p,%i]:int_counter", (void *)data, dsrc_index);
+ snprintf(key_int_fraction, sizeof(key_int_fraction),
+ "target_scale[%p,%i]:int_fraction", (void *)data, dsrc_index);
prev_counter = curr_counter;
int_counter = 0;
curr_derive = (int64_t)vl->values[dsrc_index].derive;
- ssnprintf(key_prev_derive, sizeof(key_prev_derive),
- "target_scale[%p,%i]:prev_derive", (void *)data, dsrc_index);
- ssnprintf(key_int_derive, sizeof(key_int_derive),
- "target_scale[%p,%i]:int_derive", (void *)data, dsrc_index);
- ssnprintf(key_int_fraction, sizeof(key_int_fraction),
- "target_scale[%p,%i]:int_fraction", (void *)data, dsrc_index);
+ snprintf(key_prev_derive, sizeof(key_prev_derive),
+ "target_scale[%p,%i]:prev_derive", (void *)data, dsrc_index);
+ snprintf(key_int_derive, sizeof(key_int_derive),
+ "target_scale[%p,%i]:int_derive", (void *)data, dsrc_index);
+ snprintf(key_int_fraction, sizeof(key_int_fraction),
+ "target_scale[%p,%i]:int_fraction", (void *)data, dsrc_index);
prev_derive = curr_derive;
int_derive = 0;
curr_absolute = (uint64_t)vl->values[dsrc_index].absolute;
- ssnprintf(key_int_fraction, sizeof(key_int_fraction),
- "target_scale[%p,%i]:int_fraction", (void *)data, dsrc_index);
+ snprintf(key_int_fraction, sizeof(key_int_fraction),
+ "target_scale[%p,%i]:int_fraction", (void *)data, dsrc_index);
int_fraction = 0.0;
char *value_str;
const char *key = meta_toc[i];
- ssnprintf(meta_name, sizeof(meta_name), "%%{meta:%s}", key);
+ snprintf(meta_name, sizeof(meta_name), "%%{meta:%s}", key);
if (meta_data_as_string(vl->meta, key, &value_str) != 0)
continue;
/* Dispatch new value lists instead of this one */
new_vl.values[0].derive = (derive_t)vl->values[0].counter;
- ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
- "demand_data-%s", is_hits ? "hit" : "miss");
+ snprintf(new_vl.type_instance, sizeof(new_vl.type_instance), "demand_data-%s",
+ is_hits ? "hit" : "miss");
plugin_dispatch_values(&new_vl);
new_vl.values[0].derive = (derive_t)vl->values[1].counter;
- ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
- "demand_metadata-%s", is_hits ? "hit" : "miss");
+ snprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
+ "demand_metadata-%s", is_hits ? "hit" : "miss");
plugin_dispatch_values(&new_vl);
new_vl.values[0].derive = (derive_t)vl->values[2].counter;
- ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
- "prefetch_data-%s", is_hits ? "hit" : "miss");
+ snprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
+ "prefetch_data-%s", is_hits ? "hit" : "miss");
plugin_dispatch_values(&new_vl);
new_vl.values[0].derive = (derive_t)vl->values[3].counter;
- ssnprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
- "prefetch_metadata-%s", is_hits ? "hit" : "miss");
+ snprintf(new_vl.type_instance, sizeof(new_vl.type_instance),
+ "prefetch_metadata-%s", is_hits ? "hit" : "miss");
plugin_dispatch_values(&new_vl);
/* Abort processing */
#undef HAVE_SYSCTLBYNAME /* force HAVE_LIBKVM_NLIST path */
#endif
-#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_KVM_GETFILES && !HAVE_LIBKVM_NLIST && !KERNEL_AIX
+#if !KERNEL_LINUX && !HAVE_SYSCTLBYNAME && !HAVE_KVM_GETFILES && \
+ !HAVE_LIBKVM_NLIST && !KERNEL_AIX
#error "No applicable input method."
#endif
/* #endif HAVE_SYSCTLBYNAME */
#elif HAVE_KVM_GETFILES
-#include <sys/types.h>
#include <sys/sysctl.h>
+#include <sys/types.h>
#define _KERNEL /* for DTYPE_SOCKET */
#include <sys/file.h>
#undef _KERNEL
#include <net/route.h>
#include <netdb.h>
#include <netinet/in.h>
-#include <netinet/ip.h>
#include <netinet/in_pcb.h>
#include <netinet/in_systm.h>
+#include <netinet/ip.h>
#include <netinet/ip_var.h>
#include <netinet/tcp.h>
#include <netinet/tcp_timer.h>
if (((port_collect_listening != 0) && (pe->flags & PORT_IS_LISTENING)) ||
(pe->flags & PORT_COLLECT_LOCAL)) {
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance),
- "%" PRIu16 "-local", pe->port);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance),
+ "%" PRIu16 "-local", pe->port);
for (int i = 1; i <= TCP_STATE_MAX; i++) {
vl.values[0].gauge = pe->count_local[i];
}
if (pe->flags & PORT_COLLECT_REMOTE) {
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance),
- "%" PRIu16 "-remote", pe->port);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance),
+ "%" PRIu16 "-remote", pe->port);
for (int i = 1; i <= TCP_STATE_MAX; i++) {
vl.values[0].gauge = pe->count_remote[i];
conn_reset_port_entry();
- kf = kvm_getfiles(kvmd, KERN_FILE_BYFILE, DTYPE_SOCKET,
- sizeof(*kf), &fcnt);
+ kf = kvm_getfiles(kvmd, KERN_FILE_BYFILE, DTYPE_SOCKET, sizeof(*kf), &fcnt);
if (kf == NULL) {
ERROR("tcpconns plugin: kvm_getfiles failed.");
return -1;
int status;
/* Send request */
- ssnprintf(command, sizeof(command), "sel %i\r\n", vserver->port);
+ snprintf(command, sizeof(command), "sel %i\r\n", vserver->port);
status = tss2_send_request(write_fh, command);
if (status != 0) {
status = tss2_send_request(write_fh, "gi\r\n");
} else {
/* Request server information */
- ssnprintf(plugin_instance, sizeof(plugin_instance), "vserver%i",
- vserver->port);
+ snprintf(plugin_instance, sizeof(plugin_instance), "vserver%i",
+ vserver->port);
/* Select the server */
status = tss2_select_vserver(read_fh, write_fh, vserver);
if (device_list && ignorelist_match(device_list, name))
return -1;
- ssnprintf(filename, sizeof(filename), "%s/%s/temp", dirname_sysfs, name);
+ snprintf(filename, sizeof(filename), "%s/%s/temp", dirname_sysfs, name);
if (parse_value_file(filename, &value, DS_TYPE_GAUGE) == 0) {
value.gauge /= 1000.0;
thermal_submit(name, TEMP, value);
success = 1;
}
- ssnprintf(filename, sizeof(filename), "%s/%s/cur_state", dirname_sysfs, name);
+ snprintf(filename, sizeof(filename), "%s/%s/cur_state", dirname_sysfs, name);
if (parse_value_file(filename, &value, DS_TYPE_GAUGE) == 0) {
thermal_submit(name, COOLING_DEV, value);
success = 1;
* temperature: 55 C
*/
- len = ssnprintf(filename, sizeof(filename), "%s/%s/temperature",
- dirname_procfs, name);
+ len = snprintf(filename, sizeof(filename), "%s/%s/temperature",
+ dirname_procfs, name);
if ((len < 0) || ((size_t)len >= sizeof(filename)))
return -1;
return status;
} /* int ut_config_host */
- /*
- * End of the functions used to configure threshold values.
- */
+/*
+ * End of the functions used to configure threshold values.
+ */
/* }}} */
/*
n.time = vl->time;
- status = ssnprintf(buf, bufsize, "Host %s, plugin %s", vl->host, vl->plugin);
+ status = snprintf(buf, bufsize, "Host %s, plugin %s", vl->host, vl->plugin);
buf += status;
bufsize -= status;
if (vl->plugin_instance[0] != '\0') {
- status = ssnprintf(buf, bufsize, " (instance %s)", vl->plugin_instance);
+ status = snprintf(buf, bufsize, " (instance %s)", vl->plugin_instance);
buf += status;
bufsize -= status;
}
- status = ssnprintf(buf, bufsize, " type %s", vl->type);
+ status = snprintf(buf, bufsize, " type %s", vl->type);
buf += status;
bufsize -= status;
if (vl->type_instance[0] != '\0') {
- status = ssnprintf(buf, bufsize, " (instance %s)", vl->type_instance);
+ status = snprintf(buf, bufsize, " (instance %s)", vl->type_instance);
buf += status;
bufsize -= status;
}
/* Send an okay notification */
if (state == STATE_OKAY) {
if (state_old == STATE_MISSING)
- ssnprintf(buf, bufsize, ": Value is no longer missing.");
+ snprintf(buf, bufsize, ": Value is no longer missing.");
else
- ssnprintf(buf, bufsize, ": All data sources are within range again. "
- "Current value of \"%s\" is %f.",
- ds->ds[ds_index].name, values[ds_index]);
+ snprintf(buf, bufsize, ": All data sources are within range again. "
+ "Current value of \"%s\" is %f.",
+ ds->ds[ds_index].name, values[ds_index]);
} else {
double min;
double max;
if (th->flags & UT_FLAG_INVERT) {
if (!isnan(min) && !isnan(max)) {
- ssnprintf(buf, bufsize,
- ": Data source \"%s\" is currently "
- "%f. That is within the %s region of %f%s and %f%s.",
- ds->ds[ds_index].name, values[ds_index],
- (state == STATE_ERROR) ? "failure" : "warning", min,
- ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "", max,
- ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
+ snprintf(buf, bufsize,
+ ": Data source \"%s\" is currently "
+ "%f. That is within the %s region of %f%s and %f%s.",
+ ds->ds[ds_index].name, values[ds_index],
+ (state == STATE_ERROR) ? "failure" : "warning", min,
+ ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "", max,
+ ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
} else {
- ssnprintf(buf, bufsize, ": Data source \"%s\" is currently "
- "%f. That is %s the %s threshold of %f%s.",
- ds->ds[ds_index].name, values[ds_index],
- isnan(min) ? "below" : "above",
- (state == STATE_ERROR) ? "failure" : "warning",
- isnan(min) ? max : min,
- ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
+ snprintf(buf, bufsize, ": Data source \"%s\" is currently "
+ "%f. That is %s the %s threshold of %f%s.",
+ ds->ds[ds_index].name, values[ds_index],
+ isnan(min) ? "below" : "above",
+ (state == STATE_ERROR) ? "failure" : "warning",
+ isnan(min) ? max : min,
+ ((th->flags & UT_FLAG_PERCENTAGE) != 0) ? "%" : "");
}
} else if (th->flags & UT_FLAG_PERCENTAGE) {
gauge_t value;
else
value = 100.0 * values[ds_index] / sum;
- ssnprintf(buf, bufsize,
- ": Data source \"%s\" is currently "
- "%g (%.2f%%). That is %s the %s threshold of %.2f%%.",
- ds->ds[ds_index].name, values[ds_index], value,
- (value < min) ? "below" : "above",
- (state == STATE_ERROR) ? "failure" : "warning",
- (value < min) ? min : max);
+ snprintf(buf, bufsize,
+ ": Data source \"%s\" is currently "
+ "%g (%.2f%%). That is %s the %s threshold of %.2f%%.",
+ ds->ds[ds_index].name, values[ds_index], value,
+ (value < min) ? "below" : "above",
+ (state == STATE_ERROR) ? "failure" : "warning",
+ (value < min) ? min : max);
} else /* is not inverted */
{
- ssnprintf(buf, bufsize, ": Data source \"%s\" is currently "
- "%f. That is %s the %s threshold of %f.",
- ds->ds[ds_index].name, values[ds_index],
- (values[ds_index] < min) ? "below" : "above",
- (state == STATE_ERROR) ? "failure" : "warning",
- (values[ds_index] < min) ? min : max);
+ snprintf(buf, bufsize, ": Data source \"%s\" is currently "
+ "%f. That is %s the %s threshold of %f.",
+ ds->ds[ds_index].name, values[ds_index],
+ (values[ds_index] < min) ? "below" : "above",
+ (state == STATE_ERROR) ? "failure" : "warning",
+ (values[ds_index] < min) ? min : max);
}
}
FORMAT_VL(identifier, sizeof(identifier), vl);
NOTIFICATION_INIT_VL(&n, vl);
- ssnprintf(n.message, sizeof(n.message),
- "%s has not been updated for %.3f seconds.", identifier,
- CDTIME_T_TO_DOUBLE(missing_time));
+ snprintf(n.message, sizeof(n.message),
+ "%s has not been updated for %.3f seconds.", identifier,
+ CDTIME_T_TO_DOUBLE(missing_time));
n.time = now;
plugin_dispatch_notification(&n);
#include "plugin.h"
#include "utils_time.h"
-#include <asm/msr-index.h>
+#include "msr-index.h"
#include <cpuid.h>
#ifdef HAVE_SYS_CAPABILITY_H
#include <sys/capability.h>
}
}
- ssnprintf(pathname, sizeof(pathname), "/dev/cpu/%d/msr", cpu);
+ snprintf(pathname, sizeof(pathname), "/dev/cpu/%d/msr", cpu);
fd = open(pathname, O_RDONLY);
if (fd < 0) {
ERROR("turbostat plugin: failed to open %s", pathname);
DEBUG("turbostat plugin: submit stats for cpu: %d, core: %d, pkg: %d",
t->cpu_id, c->core_id, p->package_id);
- ssnprintf(name, sizeof(name), "cpu%02d", t->cpu_id);
+ snprintf(name, sizeof(name), "cpu%02d", t->cpu_id);
if (!aperf_mperf_unstable)
turbostat_submit(name, "percent", "c0", 100.0 * t->mperf / t->tsc);
1.0 / 1000000 * t->aperf / interval_float);
if ((!aperf_mperf_unstable) || (!(t->aperf > t->tsc || t->mperf > t->tsc)))
- turbostat_submit(name, "frequency", "busy", 1.0 * t->tsc / 1000000 *
- t->aperf / t->mperf /
- interval_float);
+ turbostat_submit(name, "frequency", "busy",
+ 1.0 * t->tsc / 1000000 * t->aperf / t->mperf /
+ interval_float);
/* Sanity check (should stay stable) */
turbostat_submit(name, "gauge", "TSC",
/* If not using logical core numbering, set core id */
if (!config_lcn) {
- ssnprintf(name, sizeof(name), "core%02d", c->core_id);
+ if (topology.num_packages > 1)
+ snprintf(name, sizeof(name), "pkg%02d-core%02d", p->package_id, c->core_id);
+ else
+ snprintf(name, sizeof(name), "core%02d", c->core_id);
}
if (do_core_cstate & (1 << 3))
if (!(t->flags & CPU_IS_FIRST_CORE_IN_PACKAGE))
goto done;
- ssnprintf(name, sizeof(name), "pkg%02d", p->package_id);
+ snprintf(name, sizeof(name), "pkg%02d", p->package_id);
if (do_ptm)
turbostat_submit(name, "temperature", NULL, p->pkg_temp_c);
int matches;
char character;
- ssnprintf(path, sizeof(path),
- "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu);
+ snprintf(path, sizeof(path),
+ "/sys/devices/system/cpu/cpu%d/topology/thread_siblings_list", cpu);
filep = fopen(path, "r");
if (!filep) {
ERROR("turbostat plugin: Failed to open '%s'", path);
connections value:DERIVE:0:U
conntrack value:GAUGE:0:4294967295
contextswitch value:DERIVE:0:U
+cookies value:DERIVE:0:U
count value:GAUGE:0:U
counter value:COUNTER:U:U
cpu value:DERIVE:0:U
if_tx_packets value:DERIVE:0:U
invocations value:DERIVE:0:U
io_octets rx:DERIVE:0:U, tx:DERIVE:0:U
+io_ops read:DERIVE:0:U, write:DERIVE:0:U
io_packets rx:DERIVE:0:U, tx:DERIVE:0:U
ipc value:GAUGE:0:U
ipt_bytes value:DERIVE:0:U
ping_droprate value:GAUGE:0:100
ping_stddev value:GAUGE:0:65535
players value:GAUGE:0:1000000
+pools value:GAUGE:0:U
power value:GAUGE:U:U
pressure value:GAUGE:0:U
protocol_counter value:DERIVE:0:U
#include "plugin.h"
#if KERNEL_LINUX
-#define STAT_FILE "/proc/stat"
-/* Using /proc filesystem to retrieve the boot time, Linux only. */
+#include <sys/sysinfo.h>
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
/*
* Global variables
*/
-/* boottime always used, no OS distinction */
-static time_t boottime;
#if HAVE_LIBKSTAT
extern kstat_ctl_t *kc;
plugin_dispatch_values(&vl);
}
-static int uptime_init(void) /* {{{ */
-{
/*
* On most unix systems the uptime is calculated by looking at the boot
* time (stored in unix time, since epoch) and the current one. We are
* the boot time, the plugin is unregistered and there is no chance to
* try again later. Nevertheless, this is very unlikely to happen.
*/
-
+static time_t uptime_get_sys(void) { /* {{{ */
+ time_t result;
#if KERNEL_LINUX
- unsigned long starttime;
- char buffer[1024];
- int ret;
- FILE *fh;
-
- ret = 0;
-
- fh = fopen(STAT_FILE, "r");
+ struct sysinfo info;
+ int status;
- if (fh == NULL) {
+ status = sysinfo(&info);
+ if (status != 0) {
char errbuf[1024];
- ERROR("uptime plugin: Cannot open " STAT_FILE ": %s",
+ ERROR("uptime plugin: Error calling sysinfo: %s",
sstrerror(errno, errbuf, sizeof(errbuf)));
return -1;
}
- while (fgets(buffer, 1024, fh) != NULL) {
- /* look for the btime string and read the value */
- ret = sscanf(buffer, "btime %lu", &starttime);
- /* avoid further loops if btime has been found and read
- * correctly (hopefully) */
- if (ret == 1)
- break;
- }
-
- fclose(fh);
-
- /* loop done, check if no value has been found/read */
- if (ret != 1) {
- ERROR("uptime plugin: No value read from " STAT_FILE "");
- return -1;
- }
-
- boottime = (time_t)starttime;
-
- if (boottime == 0) {
- ERROR("uptime plugin: btime read from " STAT_FILE ", "
- "but `boottime' is zero!");
- return -1;
- }
+ result = (time_t)info.uptime;
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
return -1;
}
- boottime = (time_t)knp->value.ui32;
-
- if (boottime == 0) {
+ if (knp->value.ui32 == 0) {
ERROR("uptime plugin: kstat_data_lookup returned success, "
"but `boottime' is zero!");
return -1;
}
+
+ result = time(NULL) - (time_t)knp->value.ui32;
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYS_SYSCTL_H
return -1;
}
- boottime = boottv.tv_sec;
-
- if (boottime == 0) {
+ if (boottv.tv_sec == 0) {
ERROR("uptime plugin: sysctl(3) returned success, "
"but `boottime' is zero!");
return -1;
}
+
+ result = time(NULL) - boottv.tv_sec;
/* #endif HAVE_SYS_SYSCTL_H */
#elif HAVE_PERFSTAT
if (hertz <= 0)
hertz = HZ;
- boottime = time(NULL) - cputotal.lbolt / hertz;
+ result = cputotal.lbolt / hertz;
#endif /* HAVE_PERFSTAT */
- return 0;
-} /* }}} int uptime_init */
+ return result;
+} /* }}} int uptime_get_sys */
static int uptime_read(void) {
gauge_t uptime;
time_t elapsed;
/* calculate the amount of time elapsed since boot, AKA uptime */
- elapsed = time(NULL) - boottime;
+ elapsed = uptime_get_sys();
uptime = (gauge_t)elapsed;
}
void module_register(void) {
- plugin_register_init("uptime", uptime_init);
plugin_register_read("uptime", uptime_read);
} /* void module_register */
return status;
escape_string(buffer_values, sizeof(buffer_values));
- ssnprintf(ret, ret_len, "PUTVAL %s interval=%.3f %s", buffer_ident,
- (vl->interval > 0) ? CDTIME_T_TO_DOUBLE(vl->interval)
- : CDTIME_T_TO_DOUBLE(plugin_get_interval()),
- buffer_values);
+ snprintf(ret, ret_len, "PUTVAL %s interval=%.3f %s", buffer_ident,
+ (vl->interval > 0) ? CDTIME_T_TO_DOUBLE(vl->interval)
+ : CDTIME_T_TO_DOUBLE(plugin_get_interval()),
+ buffer_values);
return 0;
} /* }}} int cmd_create_putval */
* Sebastian 'tokkee' Harl <sh at tokkee.org>
**/
+#include "utils_cmds.h"
#include "daemon/common.h"
#include "utils_cmd_flush.h"
#include "utils_cmd_getval.h"
#include "utils_cmd_listval.h"
#include "utils_cmd_putval.h"
-#include "utils_cmds.h"
#include "utils_parse_option.h"
#include <stdbool.h>
if (s == NULL)
return 0;
- if ((curl == NULL) || (hostname == NULL) || (plugin == NULL)) {
+ if ((curl == NULL) || (plugin == NULL)) {
ERROR("curl stats: dispatch() called with missing arguments "
- "(curl=%p; hostname=%s; plugin=%s)",
- curl, hostname == NULL ? "<NULL>" : hostname,
- plugin == NULL ? "<NULL>" : plugin);
+ "(curl=%p; plugin=%s)",
+ curl, plugin == NULL ? "<NULL>" : plugin);
return -1;
}
- sstrncpy(vl.host, hostname, sizeof(vl.host));
+ if (hostname != NULL)
+ sstrncpy(vl.host, hostname, sizeof(vl.host));
sstrncpy(vl.plugin, plugin, sizeof(vl.plugin));
if (plugin_instance != NULL)
sstrncpy(vl.plugin_instance, plugin_instance, sizeof(vl.plugin_instance));
return "ANY"; /* ... 255 */
#endif /* __BIND >= 19950621 */
default:
- ssnprintf(buf, sizeof(buf), "#%i", t);
+ snprintf(buf, sizeof(buf), "#%i", t);
return buf;
} /* switch (t) */
}
case 5:
return "Update";
default:
- ssnprintf(buf, sizeof(buf), "Opcode%d", o);
+ snprintf(buf, sizeof(buf), "Opcode%d", o);
return buf;
}
}
#endif /* RFC2136 rcodes */
#endif /* __BIND >= 19950621 */
default:
- ssnprintf(buf, sizeof(buf), "RCode%i", rcode);
+ snprintf(buf, sizeof(buf), "RCode%i", rcode);
return buf;
}
} /* const char *rcode_str (int rcode) */
DPDK_HELPER_TRACE(phc->shm_name);
- ssnprintf(phc->eal_config.coremask, DATA_MAX_NAME_LEN, "%s", "0xf");
- ssnprintf(phc->eal_config.memory_channels, DATA_MAX_NAME_LEN, "%s", "1");
- ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN, "%s",
- DPDK_DEFAULT_RTE_CONFIG);
+ snprintf(phc->eal_config.coremask, DATA_MAX_NAME_LEN, "%s", "0xf");
+ snprintf(phc->eal_config.memory_channels, DATA_MAX_NAME_LEN, "%s", "1");
+ snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN, "%s",
+ DPDK_DEFAULT_RTE_CONFIG);
}
int dpdk_helper_eal_config_set(dpdk_helper_ctx_t *phc, dpdk_eal_config_t *ec) {
status = cf_util_get_string_buffer(child, prefix, sizeof(prefix));
if (status == 0) {
- ssnprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
+ snprintf(phc->eal_config.file_prefix, DATA_MAX_NAME_LEN,
"/var/run/.%s_config", prefix);
DEBUG("dpdk_common: EAL:File prefix %s", phc->eal_config.file_prefix);
}
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(ret + offset, ret_len - offset, __VA_ARGS__); \
+ status = snprintf(ret + offset, ret_len - offset, __VA_ARGS__); \
if (status < 1) { \
return -1; \
} else if (((size_t)status) >= (ret_len - offset)) { \
sizeof(n_type_instance), escape_char, preserve_separator);
if (n_plugin_instance[0] != '\0')
- ssnprintf(tmp_plugin, sizeof(tmp_plugin), "%s%c%s", n_plugin,
- (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
- n_plugin_instance);
+ snprintf(tmp_plugin, sizeof(tmp_plugin), "%s%c%s", n_plugin,
+ (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+ n_plugin_instance);
else
sstrncpy(tmp_plugin, n_plugin, sizeof(tmp_plugin));
if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0)
sstrncpy(tmp_type, n_type_instance, sizeof(tmp_type));
else
- ssnprintf(tmp_type, sizeof(tmp_type), "%s%c%s", n_type,
- (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
- n_type_instance);
+ snprintf(tmp_type, sizeof(tmp_type), "%s%c%s", n_type,
+ (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+ n_type_instance);
} else
sstrncpy(tmp_type, n_type, sizeof(tmp_type));
if (ds_name != NULL) {
if ((flags & GRAPHITE_DROP_DUPE_FIELDS) &&
strcmp(tmp_plugin, tmp_type) == 0)
- ssnprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix,
- tmp_plugin, ds_name);
+ snprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix,
+ tmp_plugin, ds_name);
else
- ssnprintf(ret, ret_len, "%s%s%s.%s.%s.%s", prefix, n_host, postfix,
- tmp_plugin, tmp_type, ds_name);
+ snprintf(ret, ret_len, "%s%s%s.%s.%s.%s", prefix, n_host, postfix,
+ tmp_plugin, tmp_type, ds_name);
} else
- ssnprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix, tmp_plugin,
- tmp_type);
+ snprintf(ret, ret_len, "%s%s%s.%s.%s", prefix, n_host, postfix, tmp_plugin,
+ tmp_type);
return 0;
}
/* Compute the graphite command */
message_len =
- (size_t)ssnprintf(message, sizeof(message), "%s %s %u\r\n", key, values,
- (unsigned int)CDTIME_T_TO_TIME_T(vl->time));
+ (size_t)snprintf(message, sizeof(message), "%s %s %u\r\n", key, values,
+ (unsigned int)CDTIME_T_TO_TIME_T(vl->time));
if (message_len >= sizeof(message)) {
ERROR("format_graphite: message buffer too small: "
"Need %zu bytes.",
#define BUFFER_ADD(...) \
do { \
int status; \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) { \
sfree(rates); \
return -1; \
#define BUFFER_ADD(...) \
do { \
int status; \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) \
return -1; \
else if (((size_t)status) >= (buffer_size - offset)) \
#define BUFFER_ADD(...) \
do { \
int status; \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) \
return -1; \
else if (((size_t)status) >= (buffer_size - offset)) \
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) \
return -1; \
else if (((size_t)status) >= (buffer_size - offset)) \
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) \
return -1; \
else if (((size_t)status) >= (buffer_size - offset)) \
}
JSON_ADD(g, "severity");
- JSON_ADD(g, (n->severity == NOTIF_FAILURE)
- ? "FAILURE"
- : (n->severity == NOTIF_WARNING)
- ? "WARNING"
- : (n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN");
+ JSON_ADD(g,
+ (n->severity == NOTIF_FAILURE)
+ ? "FAILURE"
+ : (n->severity == NOTIF_WARNING)
+ ? "WARNING"
+ : (n->severity == NOTIF_OKAY) ? "OKAY" : "UNKNOWN");
JSON_ADD(g, "service");
JSON_ADD(g, "collectd");
#define BUFFER_ADD(...) \
do { \
int status; \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) { \
sfree(rates); \
return -1; \
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
+ status = snprintf(buffer + offset, buffer_size - offset, __VA_ARGS__); \
if (status < 1) \
return -1; \
else if (((size_t)status) >= (buffer_size - offset)) \
if (*ret_buffer_free < 3)
return -ENOMEM;
- return format_kairosdb_value_list_nocheck(buffer, ret_buffer_fill,
- ret_buffer_free, ds, vl,
- store_rates,
- (*ret_buffer_free) - 2,
- http_attrs, http_attrs_num,
- data_ttl);
+ return format_kairosdb_value_list_nocheck(
+ buffer, ret_buffer_fill, ret_buffer_free, ds, vl, store_rates,
+ (*ret_buffer_free) - 2, http_attrs, http_attrs_num, data_ttl);
} /* }}} int format_kairosdb_value_list */
/* vim: set sw=2 sts=2 et fdm=marker : */
* Pavel Rochnyack <pavel2000 at ngs.ru>
*/
-#include "common.h"
#include "utils_latency_config.h"
+#include "common.h"
#include "collectd.h"
static int latency_config_add_percentile(latency_config_t *conf,
status = latency_config_add_percentile(conf, child, plugin);
else if (strcasecmp("Bucket", child->key) == 0)
status = latency_config_add_bucket(conf, child, plugin);
+ else if (strcasecmp("BucketType", child->key) == 0)
+ status = cf_util_get_string(child, &conf->bucket_type);
else
WARNING("%s plugin: \"%s\" is not a valid option within a \"%s\" block.",
plugin, child->key, ci->key);
return ENOMEM;
}
+ if (src.bucket_type != NULL) {
+ dst->bucket_type = strdup(src.bucket_type);
+ if (dst->bucket_type == NULL) {
+ latency_config_free(*dst);
+ return ENOMEM;
+ }
+ }
+
memmove(dst->percentile, src.percentile,
dst->percentile_num * sizeof(*dst->percentile));
memmove(dst->buckets, src.buckets, dst->buckets_num * sizeof(*dst->buckets));
void latency_config_free(latency_config_t conf) {
sfree(conf.percentile);
sfree(conf.buckets);
+ sfree(conf.bucket_type);
} /* void latency_config_free */
latency_bucket_t *buckets;
size_t buckets_num;
+ char *bucket_type;
/*
_Bool lower;
* GCC will complain about the macro definition. */
#define DONT_POISON_SPRINTF_YET
-#include "common.h"
#include "utils_lua.h"
+#include "common.h"
static int ltoc_values(lua_State *L, /* {{{ */
const data_set_t *ds, value_t *ret_values) {
/* Reset GAUGE metrics only and except GAUGE_PERSIST. */
if ((mv->ds_type & UTILS_MATCH_DS_TYPE_GAUGE) &&
!(mv->ds_type & UTILS_MATCH_CF_GAUGE_PERSIST)) {
- mv->value.gauge = NAN;
+ mv->value.gauge = (mv->ds_type & UTILS_MATCH_CF_GAUGE_INC) ? 0 : NAN;
mv->values_num = 0;
}
} /* }}} void match_value_reset */
* (This is useful, if the cdrom on /dev/hdc must not
* be accessed.)
*/
- ssnprintf(device, sizeof(device), "%s/%s", DEVLABELDIR, ptname);
+ snprintf(device, sizeof(device), "%s/%s", DEVLABELDIR, ptname);
if (!get_label_uuid(device, &label, uuid)) {
uuidcache_addentry(sstrdup(device), label, uuid);
}
return first;
} /* static cu_mount_t *cu_mount_gen_getmntent (void) */
-/* #endif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT */
+ /* #endif HAVE_TWO_GETMNTENT || HAVE_GEN_GETMNTENT || HAVE_SUN_GETMNTENT */
#elif HAVE_SEQ_GETMNTENT
#warn "This version of `getmntent' hat not yet been implemented!"
*
* Copyright(c) 2016 Intel Corporation. All rights reserved.
*
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ *of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
+ * of the Software, and to permit persons to whom the Software is furnished to
+ *do
* so, subject to the following conditions:
*
- * The above copyright notice and this permission notice shall be included in all
+ * The above copyright notice and this permission notice shall be included in
+ *all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
*/
static yajl_gen_status ovs_yajl_gen_tstring(yajl_gen hander,
const char *string) {
- return yajl_gen_string(hander, (const unsigned char *)string,
- strlen(string));
+ return yajl_gen_string(hander, (const unsigned char *)string, strlen(string));
}
/* Add YAJL value into YAJL generator handle (JSON object)
/* generate id field */
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, "id");
uid = ovs_uid_generate();
- ssnprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid);
+ snprintf(uid_buff, sizeof(uid_buff), "%" PRIX64, uid);
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_buff);
OVS_YAJL_CALL(yajl_gen_map_close, jgen);
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, OVS_DB_DEFAULT_DB_NAME);
/* uid string <json-value> */
- ssnprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid);
+ snprintf(uid_str, sizeof(uid_str), "%" PRIX64, new_cb->uid);
OVS_YAJL_CALL(ovs_yajl_gen_tstring, jgen, uid_str);
/* <monitor-requests> */
if (rra_num >= rra_max)
break;
- status = ssnprintf(buffer, sizeof(buffer), "RRA:%s:%.10f:%u:%u",
- rra_types[j], cfg->xff, cdp_len, cdp_num);
+ status = snprintf(buffer, sizeof(buffer), "RRA:%s:%.10f:%u:%u",
+ rra_types[j], cfg->xff, cdp_len, cdp_num);
if ((status < 0) || ((size_t)status >= sizeof(buffer))) {
ERROR("rra_get: Buffer would have been truncated.");
if (isnan(d->min)) {
sstrncpy(min, "U", sizeof(min));
} else
- ssnprintf(min, sizeof(min), "%f", d->min);
+ snprintf(min, sizeof(min), "%f", d->min);
if (isnan(d->max)) {
sstrncpy(max, "U", sizeof(max));
} else
- ssnprintf(max, sizeof(max), "%f", d->max);
+ snprintf(max, sizeof(max), "%f", d->max);
- status = ssnprintf(buffer, sizeof(buffer), "DS:%s:%s:%i:%s:%s", d->name,
- type, (cfg->heartbeat > 0)
- ? cfg->heartbeat
- : (int)CDTIME_T_TO_TIME_T(2 * vl->interval),
- min, max);
+ status = snprintf(
+ buffer, sizeof(buffer), "DS:%s:%s:%i:%s:%s", d->name, type,
+ (cfg->heartbeat > 0) ? cfg->heartbeat
+ : (int)CDTIME_T_TO_TIME_T(2 * vl->interval),
+ min, max);
if ((status < 1) || ((size_t)status >= sizeof(buffer)))
break;
if (last_up == 0)
last_up = time(NULL) - 10;
- ssnprintf(pdp_step_str, sizeof(pdp_step_str), "%lu", pdp_step);
- ssnprintf(last_up_str, sizeof(last_up_str), "%lu", (unsigned long)last_up);
+ snprintf(pdp_step_str, sizeof(pdp_step_str), "%lu", pdp_step);
+ snprintf(last_up_str, sizeof(last_up_str), "%lu", (unsigned long)last_up);
new_argv[0] = "create";
new_argv[1] = (void *)filename;
return 0;
}
- ssnprintf(tmpfile, sizeof(tmpfile), "%s.async", args->filename);
+ snprintf(tmpfile, sizeof(tmpfile), "%s.async", args->filename);
status = srrd_create(tmpfile, args->pdp_step, args->last_up, args->argc,
(void *)args->argv);
if (match_value == NULL)
return -1;
- sstrncpy(vl.host, hostname_g, sizeof(vl.host));
sstrncpy(vl.plugin, data->plugin, sizeof(vl.plugin));
sstrncpy(vl.plugin_instance, data->plugin_instance,
sizeof(vl.plugin_instance));
sstrncpy(vl.type, data->type, sizeof(vl.type));
for (size_t i = 0; i < data->latency_config.percentile_num; i++) {
if (strlen(data->type_instance) != 0)
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%.0f",
- data->type_instance, data->latency_config.percentile[i]);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%.0f",
+ data->type_instance, data->latency_config.percentile[i]);
else
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%.0f",
- data->latency_config.percentile[i]);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%.0f",
+ data->latency_config.percentile[i]);
vl.values = &(value_t){
.gauge =
}
/* Submit buckets */
- sstrncpy(vl.type, "bucket", sizeof(vl.type));
+ if (data->latency_config.bucket_type != NULL)
+ sstrncpy(vl.type, data->latency_config.bucket_type, sizeof(vl.type));
+ else
+ sstrncpy(vl.type, "bucket", sizeof(vl.type));
+
for (size_t i = 0; i < data->latency_config.buckets_num; i++) {
latency_bucket_t bucket = data->latency_config.buckets[i];
bucket.upper_bound ? CDTIME_T_TO_DOUBLE(bucket.upper_bound) : INFINITY;
if (strlen(data->type_instance) != 0)
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s-%g_%g",
- data->type, data->type_instance, lower_bound, upper_bound);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%s-%g_%g",
+ data->type, data->type_instance, lower_bound, upper_bound);
else
- ssnprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%g_%g",
- data->type, lower_bound, upper_bound);
+ snprintf(vl.type_instance, sizeof(vl.type_instance), "%s-%g_%g",
+ data->type, lower_bound, upper_bound);
vl.values = &(value_t){
.gauge =
* Jérôme Renard <jerome.renard at gmail.com>
* Marc Fournier <marc.fournier at camptocamp.com>
* Florian octo Forster <octo at collectd.org>
+ * Denes Matetelki <dmatetelki at varnish-software.com>
**/
#include "collectd.h"
_Bool collect_sms;
#if HAVE_VARNISH_V2
_Bool collect_sm;
+#endif
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
_Bool collect_sma;
#endif
_Bool collect_struct;
_Bool collect_workers;
#if HAVE_VARNISH_V4
_Bool collect_vsm;
+ _Bool collect_lck;
+ _Bool collect_mempool;
+ _Bool collect_mgt;
+ _Bool collect_smf;
+ _Bool collect_vbe;
#endif
};
typedef struct user_config_s user_config_t; /* }}} */
if (plugin_instance == NULL)
plugin_instance = "default";
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
- plugin_instance, category);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%s-%s",
+ plugin_instance, category);
sstrncpy(vl.type, type, sizeof(vl.type));
const char *category, const char *type,
const char *type_instance,
uint64_t gauge_value) {
- return varnish_submit(plugin_instance, category, type, type_instance, (value_t){
- .gauge=(gauge_t)gauge_value,
- });
+ return varnish_submit(plugin_instance, category, type, type_instance,
+ (value_t){
+ .gauge = (gauge_t)gauge_value,
+ });
} /* }}} int varnish_submit_gauge */
static int varnish_submit_derive(const char *plugin_instance, /* {{{ */
const char *category, const char *type,
const char *type_instance,
uint64_t derive_value) {
- return varnish_submit(plugin_instance, category, type, type_instance, (value_t){
- .derive=(derive_t)derive_value,
- });
+ return varnish_submit(plugin_instance, category, type, type_instance,
+ (value_t){
+ .derive = (derive_t)derive_value,
+ });
} /* }}} int varnish_submit_derive */
#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
if (conf->collect_connections) {
if (strcmp(name, "client_conn") == 0)
- return varnish_submit_derive(conf->instance, "connections",
- "connections", "accepted", val);
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "accepted", val);
else if (strcmp(name, "client_drop") == 0)
- return varnish_submit_derive(conf->instance, "connections",
- "connections", "dropped", val);
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "dropped", val);
else if (strcmp(name, "client_req") == 0)
- return varnish_submit_derive(conf->instance, "connections",
- "connections", "received", val);
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "received", val);
+#ifdef HAVE_VARNISH_V4
+ else if (strcmp(name, "client_req_400") == 0)
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "error_400", val);
+ else if (strcmp(name, "client_req_417") == 0)
+ return varnish_submit_derive(conf->instance, "connections", "connections",
+ "error_417", val);
+#endif
}
#ifdef HAVE_VARNISH_V3
if (conf->collect_dirdns) {
if (strcmp(name, "dir_dns_lookups") == 0)
- return varnish_submit_derive(conf->instance, "dirdns",
- "cache_operation", "lookups", val);
+ return varnish_submit_derive(conf->instance, "dirdns", "cache_operation",
+ "lookups", val);
else if (strcmp(name, "dir_dns_failed") == 0)
return varnish_submit_derive(conf->instance, "dirdns", "cache_result",
"failed", val);
else if (strcmp(name, "fetch_304") == 0)
return varnish_submit_derive(conf->instance, "fetch", "http_requests",
"no_body_304", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "fetch_no_thread") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "no_thread", val);
+ else if (strcmp(name, "fetch_none") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "none", val);
+ else if (strcmp(name, "busy_sleep") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "busy_sleep", val);
+ else if (strcmp(name, "busy_wakeup") == 0)
+ return varnish_submit_derive(conf->instance, "fetch", "http_requests",
+ "busy_wakeup", val);
+#endif
}
if (conf->collect_hcb) {
else if (strcmp(name, "n_objoverflow") == 0)
return varnish_submit_derive(conf->instance, "objects", "total_objects",
"workspace_overflow", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "exp_mailed") == 0)
+ return varnish_submit_derive(conf->instance, "struct", "objects",
+ "exp_mailed", val);
+ else if (strcmp(name, "exp_received") == 0)
+ return varnish_submit_derive(conf->instance, "struct", "objects",
+ "exp_received", val);
+#endif
}
#if HAVE_VARNISH_V3
else if (strcmp(name, "bans_dups") == 0)
return varnish_submit_derive(conf->instance, "ban", "total_operations",
"duplicate", val);
+ else if (strcmp(name, "bans_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "tested", val);
+ else if (strcmp(name, "bans_lurker_contention") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_contention", val);
+ else if (strcmp(name, "bans_lurker_obj_killed") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_obj_killed", val);
+ else if (strcmp(name, "bans_lurker_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_tested", val);
+ else if (strcmp(name, "bans_lurker_tests_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "lurker_tests_tested", val);
+ else if (strcmp(name, "bans_obj_killed") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "obj_killed", val);
+ else if (strcmp(name, "bans_persisted_bytes") == 0)
+ return varnish_submit_gauge(conf->instance, "ban", "total_bytes",
+ "persisted_bytes", val);
+ else if (strcmp(name, "bans_persisted_fragmentation") == 0)
+ return varnish_submit_gauge(conf->instance, "ban", "total_bytes",
+ "persisted_fragmentation", val);
+ else if (strcmp(name, "bans_tests_tested") == 0)
+ return varnish_submit_derive(conf->instance, "ban", "total_operations",
+ "tests_tested", val);
+
}
#endif
else if (strcmp(name, "sess_herd") == 0)
return varnish_submit_derive(conf->instance, "session",
"total_operations", "herd", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "sess_closed_err") == 0)
+ return varnish_submit_derive(conf->instance, "session",
+ "total_operations", "closed_err", val);
+ else if (strcmp(name, "sess_dropped") == 0)
+ return varnish_submit_derive(conf->instance, "session",
+ "total_operations", "dropped_for_thread", val);
+#endif
}
if (conf->collect_shm) {
return varnish_submit_gauge(conf->instance, "sms", "requests",
"outstanding", val);
else if (strcmp(name, "sms_nbytes") == 0)
- return varnish_submit_gauge(conf->instance, "sms", "bytes",
- "outstanding", val);
+ return varnish_submit_gauge(conf->instance, "sms", "bytes", "outstanding",
+ val);
else if (strcmp(name, "sms_balloc") == 0)
return varnish_submit_derive(conf->instance, "sms", "total_bytes",
"allocated", val);
else if (strcmp(name, "sms_bfree") == 0)
- return varnish_submit_derive(conf->instance, "sms", "total_bytes",
- "free", val);
+ return varnish_submit_derive(conf->instance, "sms", "total_bytes", "free",
+ val);
}
if (conf->collect_struct) {
if (strcmp(name, "n_sess_mem") == 0)
- return varnish_submit_gauge(conf->instance, "struct",
- "current_sessions", "sess_mem", val);
+ return varnish_submit_gauge(conf->instance, "struct", "current_sessions",
+ "sess_mem", val);
else if (strcmp(name, "n_sess") == 0)
- return varnish_submit_gauge(conf->instance, "struct",
- "current_sessions", "sess", val);
+ return varnish_submit_gauge(conf->instance, "struct", "current_sessions",
+ "sess", val);
else if (strcmp(name, "n_object") == 0)
- return varnish_submit_gauge(conf->instance, "struct", "objects",
- "object", val);
+ return varnish_submit_gauge(conf->instance, "struct", "objects", "object",
+ val);
else if (strcmp(name, "n_vampireobject") == 0)
return varnish_submit_gauge(conf->instance, "struct", "objects",
"vampireobject", val);
return varnish_submit_derive(conf->instance, "totals", "total_requests",
"requests", val);
else if (strcmp(name, "s_pipe") == 0)
- return varnish_submit_derive(conf->instance, "totals",
- "total_operations", "pipe", val);
+ return varnish_submit_derive(conf->instance, "totals", "total_operations",
+ "pipe", val);
else if (strcmp(name, "s_pass") == 0)
- return varnish_submit_derive(conf->instance, "totals",
- "total_operations", "pass", val);
+ return varnish_submit_derive(conf->instance, "totals", "total_operations",
+ "pass", val);
else if (strcmp(name, "s_fetch") == 0)
- return varnish_submit_derive(conf->instance, "totals",
- "total_operations", "fetches", val);
+ return varnish_submit_derive(conf->instance, "totals", "total_operations",
+ "fetches", val);
else if (strcmp(name, "s_synth") == 0)
return varnish_submit_derive(conf->instance, "totals", "total_bytes",
"synth", val);
return varnish_submit_derive(conf->instance, "totals", "total_bytes",
"pipe_out", val);
else if (strcmp(name, "n_purges") == 0)
- return varnish_submit_derive(conf->instance, "totals",
- "total_operations", "purges", val);
+ return varnish_submit_derive(conf->instance, "totals", "total_operations",
+ "purges", val);
else if (strcmp(name, "s_hdrbytes") == 0)
return varnish_submit_derive(conf->instance, "totals", "total_bytes",
"header-bytes", val);
return varnish_submit_derive(conf->instance, "totals", "total_bytes",
"body-bytes", val);
else if (strcmp(name, "n_gzip") == 0)
- return varnish_submit_derive(conf->instance, "totals",
- "total_operations", "gzip", val);
+ return varnish_submit_derive(conf->instance, "totals", "total_operations",
+ "gzip", val);
else if (strcmp(name, "n_gunzip") == 0)
- return varnish_submit_derive(conf->instance, "totals",
- "total_operations", "gunzip", val);
+ return varnish_submit_derive(conf->instance, "totals", "total_operations",
+ "gunzip", val);
}
if (conf->collect_uptime) {
return varnish_submit_gauge(conf->instance, "vcl", "vcl", "avail_vcl",
val);
else if (strcmp(name, "n_vcl_discard") == 0)
- return varnish_submit_gauge(conf->instance, "vcl", "vcl",
- "discarded_vcl", val);
+ return varnish_submit_gauge(conf->instance, "vcl", "vcl", "discarded_vcl",
+ val);
else if (strcmp(name, "vmods") == 0)
return varnish_submit_gauge(conf->instance, "vcl", "objects", "vmod",
val);
return varnish_submit_derive(conf->instance, "workers", "total_threads",
"dropped", val);
else if (strcmp(name, "n_wrk_queue") == 0)
- return varnish_submit_derive(conf->instance, "workers",
- "total_requests", "queued", val);
+ return varnish_submit_derive(conf->instance, "workers", "total_requests",
+ "queued", val);
else if (strcmp(name, "n_wrk_overflow") == 0)
- return varnish_submit_derive(conf->instance, "workers",
- "total_requests", "overflowed", val);
+ return varnish_submit_derive(conf->instance, "workers", "total_requests",
+ "overflowed", val);
else if (strcmp(name, "n_wrk_queued") == 0)
- return varnish_submit_derive(conf->instance, "workers",
- "total_requests", "queued", val);
+ return varnish_submit_derive(conf->instance, "workers", "total_requests",
+ "queued", val);
else if (strcmp(name, "n_wrk_lqueue") == 0)
- return varnish_submit_derive(conf->instance, "workers",
- "total_requests", "queue_length", val);
+ return varnish_submit_derive(conf->instance, "workers", "total_requests",
+ "queue_length", val);
+#if HAVE_VARNISH_V4
+ else if (strcmp(name, "pools") == 0)
+ return varnish_submit_gauge(conf->instance, "workers", "pools",
+ "pools", val);
+ else if (strcmp(name, "busy_killed") == 0)
+ return varnish_submit_derive(conf->instance, "workers", "http_requests",
+ "busy_killed", val);
+
+#endif
}
#if HAVE_VARNISH_V4
return varnish_submit_derive(conf->instance, "vsm", "total_bytes",
"overflowed", val);
}
+
+ if (conf->collect_vbe) {
+ /* @TODO figure out the collectd type for bitmap
+ if (strcmp(name, "happy") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "bitmap", "happy_hprobes", val);
+ */
+ if (strcmp(name, "bereq_hdrbytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "bereq_hdrbytes", val);
+ else if (strcmp(name, "bereq_bodybytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "bereq_bodybytes", val);
+ else if (strcmp(name, "beresp_hdrbytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "beresp_hdrbytes", val);
+ else if (strcmp(name, "beresp_bodybytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "beresp_bodybytes", val);
+ else if (strcmp(name, "pipe_hdrbytes") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "pipe_hdrbytes", val);
+ else if (strcmp(name, "pipe_out") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "pipe_out", val);
+ else if (strcmp(name, "pipe_in") == 0)
+ return varnish_submit_derive(conf->instance, "vbe",
+ "total_bytes", "pipe_in", val);
+ else if (strcmp(name, "conn") == 0)
+ return varnish_submit_derive(conf->instance, "vbe", "connections",
+ "c_conns", val);
+ else if (strcmp(name, "req") == 0)
+ return varnish_submit_gauge(conf->instance, "vbe", "http_requests",
+ "b_reqs", val);
+ }
+
+ /* All Stevedores support these counters */
+ if (conf->collect_sma || conf->collect_smf) {
+
+ char category[4];
+ if (conf->collect_sma)
+ strncpy(category, "sma", 4);
+ else
+ strncpy(category, "smf", 4);
+
+ if (strcmp(name, "c_req") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_operations", "alloc_req", val);
+ else if (strcmp(name, "c_fail") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_operations", "alloc_fail", val);
+ else if (strcmp(name, "c_bytes") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_bytes", "bytes_allocated", val);
+ else if (strcmp(name, "c_freed") == 0)
+ return varnish_submit_derive(conf->instance, category,
+ "total_bytes", "bytes_freed", val);
+ else if (strcmp(name, "g_alloc") == 0)
+ return varnish_submit_gauge(conf->instance, category,
+ "total_operations", "alloc_outstanding", val);
+ else if (strcmp(name, "g_bytes") == 0)
+ return varnish_submit_gauge(conf->instance, category, "bytes",
+ "bytes_outstanding", val);
+ else if (strcmp(name, "g_space") == 0)
+ return varnish_submit_gauge(conf->instance, category, "bytes",
+ "bytes_available", val);
+ }
+
+ /* No SMA specific counters */
+
+ if (conf->collect_smf) {
+ if (strcmp(name, "g_smf") == 0)
+ return varnish_submit_gauge(conf->instance, "smf", "objects",
+ "n_struct_smf", val);
+ else if (strcmp(name, "g_smf_frag") == 0)
+ return varnish_submit_gauge(conf->instance, "smf", "objects",
+ "n_small_free_smf", val);
+ else if (strcmp(name, "g_smf_large") == 0)
+ return varnish_submit_gauge(conf->instance, "smf", "objects",
+ "n_large_free_smf", val);
+ }
+
+ if (conf->collect_mgt) {
+ if (strcmp(name, "uptime") == 0)
+ return varnish_submit_gauge(conf->instance, "mgt", "uptime",
+ "mgt_proc_uptime", val);
+ else if (strcmp(name, "child_start") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_start", val);
+ else if (strcmp(name, "child_exit") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_exit", val);
+ else if (strcmp(name, "child_stop") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_stop", val);
+ else if (strcmp(name, "child_died") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_died", val);
+ else if (strcmp(name, "child_dump") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_dump", val);
+ else if (strcmp(name, "child_panic") == 0)
+ return varnish_submit_derive(conf->instance, "mgt",
+ "total_operations", "child_panic", val);
+ }
+
+ if (conf->collect_lck) {
+ if (strcmp(name, "creat") == 0)
+ return varnish_submit_derive(conf->instance, "lck", "objects",
+ "created", val);
+ else if (strcmp(name, "destroy") == 0)
+ return varnish_submit_derive(conf->instance, "lck", "objects",
+ "destroyed", val);
+ else if (strcmp(name, "locks") == 0)
+ return varnish_submit_derive(conf->instance, "lck", "total_operations",
+ "lock_ops", val);
+ }
+
+ if (conf->collect_mempool) {
+ if (strcmp(name, "live") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "objects",
+ "in_use", val);
+ else if (strcmp(name, "pool") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "objects",
+ "in_pool", val);
+ else if (strcmp(name, "sz_wanted") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "bytes",
+ "size_requested", val);
+ else if (strcmp(name, "sz_actual") == 0)
+ return varnish_submit_gauge(conf->instance, "mempool", "bytes",
+ "size_allocated", val);
+ else if (strcmp(name, "allocs") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "total_operations", "allocations", val);
+ else if (strcmp(name, "frees") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "total_operations", "frees", val);
+ else if (strcmp(name, "recycle") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "recycled", val);
+ else if (strcmp(name, "timeout") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "timed_out", val);
+ else if (strcmp(name, "toosmall") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "too_small", val);
+ else if (strcmp(name, "surplus") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "surplus", val);
+ else if (strcmp(name, "randry") == 0)
+ return varnish_submit_derive(conf->instance, "mempool",
+ "objects", "ran_dry", val);
+ }
#endif
return 0;
conf->collect_shm = 1;
#if HAVE_VARNISH_V2
conf->collect_sm = 0;
+#endif
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
conf->collect_sma = 0;
#endif
conf->collect_sms = 0;
conf->collect_workers = 0;
#if HAVE_VARNISH_V4
conf->collect_vsm = 0;
+ conf->collect_lck = 0;
+ conf->collect_mempool = 0;
+ conf->collect_mgt = 0;
+ conf->collect_smf = 0;
+ conf->collect_vbe = 0;
#endif
return 0;
/* group = */ "varnish",
/* name = */ "varnish/localhost",
/* callback = */ varnish_read,
- /* interval = */ 0, &(user_data_t){
- .data = conf, .free_func = varnish_config_free,
- });
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = conf, .free_func = varnish_config_free,
+ });
return 0;
} /* }}} int varnish_init */
else if (strcasecmp("CollectSMS", child->key) == 0)
cf_util_get_boolean(child, &conf->collect_sms);
else if (strcasecmp("CollectSMA", child->key) == 0)
-#if HAVE_VARNISH_V2
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
cf_util_get_boolean(child, &conf->collect_sma);
#else
WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
- child->key, "v2");
+ child->key, "v2 and v4");
#endif
else if (strcasecmp("CollectSM", child->key) == 0)
#if HAVE_VARNISH_V2
WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
child->key, "v4");
#endif
+ else if (strcasecmp("CollectLock", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_lck);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectMempool", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_mempool);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectManagement", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_mgt);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectSMF", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_smf);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectSMF", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_smf);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
+ else if (strcasecmp("CollectVBE", child->key) == 0)
+#if HAVE_VARNISH_V4
+ cf_util_get_boolean(child, &conf->collect_vbe);
+#else
+ WARNING("Varnish plugin: \"%s\" is available for Varnish %s only.",
+ child->key, "v4");
+#endif
else {
WARNING("Varnish plugin: Ignoring unknown "
"configuration option: \"%s\". Did "
#endif
&& !conf->collect_session && !conf->collect_shm && !conf->collect_sms
#if HAVE_VARNISH_V2
- && !conf->collect_sma && !conf->collect_sm
+ && !conf->collect_sm
+#endif
+#if HAVE_VARNISH_V2 || HAVE_VARNISH_V4
+ && !conf->collect_sma
#endif
&& !conf->collect_struct && !conf->collect_totals
#if HAVE_VARNISH_V3 || HAVE_VARNISH_V4
#endif
&& !conf->collect_vcl && !conf->collect_workers
#if HAVE_VARNISH_V4
- && !conf->collect_vsm
+ && !conf->collect_vsm && !conf->collect_vbe && !conf->collect_smf
+ && !conf->collect_mgt && !conf->collect_lck && !conf->collect_mempool
#endif
) {
WARNING("Varnish plugin: No metric has been configured for "
return EINVAL;
}
- ssnprintf(callback_name, sizeof(callback_name), "varnish/%s",
- (conf->instance == NULL) ? "localhost" : conf->instance);
+ snprintf(callback_name, sizeof(callback_name), "varnish/%s",
+ (conf->instance == NULL) ? "localhost" : conf->instance);
plugin_register_complex_read(
/* group = */ "varnish",
/* name = */ callback_name,
/* callback = */ varnish_read,
- /* interval = */ 0, &(user_data_t){
- .data = conf, .free_func = varnish_config_free,
- });
+ /* interval = */ 0,
+ &(user_data_t){
+ .data = conf, .free_func = varnish_config_free,
+ });
have_instance = 1;
const char *type) {
char type_instance[DATA_MAX_NAME_LEN];
- ssnprintf(type_instance, sizeof(type_instance), "%d", vcpu_nr);
+ snprintf(type_instance, sizeof(type_instance), "%d", vcpu_nr);
submit(dom, type, type_instance, &(value_t){.derive = value}, 1);
}
}
char flush_type_instance[DATA_MAX_NAME_LEN];
- ssnprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s",
- type_instance);
+ snprintf(flush_type_instance, sizeof(flush_type_instance), "flush-%s",
+ type_instance);
if ((binfo->bi.rd_req != -1) && (binfo->bi.wr_req != -1))
submit_derive2("disk_ops", (derive_t)binfo->bi.rd_req,
const char *reason_str = "N/A";
#endif
- ssnprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str,
- reason_str);
+ snprintf(msg, sizeof(msg), "Domain state: %s. Reason: %s", state_str,
+ reason_str);
int severity;
switch (state) {
char type_instance[DATA_MAX_NAME_LEN];
_Bool is_set = VIR_CPU_USABLE(cpu_maps, cpu_map_len, vcpu, cpu) ? 1 : 0;
- ssnprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu,
- cpu);
+ snprintf(type_instance, sizeof(type_instance), "vcpu_%d-cpu_%d", vcpu, cpu);
submit(dom, "cpu_affinity", type_instance, &(value_t){.gauge = is_set}, 1);
}
}
memset(lv_ud, 0, sizeof(*lv_ud));
- ssnprintf(inst->tag, sizeof(inst->tag), "%s-%zu", PLUGIN_NAME, i);
+ snprintf(inst->tag, sizeof(inst->tag), "%s-%zu", PLUGIN_NAME, i);
inst->id = i;
user_data_t *ud = &(lv_ud->ud);
goto done;
}
- ssnprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()",
- METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_ELEMENT);
+ snprintf(xpath_str, sizeof(xpath_str), "/domain/metadata/%s:%s/text()",
+ METADATA_VM_PARTITION_PREFIX, METADATA_VM_PARTITION_ELEMENT);
xpath_obj = xmlXPathEvalExpression((xmlChar *)xpath_str, xpath_ctx);
if (xpath_obj == NULL) {
ERROR(PLUGIN_NAME " plugin: xmlXPathEval(%s) failed on domain %s",
ERROR(PLUGIN_NAME " plugin: malloc failed.");
return 0;
}
- ssnprintf(name, n, "%s:%s", domname, devpath);
+ snprintf(name, n, "%s:%s", domname, devpath);
r = ignorelist_match(il, name);
sfree(name);
return r;
* Florian octo Forster <octo at collectd.org>
**/
-#include "virt.c" /* sic */
#include "testing.h"
+#include "virt.c" /* sic */
#include <unistd.h>
if (dent->d_name[0] == '.')
continue;
- len = ssnprintf(file, sizeof(file), PROCDIR "/%s", dent->d_name);
+ len = snprintf(file, sizeof(file), PROCDIR "/%s", dent->d_name);
if ((len < 0) || (len >= BUFSIZE))
continue;
continue;
/* socket message accounting */
- len = ssnprintf(file, sizeof(file), PROCDIR "/%s/cacct", dent->d_name);
+ len = snprintf(file, sizeof(file), PROCDIR "/%s/cacct", dent->d_name);
if ((len < 0) || ((size_t)len >= sizeof(file)))
continue;
}
/* thread information and load */
- len = ssnprintf(file, sizeof(file), PROCDIR "/%s/cvirt", dent->d_name);
+ len = snprintf(file, sizeof(file), PROCDIR "/%s/cvirt", dent->d_name);
if ((len < 0) || ((size_t)len >= sizeof(file)))
continue;
}
/* processes and memory usage */
- len = ssnprintf(file, sizeof(file), PROCDIR "/%s/limit", dent->d_name);
+ len = snprintf(file, sizeof(file), PROCDIR "/%s/limit", dent->d_name);
if ((len < 0) || ((size_t)len >= sizeof(file)))
continue;
/* FIXME: Legacy configuration syntax. */
if (cb->name == NULL)
- ssnprintf(callback_name, sizeof(callback_name), "write_graphite/%s/%s/%s",
- cb->node, cb->service, cb->protocol);
+ snprintf(callback_name, sizeof(callback_name), "write_graphite/%s/%s/%s",
+ cb->node, cb->service, cb->protocol);
else
- ssnprintf(callback_name, sizeof(callback_name), "write_graphite/%s",
- cb->name);
+ snprintf(callback_name, sizeof(callback_name), "write_graphite/%s",
+ cb->name);
plugin_register_write(callback_name, wg_write,
&(user_data_t){
return -1;
}
- ssnprintf(cb->credentials, credentials_size, "%s:%s", cb->user,
- (cb->pass == NULL) ? "" : cb->pass);
+ snprintf(cb->credentials, credentials_size, "%s:%s", cb->user,
+ (cb->pass == NULL) ? "" : cb->pass);
curl_easy_setopt(cb->curl, CURLOPT_USERPWD, cb->credentials);
#endif
curl_easy_setopt(cb->curl, CURLOPT_HTTPAUTH, CURLAUTH_ANY);
return status;
}
- command_len = (size_t)ssnprintf(command, sizeof(command),
- "PUTVAL %s interval=%.3f %s\r\n", key,
- CDTIME_T_TO_DOUBLE(vl->interval), values);
+ command_len = (size_t)snprintf(command, sizeof(command),
+ "PUTVAL %s interval=%.3f %s\r\n", key,
+ CDTIME_T_TO_DOUBLE(vl->interval), values);
if (command_len >= sizeof(command)) {
ERROR("write_http plugin: Command buffer too small: "
"Need %zu bytes.",
/* Nulls the buffer and sets ..._free and ..._fill. */
wh_reset_buffer(cb);
- ssnprintf(callback_name, sizeof(callback_name), "write_http/%s", cb->name);
+ snprintf(callback_name, sizeof(callback_name), "write_http/%s", cb->name);
DEBUG("write_http: Registering write callback '%s' with URL '%s'",
callback_name, cb->location);
#define KAFKA_RANDOM_KEY_BUFFER \
(char[KAFKA_RANDOM_KEY_SIZE]) { "" }
static char *kafka_random_key(char buffer[static KAFKA_RANDOM_KEY_SIZE]) {
- ssnprintf(buffer, KAFKA_RANDOM_KEY_SIZE, "%08" PRIX32, cdrand_u());
+ snprintf(buffer, KAFKA_RANDOM_KEY_SIZE, "%08" PRIX32, cdrand_u());
return buffer;
}
rd_kafka_topic_conf_set_partitioner_cb(tctx->conf, kafka_partition);
rd_kafka_topic_conf_set_opaque(tctx->conf, tctx);
- ssnprintf(callback_name, sizeof(callback_name), "write_kafka/%s",
- tctx->topic_name);
+ snprintf(callback_name, sizeof(callback_name), "write_kafka/%s",
+ tctx->topic_name);
status = plugin_register_write(
callback_name, kafka_write,
for (size_t i = 0; i < ds->ds_num; i++) {
char key[16];
- ssnprintf(key, sizeof(key), "%zu", i);
+ snprintf(key, sizeof(key), "%zu", i);
if (ds->ds[i].type == DS_TYPE_GAUGE)
BSON_APPEND_DOUBLE(&subarray, key, vl->values[i].gauge);
for (size_t i = 0; i < ds->ds_num; i++) {
char key[16];
- ssnprintf(key, sizeof(key), "%zu", i);
+ snprintf(key, sizeof(key), "%zu", i);
if (store_rates)
BSON_APPEND_UTF8(&subarray, key, "gauge");
for (size_t i = 0; i < ds->ds_num; i++) {
char key[16];
- ssnprintf(key, sizeof(key), "%zu", i);
+ snprintf(key, sizeof(key), "%zu", i);
BSON_APPEND_UTF8(&subarray, key, ds->ds[i].name);
}
bson_append_array_end(ret, &subarray); /* }}} dsnames */
}
if (status == 0) {
- char cb_name[DATA_MAX_NAME_LEN];
+ char cb_name[sizeof("write_mongodb/") + DATA_MAX_NAME_LEN];
- ssnprintf(cb_name, sizeof(cb_name), "write_mongodb/%s", node->name);
+ snprintf(cb_name, sizeof(cb_name), "write_mongodb/%s", node->name);
status =
plugin_register_write(cb_name, wm_write,
* know that they are sane. */
for (size_t i = 0; i < m->n_label; i++) {
char value[LABEL_VALUE_SIZE];
- ssnprintf(labels[i], LABEL_BUFFER_SIZE, "%s=\"%s\"", m->label[i]->name,
- escape_label_value(value, sizeof(value), m->label[i]->value));
+ snprintf(labels[i], LABEL_BUFFER_SIZE, "%s=\"%s\"", m->label[i]->name,
+ escape_label_value(value, sizeof(value), m->label[i]->value));
}
strjoin(buffer, buffer_size, labels, m->n_label, ",");
while (c_avl_iterator_next(iter, (void *)&unused_name, (void *)&fam) == 0) {
char line[1024]; /* 4x DATA_MAX_NAME_LEN? */
- ssnprintf(line, sizeof(line), "# HELP %s %s\n", fam->name, fam->help);
+ snprintf(line, sizeof(line), "# HELP %s %s\n", fam->name, fam->help);
buffer->append(buffer, strlen(line), (uint8_t *)line);
- ssnprintf(line, sizeof(line), "# TYPE %s %s\n", fam->name,
- (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
- ? "gauge"
- : "counter");
+ snprintf(line, sizeof(line), "# TYPE %s %s\n", fam->name,
+ (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
+ ? "gauge"
+ : "counter");
buffer->append(buffer, strlen(line), (uint8_t *)line);
for (size_t i = 0; i < fam->n_metric; i++) {
char timestamp_ms[24] = "";
if (m->has_timestamp_ms)
- ssnprintf(timestamp_ms, sizeof(timestamp_ms), " %" PRIi64,
- m->timestamp_ms);
+ snprintf(timestamp_ms, sizeof(timestamp_ms), " %" PRIi64,
+ m->timestamp_ms);
if (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
- ssnprintf(line, sizeof(line), "%s{%s} " GAUGE_FORMAT "%s\n", fam->name,
- format_labels(labels, sizeof(labels), m), m->gauge->value,
- timestamp_ms);
+ snprintf(line, sizeof(line), "%s{%s} " GAUGE_FORMAT "%s\n", fam->name,
+ format_labels(labels, sizeof(labels), m), m->gauge->value,
+ timestamp_ms);
else /* if (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__COUNTER) */
- ssnprintf(line, sizeof(line), "%s{%s} %.0f%s\n", fam->name,
- format_labels(labels, sizeof(labels), m), m->counter->value,
- timestamp_ms);
+ snprintf(line, sizeof(line), "%s{%s} %.0f%s\n", fam->name,
+ format_labels(labels, sizeof(labels), m), m->counter->value,
+ timestamp_ms);
buffer->append(buffer, strlen(line), (uint8_t *)line);
}
c_avl_iterator_destroy(iter);
char server[1024];
- ssnprintf(server, sizeof(server), "\n# collectd/write_prometheus %s at %s\n",
- PACKAGE_VERSION, hostname_g);
+ snprintf(server, sizeof(server), "\n# collectd/write_prometheus %s at %s\n",
+ PACKAGE_VERSION, hostname_g);
buffer->append(buffer, strlen(server), (uint8_t *)server);
pthread_mutex_unlock(&metrics_lock);
if (m == NULL)
return -1;
- return metric_update(m, vl->values[ds_index], ds->ds[ds_index].type,
- vl->time, vl->interval);
+ return metric_update(m, vl->values[ds_index], ds->ds[ds_index].type, vl->time,
+ vl->interval);
}
/* metric_family_destroy frees the memory used by a metric family. */
msg->name = name;
char help[1024];
- ssnprintf(
+ snprintf(
help, sizeof(help),
"write_prometheus plugin: '%s' Type: '%s', Dstype: '%s', Dsname: '%s'",
vl->plugin, vl->type, DS_TYPE_TO_STRING(ds->ds[ds_index].type),
char *prefix;
int database;
int max_set_size;
+ int max_set_duration;
_Bool store_rates;
redisContext *conn;
status = FORMAT_VL(ident, sizeof(ident), vl);
if (status != 0)
return status;
- ssnprintf(key, sizeof(key), "%s%s",
- (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX,
- ident);
- ssnprintf(time, sizeof(time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
+ snprintf(key, sizeof(key), "%s%s",
+ (node->prefix != NULL) ? node->prefix : REDIS_DEFAULT_PREFIX, ident);
+ snprintf(time, sizeof(time), "%.9f", CDTIME_T_TO_DOUBLE(vl->time));
value_size = sizeof(value);
value_ptr = &value[0];
freeReplyObject(rr);
}
+ if (node->max_set_duration > 0) {
+ /*
+ * remove element, scored less than 'current-max_set_duration'
+ * '(%d' indicates 'less than' in redis CLI.
+ */
+ rr = redisCommand(node->conn, "ZREMRANGEBYSCORE %s -1 (%d", key,
+ (time - node->max_set_duration) + 1);
+ if (rr == NULL)
+ WARNING("ZREMRANGEBYSCORE command error. key:%s message:%s", key,
+ node->conn->errstr);
+ else
+ freeReplyObject(rr);
+ }
+
/* TODO(octo): This is more overhead than necessary. Use the cache and
* metadata to determine if it is a new metric and call SADD only once for
* each metric. */
node->prefix = NULL;
node->database = 0;
node->max_set_size = -1;
+ node->max_set_duration = -1;
node->store_rates = 1;
pthread_mutex_init(&node->lock, /* attr = */ NULL);
status = cf_util_get_int(child, &node->database);
} else if (strcasecmp("MaxSetSize", child->key) == 0) {
status = cf_util_get_int(child, &node->max_set_size);
+ } else if (strcasecmp("MaxSetDuration", child->key) == 0) {
+ status = cf_util_get_int(child, &node->max_set_duration);
} else if (strcasecmp("StoreRates", child->key) == 0) {
status = cf_util_get_boolean(child, &node->store_rates);
} else
} /* for (i = 0; i < ci->children_num; i++) */
if (status == 0) {
- char cb_name[DATA_MAX_NAME_LEN];
+ char cb_name[sizeof("write_redis/") + DATA_MAX_NAME_LEN];
- ssnprintf(cb_name, sizeof(cb_name), "write_redis/%s", node->name);
+ snprintf(cb_name, sizeof(cb_name), "write_redis/%s", node->name);
- status = plugin_register_write(
- cb_name, wr_write, &(user_data_t){
- .data = node, .free_func = wr_config_free,
- });
+ status =
+ plugin_register_write(cb_name, wr_write,
+ &(user_data_t){
+ .data = node, .free_func = wr_config_free,
+ });
}
if (status != 0)
vl->type_instance);
if (host->always_append_ds || (ds->ds_num > 1)) {
if (host->event_service_prefix == NULL)
- ssnprintf(service_buffer, sizeof(service_buffer), "%s/%s",
- &name_buffer[1], ds->ds[index].name);
+ snprintf(service_buffer, sizeof(service_buffer), "%s/%s", &name_buffer[1],
+ ds->ds[index].name);
else
- ssnprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
- host->event_service_prefix, &name_buffer[1],
- ds->ds[index].name);
+ snprintf(service_buffer, sizeof(service_buffer), "%s%s/%s",
+ host->event_service_prefix, &name_buffer[1], ds->ds[index].name);
} else {
if (host->event_service_prefix == NULL)
sstrncpy(service_buffer, &name_buffer[1], sizeof(service_buffer));
else
- ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
- host->event_service_prefix, &name_buffer[1]);
+ snprintf(service_buffer, sizeof(service_buffer), "%s%s",
+ host->event_service_prefix, &name_buffer[1]);
}
riemann_event_set(
if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
char ds_type[DATA_MAX_NAME_LEN];
- ssnprintf(ds_type, sizeof(ds_type), "%s:rate",
- DS_TYPE_TO_STRING(ds->ds[index].type));
+ snprintf(ds_type, sizeof(ds_type), "%s:rate",
+ DS_TYPE_TO_STRING(ds->ds[index].type));
riemann_event_string_attribute_add(event, "ds_type", ds_type);
} else {
riemann_event_string_attribute_add(event, "ds_type",
{
char ds_index[DATA_MAX_NAME_LEN];
- ssnprintf(ds_index, sizeof(ds_index), "%zu", index);
+ snprintf(ds_index, sizeof(ds_index), "%zu", index);
riemann_event_string_attribute_add(event, "ds_index", ds_index);
}
return status;
}
- ssnprintf(callback_name, sizeof(callback_name), "write_riemann/%s",
- host->name);
+ snprintf(callback_name, sizeof(callback_name), "write_riemann/%s",
+ host->name);
user_data_t ud = {.data = host, .free_func = wrr_free};
// incorporate the data source type
if ((ds->ds[index].type != DS_TYPE_GAUGE) && (rates != NULL)) {
char ds_type[DATA_MAX_NAME_LEN];
- ssnprintf(ds_type, sizeof(ds_type), "%s:rate",
- DS_TYPE_TO_STRING(ds->ds[index].type));
+ snprintf(ds_type, sizeof(ds_type), "%s:rate",
+ DS_TYPE_TO_STRING(ds->ds[index].type));
res = my_asprintf(&temp_str, "%s, \"collectd_data_source_type\": \"%s\"",
ret_str, ds_type);
free(ret_str);
// incorporate the data source index
{
char ds_index[DATA_MAX_NAME_LEN];
- ssnprintf(ds_index, sizeof(ds_index), "%zu", index);
+ snprintf(ds_index, sizeof(ds_index), "%zu", index);
res = my_asprintf(&temp_str, "%s, \"collectd_data_source_index\": %s",
ret_str, ds_index);
free(ret_str);
host->separator);
if (host->always_append_ds || (ds->ds_num > 1)) {
if (host->event_service_prefix == NULL)
- ssnprintf(service_buffer, sizeof(service_buffer), "%s.%s", name_buffer,
- ds->ds[index].name);
+ snprintf(service_buffer, sizeof(service_buffer), "%s.%s", name_buffer,
+ ds->ds[index].name);
else
- ssnprintf(service_buffer, sizeof(service_buffer), "%s%s.%s",
- host->event_service_prefix, name_buffer, ds->ds[index].name);
+ snprintf(service_buffer, sizeof(service_buffer), "%s%s.%s",
+ host->event_service_prefix, name_buffer, ds->ds[index].name);
} else {
if (host->event_service_prefix == NULL)
sstrncpy(service_buffer, name_buffer, sizeof(service_buffer));
else
- ssnprintf(service_buffer, sizeof(service_buffer), "%s%s",
- host->event_service_prefix, name_buffer);
+ snprintf(service_buffer, sizeof(service_buffer), "%s%s",
+ host->event_service_prefix, name_buffer);
}
// Replace collectd sensor name reserved characters so that time series DB is
return -1;
}
- ssnprintf(callback_name, sizeof(callback_name), "write_sensu/%s", host->name);
+ snprintf(callback_name, sizeof(callback_name), "write_sensu/%s", host->name);
user_data_t ud = {.data = host, .free_func = sensu_free};
#define BUFFER_ADD(...) \
do { \
- status = ssnprintf(ret + offset, ret_len - offset, __VA_ARGS__); \
+ status = snprintf(ret + offset, ret_len - offset, __VA_ARGS__); \
if (status < 1) { \
sfree(rates); \
return -1; \
if (ds_name != NULL) {
if (vl->plugin_instance[0] == '\0') {
if (vl->type_instance[0] == '\0') {
- ssnprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin, vl->type,
- ds_name);
+ snprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin, vl->type,
+ ds_name);
} else {
- ssnprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin, vl->type,
- vl->type_instance, ds_name);
+ snprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin, vl->type,
+ vl->type_instance, ds_name);
}
} else { /* vl->plugin_instance != "" */
if (vl->type_instance[0] == '\0') {
- ssnprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
- vl->plugin_instance, vl->type, ds_name);
+ snprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
+ vl->plugin_instance, vl->type, ds_name);
} else {
- ssnprintf(ret, ret_len, "%s%s.%s.%s.%s.%s", prefix, vl->plugin,
- vl->plugin_instance, vl->type, vl->type_instance, ds_name);
+ snprintf(ret, ret_len, "%s%s.%s.%s.%s.%s", prefix, vl->plugin,
+ vl->plugin_instance, vl->type, vl->type_instance, ds_name);
}
}
} else { /* ds_name == NULL */
if (vl->plugin_instance[0] == '\0') {
if (vl->type_instance[0] == '\0') {
- ssnprintf(ret, ret_len, "%s%s.%s", prefix, vl->plugin, vl->type);
+ snprintf(ret, ret_len, "%s%s.%s", prefix, vl->plugin, vl->type);
} else {
- ssnprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
- vl->type_instance, vl->type);
+ snprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
+ vl->type_instance, vl->type);
}
} else { /* vl->plugin_instance != "" */
if (vl->type_instance[0] == '\0') {
- ssnprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
- vl->plugin_instance, vl->type);
+ snprintf(ret, ret_len, "%s%s.%s.%s", prefix, vl->plugin,
+ vl->plugin_instance, vl->type);
} else {
- ssnprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
- vl->plugin_instance, vl->type, vl->type_instance);
+ snprintf(ret, ret_len, "%s%s.%s.%s.%s", prefix, vl->plugin,
+ vl->plugin_instance, vl->type, vl->type_instance);
}
}
}
}
status =
- ssnprintf(message, sizeof(message), "put %s %.0f %s fqdn=%s %s %s\r\n",
- key, CDTIME_T_TO_DOUBLE(time), value, host, tags, host_tags);
+ snprintf(message, sizeof(message), "put %s %.0f %s fqdn=%s %s %s\r\n",
+ key, CDTIME_T_TO_DOUBLE(time), value, host, tags, host_tags);
sfree(temp);
if (status < 0)
return -1;
}
}
- ssnprintf(callback_name, sizeof(callback_name), "write_tsdb/%s/%s",
- cb->node != NULL ? cb->node : WT_DEFAULT_NODE,
- cb->service != NULL ? cb->service : WT_DEFAULT_SERVICE);
+ snprintf(callback_name, sizeof(callback_name), "write_tsdb/%s/%s",
+ cb->node != NULL ? cb->node : WT_DEFAULT_NODE,
+ cb->service != NULL ? cb->service : WT_DEFAULT_SERVICE);
user_data_t user_data = {.data = cb, .free_func = wt_callback_free};
sstrncpy(vl.type_instance, "load", sizeof(vl.type_instance));
if (cpu_num >= 0) {
- ssnprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", cpu_num);
+ snprintf(vl.plugin_instance, sizeof(vl.plugin_instance), "%i", cpu_num);
}
plugin_dispatch_values(&vl);
} /* static void submit_value */
/*
* Global variables
*/
+static value_to_rate_state_t arc_hits_state;
+static value_to_rate_state_t arc_misses_state;
+static value_to_rate_state_t l2_hits_state;
+static value_to_rate_state_t l2_misses_state;
#if defined(KERNEL_LINUX)
#include "utils_llist.h"
size_t valuelen = sizeof(value);
int rv;
- ssnprintf(buffer, sizeof(buffer), "%s%s", zfs_arcstat, name);
+ snprintf(buffer, sizeof(buffer), "%s%s", zfs_arcstat, name);
rv = sysctlbyname(buffer, (void *)&value, &valuelen,
/* new value = */ NULL, /* new length = */ (size_t)0);
if (rv == 0)
// See kstat_seq_show_headers module/spl/spl-kstat.c of the spl kernel
// module.
if (fgets(buffer, sizeof(buffer), fh) == NULL) {
- ERROR("zfs_arc plugin: \"%s\" does not contain a single line.", ZOL_ARCSTATS_FILE);
+ ERROR("zfs_arc plugin: \"%s\" does not contain a single line.",
+ ZOL_ARCSTATS_FILE);
fclose(fh);
return -1;
}
if (fgets(buffer, sizeof(buffer), fh) == NULL) {
- ERROR("zfs_arc plugin: \"%s\" does not contain at least two lines.", ZOL_ARCSTATS_FILE);
+ ERROR("zfs_arc plugin: \"%s\" does not contain at least two lines.",
+ ZOL_ARCSTATS_FILE);
fclose(fh);
return -1;
}
za_read_derive(ksp, "mru_hits", "cache_result", "mru-hit");
za_read_derive(ksp, "mru_ghost_hits", "cache_result", "mru_ghost-hit");
+ cdtime_t now = cdtime();
+
/* Ratios */
- arc_hits = (gauge_t)get_zfs_value(ksp, "hits");
- arc_misses = (gauge_t)get_zfs_value(ksp, "misses");
- l2_hits = (gauge_t)get_zfs_value(ksp, "l2_hits");
- l2_misses = (gauge_t)get_zfs_value(ksp, "l2_misses");
+ if ((value_to_rate(&arc_hits, (value_t){.derive = get_zfs_value(ksp, "hits")},
+ DS_TYPE_DERIVE, now, &arc_hits_state) == 0) &&
+ (value_to_rate(&arc_misses,
+ (value_t){.derive = get_zfs_value(ksp, "misses")},
+ DS_TYPE_DERIVE, now, &arc_misses_state) == 0)) {
+ za_submit_ratio("arc", arc_hits, arc_misses);
+ }
- za_submit_ratio("arc", arc_hits, arc_misses);
- za_submit_ratio("L2", l2_hits, l2_misses);
+ if ((value_to_rate(&l2_hits,
+ (value_t){.derive = get_zfs_value(ksp, "l2_hits")},
+ DS_TYPE_DERIVE, now, &l2_hits_state) == 0) &&
+ (value_to_rate(&l2_misses,
+ (value_t){.derive = get_zfs_value(ksp, "l2_misses")},
+ DS_TYPE_DERIVE, now, &l2_misses_state) == 0)) {
+ za_submit_ratio("L2", l2_hits, l2_misses);
+ }
/* I/O */
value_t l2_io[] = {