# protobuf stuff:
src/*.pb-c.[ch]
+src/*.grpc.pb.cc
+src/*.pb.cc
+src/*.pb.h
# make dist stuff:
/collectd-*.tar.gz
# backup stuff
*~
+
# Unit tests
+src/daemon/test-suite.log
src/tests/
+src/test-suite.log
test_*
# src/daemon/...
Florian "octo" Forster <octo at verplant.org>
- Initial author.
+Marc Fournier <marc.fournier at camptocamp.com>
+ - Various fixes to the varnish plugin.
+ - RPM specfile maintenance.
+ - libmnl support in the netlink plugin.
+ - linux support in the zfs_arc plugin.
+ - openldap plugin.
+ - continuous integration system.
+
+Pierre-Yves Ritschard <pyr at spootnik.org>
+ - Write-Riemann plugin.
+ - Write-Graphite plugin: Notification support.
+ - Write-Kafka plugin.
+ - Log-Logstash plugin.
+ - Normalization in the CPU plugin.
+ - Relative values in the Load plugin.
+
+Ruben Kerkhof <ruben@rubenkerkhof.com>
+ - Bugfixes and enhancements in many places all around the project.
+ - Fedora package.
+
Sebastian "tokkee" Harl <sh at tokkee.org>
- Bugfixes and enhancements in many places all around the project.
+ - gprc plugin.
- perl plugin.
+ - postgresql plugin.
- users plugin.
- vserver plugin.
- Debian package.
- The version 3 `log' mode.
- Many Solaris related hints and fixes.
+Claudius Zingerli <gitmail at zeuz.ch>
+ - chrony plugin.
+
Cyril Feraudet <cyril at feraudet.com>
- ethstat plugin.
Dagobert Michelsen <dam at opencsw.org>
- zone plugin.
+ - Many Solaris related hints and fixes.
Dan Berrange <berrange at redhat.com>
- uuid plugin.
Franck Lombardi
- UNIX socket code for the memcached plugin.
+Gergely Nagy <algernon at madhouse-project.org>
+ - Write-Riemann plugin.
+
Jason Pepas <cell at ices.utexas.edu>
- nfs plugin.
+ swap
- Various AIX-related fixes and hacks.
-Marc Fournier <marc.fournier at camptocamp.com>
- - Various fixes to the varnish plugin.
- - RPM specfile update.
- - libmnl support in the netlink plugin.
- - linux support in the zfs_arc plugin.
- - openldap plugin.
-
Marco Chiappero <marco at absence.it>
- uptime plugin.
- ip6tables support in the iptables plugin.
- `ReportByDevice' option of the df plugin.
- write_http plugin.
+Pavel Rochnyack <pavel2000 at ngs.ru>
+ - xencpu plugin.
+ - Bugfixes and enhancements in many places all around the project.
+
Peter Holik <peter at holik.at>
- cpufreq plugin.
- multimeter plugin.
Phoenix Kayo <kayo.k11.4 at gmail.com>
- pinba plugin.
-Pierre-Yves Ritschard <pyr at spootnik.org>
- - Write-Riemann plugin.
- - Write-Graphite plugin: Notification support.
- - Write-Kafka plugin.
- - Log-Logstash plugin.
- - Normalization in the CPU plugin.
- - Relative values in the Load plugin.
-
Piotr Hosowicz <the55 at wp.pl>
- SMF manifest for collectd.
SUBDIRS += libltdl
endif
-SUBDIRS += src bindings .
+SUBDIRS += proto src bindings .
AM_CPPFLAGS = $(LTDLINCL)
-EXTRA_DIST = contrib version-gen.sh
+EXTRA_DIST = contrib version-gen.sh testwrapper.sh
install-exec-hook:
$(mkinstalldirs) $(DESTDIR)$(localstatedir)/run
collectd - System information collection daemon
=================================================
-http://collectd.org/
+https://collectd.org/
About
-----
- cgroups
CPU accounting information for process groups under Linux.
+ - chrony
+ Chrony daemon statistics: Local clock drift, offset to peers, etc.
+
- conntrack
Number of nf_conntrack entries.
- gmond
Receive multicast traffic from Ganglia instances.
+ - grpc
+ Receive values over the network using the gRPC framework.
+
- hddtemp
Hard disk temperatures using hddtempd.
- wireless
Link quality of wireless cards. Linux only.
+ - xencpu
+ XEN Hypervisor CPU stats.
+
- xmms
Bitrate and frequency of music played with XMMS.
Send an E-mail with the notification message to the configured
recipients.
+ - notify_nagios
+ Submit notifications as passive check results to a local nagios instance.
+
- exec
Execute a program or script to handle the notification.
See collectd-exec(5).
Used by the `gmond' plugin to process data received from Ganglia.
<http://ganglia.info/>
+ * libgrpc (optional)
+ Used by the `grpc' plugin. gRPC requires a C++ compiler supporting the
+ C++11 standard.
+ <https://grpc.io/>
+
* libgcrypt (optional)
Used by the `network' plugin for encryption and authentication.
<http://www.gnupg.org/>
The PostgreSQL C client library used by the `postgresql' plugin.
<http://www.postgresql.org/>
+ * libprotobuf, protoc 3.0+ (optional)
+ Used by the `grpc' plugin to generate service stubs and code to handle
+ network packets of collectd's protobuf-based network protocol.
+ <https://developers.google.com/protocol-buffers/>
+
* libprotobuf-c, protoc-c (optional)
Used by the `pinba' plugin to generate a parser for the network packets
sent by the Pinba PHP extension.
`virt' plugins.
<http://xmlsoft.org/>
+ * libxen (optional)
+ Used by the `xencpu' plugin.
+ <http://xenbits.xensource.com/>
+
* libxmms (optional)
<http://www.xmms.org/>
AM_CONDITIONAL([BUILD_INCLUDED_LTDL], [test "x$LTDLDEPS" != "x"])
-AM_INIT_AUTOMAKE([subdir-objects tar-pax dist-bzip2 foreign])
+AM_INIT_AUTOMAKE([subdir-objects tar-pax dist-bzip2 no-dist-gzip foreign])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])])
AC_LANG(C)
# Checks for programs.
#
AC_PROG_CC
+AC_PROG_CXX
AC_PROG_CPP
AC_PROG_EGREP
AC_PROG_INSTALL
AC_PROG_LEX
AC_PROG_YACC
+AC_PATH_PROG([VALGRIND], [valgrind])
+
# Warn when pkg.m4 is missing
m4_pattern_forbid([^_?PKG_[A-Z_]+$],[*** pkg.m4 missing, please install pkg-config])
AC_MSG_ERROR([bison is missing and you do not have ${srcdir}/src/liboconfig/parser.c. Please install bison])
fi
+AC_PATH_PROG([PROTOC], [protoc])
+have_protoc3="no"
+if test "x$PROTOC" != "x"; then
+ AC_MSG_CHECKING([for protoc 3.0.0+])
+ if $PROTOC --version | grep -q libprotoc.3; then
+ protoc3="yes (`$PROTOC --version`)"
+ have_protoc3="yes"
+ else
+ protoc3="no (`$PROTOC --version`)"
+ fi
+ AC_MSG_RESULT([$protoc3])
+fi
+AM_CONDITIONAL(HAVE_PROTOC3, test "x$have_protoc3" = "xyes")
+
+AC_PATH_PROG([GRPC_CPP_PLUGIN], [grpc_cpp_plugin])
+AM_CONDITIONAL(HAVE_GRPC_CPP, test "x$GRPC_CPP_PLUGIN" != "x")
+
AC_CHECK_PROG([have_protoc_c], [protoc-c], [yes], [no])
if test "x$have_protoc_c" = "xno"
then
esac
AC_MSG_RESULT([$ac_system])
-AM_CONDITIONAL([BUILD_LINUX],[test "x$ac_system" = "xLinux"])
-AM_CONDITIONAL([BUILD_SOLARIS],[test "x$ac_system" = "xSolaris"])
-AM_CONDITIONAL([BUILD_DARWIN],[test "x$ac_system" = "xDarwin"])
-AM_CONDITIONAL([BUILD_OPENBSD],[test "x$ac_system" = "xOpenBSD"])
-AM_CONDITIONAL([BUILD_AIX],[test "x$ac_system" = "xAIX"])
-AM_CONDITIONAL([BUILD_FREEBSD],[test "x$ac_system" = "xFreeBSD"])
+AM_CONDITIONAL([BUILD_AIX], [test "x$ac_system" = "xAIX"])
+AM_CONDITIONAL([BUILD_DARWIN], [test "x$ac_system" = "xDarwin"])
+AM_CONDITIONAL([BUILD_FREEBSD], [test "x$ac_system" = "xFreeBSD"])
+AM_CONDITIONAL([BUILD_LINUX], [test "x$ac_system" = "xLinux"])
+AM_CONDITIONAL([BUILD_OPENBSD], [test "x$ac_system" = "xOpenBSD"])
+AM_CONDITIONAL([BUILD_SOLARIS], [test "x$ac_system" = "xSolaris"])
if test "x$ac_system" = "xLinux"
then
#
# Checks for library functions.
#
-AC_PROG_GCC_TRADITIONAL
AC_CHECK_FUNCS(gettimeofday select strdup strtol getaddrinfo getnameinfo strchr memcpy strstr strcmp strncmp strncpy strlen strncasecmp strcasecmp openlog closelog sysconf setenv if_indextoname setlocale)
AC_FUNC_STRERROR_R
+test_cxx_flags() {
+ AC_LANG_PUSH([C++])
+ AC_LANG_CONFTEST([
+ AC_LANG_SOURCE([[int main(void){}]])
+ ])
+ $CXX -c conftest.cpp $CXXFLAGS $@ > /dev/null 2> /dev/null
+ ret=$?
+ rm -f conftest.o
+ AC_LANG_POP([C++])
+ return $ret
+}
+
SAVE_CFLAGS="$CFLAGS"
# Emulate behavior of src/Makefile.am
if test "x$GCC" = "xyes"
fi
fi
-# --with-libpthread {{{
-AC_ARG_WITH(libpthread, [AS_HELP_STRING([--with-libpthread=@<:@=PREFIX@:>@], [Path to libpthread.])],
-[ if test "x$withval" != "xno" \
- && test "x$withval" != "xyes"
- then
- LDFLAGS="$LDFLAGS -L$withval/lib"
- CPPFLAGS="$CPPFLAGS -I$withval/include"
- with_libpthread="yes"
- else
- if test "x$withval" = "xno"
- then
- with_libpthread="no (disabled)"
- fi
- fi
-], [with_libpthread="yes"])
+SAVE_LIBS="$LIBS"
+AC_CHECK_LIB([pthread],
+ [pthread_create],
+ [],
+ [AC_MSG_ERROR([Symbol 'pthread_create' not found in libpthread"])],
+ []
+)
+PTHREAD_LIBS="$LIBS"
+LIBS="$SAVE_LIBS"
+AC_CHECK_HEADERS([pthread.h],
+ [],
+ [AC_MSG_ERROR([pthread.h not found])]
+)
AC_SUBST([PTHREAD_LIBS])
-if test "x$with_libpthread" = "xyes"
-then
- SAVE_LIBS="$LIBS"
- AC_CHECK_LIB(pthread, pthread_create, [], [with_libpthread="no (Symbol 'pthread_create' not found)"], [])
- PTHREAD_LIBS="$LIBS"
- LIBS="$SAVE_LIBS"
-fi
-
-if test "x$with_libpthread" = "xyes"
-then
- AC_CHECK_HEADERS(pthread.h,, [with_libpthread="no (pthread.h not found)"])
-fi
-if test "x$with_libpthread" = "xyes"
-then
- collect_pthread=1
-else
- collect_pthread=0
-fi
-AC_DEFINE_UNQUOTED(HAVE_LIBPTHREAD, [$collect_pthread],
- [Wether or not to use pthread (POSIX threads) library])
-AM_CONDITIONAL(BUILD_WITH_LIBPTHREAD, test "x$with_libpthread" = "xyes")
-# }}}
m4_divert_once([HELP_WITH], [
collectd additional packages:])
fi
if test "x$with_libcurl" = "xyes"
then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_curl_cflags"
+ LDFLAGS="$LDFLAGS $with_curl_libs"
+ AC_CACHE_CHECK([for CURLINFO_APPCONNECT_TIME],
+ [c_cv_have_curlinfo_appconnect_time],
+ AC_LINK_IFELSE([AC_LANG_PROGRAM(
+[[
+#include <curl/curl.h>
+]],
+[[
+int val = CURLINFO_APPCONNECT_TIME;
+return val;
+]]
+ )],
+ [c_cv_have_curlinfo_appconnect_time="yes"],
+ [c_cv_have_curlinfo_appconnect_time="no"]
+ )
+ )
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
+if test "x$c_cv_have_curlinfo_appconnect_time" = "xyes"
+then
+ AC_DEFINE(HAVE_CURLINFO_APPCONNECT_TIME, 1, [Define if curl.h defines CURLINFO_APPCONNECT_TIME.])
+fi
+
+if test "x$with_libcurl" = "xyes"
+then
BUILD_WITH_LIBCURL_CFLAGS="$with_curl_cflags"
BUILD_WITH_LIBCURL_LIBS="$with_curl_libs"
AC_SUBST(BUILD_WITH_LIBCURL_CFLAGS)
AC_DEFINE(HAVE_CURLOPT_TIMEOUT_MS, 1, [Define if libcurl supports CURLOPT_TIMEOUT_MS option.])
fi
fi
-AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes")
# }}}
# --with-libdbi {{{
AM_CONDITIONAL(BUILD_WITH_LIBGCRYPT, test "x$with_libgcrypt" = "xyes")
# }}}
+# --with-grpc {{{
+AC_ARG_WITH(grpc, [AS_HELP_STRING([--without-grpc], [Disable gRPC (default: autodetect).])],
+[
+ with_grpc="$withval"
+],
+[
+ with_grpc="yes"
+])
+
+if test "x$with_grpc" = "xyes"
+then
+ if test "x$have_protoc3" != "xyes"
+ then
+ with_grpc="no (requires protoc 3.0.0+)"
+ else if test "x$GRPC_CPP_PLUGIN" = "x"
+ then
+ with_grpc"no (requires grpc_cpp_plugin)"
+ fi; fi
+fi
+
+if test "x$with_grpc" = "xyes"
+then
+ AC_MSG_CHECKING([whether $CXX accepts -std=c++11])
+ if test_cxx_flags -std=c++11; then
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT([no])
+ with_grpc="no (requires C++11 support)"
+ fi
+fi
+
+if test "x$with_grpc" = "xyes"
+then
+ AC_LANG_PUSH(C++)
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_CXXFLAGS="$CXXFLAGS"
+ CPPFLAGS="$CPPFLAGS -std=c++11"
+ CXXFLAGS="$CXXFLAGS -std=c++11"
+ AC_CHECK_HEADERS([grpc++/grpc++.h], [],
+ [with_grpc="no (grpc++/grpc++.h not found)"])
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ CXXFLAGS="$SAVE_CXXFLAGS"
+ AC_LANG_POP(C++)
+fi
+with_libgrpc="no"
+if test "x$with_grpc" = "xyes"
+then
+ AC_LANG_PUSH(C++)
+ AC_CHECK_LIB([grpc], [grpc_register_plugin],
+ [with_libgrpc="yes"],
+ [with_grpc="no (libgrpc not found)"],
+ [-lgpr -lprotobuf])
+ AC_LANG_POP(C++)
+fi
+# }}}
+
# --with-libiptc {{{
AC_ARG_WITH(libiptc, [AS_HELP_STRING([--with-libiptc@<:@=PREFIX@:>@], [Path to libiptc.])],
[
fi
if test "x$with_oracle" = "xyes"
then
- BUILD_WITH_ORACLE_CFLAGS="$with_oracle_cppflags"
+ BUILD_WITH_ORACLE_CPPFLAGS="$with_oracle_cppflags"
BUILD_WITH_ORACLE_LIBS="$with_oracle_libs"
- AC_SUBST(BUILD_WITH_ORACLE_CFLAGS)
+ AC_SUBST(BUILD_WITH_ORACLE_CPPFLAGS)
AC_SUBST(BUILD_WITH_ORACLE_LIBS)
fi
# }}}
CPPFLAGS="$SAVE_CPPFLAGS"
LDFLAGS="$SAVE_LDFLAGS"
+ LIBXENCTL_CPPFLAGS="$with_libxenctl_cppflags"
+ LIBXENCTL_LDFLAGS="$with_libxenctl_ldflags"
+ AC_SUBST(LIBXENCTL_CPPFLAGS)
+ AC_SUBST(LIBXENCTL_LDFLAGS)
fi
+# }}}
# --with-libxmms {{{
with_xmms_config="xmms-config"
then
enable_plugin="yes"
else
- enable_plugin="no"
+ enable_plugin="$2"
fi
else
enable_plugin="$enable_all_plugins"
fi
else # User passed "yes" but dependency checking yielded "no" => Dependency problem.
dependency_error="yes"
- enable_plugin="no (dependency error)"
+ enable_plugin="$2 (dependency error)"
fi
fi
AM_CONDITIONAL([BUILD_PLUGIN_]my_toupper([$1]), test "x$enable_plugin" = "xyes")
AC_PLUGIN([bind], [$plugin_bind], [ISC Bind nameserver statistics])
AC_PLUGIN([ceph], [$plugin_ceph], [Ceph daemon statistics])
AC_PLUGIN([cgroups], [$plugin_cgroups], [CGroups CPU usage accounting])
+AC_PLUGIN([chrony], [yes], [Chrony statistics])
AC_PLUGIN([conntrack], [$plugin_conntrack], [nf_conntrack statistics])
AC_PLUGIN([contextswitch], [$plugin_contextswitch], [context switch statistics])
AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics])
AC_PLUGIN([filecount], [yes], [Count files in directories])
AC_PLUGIN([fscache], [$plugin_fscache], [fscache statistics])
AC_PLUGIN([gmond], [$with_libganglia], [Ganglia plugin])
+AC_PLUGIN([grpc], [$with_grpc], [gRPC plugin])
AC_PLUGIN([hddtemp], [yes], [Query hddtempd])
AC_PLUGIN([interface], [$plugin_interface], [Interface traffic statistics])
AC_PLUGIN([ipc], [$plugin_ipc], [IPC statistics])
AC_CONFIG_FILES(src/libcollectdclient/collectd/lcc_features.h)
AM_CFLAGS="-Wall"
+AM_CXXFLAGS="-Wall"
if test "x$enable_werror" != "xno"
then
AM_CFLAGS="$AM_CFLAGS -Werror"
+ AM_CXXFLAGS="$AM_CXXFLAGS -Werror"
fi
AC_SUBST([AM_CFLAGS])
+AC_SUBST([AM_CXXFLAGS])
-AC_CONFIG_FILES([Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
+AC_CONFIG_FILES([Makefile proto/Makefile src/Makefile src/daemon/Makefile src/collectd.conf src/libcollectdclient/Makefile src/libcollectdclient/libcollectdclient.pc src/liboconfig/Makefile bindings/Makefile bindings/java/Makefile])
AC_OUTPUT
if test "x$with_librrd" = "xyes" \
with_perl_bindings="yes ($PERL_BINDINGS_OPTIONS)"
fi
-cat <<EOF;
-
-Configuration:
- Build:
- Platform . . . . . . $ac_system
- CC . . . . . . . . . $CC
- CFLAGS . . . . . . . $AM_CFLAGS $CFLAGS
- CPP . . . . . . . . . $CPP
- CPPFLAGS . . . . . . $CPPFLAGS
- LD . . . . . . . . . $LD
- LDFLAGS . . . . . . . $LDFLAGS
- YACC . . . . . . . . $YACC
- YFLAGS . . . . . . . $YFLAGS
-
- Libraries:
- intel mic . . . . . . $with_mic
- libaquaero5 . . . . . $with_libaquaero5
- libatasmart . . . . . $with_libatasmart
- libcurl . . . . . . . $with_libcurl
- libdbi . . . . . . . $with_libdbi
- libesmtp . . . . . . $with_libesmtp
- libganglia . . . . . $with_libganglia
- libgcrypt . . . . . . $with_libgcrypt
- libhal . . . . . . . $with_libhal
- libhiredis . . . . . $with_libhiredis
- libi2c-dev . . . . . $with_libi2c
- libiokit . . . . . . $with_libiokit
- libiptc . . . . . . . $with_libiptc
- libjvm . . . . . . . $with_java
- libkstat . . . . . . $with_kstat
- libkvm . . . . . . . $with_libkvm
- libldap . . . . . . . $with_libldap
- liblvm2app . . . . . $with_liblvm2app
- libmemcached . . . . $with_libmemcached
- libmnl . . . . . . . $with_libmnl
- libmodbus . . . . . . $with_libmodbus
- libmongoc . . . . . . $with_libmongoc
- libmosquitto . . . . $with_libmosquitto
- libmysql . . . . . . $with_libmysql
- libnetapp . . . . . . $with_libnetapp
- libnetsnmp . . . . . $with_libnetsnmp
- libnotify . . . . . . $with_libnotify
- liboconfig . . . . . $with_liboconfig
- libopenipmi . . . . . $with_libopenipmipthread
- liboping . . . . . . $with_liboping
- libowcapi . . . . . . $with_libowcapi
- libpcap . . . . . . . $with_libpcap
- libperfstat . . . . . $with_perfstat
- libperl . . . . . . . $with_libperl
- libpq . . . . . . . . $with_libpq
- libpthread . . . . . $with_libpthread
- librabbitmq . . . . . $with_librabbitmq
- libriemann-client . . $with_libriemann_client
- librdkafka . . . . . $with_librdkafka
- librouteros . . . . . $with_librouteros
- librrd . . . . . . . $with_librrd
- libsensors . . . . . $with_libsensors
- libsigrok . . . . . $with_libsigrok
- libstatgrab . . . . . $with_libstatgrab
- libtokyotyrant . . . $with_libtokyotyrant
- libudev . . . . . . . $with_libudev
- libupsclient . . . . $with_libupsclient
- libvarnish . . . . . $with_libvarnish
- libvirt . . . . . . . $with_libvirt
- libxenctrl . . . . . $with_libxenctrl
- libxml2 . . . . . . . $with_libxml2
- libxmms . . . . . . . $with_libxmms
- libyajl . . . . . . . $with_libyajl
- oracle . . . . . . . $with_oracle
- protobuf-c . . . . . $have_protoc_c
- python . . . . . . . $with_python
-
- Features:
- daemon mode . . . . . $enable_daemon
- debug . . . . . . . . $enable_debug
-
- Bindings:
- perl . . . . . . . . $with_perl_bindings
-
- Modules:
- aggregation . . . . . $enable_aggregation
- amqp . . . . . . . $enable_amqp
- apache . . . . . . . $enable_apache
- apcups . . . . . . . $enable_apcups
- apple_sensors . . . . $enable_apple_sensors
- aquaero . . . . . . . $enable_aquaero
- ascent . . . . . . . $enable_ascent
- barometer . . . . . . $enable_barometer
- battery . . . . . . . $enable_battery
- bind . . . . . . . . $enable_bind
- ceph . . . . . . . . $enable_ceph
- cgroups . . . . . . . $enable_cgroups
- conntrack . . . . . . $enable_conntrack
- contextswitch . . . . $enable_contextswitch
- cpu . . . . . . . . . $enable_cpu
- cpufreq . . . . . . . $enable_cpufreq
- cpusleep . . . . . . $enable_cpusleep
- csv . . . . . . . . . $enable_csv
- curl . . . . . . . . $enable_curl
- curl_json . . . . . . $enable_curl_json
- curl_xml . . . . . . $enable_curl_xml
- dbi . . . . . . . . . $enable_dbi
- df . . . . . . . . . $enable_df
- disk . . . . . . . . $enable_disk
- dns . . . . . . . . . $enable_dns
- drbd . . . . . . . . $enable_drbd
- email . . . . . . . . $enable_email
- entropy . . . . . . . $enable_entropy
- ethstat . . . . . . . $enable_ethstat
- exec . . . . . . . . $enable_exec
- fhcount . . . . . . . $enable_fhcount
- filecount . . . . . . $enable_filecount
- fscache . . . . . . . $enable_fscache
- gmond . . . . . . . . $enable_gmond
- hddtemp . . . . . . . $enable_hddtemp
- interface . . . . . . $enable_interface
- ipc . . . . . . . . . $enable_ipc
- ipmi . . . . . . . . $enable_ipmi
- iptables . . . . . . $enable_iptables
- ipvs . . . . . . . . $enable_ipvs
- irq . . . . . . . . . $enable_irq
- java . . . . . . . . $enable_java
- load . . . . . . . . $enable_load
- logfile . . . . . . . $enable_logfile
- log_logstash . . . . $enable_log_logstash
- lpar . . . . . . . . $enable_lpar
- lvm . . . . . . . . . $enable_lvm
- madwifi . . . . . . . $enable_madwifi
- match_empty_counter . $enable_match_empty_counter
- match_hashed . . . . $enable_match_hashed
- match_regex . . . . . $enable_match_regex
- match_timediff . . . $enable_match_timediff
- match_value . . . . . $enable_match_value
- mbmon . . . . . . . . $enable_mbmon
- md . . . . . . . . . $enable_md
- memcachec . . . . . . $enable_memcachec
- memcached . . . . . . $enable_memcached
- memory . . . . . . . $enable_memory
- mic . . . . . . . . . $enable_mic
- modbus . . . . . . . $enable_modbus
- mqtt . . . . . . . . $enable_mqtt
- multimeter . . . . . $enable_multimeter
- mysql . . . . . . . . $enable_mysql
- netapp . . . . . . . $enable_netapp
- netlink . . . . . . . $enable_netlink
- network . . . . . . . $enable_network
- nfs . . . . . . . . . $enable_nfs
- nginx . . . . . . . . $enable_nginx
- notify_desktop . . . $enable_notify_desktop
- notify_email . . . . $enable_notify_email
- notify_nagios . . . . $enable_notify_nagios
- ntpd . . . . . . . . $enable_ntpd
- numa . . . . . . . . $enable_numa
- nut . . . . . . . . . $enable_nut
- olsrd . . . . . . . . $enable_olsrd
- onewire . . . . . . . $enable_onewire
- openldap . . . . . . $enable_openldap
- openvpn . . . . . . . $enable_openvpn
- oracle . . . . . . . $enable_oracle
- perl . . . . . . . . $enable_perl
- pf . . . . . . . . . $enable_pf
- pinba . . . . . . . . $enable_pinba
- ping . . . . . . . . $enable_ping
- postgresql . . . . . $enable_postgresql
- powerdns . . . . . . $enable_powerdns
- processes . . . . . . $enable_processes
- protocols . . . . . . $enable_protocols
- python . . . . . . . $enable_python
- redis . . . . . . . . $enable_redis
- routeros . . . . . . $enable_routeros
- rrdcached . . . . . . $enable_rrdcached
- rrdtool . . . . . . . $enable_rrdtool
- sensors . . . . . . . $enable_sensors
- serial . . . . . . . $enable_serial
- sigrok . . . . . . . $enable_sigrok
- smart . . . . . . . . $enable_smart
- snmp . . . . . . . . $enable_snmp
- statsd . . . . . . . $enable_statsd
- swap . . . . . . . . $enable_swap
- syslog . . . . . . . $enable_syslog
- table . . . . . . . . $enable_table
- tail_csv . . . . . . $enable_tail_csv
- tail . . . . . . . . $enable_tail
- tape . . . . . . . . $enable_tape
- target_notification . $enable_target_notification
- target_replace . . . $enable_target_replace
- target_scale . . . . $enable_target_scale
- target_set . . . . . $enable_target_set
- target_v5upgrade . . $enable_target_v5upgrade
- tcpconns . . . . . . $enable_tcpconns
- teamspeak2 . . . . . $enable_teamspeak2
- ted . . . . . . . . . $enable_ted
- thermal . . . . . . . $enable_thermal
- threshold . . . . . . $enable_threshold
- tokyotyrant . . . . . $enable_tokyotyrant
- turbostat . . . . . . $enable_turbostat
- unixsock . . . . . . $enable_unixsock
- uptime . . . . . . . $enable_uptime
- users . . . . . . . . $enable_users
- uuid . . . . . . . . $enable_uuid
- varnish . . . . . . . $enable_varnish
- virt . . . . . . . . $enable_virt
- vmem . . . . . . . . $enable_vmem
- vserver . . . . . . . $enable_vserver
- wireless . . . . . . $enable_wireless
- write_graphite . . . $enable_write_graphite
- write_http . . . . . $enable_write_http
- write_kafka . . . . . $enable_write_kafka
- write_log . . . . . . $enable_write_log
- write_mongodb . . . . $enable_write_mongodb
- write_redis . . . . . $enable_write_redis
- write_riemann . . . . $enable_write_riemann
- write_sensu . . . . . $enable_write_sensu
- write_tsdb . . . . . $enable_write_tsdb
- xencpu . . . . . . . $enable_xencpu
- xmms . . . . . . . . $enable_xmms
- zfs_arc . . . . . . . $enable_zfs_arc
- zone . . . . . . . . $enable_zone
- zookeeper . . . . . . $enable_zookeeper
-
-EOF
+AC_MSG_RESULT()
+AC_MSG_RESULT([Configuration:])
+AC_MSG_RESULT([ Build:])
+AC_MSG_RESULT([ Platform . . . . . . $ac_system])
+AC_MSG_RESULT([ CC . . . . . . . . . $CC])
+AC_MSG_RESULT([ CFLAGS . . . . . . . $AM_CFLAGS $CFLAGS])
+AC_MSG_RESULT([ CXXFLAGS . . . . . . $AM_CXXFLAGS $CXXFLAGS])
+AC_MSG_RESULT([ CPP . . . . . . . . . $CPP])
+AC_MSG_RESULT([ CPPFLAGS . . . . . . $CPPFLAGS])
+AC_MSG_RESULT([ GRPC_CPP_PLUGIN . . . $GRPC_CPP_PLUGIN])
+AC_MSG_RESULT([ LD . . . . . . . . . $LD])
+AC_MSG_RESULT([ LDFLAGS . . . . . . . $LDFLAGS])
+AC_MSG_RESULT([ PROTOC . . . . . . . $PROTOC])
+AC_MSG_RESULT([ YACC . . . . . . . . $YACC])
+AC_MSG_RESULT([ YFLAGS . . . . . . . $YFLAGS])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Libraries:])
+AC_MSG_RESULT([ intel mic . . . . . . $with_mic])
+AC_MSG_RESULT([ libaquaero5 . . . . . $with_libaquaero5])
+AC_MSG_RESULT([ libatasmart . . . . . $with_libatasmart])
+AC_MSG_RESULT([ libcurl . . . . . . . $with_libcurl])
+AC_MSG_RESULT([ libdbi . . . . . . . $with_libdbi])
+AC_MSG_RESULT([ libesmtp . . . . . . $with_libesmtp])
+AC_MSG_RESULT([ libganglia . . . . . $with_libganglia])
+AC_MSG_RESULT([ libgcrypt . . . . . . $with_libgcrypt])
+AC_MSG_RESULT([ libgrpc . . . . . . . $with_libgrpc])
+AC_MSG_RESULT([ libhal . . . . . . . $with_libhal])
+AC_MSG_RESULT([ libhiredis . . . . . $with_libhiredis])
+AC_MSG_RESULT([ libi2c-dev . . . . . $with_libi2c])
+AC_MSG_RESULT([ libiokit . . . . . . $with_libiokit])
+AC_MSG_RESULT([ libiptc . . . . . . . $with_libiptc])
+AC_MSG_RESULT([ libjvm . . . . . . . $with_java])
+AC_MSG_RESULT([ libkstat . . . . . . $with_kstat])
+AC_MSG_RESULT([ libkvm . . . . . . . $with_libkvm])
+AC_MSG_RESULT([ libldap . . . . . . . $with_libldap])
+AC_MSG_RESULT([ liblvm2app . . . . . $with_liblvm2app])
+AC_MSG_RESULT([ libmemcached . . . . $with_libmemcached])
+AC_MSG_RESULT([ libmnl . . . . . . . $with_libmnl])
+AC_MSG_RESULT([ libmodbus . . . . . . $with_libmodbus])
+AC_MSG_RESULT([ libmongoc . . . . . . $with_libmongoc])
+AC_MSG_RESULT([ libmosquitto . . . . $with_libmosquitto])
+AC_MSG_RESULT([ libmysql . . . . . . $with_libmysql])
+AC_MSG_RESULT([ libnetapp . . . . . . $with_libnetapp])
+AC_MSG_RESULT([ libnetsnmp . . . . . $with_libnetsnmp])
+AC_MSG_RESULT([ libnotify . . . . . . $with_libnotify])
+AC_MSG_RESULT([ liboconfig . . . . . $with_liboconfig])
+AC_MSG_RESULT([ libopenipmi . . . . . $with_libopenipmipthread])
+AC_MSG_RESULT([ liboping . . . . . . $with_liboping])
+AC_MSG_RESULT([ libowcapi . . . . . . $with_libowcapi])
+AC_MSG_RESULT([ libpcap . . . . . . . $with_libpcap])
+AC_MSG_RESULT([ libperfstat . . . . . $with_perfstat])
+AC_MSG_RESULT([ libperl . . . . . . . $with_libperl])
+AC_MSG_RESULT([ libpq . . . . . . . . $with_libpq])
+AC_MSG_RESULT([ librabbitmq . . . . . $with_librabbitmq])
+AC_MSG_RESULT([ libriemann-client . . $with_libriemann_client])
+AC_MSG_RESULT([ librdkafka . . . . . $with_librdkafka])
+AC_MSG_RESULT([ librouteros . . . . . $with_librouteros])
+AC_MSG_RESULT([ librrd . . . . . . . $with_librrd])
+AC_MSG_RESULT([ libsensors . . . . . $with_libsensors])
+AC_MSG_RESULT([ libsigrok . . . . . $with_libsigrok])
+AC_MSG_RESULT([ libstatgrab . . . . . $with_libstatgrab])
+AC_MSG_RESULT([ libtokyotyrant . . . $with_libtokyotyrant])
+AC_MSG_RESULT([ libudev . . . . . . . $with_libudev])
+AC_MSG_RESULT([ libupsclient . . . . $with_libupsclient])
+AC_MSG_RESULT([ libvarnish . . . . . $with_libvarnish])
+AC_MSG_RESULT([ libvirt . . . . . . . $with_libvirt])
+AC_MSG_RESULT([ libxenctrl . . . . . $with_libxenctrl])
+AC_MSG_RESULT([ libxml2 . . . . . . . $with_libxml2])
+AC_MSG_RESULT([ libxmms . . . . . . . $with_libxmms])
+AC_MSG_RESULT([ libyajl . . . . . . . $with_libyajl])
+AC_MSG_RESULT([ oracle . . . . . . . $with_oracle])
+AC_MSG_RESULT([ protobuf-c . . . . . $have_protoc_c])
+AC_MSG_RESULT([ protoc 3 . . . . . . $protoc3])
+AC_MSG_RESULT([ python . . . . . . . $with_python])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Features:])
+AC_MSG_RESULT([ daemon mode . . . . . $enable_daemon])
+AC_MSG_RESULT([ debug . . . . . . . . $enable_debug])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Bindings:])
+AC_MSG_RESULT([ perl . . . . . . . . $with_perl_bindings])
+AC_MSG_RESULT()
+AC_MSG_RESULT([ Modules:])
+AC_MSG_RESULT([ aggregation . . . . . $enable_aggregation])
+AC_MSG_RESULT([ amqp . . . . . . . $enable_amqp])
+AC_MSG_RESULT([ apache . . . . . . . $enable_apache])
+AC_MSG_RESULT([ apcups . . . . . . . $enable_apcups])
+AC_MSG_RESULT([ apple_sensors . . . . $enable_apple_sensors])
+AC_MSG_RESULT([ aquaero . . . . . . . $enable_aquaero])
+AC_MSG_RESULT([ ascent . . . . . . . $enable_ascent])
+AC_MSG_RESULT([ barometer . . . . . . $enable_barometer])
+AC_MSG_RESULT([ battery . . . . . . . $enable_battery])
+AC_MSG_RESULT([ bind . . . . . . . . $enable_bind])
+AC_MSG_RESULT([ ceph . . . . . . . . $enable_ceph])
+AC_MSG_RESULT([ cgroups . . . . . . . $enable_cgroups])
+AC_MSG_RESULT([ chrony. . . . . . . . $enable_chrony])
+AC_MSG_RESULT([ conntrack . . . . . . $enable_conntrack])
+AC_MSG_RESULT([ contextswitch . . . . $enable_contextswitch])
+AC_MSG_RESULT([ cpu . . . . . . . . . $enable_cpu])
+AC_MSG_RESULT([ cpufreq . . . . . . . $enable_cpufreq])
+AC_MSG_RESULT([ cpusleep . . . . . . $enable_cpusleep])
+AC_MSG_RESULT([ csv . . . . . . . . . $enable_csv])
+AC_MSG_RESULT([ curl . . . . . . . . $enable_curl])
+AC_MSG_RESULT([ curl_json . . . . . . $enable_curl_json])
+AC_MSG_RESULT([ curl_xml . . . . . . $enable_curl_xml])
+AC_MSG_RESULT([ dbi . . . . . . . . . $enable_dbi])
+AC_MSG_RESULT([ df . . . . . . . . . $enable_df])
+AC_MSG_RESULT([ disk . . . . . . . . $enable_disk])
+AC_MSG_RESULT([ dns . . . . . . . . . $enable_dns])
+AC_MSG_RESULT([ drbd . . . . . . . . $enable_drbd])
+AC_MSG_RESULT([ email . . . . . . . . $enable_email])
+AC_MSG_RESULT([ entropy . . . . . . . $enable_entropy])
+AC_MSG_RESULT([ ethstat . . . . . . . $enable_ethstat])
+AC_MSG_RESULT([ exec . . . . . . . . $enable_exec])
+AC_MSG_RESULT([ fhcount . . . . . . . $enable_fhcount])
+AC_MSG_RESULT([ filecount . . . . . . $enable_filecount])
+AC_MSG_RESULT([ fscache . . . . . . . $enable_fscache])
+AC_MSG_RESULT([ gmond . . . . . . . . $enable_gmond])
+AC_MSG_RESULT([ grpc . . . . . . . . $enable_grpc])
+AC_MSG_RESULT([ hddtemp . . . . . . . $enable_hddtemp])
+AC_MSG_RESULT([ interface . . . . . . $enable_interface])
+AC_MSG_RESULT([ ipc . . . . . . . . . $enable_ipc])
+AC_MSG_RESULT([ ipmi . . . . . . . . $enable_ipmi])
+AC_MSG_RESULT([ iptables . . . . . . $enable_iptables])
+AC_MSG_RESULT([ ipvs . . . . . . . . $enable_ipvs])
+AC_MSG_RESULT([ irq . . . . . . . . . $enable_irq])
+AC_MSG_RESULT([ java . . . . . . . . $enable_java])
+AC_MSG_RESULT([ load . . . . . . . . $enable_load])
+AC_MSG_RESULT([ logfile . . . . . . . $enable_logfile])
+AC_MSG_RESULT([ log_logstash . . . . $enable_log_logstash])
+AC_MSG_RESULT([ lpar . . . . . . . . $enable_lpar])
+AC_MSG_RESULT([ lvm . . . . . . . . . $enable_lvm])
+AC_MSG_RESULT([ madwifi . . . . . . . $enable_madwifi])
+AC_MSG_RESULT([ match_empty_counter . $enable_match_empty_counter])
+AC_MSG_RESULT([ match_hashed . . . . $enable_match_hashed])
+AC_MSG_RESULT([ match_regex . . . . . $enable_match_regex])
+AC_MSG_RESULT([ match_timediff . . . $enable_match_timediff])
+AC_MSG_RESULT([ match_value . . . . . $enable_match_value])
+AC_MSG_RESULT([ mbmon . . . . . . . . $enable_mbmon])
+AC_MSG_RESULT([ md . . . . . . . . . $enable_md])
+AC_MSG_RESULT([ memcachec . . . . . . $enable_memcachec])
+AC_MSG_RESULT([ memcached . . . . . . $enable_memcached])
+AC_MSG_RESULT([ memory . . . . . . . $enable_memory])
+AC_MSG_RESULT([ mic . . . . . . . . . $enable_mic])
+AC_MSG_RESULT([ modbus . . . . . . . $enable_modbus])
+AC_MSG_RESULT([ mqtt . . . . . . . . $enable_mqtt])
+AC_MSG_RESULT([ multimeter . . . . . $enable_multimeter])
+AC_MSG_RESULT([ mysql . . . . . . . . $enable_mysql])
+AC_MSG_RESULT([ netapp . . . . . . . $enable_netapp])
+AC_MSG_RESULT([ netlink . . . . . . . $enable_netlink])
+AC_MSG_RESULT([ network . . . . . . . $enable_network])
+AC_MSG_RESULT([ nfs . . . . . . . . . $enable_nfs])
+AC_MSG_RESULT([ nginx . . . . . . . . $enable_nginx])
+AC_MSG_RESULT([ notify_desktop . . . $enable_notify_desktop])
+AC_MSG_RESULT([ notify_email . . . . $enable_notify_email])
+AC_MSG_RESULT([ notify_nagios . . . . $enable_notify_nagios])
+AC_MSG_RESULT([ ntpd . . . . . . . . $enable_ntpd])
+AC_MSG_RESULT([ numa . . . . . . . . $enable_numa])
+AC_MSG_RESULT([ nut . . . . . . . . . $enable_nut])
+AC_MSG_RESULT([ olsrd . . . . . . . . $enable_olsrd])
+AC_MSG_RESULT([ onewire . . . . . . . $enable_onewire])
+AC_MSG_RESULT([ openldap . . . . . . $enable_openldap])
+AC_MSG_RESULT([ openvpn . . . . . . . $enable_openvpn])
+AC_MSG_RESULT([ oracle . . . . . . . $enable_oracle])
+AC_MSG_RESULT([ perl . . . . . . . . $enable_perl])
+AC_MSG_RESULT([ pf . . . . . . . . . $enable_pf])
+AC_MSG_RESULT([ pinba . . . . . . . . $enable_pinba])
+AC_MSG_RESULT([ ping . . . . . . . . $enable_ping])
+AC_MSG_RESULT([ postgresql . . . . . $enable_postgresql])
+AC_MSG_RESULT([ powerdns . . . . . . $enable_powerdns])
+AC_MSG_RESULT([ processes . . . . . . $enable_processes])
+AC_MSG_RESULT([ protocols . . . . . . $enable_protocols])
+AC_MSG_RESULT([ python . . . . . . . $enable_python])
+AC_MSG_RESULT([ redis . . . . . . . . $enable_redis])
+AC_MSG_RESULT([ routeros . . . . . . $enable_routeros])
+AC_MSG_RESULT([ rrdcached . . . . . . $enable_rrdcached])
+AC_MSG_RESULT([ rrdtool . . . . . . . $enable_rrdtool])
+AC_MSG_RESULT([ sensors . . . . . . . $enable_sensors])
+AC_MSG_RESULT([ serial . . . . . . . $enable_serial])
+AC_MSG_RESULT([ sigrok . . . . . . . $enable_sigrok])
+AC_MSG_RESULT([ smart . . . . . . . . $enable_smart])
+AC_MSG_RESULT([ snmp . . . . . . . . $enable_snmp])
+AC_MSG_RESULT([ statsd . . . . . . . $enable_statsd])
+AC_MSG_RESULT([ swap . . . . . . . . $enable_swap])
+AC_MSG_RESULT([ syslog . . . . . . . $enable_syslog])
+AC_MSG_RESULT([ table . . . . . . . . $enable_table])
+AC_MSG_RESULT([ tail_csv . . . . . . $enable_tail_csv])
+AC_MSG_RESULT([ tail . . . . . . . . $enable_tail])
+AC_MSG_RESULT([ tape . . . . . . . . $enable_tape])
+AC_MSG_RESULT([ target_notification . $enable_target_notification])
+AC_MSG_RESULT([ target_replace . . . $enable_target_replace])
+AC_MSG_RESULT([ target_scale . . . . $enable_target_scale])
+AC_MSG_RESULT([ target_set . . . . . $enable_target_set])
+AC_MSG_RESULT([ target_v5upgrade . . $enable_target_v5upgrade])
+AC_MSG_RESULT([ tcpconns . . . . . . $enable_tcpconns])
+AC_MSG_RESULT([ teamspeak2 . . . . . $enable_teamspeak2])
+AC_MSG_RESULT([ ted . . . . . . . . . $enable_ted])
+AC_MSG_RESULT([ thermal . . . . . . . $enable_thermal])
+AC_MSG_RESULT([ threshold . . . . . . $enable_threshold])
+AC_MSG_RESULT([ tokyotyrant . . . . . $enable_tokyotyrant])
+AC_MSG_RESULT([ turbostat . . . . . . $enable_turbostat])
+AC_MSG_RESULT([ unixsock . . . . . . $enable_unixsock])
+AC_MSG_RESULT([ uptime . . . . . . . $enable_uptime])
+AC_MSG_RESULT([ users . . . . . . . . $enable_users])
+AC_MSG_RESULT([ uuid . . . . . . . . $enable_uuid])
+AC_MSG_RESULT([ varnish . . . . . . . $enable_varnish])
+AC_MSG_RESULT([ virt . . . . . . . . $enable_virt])
+AC_MSG_RESULT([ vmem . . . . . . . . $enable_vmem])
+AC_MSG_RESULT([ vserver . . . . . . . $enable_vserver])
+AC_MSG_RESULT([ wireless . . . . . . $enable_wireless])
+AC_MSG_RESULT([ write_graphite . . . $enable_write_graphite])
+AC_MSG_RESULT([ write_http . . . . . $enable_write_http])
+AC_MSG_RESULT([ write_kafka . . . . . $enable_write_kafka])
+AC_MSG_RESULT([ write_log . . . . . . $enable_write_log])
+AC_MSG_RESULT([ write_mongodb . . . . $enable_write_mongodb])
+AC_MSG_RESULT([ write_redis . . . . . $enable_write_redis])
+AC_MSG_RESULT([ write_riemann . . . . $enable_write_riemann])
+AC_MSG_RESULT([ write_sensu . . . . . $enable_write_sensu])
+AC_MSG_RESULT([ write_tsdb . . . . . $enable_write_tsdb])
+AC_MSG_RESULT([ xencpu . . . . . . . $enable_xencpu])
+AC_MSG_RESULT([ xmms . . . . . . . . $enable_xmms])
+AC_MSG_RESULT([ zfs_arc . . . . . . . $enable_zfs_arc])
+AC_MSG_RESULT([ zone . . . . . . . . $enable_zone])
+AC_MSG_RESULT([ zookeeper . . . . . . $enable_zookeeper])
+AC_MSG_RESULT()
if test "x$dependency_error" = "xyes"; then
AC_MSG_ERROR("Some plugins are missing dependencies - see the summary above for details")
%global _hardened_build 1
%{?perl_default_filter}
-# plugins only buildable on RHEL6
-# (NB: %{elN} macro is not available on RHEL < 6)
-%{?el6:%global _has_libyajl 1}
-%{?el6:%global _has_recent_libpcap 1}
-%{?el6:%global _has_recent_sockios_h 1}
-%{?el6:%global _has_recent_libganglia 1}
-%{?el6:%global _has_working_libiptc 1}
-%{?el6:%global _has_ip_vs_h 1}
-%{?el6:%global _has_lvm2app_h 1}
-%{?el6:%global _has_libmodbus 1}
-%{?el6:%global _has_libudev 1}
-%{?el6:%global _has_iproute 1}
-%{?el6:%global _has_atasmart 1}
-%{?el6:%global _has_hiredis 1}
-%{?el6:%global _has_asm_msr_index 1}
-
-%{?el7:%global _has_libyajl 1}
-%{?el7:%global _has_recent_libpcap 1}
-%{?el7:%global _has_recent_sockios_h 1}
-%{?el7:%global _has_working_libiptc 1}
-%{?el7:%global _has_ip_vs_h 1}
-%{?el7:%global _has_lvm2app_h 1}
-%{?el7:%global _has_libudev 1}
-%{?el7:%global _has_recent_librrd 1}
-%{?el7:%global _has_iproute 1}
-%{?el7:%global _has_atasmart 1}
-%{?el7:%global _has_hiredis 1}
-%{?el7:%global _has_asm_msr_index 1}
-%{?el7:%global _has_libmosquitto 1}
-%{?el7:%global _has_libmodbus 1}
-%{?el7:%global _has_xmms 1}
-
# plugins enabled by default
%define with_aggregation 0%{!?_without_aggregation:1}
%define with_amqp 0%{!?_without_amqp:1}
%define with_ascent 0%{!?_without_ascent:1}
%define with_battery 0%{!?_without_battery:1}
%define with_bind 0%{!?_without_bind:1}
-%define with_ceph 0%{!?_without_ceph:0%{?_has_libyajl}}
+%define with_ceph 0%{!?_without_ceph:1}
%define with_cgroups 0%{!?_without_cgroups:1}
+%define with_chrony 0%{!?_without_chrony:1}
%define with_conntrack 0%{!?_without_conntrack:1}
%define with_contextswitch 0%{!?_without_contextswitch:1}
%define with_cpu 0%{!?_without_cpu:1}
%define with_cpufreq 0%{!?_without_cpufreq:1}
%define with_csv 0%{!?_without_csv:1}
%define with_curl 0%{!?_without_curl:1}
-%define with_curl_json 0%{!?_without_curl_json:0%{?_has_libyajl}}
+%define with_curl_json 0%{!?_without_curl_json:1}
%define with_curl_xml 0%{!?_without_curl_xml:1}
%define with_dbi 0%{!?_without_dbi:1}
%define with_df 0%{!?_without_df:1}
%define with_disk 0%{!?_without_disk:1}
-%define with_dns 0%{!?_without_dns:0%{?_has_recent_libpcap}}
+%define with_dns 0%{!?_without_dns:1}
%define with_drbd 0%{!?_without_drbd:1}
%define with_email 0%{!?_without_email:1}
%define with_entropy 0%{!?_without_entropy:1}
-%define with_ethstat 0%{!?_without_ethstat:0%{?_has_recent_sockios_h}}
+%define with_ethstat 0%{!?_without_ethstat:1}
%define with_exec 0%{!?_without_exec:1}
%define with_fhcount 0%{!?_without_fhcount:1}
%define with_filecount 0%{!?_without_filecount:1}
%define with_fscache 0%{!?_without_fscache:1}
-%define with_gmond 0%{!?_without_gmond:0%{?_has_recent_libganglia}}
+%define with_gmond 0%{!?_without_gmond:1}
%define with_hddtemp 0%{!?_without_hddtemp:1}
%define with_interface 0%{!?_without_interface:1}
%define with_ipc 0%{!?_without_ipc:1}
%define with_ipmi 0%{!?_without_ipmi:1}
-%define with_iptables 0%{!?_without_iptables:0%{?_has_working_libiptc}}
-%define with_ipvs 0%{!?_without_ipvs:0%{?_has_ip_vs_h}}
+%define with_iptables 0%{!?_without_iptables:1}
+%define with_ipvs 0%{!?_without_ipvs:1}
%define with_irq 0%{!?_without_irq:1}
%define with_java 0%{!?_without_java:1}
-%define with_virt 0%{!?_without_virt:1}
%define with_load 0%{!?_without_load:1}
+%define with_log_logstash 0%{!?_without_log_logstash:1}
%define with_logfile 0%{!?_without_logfile:1}
-%define with_log_logstash 0%{!?_without_log_logstash:0%{?_has_libyajl}}
-%define with_lvm 0%{!?_without_lvm:0%{?_has_lvm2app_h}}
+%define with_lvm 0%{!?_without_lvm:1}
%define with_madwifi 0%{!?_without_madwifi:1}
%define with_mbmon 0%{!?_without_mbmon:1}
%define with_md 0%{!?_without_md:1}
%define with_memcachec 0%{!?_without_memcachec:1}
%define with_memcached 0%{!?_without_memcached:1}
%define with_memory 0%{!?_without_memory:1}
+%define with_modbus 0%{!?_without_modbus:1}
+%define with_mqtt 0%{!?_without_mqtt:1}
%define with_multimeter 0%{!?_without_multimeter:1}
-%define with_modbus 0%{!?_without_modbus:0%{?_has_libmodbus}}
-%define with_mqtt 0%{!?_without_mqtt:0%{?_has_libmosquitto}}
%define with_mysql 0%{!?_without_mysql:1}
-%define with_netlink 0%{!?_without_netlink:0%{?_has_iproute}}
+%define with_netlink 0%{!?_without_netlink:1}
%define with_network 0%{!?_without_network:1}
%define with_nfs 0%{!?_without_nfs:1}
%define with_nginx 0%{!?_without_nginx:1}
%define with_processes 0%{!?_without_processes:1}
%define with_protocols 0%{!?_without_protocols:1}
%define with_python 0%{!?_without_python:1}
-%define with_redis 0%{!?_without_redis:0%{?_has_hiredis}}
-%define with_rrdcached 0%{!?_without_rrdcached:0%{?_has_recent_librrd}}
+%define with_redis 0%{!?_without_redis:1}
+%define with_rrdcached 0%{!?_without_rrdcached:1}
%define with_rrdtool 0%{!?_without_rrdtool:1}
%define with_sensors 0%{!?_without_sensors:1}
%define with_serial 0%{!?_without_serial:1}
-%define with_smart 0%{!?_without_smart:0%{?_has_atasmart}}
+%define with_smart 0%{!?_without_smart:1}
%define with_snmp 0%{!?_without_snmp:1}
%define with_statsd 0%{!?_without_statsd:1}
%define with_swap 0%{!?_without_swap:1}
%define with_ted 0%{!?_without_ted:1}
%define with_thermal 0%{!?_without_thermal:1}
%define with_threshold 0%{!?_without_threshold:1}
-%define with_turbostat 0%{!?_without_turbostat:0%{?_has_asm_msr_index}}
+%define with_turbostat 0%{!?_without_turbostat:1}
%define with_unixsock 0%{!?_without_unixsock:1}
%define with_uptime 0%{!?_without_uptime:1}
%define with_users 0%{!?_without_users:1}
%define with_uuid 0%{!?_without_uuid:1}
%define with_varnish 0%{!?_without_varnish:1}
+%define with_virt 0%{!?_without_virt:1}
%define with_vmem 0%{!?_without_vmem:1}
%define with_vserver 0%{!?_without_vserver:1}
%define with_wireless 0%{!?_without_wireless:1}
%define with_write_graphite 0%{!?_without_write_graphite:1}
%define with_write_http 0%{!?_without_write_http:1}
%define with_write_log 0%{!?_without_write_log:1}
-%define with_write_redis 0%{!?_without_write_redis:0%{?_has_hiredis}}
-%define with_write_riemann 0%{!?_without_write_riemann:0%{?_has_recent_riemann_c_client}}
+%define with_write_redis 0%{!?_without_write_redis:1}
%define with_write_sensu 0%{!?_without_write_sensu:1}
%define with_write_tsdb 0%{!?_without_write_tsdb:1}
%define with_xmms 0%{!?_without_xmms:0%{?_has_xmms}}
%define with_aquaero 0%{!?_without_aquaero:0}
# plugin barometer disabled, requires a libi2c
%define with_barometer 0%{!?_without_barometer:0}
+# plugin grpc disabled, requires protobuf-compiler >= 3.0
+%define with_grpc 0%{!?_without_grpc:0}
# plugin lpar disabled, requires AIX
%define with_lpar 0%{!?_without_lpar:0}
# plugin mic disabled, requires Mic
%define with_write_kafka 0%{!?_without_write_kafka:0}
# plugin write_mongodb disabled, requires libmongoc
%define with_write_mongodb 0%{!?_without_write_mongodb:0}
+# plugin write_riemann disabled, requires a new enough riemann_c_client
+%define with_write_riemann 0%{!?_without_write_riemann:0}
# plugin xencpu disabled, requires xen-devel from non-default repo
%define with_xencpu 0%{!?_without_xencpu:0}
# plugin zone disabled, requires Solaris
%define with_zone 0%{!?_without_zone:0}
-Summary: statistics collection and monitoring daemon
+# Plugins not buildable on RHEL < 6
+%if 0%{?rhel} && 0%{?rhel} < 6
+%define with_ceph 0
+%define with_curl_json 0
+%define with_log_logstash 0
+%define with_dns 0
+%define with_ethstat 0
+%define with_gmond 0
+%define with_iptables 0
+%define with_ipvs 0
+%define with_lvm 0
+%define with_modbus 0
+%define with_netlink 0
+%define with_redis 0
+%define with_smart 0
+%define with_turbostat 0
+%define with_write_redis 0
+%endif
+
+# Plugins not buildable on RHEL < 7
+%if 0%{?rhel} && 0%{?rhel} < 7
+%define with_mqtt 0
+%define with_rrdcached 0
+%define with_xmms 0
+%endif
+
+Summary: Statistics collection and monitoring daemon
Name: collectd
Version: 5.5.1
Release: 1%{?dist}
BuildRequires: libgcrypt-devel, kernel-headers, libtool-ltdl-devel, libcap-devel
Vendor: collectd development team <collectd@verplant.org>
-%if 0%{?el7:1}
-Requires(pre): initscripts
-Requires(post): systemd
-Requires(preun): systemd
-Requires(postun): systemd
+%if 0%{?fedora} || 0%{?rhel} >= 7
+%{?systemd_requires}
+BuildRequires: systemd
%else
Requires(post): chkconfig
Requires(preun): chkconfig, initscripts
Ceph plugin for collectd
%endif
+%if %{with_chrony}
+%package chrony
+Summary: Chrony plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+%description chrony
+Chrony plugin for collectd
+%endif
+
%if %{with_curl}
%package curl
Summary: Curl plugin for collectd
the client daemon of the Ganglia project.
%endif
+%if %{with_grpc}
+%package grpc
+Summary: GRPC plugin for collectd
+Group: System Environment/Daemons
+Requires: %{name}%{?_isa} = %{version}-%{release}
+BuildRequires: protobuf-compiler
+%description grpc
+This plugin embeds a gRPC server into Collectd.
+%endif
+
%if %{with_hddtemp}
%package hddtemp
Summary: Hddtemp plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
Requires: perl(:MODULE_COMPAT_%(eval "`%{__perl} -V:version`"; echo $version))
- %if 0%{?rhel} >= 6
-BuildRequires: perl-ExtUtils-Embed
- %else
+ %if 0%{?rhel} && 0%{?rhel} < 6
BuildRequires: perl
+ %else
+BuildRequires: perl-ExtUtils-Embed
%endif
%description perl
The Perl plugin embeds a Perl interpreter into collectd and exposes the
Summary: Python plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
- %if 0%{?rhel} >= 6
-BuildRequires: python-devel
- %else
+ %if 0%{?rhel} && 0%{?rhel} < 6
BuildRequires: python26-devel
+ %else
+BuildRequires: python-devel
%endif
%description python
The Python plugin embeds a Python interpreter into collectd and exposes the
Summary: Write-kafka plugin for collectd
Group: System Environment/Daemons
Requires: %{name}%{?_isa} = %{version}-%{release}
-BuildRequires: rdkafka-devel
+BuildRequires: librdkafka-devel
%description write_kafka
The write_kafka plugin sends values to kafka, a distributed messaging system.
%endif
%define _with_cgroups --disable-cgroups
%endif
+%if %{with_chrony}
+%define _with_chrony --enable-chrony
+%else
+%define _with_chrony --disable-chrony
+%endif
+
%if %{with_conntrack}
%define _with_conntrack --enable-conntrack
%else
%define _with_gmond --disable-gmond
%endif
+%if %{with_grpc}
+%define _with_grpc --enable-grpc
+%else
+%define _with_grpc --disable-grpc
+%endif
+
%if %{with_hddtemp}
%define _with_hddtemp --enable-hddtemp
%else
%endif
%if %{with_python}
- %if 0%{?rhel} >= 6
-%define _with_python --enable-python
- %else
+ %if 0%{?rhel} && 0%{?rhel} < 6
%define _with_python --enable-python --with-python=%{_bindir}/python2.6
+ %else
+%define _with_python --enable-python
%endif
%else
%define _with_python --disable-python
%{?_with_bind} \
%{?_with_ceph} \
%{?_with_cgroups} \
+ %{?_with_chrony} \
%{?_with_conntrack} \
%{?_with_contextswitch} \
- %{?_with_cpu} \
%{?_with_cpufreq} \
+ %{?_with_cpu} \
%{?_with_csv} \
- %{?_with_curl} \
%{?_with_curl_json} \
%{?_with_curl_xml} \
+ %{?_with_curl} \
%{?_with_dbi} \
%{?_with_df} \
%{?_with_disk} \
%{?_with_filecount} \
%{?_with_fscache} \
%{?_with_gmond} \
+ %{?_with_grpc} \
%{?_with_hddtemp} \
%{?_with_interface} \
%{?_with_ipc} \
%{?_with_ipmi} \
%{?_with_iptables} \
%{?_with_ipvs} \
+ %{?_with_irq} \
%{?_with_java} \
- %{?_with_virt} \
+ %{?_with_load} \
%{?_with_log_logstash} \
+ %{?_with_logfile} \
%{?_with_lpar} \
%{?_with_lvm} \
+ %{?_with_madwifi} \
+ %{?_with_mbmon} \
+ %{?_with_md} \
%{?_with_memcachec} \
+ %{?_with_memcached} \
+ %{?_with_memory} \
%{?_with_mic} \
%{?_with_modbus} \
- %{?_with_multimeter} \
%{?_with_mqtt} \
+ %{?_with_multimeter} \
%{?_with_mysql} \
%{?_with_netapp} \
%{?_with_netlink} \
+ %{?_with_network} \
+ %{?_with_nfs} \
%{?_with_nginx} \
%{?_with_notify_desktop} \
%{?_with_notify_email} \
+ %{?_with_notify_nagios} \
+ %{?_with_ntpd} \
+ %{?_with_numa} \
%{?_with_nut} \
+ %{?_with_olsrd} \
%{?_with_onewire} \
%{?_with_openldap} \
+ %{?_with_openvpn} \
%{?_with_oracle} \
%{?_with_perl} \
%{?_with_pf} \
%{?_with_pinba} \
%{?_with_ping} \
%{?_with_postgresql} \
+ %{?_with_powerdns} \
+ %{?_with_processes} \
+ %{?_with_protocols} \
%{?_with_python} \
%{?_with_redis} \
%{?_with_routeros} \
%{?_with_rrdcached} \
%{?_with_rrdtool} \
%{?_with_sensors} \
+ %{?_with_serial} \
%{?_with_sigrok} \
%{?_with_smart} \
%{?_with_snmp} \
- %{?_with_tape} \
- %{?_with_tokyotyrant} \
- %{?_with_varnish} \
- %{?_with_write_http} \
- %{?_with_write_kafka} \
- %{?_with_write_mongodb} \
- %{?_with_write_redis} \
- %{?_with_xencpu} \
- %{?_with_xmms} \
- %{?_with_zfs_arc} \
- %{?_with_zone} \
- %{?_with_zookeeper} \
- %{?_with_irq} \
- %{?_with_load} \
- %{?_with_logfile} \
- %{?_with_madwifi} \
- %{?_with_mbmon} \
- %{?_with_md} \
- %{?_with_memcached} \
- %{?_with_memory} \
- %{?_with_network} \
- %{?_with_nfs} \
- %{?_with_notify_nagios} \
- %{?_with_ntpd} \
- %{?_with_numa} \
- %{?_with_olsrd} \
- %{?_with_openvpn} \
- %{?_with_powerdns} \
- %{?_with_processes} \
- %{?_with_protocols} \
- %{?_with_serial} \
%{?_with_statsd} \
%{?_with_swap} \
%{?_with_syslog} \
%{?_with_table} \
- %{?_with_tail} \
%{?_with_tail_csv} \
+ %{?_with_tail} \
+ %{?_with_tape} \
%{?_with_tcpconns} \
%{?_with_teamspeak2} \
%{?_with_ted} \
%{?_with_thermal} \
%{?_with_threshold} \
+ %{?_with_tokyotyrant} \
%{?_with_turbostat} \
%{?_with_unixsock} \
%{?_with_uptime} \
%{?_with_users} \
%{?_with_uuid} \
+ %{?_with_varnish} \
+ %{?_with_virt} \
%{?_with_vmem} \
%{?_with_vserver} \
%{?_with_wireless}\
%{?_with_write_graphite} \
%{?_with_write_http} \
+ %{?_with_write_http} \
+ %{?_with_write_kafka} \
%{?_with_write_log} \
+ %{?_with_write_mongodb} \
+ %{?_with_write_redis} \
%{?_with_write_riemann} \
%{?_with_write_sensu} \
- %{?_with_write_tsdb}
+ %{?_with_write_tsdb} \
+ %{?_with_xencpu} \
+ %{?_with_xmms} \
+ %{?_with_zfs_arc} \
+ %{?_with_zone} \
+ %{?_with_zookeeper}
%{__make} %{?_smp_mflags}
%install
rm -rf %{buildroot}
%{__make} install DESTDIR=%{buildroot}
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%{__install} -Dp -m0644 contrib/systemd.collectd.service %{buildroot}%{_unitdir}/collectd.service
%else
%{__install} -Dp -m0755 contrib/redhat/init.d-collectd %{buildroot}%{_initrddir}/collectd
%clean
rm -rf %{buildroot}
-%pre
-%if 0%{?el7:1}
-# stop sysv-based instance before upgrading to systemd
-if [ $1 -eq 2 ] && [ -f /var/lock/subsys/collectd ]; then
- SYSTEMCTL_SKIP_REDIRECT=1 %{_initddir}/collectd stop >/dev/null 2>&1 || :
-fi
-%endif
-
%post
-%if 0%{?el7:1}
-if [ $1 -eq 2 ]; then
- /usr/bin/systemctl daemon-reload >/dev/null 2>&1 || :
-fi
+%if 0%{?fedora} || 0%{?rhel} >= 7
%systemd_post collectd.service
%else
/sbin/chkconfig --add collectd || :
%endif
%preun
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%systemd_preun collectd.service
%else
# stop collectd only when uninstalling
%endif
%postun
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%systemd_postun_with_restart collectd.service
%else
# restart collectd only when upgrading
%files
%doc AUTHORS COPYING ChangeLog README
%config(noreplace) %{_sysconfdir}/collectd.conf
-%if 0%{?el7:1}
+%if 0%{?fedora} || 0%{?rhel} >= 7
%{_unitdir}/collectd.service
%else
%{_initrddir}/collectd
%{_libdir}/%{name}/ceph.so
%endif
+%if %{with_chrony}
+%files chrony
+%{_libdir}/%{name}/chrony.so
+%endif
+
%if %{with_curl}
%files curl
%{_libdir}/%{name}/curl.so
%{_libdir}/%{name}/gmond.so
%endif
+%if %{with_grpc}
+%files grpc
+%{_libdir}/%{name}/grpc.so
+%endif
+
%if %{with_hddtemp}
%files hddtemp
%{_libdir}/%{name}/hddtemp.so
%doc contrib/
%changelog
-#* TODO: next feature release changelog
-#- New upstream version
-#- New plugins enabled by default: mqtt, notify_nagios
-#- New plugins disabled by default: zone, xencpu
-#
+* Sat Jun 04 2016 Ruben Kerkhof <ruben@rubenkerkhof.com> 5.5.1-1
+- New upstream version
+- New plugins enabled by default: chrony, mqtt, notify_nagios
+- New plugins disabled by default: grpc, zone, xencpu
+
* Wed May 27 2015 Marc Fournier <marc.fournier@camptocamp.com> 5.5.0-1
- New upstream version
- New plugins enabled by default: ceph, drbd, log_logstash, write_tsdb, smart,
--- /dev/null
+EXTRA_DIST = collectd.proto types.proto
--- /dev/null
+// collectd - proto/collectd.proto
+// Copyright (C) 2015-2016 Sebastian Harl
+//
+// 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:
+// Sebastian Harl <sh at tokkee.org>
+
+syntax = "proto3";
+
+package collectd;
+
+import "types.proto";
+import "google/protobuf/timestamp.proto";
+
+service Collectd {
+ // Dispatch collected values to collectd.
+ rpc DispatchValues(DispatchValuesRequest) returns (DispatchValuesReply);
+
+ // Query a list of values available from collectd's value cache.
+ rpc QueryValues(QueryValuesRequest) returns (QueryValuesReply);
+}
+
+// The arguments to DispatchValues.
+message DispatchValuesRequest {
+ collectd.types.ValueList values = 1;
+}
+
+// The response from DispatchValues.
+message DispatchValuesReply {
+}
+
+// The arguments to QueryValues.
+message QueryValuesRequest {
+ // Query by the fields of the identifier. Only return values matching the
+ // specified shell wildcard patterns (see fnmatch(3)). Use '*' to match
+ // any value.
+ collectd.types.Identifier identifier = 1;
+}
+
+// The response from QueryValues.
+message QueryValuesReply {
+ repeated collectd.types.ValueList values = 1;
+}
--- /dev/null
+// collectd - proto/types.proto
+// Copyright (C) 2015-2016 Sebastian Harl
+//
+// 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:
+// Sebastian Harl <sh at tokkee.org>
+
+syntax = "proto3";
+
+package collectd.types;
+
+import "google/protobuf/duration.proto";
+import "google/protobuf/timestamp.proto";
+
+message Identifier {
+ string host = 1;
+ string plugin = 2;
+ string plugin_instance = 3;
+ string type = 4;
+ string type_instance = 5;
+}
+
+message Value {
+ oneof value {
+ uint64 counter = 1;
+ double gauge = 2;
+ int64 derive = 3;
+ uint64 absolute = 4;
+ };
+}
+
+message ValueList {
+ repeated Value value = 1;
+
+ google.protobuf.Timestamp time = 2;
+ google.protobuf.Duration interval = 3;
+
+ Identifier identifier = 4;
+}
AM_CPPFLAGS += -DPLUGINDIR='"${pkglibdir}"'
AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
+LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_top_srcdir)/testwrapper.sh
+
+V_PROTOC = $(v_protoc_@AM_V@)
+v_protoc_ = $(v_protoc_@AM_DEFAULT_V@)
+v_protoc_0 = @echo " PROTOC " $@;
+
noinst_LTLIBRARIES =
check_PROGRAMS =
TESTS =
bin_PROGRAMS = collectd-nagios collectdctl collectd-tg
collectdmon_SOURCES = collectdmon.c
-collectdmon_CPPFLAGS = $(AM_CPPFLAGS)
collectd_nagios_SOURCES = collectd-nagios.c
-collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_nagios_LDADD =
+collectd_nagios_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_nagios_LDADD = libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectd_nagios_LDADD += -lsocket
endif
collectd_nagios_LDADD += -lm
endif
-collectd_nagios_LDADD += libcollectdclient/libcollectdclient.la
-collectd_nagios_DEPENDENCIES = libcollectdclient/libcollectdclient.la
-
collectdctl_SOURCES = collectdctl.c
-collectdctl_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectdctl_LDADD =
+collectdctl_CPPFLAGS = $(AM_CPPFLAGS) \
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd
+collectdctl_LDADD = libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectdctl_LDADD += -lsocket
endif
if BUILD_AIX
collectdctl_LDADD += -lm
endif
-collectdctl_LDADD += libcollectdclient/libcollectdclient.la
-collectdctl_DEPENDENCIES = libcollectdclient/libcollectdclient.la
+
collectd_tg_SOURCES = collectd-tg.c
collectd_tg_CPPFLAGS = $(AM_CPPFLAGS) \
- -I$(top_srcdir)/src/libcollectdclient/collectd -I$(top_builddir)/src/libcollectdclient/collectd
-collectd_tg_LDADD = daemon/libheap.la
+ -I$(top_srcdir)/src/libcollectdclient/collectd \
+ -I$(top_builddir)/src/libcollectdclient/collectd
+collectd_tg_LDADD = \
+ $(PTHREAD_LIBS) \
+ daemon/libheap.la \
+ libcollectdclient/libcollectdclient.la
if BUILD_WITH_LIBSOCKET
collectd_tg_LDADD += -lsocket
endif
if BUILD_AIX
collectd_tg_LDADD += -lm
endif
-if BUILD_WITH_LIBPTHREAD
-collectd_tg_LDADD += $(PTHREAD_LIBS)
-endif
-collectd_tg_LDADD += libcollectdclient/libcollectdclient.la
-collectd_tg_DEPENDENCIES = libcollectdclient/libcollectdclient.la
pkglib_LTLIBRARIES =
BUILT_SOURCES =
CLEANFILES =
+if HAVE_PROTOC3
+if HAVE_GRPC_CPP
+BUILT_SOURCES += collectd.grpc.pb.cc collectd.pb.cc types.pb.cc
+CLEANFILES += collectd.grpc.pb.cc collectd.pb.cc types.pb.cc \
+ collectd.grpc.pb.h collectd.pb.h types.pb.h
+
+collectd.grpc.pb.cc: $(top_srcdir)/proto/collectd.proto $(top_srcdir)/proto/types.proto
+ $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto \
+ --grpc_out=$(builddir) --plugin=protoc-gen-grpc=$(GRPC_CPP_PLUGIN) $<
+
+collectd.pb.cc: $(top_srcdir)/proto/collectd.proto $(top_srcdir)/proto/types.proto
+ $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto --cpp_out=$(builddir) $<
+
+types.pb.cc: $(top_srcdir)/proto/types.proto
+ $(V_PROTOC)@PROTOC@ -I$(top_srcdir)/proto --cpp_out=$(builddir) $<
+endif
+endif
+
if BUILD_PLUGIN_AGGREGATION
pkglib_LTLIBRARIES += aggregation.la
aggregation_la_SOURCES = aggregation.c \
pkglib_LTLIBRARIES += apache.la
apache_la_SOURCES = apache.c
apache_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-apache_la_CFLAGS = $(AM_CFLAGS)
-apache_la_LIBADD =
-if BUILD_WITH_LIBCURL
-apache_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-apache_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+apache_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+apache_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
if BUILD_PLUGIN_APCUPS
if BUILD_PLUGIN_APPLE_SENSORS
pkglib_LTLIBRARIES += apple_sensors.la
apple_sensors_la_SOURCES = apple_sensors.c
-apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-apple_sensors_la_LDFLAGS += -framework IOKit
+apple_sensors_la_LDFLAGS = $(PLUGIN_LDFLAGS) -framework IOKit
endif
if BUILD_PLUGIN_AQUAERO
pkglib_LTLIBRARIES += aquaero.la
aquaero_la_SOURCES = aquaero.c
-aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS)
aquaero_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBAQUAERO5_CFLAGS)
-aquaero_la_LIBADD = $(BUILD_WITH_LIBAQUAERO5_LDFLAGS) -laquaero5
+aquaero_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBAQUAERO5_LDFLAGS)
+aquaero_la_LIBADD = -laquaero5
endif
if BUILD_PLUGIN_ASCENT
pkglib_LTLIBRARIES += battery.la
battery_la_SOURCES = battery.c
battery_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-battery_la_LIBADD =
if BUILD_WITH_LIBIOKIT
battery_la_LDFLAGS += -framework IOKit
endif
cgroups_la_LIBADD = libmount.la
endif
+if BUILD_PLUGIN_CHRONY
+pkglib_LTLIBRARIES += chrony.la
+chrony_la_SOURCES = chrony.c
+chrony_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+endif
+
if BUILD_PLUGIN_CONNTRACK
pkglib_LTLIBRARIES += conntrack.la
conntrack_la_SOURCES = conntrack.c
if BUILD_PLUGIN_CURL
pkglib_LTLIBRARIES += curl.la
-curl_la_SOURCES = curl.c
+curl_la_SOURCES = curl.c \
+ utils_curl_stats.c utils_curl_stats.h
curl_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-curl_la_CFLAGS = $(AM_CFLAGS)
-curl_la_LIBADD =
-if BUILD_WITH_LIBCURL
-curl_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-curl_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+curl_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
+curl_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
if BUILD_PLUGIN_CURL_JSON
pkglib_LTLIBRARIES += curl_json.la
-curl_json_la_SOURCES = curl_json.c
-curl_json_la_CFLAGS = $(AM_CFLAGS)
-curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_SOURCES = curl_json.c \
+ utils_curl_stats.c utils_curl_stats.h
+curl_json_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
curl_json_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
-curl_json_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
-if BUILD_WITH_LIBCURL
-curl_json_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-curl_json_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+curl_json_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
+curl_json_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS) $(BUILD_WITH_LIBYAJL_LIBS)
endif
if BUILD_PLUGIN_CURL_XML
pkglib_LTLIBRARIES += curl_xml.la
-curl_xml_la_SOURCES = curl_xml.c
+curl_xml_la_SOURCES = curl_xml.c \
+ utils_curl_stats.c utils_curl_stats.h
curl_xml_la_LDFLAGS = $(PLUGIN_LDFLAGS)
curl_xml_la_CFLAGS = $(AM_CFLAGS) \
$(BUILD_WITH_LIBCURL_CFLAGS) $(BUILD_WITH_LIBXML2_CFLAGS)
pkglib_LTLIBRARIES += dns.la
dns_la_SOURCES = dns.c utils_dns.c utils_dns.h
dns_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-dns_la_LIBADD = $(PTHREAD_LIBS) -lpcap
+dns_la_LIBADD = -lpcap
endif
if BUILD_PLUGIN_DRBD
pkglib_LTLIBRARIES += email.la
email_la_SOURCES = email.c
email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-email_la_LIBADD = $(PTHREAD_LIBS)
endif
if BUILD_PLUGIN_ENTROPY
utils_cmd_putval.c utils_cmd_putval.h \
utils_parse_option.h utils_parse_option.c
exec_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-exec_la_LIBADD = $(PTHREAD_LIBS)
endif
if BUILD_PLUGIN_ETHSTAT
gmond_la_LIBADD = $(GANGLIA_LIBS)
endif
+if BUILD_PLUGIN_GRPC
+pkglib_LTLIBRARIES += grpc.la
+grpc_la_SOURCES = grpc.cc
+nodist_grpc_la_SOURCES = collectd.grpc.pb.cc collectd.pb.cc types.pb.cc
+grpc_la_CPPFLAGS = $(AM_CPPFLAGS) -std=c++11
+grpc_la_CXXFLAGS = $(AM_CXXFLAGS) -std=c++11
+grpc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+grpc_la_LIBADD = -lgrpc++ -lgrpc -lgpr -lprotobuf
+endif
+
if BUILD_PLUGIN_HDDTEMP
pkglib_LTLIBRARIES += hddtemp.la
hddtemp_la_SOURCES = hddtemp.c
if BUILD_PLUGIN_IPC
pkglib_LTLIBRARIES += ipc.la
ipc_la_SOURCES = ipc.c
-ipc_la_CFLAGS = $(AM_CFLAGS)
ipc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
if BUILD_PLUGIN_IPVS
pkglib_LTLIBRARIES += ipvs.la
ipvs_la_SOURCES = ipvs.c
-if IP_VS_H_NEEDS_KERNEL_CFLAGS
-ipvs_la_CFLAGS = $(AM_CFLAGS) $(KERNEL_CFLAGS)
-else
ipvs_la_CFLAGS = $(AM_CFLAGS)
+if IP_VS_H_NEEDS_KERNEL_CFLAGS
+ipvs_la_CFLAGS += $(KERNEL_CFLAGS)
endif
ipvs_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
java_la_CPPFLAGS = $(AM_CPPFLAGS) $(JAVA_CPPFLAGS)
java_la_CFLAGS = $(AM_CFLAGS) $(JAVA_CFLAGS)
java_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(JAVA_LDFLAGS)
-java_la_LIBADD = $(PTHREAD_LIBS) $(JAVA_LIBS)
+java_la_LIBADD = $(JAVA_LIBS)
endif
if BUILD_PLUGIN_LOAD
if BUILD_PLUGIN_LOG_LOGSTASH
pkglib_LTLIBRARIES += log_logstash.la
log_logstash_la_SOURCES = log_logstash.c
-log_logstash_la_CFLAGS = $(AM_CFLAGS)
log_logstash_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBYAJL_LDFLAGS)
log_logstash_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBYAJL_CPPFLAGS)
log_logstash_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
if BUILD_PLUGIN_LVM
pkglib_LTLIBRARIES += lvm.la
lvm_la_SOURCES = lvm.c
-lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+lvm_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLVM2APP_CPPFLAGS)
+lvm_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLVM2APP_LDFLAGS)
lvm_la_LIBADD = $(BUILD_WITH_LIBLVM2APP_LIBS)
endif
if BUILD_PLUGIN_MYSQL
pkglib_LTLIBRARIES += mysql.la
mysql_la_SOURCES = mysql.c
+mysql_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBMYSQL_CFLAGS)
mysql_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-mysql_la_CFLAGS = $(AM_CFLAGS)
-mysql_la_LIBADD =
-if BUILD_WITH_LIBMYSQL
-mysql_la_CFLAGS += $(BUILD_WITH_LIBMYSQL_CFLAGS)
-mysql_la_LIBADD += $(BUILD_WITH_LIBMYSQL_LIBS)
-endif
+mysql_la_LIBADD = $(BUILD_WITH_LIBMYSQL_LIBS)
endif
if BUILD_PLUGIN_NETAPP
utils_fbhash.c utils_fbhash.h
network_la_CPPFLAGS = $(AM_CPPFLAGS)
network_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-network_la_LIBADD = $(PTHREAD_LIBS)
+network_la_LIBADD =
if BUILD_WITH_LIBSOCKET
network_la_LIBADD += -lsocket
endif
if BUILD_PLUGIN_NGINX
pkglib_LTLIBRARIES += nginx.la
nginx_la_SOURCES = nginx.c
-nginx_la_CFLAGS = $(AM_CFLAGS)
-nginx_la_LIBADD =
+nginx_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
nginx_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-if BUILD_WITH_LIBCURL
-nginx_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-nginx_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+nginx_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
if BUILD_PLUGIN_NOTIFY_DESKTOP
pkglib_LTLIBRARIES += notify_email.la
notify_email_la_SOURCES = notify_email.c
notify_email_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-notify_email_la_LIBADD = $(PTHREAD_LIBS) -lesmtp -lssl -lcrypto
+notify_email_la_LIBADD = -lesmtp -lssl -lcrypto
endif
if BUILD_PLUGIN_NOTIFY_NAGIOS
nut_la_SOURCES = nut.c
nut_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBUPSCLIENT_CFLAGS)
nut_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-nut_la_LIBADD = $(PTHREAD_LIBS) $(BUILD_WITH_LIBUPSCLIENT_LIBS)
+nut_la_LIBADD = $(BUILD_WITH_LIBUPSCLIENT_LIBS)
endif
if BUILD_PLUGIN_OLSRD
if BUILD_PLUGIN_ONEWIRE
pkglib_LTLIBRARIES += onewire.la
onewire_la_SOURCES = onewire.c
-onewire_la_CFLAGS = $(AM_CFLAGS)
onewire_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOWCAPI_CPPFLAGS)
onewire_la_LIBADD = $(BUILD_WITH_LIBOWCAPI_LIBS)
onewire_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBOWCAPI_LDFLAGS)
if BUILD_PLUGIN_OPENLDAP
pkglib_LTLIBRARIES += openldap.la
openldap_la_SOURCES = openldap.c
-openldap_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBLDAP_LDFLAGS)
-openldap_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBLDAP_CPPFLAGS)
+openldap_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBLDAP_LDFLAGS)
openldap_la_LIBADD = -lldap
endif
if BUILD_PLUGIN_OPENVPN
pkglib_LTLIBRARIES += openvpn.la
openvpn_la_SOURCES = openvpn.c
-openvpn_la_CFLAGS = $(AM_CFLAGS)
openvpn_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
pkglib_LTLIBRARIES += oracle.la
oracle_la_SOURCES = oracle.c \
utils_db_query.c utils_db_query.h
-oracle_la_CFLAGS = $(AM_CFLAGS)
-oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CFLAGS)
+oracle_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_ORACLE_CPPFLAGS)
oracle_la_LIBADD = $(BUILD_WITH_ORACLE_LIBS)
oracle_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
snmp_la_CFLAGS += $(BUILD_WITH_LIBSNMP_CFLAGS)
snmp_la_LIBADD += $(BUILD_WITH_LIBSNMP_LIBS)
endif
-if BUILD_WITH_LIBPTHREAD
-snmp_la_LIBADD += $(PTHREAD_LIBS)
-endif
endif
if BUILD_PLUGIN_STATSD
pkglib_LTLIBRARIES += statsd.la
statsd_la_SOURCES = statsd.c
statsd_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-statsd_la_LIBADD = $(PTHREAD_LIBS) liblatency.la -lm
+statsd_la_LIBADD = liblatency.la -lm
endif
if BUILD_PLUGIN_SWAP
utils_cmd_putnotif.h utils_cmd_putnotif.c \
utils_parse_option.h utils_parse_option.c
unixsock_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-unixsock_la_LIBADD = $(PTHREAD_LIBS)
endif
if BUILD_PLUGIN_UPTIME
pkglib_LTLIBRARIES += write_http.la
write_http_la_SOURCES = write_http.c \
utils_format_json.c utils_format_json.h
+write_http_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBCURL_CFLAGS)
write_http_la_LDFLAGS = $(PLUGIN_LDFLAGS)
-write_http_la_CFLAGS = $(AM_CFLAGS)
-write_http_la_LIBADD =
-if BUILD_WITH_LIBCURL
-write_http_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
-write_http_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
-endif
+write_http_la_LIBADD = $(BUILD_WITH_LIBCURL_LIBS)
endif
if BUILD_PLUGIN_WRITE_KAFKA
pkglib_LTLIBRARIES += write_redis.la
write_redis_la_SOURCES = write_redis.c
write_redis_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(BUILD_WITH_LIBHIREDIS_LDFLAGS)
-write_redis_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
+write_redis_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBHIREDIS_CPPFLAGS)
write_redis_la_LIBADD = -lhiredis
endif
if BUILD_PLUGIN_XENCPU
pkglib_LTLIBRARIES += xencpu.la
xencpu_la_SOURCES = xencpu.c
-xencpu_la_LDFLAGS = $(PLUGIN_LDFLAGS)
+xencpu_la_CPPFLAGS = $(AM_CPPFLAGS) $(LIBXENCTL_CPPFLAGS)
+xencpu_la_LDFLAGS = $(PLUGIN_LDFLAGS) $(LIBXENCTL_LDFLAGS)
xencpu_la_LIBADD = -lxenctrl
endif
if BUILD_PLUGIN_ZFS_ARC
pkglib_LTLIBRARIES += zfs_arc.la
zfs_arc_la_SOURCES = zfs_arc.c
-zfs_arc_la_CFLAGS = $(AM_CFLAGS)
zfs_arc_la_LDFLAGS = $(PLUGIN_LDFLAGS)
if BUILD_FREEBSD
zfs_arc_la_LIBADD = -lm
-else
-if BUILD_LINUX
-# zfs_arc requires no library on linux
-else
-# solaris
-zfs_arc_la_LIBADD = -lkstat
endif
+if BUILD_SOLARIS
+zfs_arc_la_LIBADD = -lkstat
endif
endif
if BUILD_PLUGIN_ZONE
pkglib_LTLIBRARIES += zone.la
zone_la_SOURCES = zone.c
-zone_la_CFLAGS = $(AM_CFLAGS)
zone_la_LDFLAGS = $(PLUGIN_LDFLAGS)
endif
collectd-unixsock.5 \
types.db.5
-#collectd_1_SOURCES = collectd.pod
-
-EXTRA_DIST = types.db
-
-EXTRA_DIST += collectd.conf.pod \
+EXTRA_DIST = collectd.conf.pod \
collectd-email.pod \
collectd-exec.pod \
collectdctl.pod \
collectd-threshold.pod \
collectd-unixsock.pod \
postgresql_default.conf \
- types.db.pod
+ types.db \
+ types.db.pod \
+ valgrind.FreeBSD.suppress
+
+AM_V_POD2MAN_C = $(am__v_POD2MAN_C_@AM_V@)
+am__v_POD2MAN_C_ = $(am__v_POD2MAN_C_@AM_DEFAULT_V@)
+am__v_POD2MAN_C_0 = @echo " POD2MAN " $@;
+am__v_POD2MAN_C_1 =
.pod.1:
- pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
+ $(AM_V_POD2MAN_C)pod2man --release=$(VERSION) --center=$(PACKAGE) $< \
>.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
@if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
then \
fi
.pod.5:
- pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
+ $(AM_V_POD2MAN_C)pod2man --section=5 --release=$(VERSION) --center=$(PACKAGE) $< \
>.pod2man.tmp.$$$$ 2>/dev/null && mv -f .pod2man.tmp.$$$$ $@ || true
@if grep '\<POD ERRORS\>' $@ >/dev/null 2>&1; \
then \
AM_V_PROTOC_C = $(am__v_PROTOC_C_@AM_V@)
am__v_PROTOC_C_ = $(am__v_PROTOC_C_@AM_DEFAULT_V@)
-am__v_PROTOC_C_0 = @echo " PROTOC-C " $@;
+am__v_PROTOC_C_0 = @echo " PROTOC-C" $@;
am__v_PROTOC_C_1 =
# Protocol buffer for the "pinba" plugin.
#include "collectd.h"
-#include <pthread.h>
-
#include "plugin.h"
#include "common.h"
#include "configfile.h"
#include "utils_format_json.h"
#include "utils_format_graphite.h"
-#include <pthread.h>
-
#include <amqp.h>
#include <amqp_framing.h>
if ((fd == NULL) || (*fd < 0))
return (EINVAL);
- swrite (*fd, (void *) &packet_size, sizeof (packet_size));
+ (void)swrite (*fd, (void *) &packet_size, sizeof (packet_size));
close (*fd);
*fd = -1;
CHECK_ZERO (yajl_parse_complete (hndl));
#endif
+ yajl_free (hndl);
return 0;
}
--- /dev/null
+/* chrony plugin for collectd (monitoring of chrony time server daemon)
+ **********************************************************************
+ * Copyright (C) Claudius M Zingerli, ZSeng, 2015-2016
+ *
+ * Internals roughly based on the ntpd plugin
+ * Some functions copied from chronyd/web (as marked)
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * 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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * TODO:
+ * - More robust udp parsing (using offsets instead of structs?)
+ * -> Currently chrony parses its data the same way as we do (using structs)
+ * - Plausibility checks on values received
+ * -> Done at higher levels
+ */
+
+#include "collectd.h"
+#include "common.h" /* auxiliary functions */
+#include "plugin.h" /* plugin_register_*, plugin_dispatch_values */
+
+#if HAVE_NETDB_H
+# include <netdb.h> /* struct addrinfo */
+#endif
+#if HAVE_ARPA_INET_H
+# include <arpa/inet.h> /* ntohs/ntohl */
+#endif
+
+
+#define CONFIG_KEY_HOST "Host"
+#define CONFIG_KEY_PORT "Port"
+#define CONFIG_KEY_TIMEOUT "Timeout"
+
+#define URAND_DEVICE_PATH "/dev/urandom" /* Used to initialize seq nr generator */
+#define RAND_DEVICE_PATH "/dev/random" /* Used to initialize seq nr generator (fall back) */
+
+static const char *g_config_keys[] = {
+ CONFIG_KEY_HOST,
+ CONFIG_KEY_PORT,
+ CONFIG_KEY_TIMEOUT
+};
+
+static int g_config_keys_num = STATIC_ARRAY_SIZE(g_config_keys);
+static int g_chrony_is_connected;
+static int g_chrony_socket = -1;
+static time_t g_chrony_timeout = -1;
+static char *g_chrony_plugin_instance;
+static char *g_chrony_host;
+static char *g_chrony_port;
+static uint32_t g_chrony_rand = 1;
+static uint32_t g_chrony_seq_is_initialized;
+
+#define PLUGIN_NAME_SHORT "chrony"
+#define PLUGIN_NAME PLUGIN_NAME_SHORT " plugin"
+#define DAEMON_NAME PLUGIN_NAME_SHORT
+#define CHRONY_DEFAULT_HOST "localhost"
+#define CHRONY_DEFAULT_PORT "323"
+#define CHRONY_DEFAULT_TIMEOUT 2
+
+/* Return codes (collectd expects non-zero on errors) */
+#define CHRONY_RC_OK 0
+#define CHRONY_RC_FAIL 1
+
+/* Chronyd command packet variables adapted from chrony/candm.h (GPL2) */
+#define PROTO_VERSION_NUMBER 6
+#define IPADDR_UNSPEC 0
+#define IPADDR_INET4 1
+#define IPADDR_INET6 2
+#define IPV6_STR_MAX_SIZE (8*4+7+1)
+
+typedef enum
+{
+ PKT_TYPE_CMD_REQUEST = 1,
+ PKT_TYPE_CMD_REPLY = 2
+} ePacketType;
+
+typedef enum
+{
+ REQ_N_SOURCES = 14,
+ REQ_SOURCE_DATA = 15,
+ REQ_TRACKING = 33,
+ REQ_SOURCE_STATS = 34
+} eDaemonRequests;
+
+
+typedef enum
+{
+ RPY_NULL = 1,
+ RPY_N_SOURCES = 2,
+ RPY_SOURCE_DATA = 3,
+ RPY_MANUAL_TIMESTAMP = 4,
+ RPY_TRACKING = 5,
+ RPY_SOURCE_STATS = 6,
+ RPY_RTC = 7
+} eDaemonReplies;
+
+
+#if defined(__GNUC__)
+# /* GNU gcc extension to enforce struct packing. */
+# define ATTRIB_PACKED __attribute__((packed))
+#else
+# error Not defining packed attribute (unknown compiler)
+# define ATTRIB_PACKED
+#endif
+
+typedef struct ATTRIB_PACKED
+{
+ int32_t value;
+} tFloat;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t tv_sec_high;
+ uint32_t tv_sec_low;
+ uint32_t tv_nsec;
+} tTimeval;
+
+typedef enum
+{
+ STT_SUCCESS = 0,
+ STT_FAILED = 1,
+ STT_UNAUTH = 2,
+ STT_INVALID = 3,
+ STT_NOSUCHSOURCE = 4,
+ STT_INVALIDTS = 5,
+ STT_NOTENABLED = 6,
+ STT_BADSUBNET = 7,
+ STT_ACCESSALLOWED = 8,
+ STT_ACCESSDENIED = 9,
+ STT_NOHOSTACCESS = 10,
+ STT_SOURCEALREADYKNOWN = 11,
+ STT_TOOMANYSOURCES = 12,
+ STT_NORTC = 13,
+ STT_BADRTCFILE = 14,
+ STT_INACTIVE = 15,
+ STT_BADSAMPLE = 16,
+ STT_INVALIDAF = 17,
+ STT_BADPKTVERSION = 18,
+ STT_BADPKTLENGTH = 19
+} eChrony_Status;
+
+/* Chrony client request packets */
+typedef struct ATTRIB_PACKED
+{
+ uint8_t f_dummy0[80]; /* Chrony expects 80bytes dummy data (Avoiding UDP Amplification) */
+} tChrony_Req_Tracking;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_n_sources;
+} tChrony_Req_N_Sources;
+
+typedef struct ATTRIB_PACKED
+{
+ int32_t f_index;
+ uint8_t f_dummy0[44];
+} tChrony_Req_Source_data;
+
+typedef struct ATTRIB_PACKED
+{
+ int32_t f_index;
+ uint8_t f_dummy0[56];
+} tChrony_Req_Source_stats;
+
+typedef struct ATTRIB_PACKED
+{
+ struct
+ {
+ uint8_t f_version;
+ uint8_t f_type;
+ uint8_t f_dummy0;
+ uint8_t f_dummy1;
+ uint16_t f_cmd;
+ uint16_t f_cmd_try;
+ uint32_t f_seq;
+
+ uint32_t f_dummy2;
+ uint32_t f_dummy3;
+ } header; /* Packed: 20Bytes */
+ union
+ {
+ tChrony_Req_N_Sources n_sources;
+ tChrony_Req_Source_data source_data;
+ tChrony_Req_Source_stats source_stats;
+ tChrony_Req_Tracking tracking;
+ } body;
+ uint8_t padding[4 + 16]; /* Padding to match minimal response size */
+} tChrony_Request;
+
+/* Chrony daemon response packets */
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_n_sources;
+} tChrony_Resp_N_Sources;
+
+typedef struct ATTRIB_PACKED
+{
+ union
+ {
+ uint32_t ip4;
+ uint8_t ip6[16];
+ } addr;
+ uint16_t f_family;
+} tChrony_IPAddr;
+
+typedef struct ATTRIB_PACKED
+{
+ tChrony_IPAddr addr;
+ uint16_t dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+ int16_t f_poll; /* 2^f_poll = Time between polls (s) */
+ uint16_t f_stratum; /* Remote clock stratum */
+ uint16_t f_state; /* 0 = RPY_SD_ST_SYNC, 1 = RPY_SD_ST_UNREACH, 2 = RPY_SD_ST_FALSETICKER */
+ /* 3 = RPY_SD_ST_JITTERY, 4 = RPY_SD_ST_CANDIDATE, 5 = RPY_SD_ST_OUTLIER */
+ uint16_t f_mode; /* 0 = RPY_SD_MD_CLIENT, 1 = RPY_SD_MD_PEER, 2 = RPY_SD_MD_REF */
+ uint16_t f_flags; /* unused */
+ uint16_t f_reachability; /* Bit mask of successfull tries to reach the source */
+
+ uint32_t f_since_sample; /* Time since last sample (s) */
+ tFloat f_origin_latest_meas; /* */
+ tFloat f_latest_meas; /* */
+ tFloat f_latest_meas_err; /* */
+} tChrony_Resp_Source_data;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_ref_id;
+ tChrony_IPAddr addr;
+ uint16_t dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+ uint32_t f_n_samples; /* Number of measurements done */
+ uint32_t f_n_runs; /* How many measurements to come */
+ uint32_t f_span_seconds; /* For how long we're measuring */
+ tFloat f_rtc_seconds_fast; /* ??? */
+ tFloat f_rtc_gain_rate_ppm; /* Estimated relative frequency error */
+ tFloat f_skew_ppm; /* Clock skew (ppm) (worst case freq est error (skew: peak2peak)) */
+ tFloat f_est_offset; /* Estimated offset of source */
+ tFloat f_est_offset_err; /* Error of estimation */
+} tChrony_Resp_Source_stats;
+
+typedef struct ATTRIB_PACKED
+{
+ uint32_t f_ref_id;
+ tChrony_IPAddr addr;
+ uint16_t dummy; /* FIXME: Strange dummy space. Needed on gcc 4.8.3/clang 3.4.1 on x86_64 */
+ uint16_t f_stratum;
+ uint16_t f_leap_status;
+ tTimeval f_ref_time;
+ tFloat f_current_correction;
+ tFloat f_last_offset;
+ tFloat f_rms_offset;
+ tFloat f_freq_ppm;
+ tFloat f_resid_freq_ppm;
+ tFloat f_skew_ppm;
+ tFloat f_root_delay;
+ tFloat f_root_dispersion;
+ tFloat f_last_update_interval;
+} tChrony_Resp_Tracking;
+
+typedef struct ATTRIB_PACKED
+{
+ struct
+ {
+ uint8_t f_version;
+ uint8_t f_type;
+ uint8_t f_dummy0;
+ uint8_t f_dummy1;
+ uint16_t f_cmd;
+ uint16_t f_reply;
+ uint16_t f_status;
+ uint16_t f_dummy2;
+ uint16_t f_dummy3;
+ uint16_t f_dummy4;
+ uint32_t f_seq;
+ uint32_t f_dummy5;
+ uint32_t f_dummy6;
+ } header; /* Packed: 28 Bytes */
+
+ union
+ {
+ tChrony_Resp_N_Sources n_sources;
+ tChrony_Resp_Source_data source_data;
+ tChrony_Resp_Source_stats source_stats;
+ tChrony_Resp_Tracking tracking;
+ } body;
+
+ uint8_t padding[1024];
+} tChrony_Response;
+
+
+/*****************************************************************************/
+/* Internal functions */
+/*****************************************************************************/
+
+/* connect_client code adapted from: http://long.ccaba.upc.edu/long/045Guidelines/eva/ipv6.html#daytimeClient6 */
+/* License granted by Eva M Castro via e-mail on 2016-02-18 under the terms of GPLv3 */
+static int
+connect_client(const char *p_hostname,
+ const char *p_service, int p_family, int p_socktype)
+{
+ struct addrinfo hints, *res = NULL, *ressave = NULL;
+ int n, sockfd;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+
+ hints.ai_family = p_family;
+ hints.ai_socktype = p_socktype;
+
+ n = getaddrinfo(p_hostname, p_service, &hints, &res);
+
+ if (n < 0)
+ {
+ ERROR(PLUGIN_NAME ": getaddrinfo error:: [%s]", gai_strerror(n));
+ return -1;
+ }
+
+ ressave = res;
+
+ sockfd = -1;
+ while (res)
+ {
+ sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+
+ if (!(sockfd < 0))
+ {
+ if (connect(sockfd, res->ai_addr, res->ai_addrlen) == 0)
+ {
+ /* Success */
+ break;
+ }
+
+ close(sockfd);
+ sockfd = -1;
+ }
+ res = res->ai_next;
+ }
+
+ freeaddrinfo(ressave);
+ return sockfd;
+}
+
+
+/* niptoha code originally from: git://git.tuxfamily.org/gitroot/chrony/chrony.git:util.c */
+/* Original code licensed as GPLv2, by Richard P. Purnow, Miroslav Lichvar */
+/* Original name: char * UTI_IPToString(IPAddr *addr)*/
+static char *
+niptoha(const tChrony_IPAddr * addr, char *p_buf, size_t p_buf_size)
+{
+ int rc = 1;
+ unsigned long a, b, c, d, ip;
+
+ switch (ntohs(addr->f_family))
+ {
+ case IPADDR_UNSPEC:
+ rc = snprintf(p_buf, p_buf_size, "[UNSPEC]");
+ break;
+ case IPADDR_INET4:
+ ip = ntohl(addr->addr.ip4);
+ a = (ip >> 24) & 0xff;
+ b = (ip >> 16) & 0xff;
+ c = (ip >> 8) & 0xff;
+ d = (ip >> 0) & 0xff;
+ rc = snprintf(p_buf, p_buf_size, "%ld.%ld.%ld.%ld", a, b, c, d);
+ break;
+ case IPADDR_INET6:
+ {
+ const char *rp = inet_ntop(AF_INET6, addr->addr.ip6, p_buf, p_buf_size);
+ if (rp == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error converting ipv6 address to string. Errno = %d", errno);
+ rc = snprintf(p_buf, p_buf_size, "[UNKNOWN]");
+ }
+ break;
+ }
+ default:
+ rc = snprintf(p_buf, p_buf_size, "[UNKNOWN]");
+ }
+ assert(rc > 0);
+ return p_buf;
+}
+
+
+static int
+chrony_set_timeout(void)
+{
+ /* Set the socket's timeout to g_chrony_timeout; a value of 0 signals infinite timeout */
+ /* Returns 0 on success, !0 on error (check errno) */
+
+ struct timeval tv;
+ tv.tv_sec = g_chrony_timeout;
+ tv.tv_usec = 0;
+
+ assert(g_chrony_socket >= 0);
+ if (setsockopt(g_chrony_socket, SOL_SOCKET,
+ SO_RCVTIMEO, (char *) &tv, sizeof(struct timeval)) < 0)
+ {
+ return CHRONY_RC_FAIL;
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_connect(void)
+{
+ /* Connects to the chrony daemon */
+ /* Returns 0 on success, !0 on error (check errno) */
+ int socket;
+
+ if (g_chrony_host == NULL)
+ {
+ g_chrony_host = strdup(CHRONY_DEFAULT_HOST);
+ if (g_chrony_host == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating chrony host name");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ if (g_chrony_port == NULL)
+ {
+ g_chrony_port = strdup(CHRONY_DEFAULT_PORT);
+ if (g_chrony_port == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating chrony port string");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ if (g_chrony_timeout < 0)
+ {
+ g_chrony_timeout = CHRONY_DEFAULT_TIMEOUT;
+ assert(g_chrony_timeout >= 0);
+ }
+
+ DEBUG(PLUGIN_NAME ": Connecting to %s:%s", g_chrony_host, g_chrony_port);
+ socket = connect_client(g_chrony_host, g_chrony_port, AF_UNSPEC, SOCK_DGRAM);
+ if (socket < 0)
+ {
+ ERROR(PLUGIN_NAME ": Error connecting to daemon. Errno = %d", errno);
+ return CHRONY_RC_FAIL;
+ }
+ DEBUG(PLUGIN_NAME ": Connected");
+ g_chrony_socket = socket;
+
+ if (chrony_set_timeout())
+ {
+ ERROR(PLUGIN_NAME ": Error setting timeout to %lds. Errno = %d",
+ g_chrony_timeout, errno);
+ return CHRONY_RC_FAIL;
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_send_request(const tChrony_Request * p_req, size_t p_req_size)
+{
+ if (send(g_chrony_socket, p_req, p_req_size, 0) < 0)
+ {
+ ERROR(PLUGIN_NAME ": Error sending packet. Errno = %d", errno);
+ return CHRONY_RC_FAIL;
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_recv_response(tChrony_Response * p_resp, size_t p_resp_max_size,
+ size_t * p_resp_size)
+{
+ ssize_t rc = recv(g_chrony_socket, p_resp, p_resp_max_size, 0);
+ if (rc <= 0)
+ {
+ ERROR(PLUGIN_NAME ": Error receiving packet: %s (%d)", strerror(errno),
+ errno);
+ return CHRONY_RC_FAIL;
+ }
+ else
+ {
+ *p_resp_size = rc;
+ return CHRONY_RC_OK;
+ }
+}
+
+
+static int
+chrony_query(const int p_command, tChrony_Request * p_req,
+ tChrony_Response * p_resp, size_t * p_resp_size)
+{
+ /* Check connection. We simply perform one try as collectd already handles retries */
+ assert(p_req);
+ assert(p_resp);
+ assert(p_resp_size);
+
+ if (g_chrony_is_connected == 0)
+ {
+ if (chrony_connect() == CHRONY_RC_OK)
+ {
+ g_chrony_is_connected = 1;
+ }
+ else
+ {
+ ERROR(PLUGIN_NAME ": Unable to connect. Errno = %d", errno);
+ return CHRONY_RC_FAIL;
+ }
+ }
+
+ do
+ {
+ int valid_command = 0;
+ size_t req_size = sizeof(p_req->header) + sizeof(p_req->padding);
+ size_t resp_size = sizeof(p_resp->header);
+ uint16_t resp_code = RPY_NULL;
+ switch (p_command)
+ {
+ case REQ_TRACKING:
+ req_size += sizeof(p_req->body.tracking);
+ resp_size += sizeof(p_resp->body.tracking);
+ resp_code = RPY_TRACKING;
+ valid_command = 1;
+ break;
+ case REQ_N_SOURCES:
+ req_size += sizeof(p_req->body.n_sources);
+ resp_size += sizeof(p_resp->body.n_sources);
+ resp_code = RPY_N_SOURCES;
+ valid_command = 1;
+ break;
+ case REQ_SOURCE_DATA:
+ req_size += sizeof(p_req->body.source_data);
+ resp_size += sizeof(p_resp->body.source_data);
+ resp_code = RPY_SOURCE_DATA;
+ valid_command = 1;
+ break;
+ case REQ_SOURCE_STATS:
+ req_size += sizeof(p_req->body.source_stats);
+ resp_size += sizeof(p_resp->body.source_stats);
+ resp_code = RPY_SOURCE_STATS;
+ valid_command = 1;
+ break;
+ default:
+ ERROR(PLUGIN_NAME ": Unknown request command (Was: %d)", p_command);
+ break;
+ }
+
+ if (valid_command == 0)
+ break;
+
+ uint32_t seq_nr = rand_r(&g_chrony_rand);
+ p_req->header.f_cmd = htons(p_command);
+ p_req->header.f_cmd_try = 0;
+ p_req->header.f_seq = seq_nr;
+
+ DEBUG(PLUGIN_NAME ": Sending request (.cmd = %d, .seq = %d)", p_command,
+ seq_nr);
+ if (chrony_send_request(p_req, req_size) != 0)
+ break;
+
+ DEBUG(PLUGIN_NAME ": Waiting for response");
+ if (chrony_recv_response(p_resp, resp_size, p_resp_size) != 0)
+ break;
+
+ DEBUG(PLUGIN_NAME
+ ": Received response: .version = %u, .type = %u, .cmd = %u, .reply = %u, .status = %u, .seq = %u",
+ p_resp->header.f_version, p_resp->header.f_type,
+ ntohs(p_resp->header.f_cmd), ntohs(p_resp->header.f_reply),
+ ntohs(p_resp->header.f_status), p_resp->header.f_seq);
+
+ if (p_resp->header.f_version != p_req->header.f_version)
+ {
+ ERROR(PLUGIN_NAME ": Wrong protocol version (Was: %d, expected: %d)",
+ p_resp->header.f_version, p_req->header.f_version);
+ return CHRONY_RC_FAIL;
+ }
+ if (p_resp->header.f_type != PKT_TYPE_CMD_REPLY)
+ {
+ ERROR(PLUGIN_NAME ": Wrong packet type (Was: %d, expected: %d)",
+ p_resp->header.f_type, PKT_TYPE_CMD_REPLY);
+ return CHRONY_RC_FAIL;
+ }
+ if (p_resp->header.f_seq != seq_nr)
+ {
+ /* FIXME: Implement sequence number handling */
+ ERROR(PLUGIN_NAME
+ ": Unexpected sequence number (Was: %d, expected: %d)",
+ p_resp->header.f_seq, p_req->header.f_seq);
+ return CHRONY_RC_FAIL;
+ }
+ if (p_resp->header.f_cmd != p_req->header.f_cmd)
+ {
+ ERROR(PLUGIN_NAME ": Wrong reply command (Was: %d, expected: %d)",
+ p_resp->header.f_cmd, p_req->header.f_cmd);
+ return CHRONY_RC_FAIL;
+ }
+
+ if (ntohs(p_resp->header.f_reply) != resp_code)
+ {
+ ERROR(PLUGIN_NAME ": Wrong reply code (Was: %d, expected: %d)",
+ ntohs(p_resp->header.f_reply), resp_code);
+ return CHRONY_RC_FAIL;
+ }
+
+ switch (p_resp->header.f_status)
+ {
+ case STT_SUCCESS:
+ DEBUG(PLUGIN_NAME ": Reply packet status STT_SUCCESS");
+ break;
+ default:
+ ERROR(PLUGIN_NAME
+ ": Reply packet contains error status: %d (expected: %d)",
+ p_resp->header.f_status, STT_SUCCESS);
+ return CHRONY_RC_FAIL;
+ }
+
+ /* Good result */
+ return CHRONY_RC_OK;
+ }
+ while (0);
+
+ /* Some error occured */
+ return CHRONY_RC_FAIL;
+}
+
+
+static void
+chrony_init_req(tChrony_Request * p_req)
+{
+ memset(p_req, 0, sizeof(*p_req));
+ p_req->header.f_version = PROTO_VERSION_NUMBER;
+ p_req->header.f_type = PKT_TYPE_CMD_REQUEST;
+ p_req->header.f_dummy0 = 0;
+ p_req->header.f_dummy1 = 0;
+ p_req->header.f_dummy2 = 0;
+ p_req->header.f_dummy3 = 0;
+}
+
+
+/* ntohf code originally from: git://git.tuxfamily.org/gitroot/chrony/chrony.git:util.c */
+/* Original code licensed as GPLv2, by Richard P. Purnow, Miroslav Lichvar */
+/* Original name: double UTI_tFloatNetworkToHost(tFloat f) */
+static double
+ntohf(tFloat p_float)
+{
+ /* Convert tFloat in Network-bit-order to double in host-bit-order */
+
+#define FLOAT_EXP_BITS 7
+#define FLOAT_EXP_MIN (-(1 << (FLOAT_EXP_BITS - 1)))
+#define FLOAT_EXP_MAX (-FLOAT_EXP_MIN - 1)
+#define FLOAT_COEF_BITS ((int)sizeof (int32_t) * 8 - FLOAT_EXP_BITS)
+#define FLOAT_COEF_MIN (-(1 << (FLOAT_COEF_BITS - 1)))
+#define FLOAT_COEF_MAX (-FLOAT_COEF_MIN - 1)
+
+ int32_t exp, coef;
+ uint32_t uval;
+
+ uval = ntohl(p_float.value);
+ exp = (uval >> FLOAT_COEF_BITS) - FLOAT_COEF_BITS;
+ if (exp >= 1 << (FLOAT_EXP_BITS - 1))
+ exp -= 1 << FLOAT_EXP_BITS;
+
+ /* coef = (x << FLOAT_EXP_BITS) >> FLOAT_EXP_BITS; */
+ coef = uval % (1U << FLOAT_COEF_BITS);
+ if (coef >= 1 << (FLOAT_COEF_BITS - 1))
+ coef -= 1 << FLOAT_COEF_BITS;
+
+ return coef * pow(2.0, exp);
+}
+
+
+static void
+chrony_push_data(const char *p_type, const char *p_type_inst, double p_value)
+{
+ value_t values[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ values[0].gauge = p_value; /* TODO: Check type??? (counter, gauge, derive, absolute) */
+
+ vl.values = values;
+ vl.values_len = 1;
+
+ /* XXX: Shall g_chrony_host/g_chrony_port be reflected in the plugin's output? */
+ /* hostname_g is set in daemon/collectd.c (from config, via gethostname or by resolving localhost) */
+ /* defined as: char hostname_g[DATA_MAX_NAME_LEN]; (never NULL) */
+ sstrncpy(vl.host, hostname_g, sizeof(vl.host));
+ sstrncpy(vl.plugin, PLUGIN_NAME_SHORT, sizeof(vl.plugin));
+ if (g_chrony_plugin_instance != NULL)
+ {
+ sstrncpy(vl.plugin_instance, g_chrony_plugin_instance,
+ sizeof(vl.plugin_instance));
+ }
+ if (p_type != NULL)
+ sstrncpy(vl.type, p_type, sizeof(vl.type));
+
+ if (p_type_inst != NULL)
+ sstrncpy(vl.type_instance, p_type_inst, sizeof(vl.type_instance));
+
+ plugin_dispatch_values(&vl);
+}
+
+
+static void
+chrony_push_data_valid(const char *p_type, const char *p_type_inst, const int p_is_valid,
+ double p_value)
+{
+ /* Push real value if p_is_valid is true, push NAN if p_is_valid is not true (idea from ntp plugin) */
+ if (p_is_valid == 0)
+ p_value = NAN;
+
+ chrony_push_data(p_type, p_type_inst, p_value);
+}
+
+
+static int
+chrony_init_seq(void)
+{
+ /* Initialize the sequence number generator from /dev/urandom */
+ /* Fallbacks: /dev/random and time(NULL) */
+
+ int fh;
+
+ /* Try urandom */
+ fh = open(URAND_DEVICE_PATH, O_RDONLY);
+ if (fh >= 0)
+ {
+ ssize_t rc = read(fh, &g_chrony_rand, sizeof(g_chrony_rand));
+ if (rc != sizeof(g_chrony_rand))
+ {
+ ERROR(PLUGIN_NAME ": Reading from random source \'%s\'failed: %s (%d)",
+ URAND_DEVICE_PATH, strerror(errno), errno);
+ close(fh);
+ return CHRONY_RC_FAIL;
+ }
+ close(fh);
+ DEBUG(PLUGIN_NAME ": Seeding RNG from " URAND_DEVICE_PATH);
+ }
+ else
+ {
+ if (errno == ENOENT)
+ {
+ /* URAND_DEVICE_PATH device not found. Try RAND_DEVICE_PATH as fall-back */
+ fh = open(RAND_DEVICE_PATH, O_RDONLY);
+ if (fh >= 0)
+ {
+ ssize_t rc = read(fh, &g_chrony_rand, sizeof(g_chrony_rand));
+ if (rc != sizeof(g_chrony_rand))
+ {
+ ERROR(PLUGIN_NAME
+ ": Reading from random source \'%s\'failed: %s (%d)",
+ RAND_DEVICE_PATH, strerror(errno), errno);
+ close(fh);
+ return CHRONY_RC_FAIL;
+ }
+ close(fh);
+ DEBUG(PLUGIN_NAME ": Seeding RNG from " RAND_DEVICE_PATH);
+ }
+ else
+ {
+ /* Error opening RAND_DEVICE_PATH. Try time(NULL) as fall-back */
+ DEBUG(PLUGIN_NAME ": Seeding RNG from time(NULL)");
+ g_chrony_rand = time(NULL) ^ getpid();
+ }
+ }
+ else
+ {
+ ERROR(PLUGIN_NAME ": Opening random source \'%s\' failed: %s (%d)",
+ URAND_DEVICE_PATH, strerror(errno), errno);
+ return CHRONY_RC_FAIL;
+ }
+ }
+
+ return CHRONY_RC_OK;
+}
+
+
+/*****************************************************************************/
+/* Exported functions */
+/*****************************************************************************/
+static int
+chrony_config(const char *p_key, const char *p_value)
+{
+ assert(p_key);
+ assert(p_value);
+
+ /* Parse config variables */
+ if (strcasecmp(p_key, CONFIG_KEY_HOST) == 0)
+ {
+ if (g_chrony_host != NULL)
+ free(g_chrony_host);
+
+ if ((g_chrony_host = strdup(p_value)) == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating host name");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ else
+ {
+ if (strcasecmp(p_key, CONFIG_KEY_PORT) == 0)
+ {
+ if (g_chrony_port != NULL)
+ free(g_chrony_port);
+
+ if ((g_chrony_port = strdup(p_value)) == NULL)
+ {
+ ERROR(PLUGIN_NAME ": Error duplicating port name");
+ return CHRONY_RC_FAIL;
+ }
+ }
+ else
+ {
+ if (strcasecmp(p_key, CONFIG_KEY_TIMEOUT) == 0)
+ {
+ time_t tosec = strtol(p_value, NULL, 0);
+ g_chrony_timeout = tosec;
+ }
+ else
+ {
+ WARNING(PLUGIN_NAME ": Unknown configuration variable: %s %s", p_key, p_value);
+ return CHRONY_RC_FAIL;
+ }
+ }
+ }
+ /* XXX: We could set g_chrony_plugin_instance here to "g_chrony_host-g_chrony_port", but as multiple instances aren't yet supported, we skip this for now */
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_daemon_stats(void)
+{
+ /* Perform Tracking request */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+
+ chrony_init_req(&chrony_req);
+ rc =
+ chrony_query(REQ_TRACKING, &chrony_req, &chrony_resp, &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME ": chrony_query (REQ_TRACKING) failed with status %i",
+ rc);
+ return rc;
+ }
+#if COLLECT_DEBUG
+ {
+ char src_addr[IPV6_STR_MAX_SIZE];
+ memset(src_addr, 0, sizeof(src_addr));
+ niptoha(&chrony_resp.body.tracking.addr, src_addr, sizeof(src_addr));
+ DEBUG(PLUGIN_NAME ": Daemon stat: .addr = %s, .ref_id= %u, .stratum = %u, .leap_status = %u, .ref_time = %u:%u:%u, .current_correction = %f, .last_offset = %f, .rms_offset = %f, .freq_ppm = %f, .skew_ppm = %f, .root_delay = %f, .root_dispersion = %f, .last_update_interval = %f", src_addr, ntohs(chrony_resp.body.tracking.f_ref_id),
+ ntohs(chrony_resp.body.tracking.f_stratum),
+ ntohs(chrony_resp.body.tracking.f_leap_status),
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_high),
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_low),
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_nsec),
+ ntohf(chrony_resp.body.tracking.f_current_correction),
+ ntohf(chrony_resp.body.tracking.f_last_offset),
+ ntohf(chrony_resp.body.tracking.f_rms_offset),
+ ntohf(chrony_resp.body.tracking.f_freq_ppm),
+ ntohf(chrony_resp.body.tracking.f_skew_ppm),
+ ntohf(chrony_resp.body.tracking.f_root_delay),
+ ntohf(chrony_resp.body.tracking.f_root_dispersion),
+ ntohf(chrony_resp.body.tracking.f_last_update_interval));
+ }
+#endif
+
+ double time_ref = ntohl(chrony_resp.body.tracking.f_ref_time.tv_nsec);
+ time_ref /= 1000000000.0;
+ time_ref += ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_low);
+ if (chrony_resp.body.tracking.f_ref_time.tv_sec_high)
+ {
+ double secs_high =
+ ntohl(chrony_resp.body.tracking.f_ref_time.tv_sec_high);
+ secs_high *= 4294967296.0;
+ time_ref += secs_high;
+ }
+
+ /* Forward results to collectd-daemon */
+ /* Type_instance is always 'chrony' to tag daemon-wide data */
+ /* Type Type_instan Value */
+ chrony_push_data("clock_stratum", DAEMON_NAME, ntohs(chrony_resp.body.tracking.f_stratum));
+ chrony_push_data("time_ref", DAEMON_NAME, time_ref); /* unit: s */
+ chrony_push_data("time_offset_ntp", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_current_correction)); /* Offset between system time and NTP, unit: s */
+ chrony_push_data("time_offset", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_last_offset)); /* Estimated Offset of the NTP time, unit: s */
+ chrony_push_data("time_offset_rms", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_rms_offset)); /* averaged value of the above, unit: s */
+ chrony_push_data("frequency_error", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_freq_ppm)); /* Frequency error of the local osc, unit: ppm */
+ chrony_push_data("clock_skew_ppm", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_skew_ppm));
+ chrony_push_data("root_delay", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_root_delay)); /* Network latency between local daemon and the current source */
+ chrony_push_data("root_dispersion", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_root_dispersion));
+ chrony_push_data("clock_last_update", DAEMON_NAME, ntohf(chrony_resp.body.tracking.f_last_update_interval));
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_sources_count(unsigned int *p_count)
+{
+ /* Requests the number of time sources from the chrony daemon */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+
+ DEBUG(PLUGIN_NAME ": Requesting data");
+ chrony_init_req(&chrony_req);
+ rc =
+ chrony_query(REQ_N_SOURCES, &chrony_req, &chrony_resp, &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME ": chrony_query (REQ_N_SOURCES) failed with status %i",
+ rc);
+ return rc;
+ }
+
+ *p_count = ntohl(chrony_resp.body.n_sources.f_n_sources);
+ DEBUG(PLUGIN_NAME ": Getting data of %d clock sources", *p_count);
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_source_data(int p_src_idx, int *p_is_reachable)
+{
+ /* Perform Source data request for source #p_src_idx */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+
+ char src_addr[IPV6_STR_MAX_SIZE];
+ memset(src_addr, 0, sizeof(src_addr));
+
+ chrony_init_req(&chrony_req);
+ chrony_req.body.source_data.f_index = htonl(p_src_idx);
+ rc =
+ chrony_query(REQ_SOURCE_DATA, &chrony_req, &chrony_resp,
+ &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME
+ ": chrony_query (REQ_SOURCE_DATA) failed with status %i", rc);
+ return rc;
+ }
+
+ niptoha(&chrony_resp.body.source_data.addr, src_addr, sizeof(src_addr));
+ DEBUG(PLUGIN_NAME
+ ": Source[%d] data: .addr = %s, .poll = %u, .stratum = %u, .state = %u, .mode = %u, .flags = %u, .reach = %u, .latest_meas_ago = %u, .orig_latest_meas = %f, .latest_meas = %f, .latest_meas_err = %f",
+ p_src_idx, src_addr, ntohs(chrony_resp.body.source_data.f_poll),
+ ntohs(chrony_resp.body.source_data.f_stratum),
+ ntohs(chrony_resp.body.source_data.f_state),
+ ntohs(chrony_resp.body.source_data.f_mode),
+ ntohs(chrony_resp.body.source_data.f_flags),
+ ntohs(chrony_resp.body.source_data.f_reachability),
+ ntohl(chrony_resp.body.source_data.f_since_sample),
+ ntohf(chrony_resp.body.source_data.f_origin_latest_meas),
+ ntohf(chrony_resp.body.source_data.f_latest_meas),
+ ntohf(chrony_resp.body.source_data.f_latest_meas_err));
+
+ /* Push NaN if source is currently not reachable */
+ int is_reachable =
+ ntohs(chrony_resp.body.source_data.f_reachability) & 0x01;
+ *p_is_reachable = is_reachable;
+
+ /* Forward results to collectd-daemon */
+ chrony_push_data_valid("clock_stratum", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_stratum));
+ chrony_push_data_valid("clock_state", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_state));
+ chrony_push_data_valid("clock_mode", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_mode));
+ chrony_push_data_valid("clock_reachability", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_reachability));
+ chrony_push_data_valid("clock_last_meas", src_addr, is_reachable,
+ ntohs(chrony_resp.body.source_data.f_since_sample));
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_request_source_stats(int p_src_idx, const int *p_is_reachable)
+{
+ /* Perform Source stats request for source #p_src_idx */
+ int rc;
+ size_t chrony_resp_size;
+ tChrony_Request chrony_req;
+ tChrony_Response chrony_resp;
+ double skew_ppm, frequency_error, time_offset;
+
+ char src_addr[IPV6_STR_MAX_SIZE];
+ memset(src_addr, 0, sizeof(src_addr));
+
+ if (*p_is_reachable == 0)
+ {
+ skew_ppm = 0;
+ frequency_error = 0;
+ time_offset = 0;
+ }
+ else
+ {
+ chrony_init_req(&chrony_req);
+ chrony_req.body.source_stats.f_index = htonl(p_src_idx);
+ rc =
+ chrony_query(REQ_SOURCE_STATS, &chrony_req, &chrony_resp,
+ &chrony_resp_size);
+ if (rc != 0)
+ {
+ ERROR(PLUGIN_NAME
+ ": chrony_query (REQ_SOURCE_STATS) failed with status %i", rc);
+ return rc;
+ }
+
+ skew_ppm = ntohf(chrony_resp.body.source_stats.f_skew_ppm);
+ frequency_error =
+ ntohf(chrony_resp.body.source_stats.f_rtc_gain_rate_ppm);
+ time_offset = ntohf(chrony_resp.body.source_stats.f_est_offset);
+
+ niptoha(&chrony_resp.body.source_stats.addr, src_addr, sizeof(src_addr));
+ DEBUG(PLUGIN_NAME
+ ": Source[%d] stat: .addr = %s, .ref_id= %u, .n_samples = %u, "
+ ".n_runs = %u, .span_seconds = %u, .rtc_seconds_fast = %f, "
+ ".rtc_gain_rate_ppm = %f, .skew_ppm= %f, .est_offset = %f, .est_offset_err = %f",
+ p_src_idx, src_addr,
+ ntohl(chrony_resp.body.source_stats.f_ref_id),
+ ntohl(chrony_resp.body.source_stats.f_n_samples),
+ ntohl(chrony_resp.body.source_stats.f_n_runs),
+ ntohl(chrony_resp.body.source_stats.f_span_seconds),
+ ntohf(chrony_resp.body.source_stats.f_rtc_seconds_fast),
+ frequency_error, skew_ppm, time_offset,
+ ntohf(chrony_resp.body.source_stats.f_est_offset_err));
+
+ } /* if (*is_reachable) */
+
+ /* Forward results to collectd-daemon */
+ chrony_push_data_valid("clock_skew_ppm", src_addr, *p_is_reachable, skew_ppm);
+ chrony_push_data_valid("frequency_error", src_addr, *p_is_reachable, frequency_error); /* unit: ppm */
+ chrony_push_data_valid("time_offset", src_addr, *p_is_reachable, time_offset); /* unit: s */
+
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_read(void)
+{
+ /* collectd read callback: Perform data acquisition */
+ int rc;
+ unsigned int now_src, n_sources;
+
+ if (g_chrony_seq_is_initialized == 0)
+ {
+ /* Seed RNG for sequence number generation */
+ rc = chrony_init_seq();
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ g_chrony_seq_is_initialized = 1;
+ }
+
+ /* Get daemon stats */
+ rc = chrony_request_daemon_stats();
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ /* Get number of time sources, then check every source for status */
+ rc = chrony_request_sources_count(&n_sources);
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ for (now_src = 0; now_src < n_sources; ++now_src)
+ {
+ int is_reachable;
+ rc = chrony_request_source_data(now_src, &is_reachable);
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ rc = chrony_request_source_stats(now_src, &is_reachable);
+ if (rc != CHRONY_RC_OK)
+ return rc;
+
+ }
+ return CHRONY_RC_OK;
+}
+
+
+static int
+chrony_shutdown(void)
+{
+ /* Collectd shutdown callback: Free mem */
+ if (g_chrony_is_connected != 0)
+ {
+ close(g_chrony_socket);
+ g_chrony_is_connected = 0;
+ }
+ if (g_chrony_host != NULL)
+ sfree(g_chrony_host);
+
+ if (g_chrony_port != NULL)
+ sfree(g_chrony_port);
+
+ if (g_chrony_plugin_instance != NULL)
+ sfree(g_chrony_plugin_instance);
+
+ return CHRONY_RC_OK;
+}
+
+
+void
+module_register(void)
+{
+ plugin_register_config(PLUGIN_NAME_SHORT, chrony_config, g_config_keys,
+ g_config_keys_num);
+ plugin_register_read(PLUGIN_NAME_SHORT, chrony_read);
+ plugin_register_shutdown(PLUGIN_NAME_SHORT, chrony_shutdown);
+}
=over 4
-=item
+=item *
E-Mail type (e.g. "ham", "spam", "virus", ...) and size (bytes):
If C<size> is less than or equal to zero, C<size> is ignored.
-=item
+=item *
Spam score:
s:<value>
-=item
+=item *
Successful spam checks (e.g. "BAYES_99", "SUBJECT_DRUG_GAP_C", ...):
=over 4
-=item
+=item *
The user, the binary is executed as, may not have root privileges, i.E<nbsp>e.
must have an UID that is non-zero. This is for your own good.
-=item
+=item *
Early versions of the plugin did not use a command but treated all lines as if
they were arguments to the I<PUTVAL> command. When the I<PUTNOTIF> command was
status = RET_UNKNOWN;
if (consolitation_g == CON_NONE)
- status = do_check_con_none (values_num, values, values_names);
+ status = do_check_con_none (values_num, values, values_names);
else if (consolitation_g == CON_AVERAGE)
- status = do_check_con_average (values_num, values, values_names);
+ status = do_check_con_average (values_num, values, values_names);
else if (consolitation_g == CON_SUM)
status = do_check_con_sum (values_num, values, values_names);
else if (consolitation_g == CON_PERCENTAGE)
=over 4
-=item
+=item *
Please feel free to send in new plugins to collectd's mailing list at
E<lt>collectdE<nbsp>atE<nbsp>collectd.orgE<gt> for review and, possibly,
=over 4
-=item
+=item *
collectd is heavily multi-threaded. Each collectd thread accessing the perl
plugin will be mapped to a Perl interpreter thread (see L<threads(3perl)>).
that no data is shared between threads by default. You have to use the
B<threads::shared> module to do so.
-=item
+=item *
Each function name registered with collectd has to be available before the
first thread has been created (i.E<nbsp>e. basically at compile time). This
will not work. This is due to the fact that the symbol table is not shared
across different threads.
-=item
+=item *
Each plugin is usually only loaded once and kept in memory for performance
reasons. Therefore, END blocks are only executed once when collectd shuts
down. You should not rely on END blocks anyway - use B<shutdown functions>
instead.
-=item
+=item *
The perl plugin exports the internal API of collectd which is considered
unstable and subject to change at any time. We try hard to not break backwards
=over 4
-=item
+=item *
Currently, it is not possible to flush a single Perl plugin only. You can
either flush all Perl plugins or none at all and you have to use C<perl> as
=over 4
-=item
+=item *
B<1.> collectd will try to import the B<readline> module to give you a decent
way of entering your commands. The daemonized collectd won't do that.
-=item
+=item *
B<2.> collectd will block I<SIGINT>. Pressing I<Ctrl+C> will usually cause
collectd to shut down. This would be problematic in an interactive session,
To quit collectd send I<EOF> (press I<Ctrl+D> at the beginning of a new line).
-=item
+=item *
B<3.> collectd handles I<SIGCHLD>. This means that Python won't be able to
determine the return code of spawned processes with system(), popen() and
=over 4
-=item
+=item *
I<callback> is a callable object that will be called every time the event is
triggered.
-=item
+=item *
I<data> is an optional object that will be passed back to the callback function
every time it is called. If you omit this parameter no object is passed back to
your callback, not even None.
-=item
+=item *
I<name> is an optional identifier for this callback. The default name is
B<python>.I<module>. I<module> is taken from the B<__module__> attribute of
want to register the same callback multiple times in the same module you need to
specify a name here. Otherwise it's safe to ignore this parameter.
-=item
+=item *
I<identifier> is the full identifier assigned to this callback.
=back
-=item B<flush>(I<plugin>[, I<timeout>][, I<identifier>]) -> None
+=item B<flush>(I<plugin[, timeout][, identifier]) -> None
Flush one or all plugins. I<timeout> and the specified I<identifiers> are
passed on to the registered flush-callbacks. If omitted, the timeout defaults
=over 4
-=item
+=item *
Please feel free to send in new plugins to collectd's mailing list at
E<lt>collectdE<nbsp>atE<nbsp>collectd.orgE<gt> for review and, possibly,
=over 4
-=item
+=item *
collectd is heavily multi-threaded. Each collectd thread accessing the Python
plugin will be mapped to a Python interpreter thread. Any such thread will be
from collectd (i.E<nbsp>e. if it registers more than one callback or if a
registered callback may be called more than once in parallel).
-=item
+=item *
The Python thread module is initialized just before calling the init callbacks.
This means you must not use Python's threading module prior to this point. This
includes all config and possibly other callback as well.
-=item
+=item *
The python plugin exports the internal API of collectd which is considered
unstable and subject to change at any time. We try hard to not break backwards
=over 4
-=item
+=item *
Not all aspects of the collectd API are accessible from Python. This includes
but is not limited to filters and data sets.
#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
#@BUILD_PLUGIN_CEPH_TRUE@LoadPlugin ceph
#@BUILD_PLUGIN_CGROUPS_TRUE@LoadPlugin cgroups
+#@BUILD_PLUGIN_CHRONY_TRUE@LoadPlugin chrony
#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
#@BUILD_PLUGIN_CONTEXTSWITCH_TRUE@LoadPlugin contextswitch
@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
#@BUILD_PLUGIN_FILECOUNT_TRUE@LoadPlugin filecount
#@BUILD_PLUGIN_FSCACHE_TRUE@LoadPlugin fscache
#@BUILD_PLUGIN_GMOND_TRUE@LoadPlugin gmond
+#@BUILD_PLUGIN_GRPC_TRUE@LoadPlugin grpc
#@BUILD_PLUGIN_HDDTEMP_TRUE@LoadPlugin hddtemp
@BUILD_PLUGIN_INTERFACE_TRUE@@BUILD_PLUGIN_INTERFACE_TRUE@LoadPlugin interface
#@BUILD_PLUGIN_IPC_TRUE@LoadPlugin ipc
# </Daemon>
#</Plugin>
+#<Plugin chrony>
+# Host "localhost"
+# Port "323"
+# Timeout "2"
+#</Plugin>
+
#<Plugin cgroups>
# CGroup "libvirt"
# IgnoreSelected false
# </Metric>
#</Plugin>
+#<Plugin grpc>
+# WorkerThreads 5
+# <Listen "0.0.0.0" "50051">
+# EnableSSL true
+# SSLRootCerts "/path/to/root.pem"
+# SSLServerCert "/path/to/server.pem"
+# SSLServerKey "/path/to/server.key"
+# </Listen>
+#</Plugin>
+
#<Plugin hddtemp>
# Host "127.0.0.1"
# Port "7634"
=over 4
-=item
+=item *
The I<Type> cannot be left unspecified, because it is not reasonable to add
apples to oranges. Also, the internal lookup structure won't work if you try
to group by type.
-=item
+=item *
There must be at least one unspecified, ungrouped field. Otherwise nothing
will be aggregated.
=over 4
-=item
+=item *
foo.example.com/cpu-even-average/cpu-idle
-=item
+=item *
foo.example.com/cpu-even-average/cpu-system
-=item
+=item *
foo.example.com/cpu-even-average/cpu-user
-=item
+=item *
...
=back
+=head2 Plugin C<chrony>
+
+The C<chrony> plugin collects ntp data from a B<chronyd> server, such as clock
+skew and per-peer stratum.
+
+For talking to B<chronyd>, it mimics what the B<chronyc> control program does
+on the wire.
+
+Available configuration options for the C<chrony> plugin:
+
+=over 4
+
+=item B<Host> I<Hostname>
+
+Hostname of the host running B<chronyd>. Defaults to B<localhost>.
+
+=item B<Port> I<Port>
+
+UDP-Port to connect to. Defaults to B<323>.
+
+=item B<Timeout> I<Timeout>
+
+Connection timeout in seconds. Defaults to B<2>.
+
+=back
+
=head2 Plugin C<conntrack>
This plugin collects IP conntrack statistics.
=over 4
-=item
+=item *
Sum, per-state, over all CPUs installed in the system; and
-=item
+=item *
Sum, per-CPU, over all non-idle states of a CPU, creating an "active" state.
=back
+=head2 cURL Statistics
+
+All cURL-based plugins support collection of generic, request-based
+statistics. These are disabled by default and can be enabled selectively for
+each page or URL queried from the curl, curl_json, or curl_xml plugins. See
+the documentation of those plugins for specific information. This section
+describes the available metrics that can be configured for each plugin. All
+options are disabled by default.
+
+See L<http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html> for more details.
+
+=over 4
+
+=item B<TotalTime> B<true|false>
+
+Total time of the transfer, including name resolving, TCP connect, etc.
+
+=item B<NamelookupTime> B<true|false>
+
+Time it took from the start until name resolving was completed.
+
+=item B<ConnectTime> B<true|false>
+
+Time it took from the start until the connect to the remote host (or proxy)
+was completed.
+
+=item B<AppconnectTime> B<true|false>
+
+Time it took from the start until the SSL/SSH connect/handshake to the remote
+host was completed.
+
+=item B<PretransferTime> B<true|false>
+
+Time it took from the start until just before the transfer begins.
+
+=item B<StarttransferTime> B<true|false>
+
+Time it took from the start until the first byte was received.
+
+=item B<RedirectTime> B<true|false>
+
+Time it took for all redirection steps include name lookup, connect,
+pre-transfer and transfer before final transaction was started.
+
+=item B<RedirectCount> B<true|false>
+
+The total number of redirections that were actually followed.
+
+=item B<SizeUpload> B<true|false>
+
+The total amount of bytes that were uploaded.
+
+=item B<SizeDownload> B<true|false>
+
+The total amount of bytes that were downloaded.
+
+=item B<SpeedDownload> B<true|false>
+
+The average download speed that curl measured for the complete download.
+
+=item B<SpeedUpload> B<true|false>
+
+The average upload speed that curl measured for the complete upload.
+
+=item B<HeaderSize> B<true|false>
+
+The total size of all the headers received.
+
+=item B<RequestSize> B<true|false>
+
+The total size of the issued requests.
+
+=item B<ContentLengthDownload> B<true|false>
+
+The content-length of the download.
+
+=item B<ContentLengthUpload> B<true|false>
+
+The specified size of the upload.
+
+=item B<NumConnects> B<true|false>
+
+The number of new connections that were created to achieve the transfer.
+
+=back
+
=head2 Plugin C<curl>
The curl plugin uses the B<libcurl> (L<http://curl.haxx.se/>) to read web pages
B<Timeout> accordingly if you expect B<MeasureResponseTime> to report such slow
requests.
+This option is similar to enabling the B<TotalTime> statistic but it's
+measured by collectd instead of cURL.
+
=item B<MeasureResponseCode> B<true>|B<false>
Measure response code for the request. If this setting is enabled, B<Match>
blocks (see below) are optional. Disabled by default.
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote web site. See the section "cURL Statistics"
+above for details. If this setting is enabled, B<Match> blocks (see below) are
+optional.
+
=item B<E<lt>MatchE<gt>>
One or more B<Match> blocks that define how to match information in the data
These options behave exactly equivalent to the appropriate options of the
I<cURL> plugin. Please see there for a detailed description.
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote URL. See the section "cURL Statistics" above
+for details.
+
=back
The following options are valid within B<Key> blocks:
These options behave exactly equivalent to the appropriate options of the
I<cURL plugin>. Please see there for a detailed description.
+=item B<E<lt>StatisticsE<gt>>
+
+One B<Statistics> block can be used to specify cURL statistics to be collected
+for each request to the remote URL. See the section "cURL Statistics" above
+for details.
+
=item E<lt>B<XPath> I<XPath-expression>E<gt>
Within each B<URL> block, there must be one or more B<XPath> blocks. Each
=back
+=head2 Plugin C<grpc>
+
+The I<grpc> plugin provides an RPC interface to submit values to or query
+values from collectd based on the open source gRPC framework. It exposes an
+end-point for dispatching values to the daemon.
+
+The B<gRPC> homepage can be found at L<https://grpc.io/>.
+
+=over 4
+
+=item B<Listen> I<Host> I<Port>
+
+The B<Listen> statement sets the network address to bind to. When multiple
+statements are specified, the daemon will bind to all of them. If none are
+specified, it defaults to B<0.0.0.0:50051>.
+
+The argument I<Host> may be a hostname, an IPv4 address, or an IPv6 address.
+
+Optionally, B<Listen> may be specified as a configuration block which
+supports the following options:
+
+=over 4
+
+=item B<EnableSSL> I<true>|I<false>
+
+Whether to enable SSL for incoming connections. Default: false.
+
+=item B<SSLRootCerts> I<Filename>
+
+=item B<SSLServerKey> I<Filename>
+
+=item B<SSLServerCert> I<Filename>
+
+Filenames specifying SSL certificate and key material to be used with SSL
+connections.
+
+=back
+
+=item B<WorkerThreads> I<Num>
+
+Number of threads to start for handling incoming connections. The default
+value is B<5>.
+
+=back
+
=head2 Plugin C<hddtemp>
To get values from B<hddtemp> collectd connects to B<localhost> (127.0.0.1),
=head2 Plugin C<ntpd>
-The C<ntpd> plugin collects per-peer ntpd data such as time offset and time
+The C<ntpd> plugin collects per-peer ntp data such as time offset and time
dispersion.
For talking to B<ntpd>, it mimics what the B<ntpdc> control program does on
-wire - using B<mode 7> specific requests. This mode is deprecated with
+the wire - using B<mode 7> specific requests. This mode is deprecated with
newer B<ntpd> releases (4.2.7p230 and later). For the C<ntpd> plugin to work
correctly with them, the ntp daemon must be explicitly configured to
enable B<mode 7> (which is disabled by default). Refer to the I<ntp.conf(5)>
database definition. It accepts a single mandatory argument which specifies
the name of the query. The names of all queries have to be unique (see the
B<MinVersion> and B<MaxVersion> options below for an exception to this
-rule). The following configuration options are available to define the query:
+rule).
-In each B<Query> block, there is one or more B<Result> blocks. B<Result>
-blocks define how to handle the values returned from the query. They define
-which column holds which value and how to dispatch that value to the daemon.
-Multiple B<Result> blocks may be used to extract multiple values from a single
-query.
+In each B<Query> block, there is one or more B<Result> blocks. Multiple
+B<Result> blocks may be used to extract multiple values from a single query.
+
+The following configuration options are available to define the query:
=over 4
The returned lines will be handled separately one after another.
-=item B<Param> I<hostname>|I<database>|I<username>|I<interval>
+=item B<Param> I<hostname>|I<database>|I<instance>|I<username>|I<interval>
Specify the parameters which should be passed to the SQL query. The parameters
are referred to in the SQL query as B<$1>, B<$2>, etc. in the same order as
Please note that parameters are only supported by PostgreSQL's protocol
version 3 and above which was introduced in version 7.4 of PostgreSQL.
+=item B<PluginInstanceFrom> I<column>
+
+Specify how to create the "PluginInstance" for reporting this query results.
+Only one column is supported. You may concatenate fields and string values in
+the query statement to get the required results.
+
+=item B<MinVersion> I<version>
+
+=item B<MaxVersion> I<version>
+
+Specify the minimum or maximum version of PostgreSQL that this query should be
+used with. Some statistics might only be available with certain versions of
+PostgreSQL. This allows you to specify multiple queries with the same name but
+which apply to different versions, thus allowing you to use the same
+configuration in a heterogeneous environment.
+
+The I<version> has to be specified as the concatenation of the major, minor
+and patch-level versions, each represented as two-decimal-digit numbers. For
+example, version 8.2.3 will become 80203.
+
+=back
+
+The B<Result> block defines how to handle the values returned from the query.
+It defines which column holds which value and how to dispatch that value to
+the daemon.
+
+=over 4
+
=item B<Type> I<type>
The I<type> name to be used when dispatching the values. The type describes
details on types and their configuration. The number and type of values (as
selected by the B<ValuesFrom> option) has to match the type of the given name.
-This option is required inside a B<Result> block.
+This option is mandatory.
=item B<InstancePrefix> I<prefix>
times. If multiple B<ValuesFrom> options are specified, the columns are read
in the given order.
-=item B<MinVersion> I<version>
-
-=item B<MaxVersion> I<version>
-
-Specify the minimum or maximum version of PostgreSQL that this query should be
-used with. Some statistics might only be available with certain versions of
-PostgreSQL. This allows you to specify multiple queries with the same name but
-which apply to different versions, thus allowing you to use the same
-configuration in a heterogeneous environment.
-
-The I<version> has to be specified as the concatenation of the major, minor
-and patch-level versions, each represented as two-decimal-digit numbers. For
-example, version 8.2.3 will become 80203.
-
=back
The following predefined queries are available (the definitions can be found
name (which is the default, if this option has not been specified). This
allows to query multiple databases of the same name on the same host (e.g.
when running multiple database server versions in parallel).
+The plugin instance name can also be set from the query result using
+the B<PluginInstanceFrom> option in B<Query> block.
=item B<Host> I<hostname>
set to B<false>, B<only> matching disks will be collected. If B<IgnoreSelected>
is set to B<true>, all disks are collected B<except> the ones matched.
+=item B<IgnoreSleepMode> B<true>|B<false>
+
+Normally, the C<smart> plugin will ignore disks that are reported to be asleep.
+This option disables the sleep mode check and allows the plugin to collect data
+from these disks anyway. This is useful in cases where libatasmart mistakenly
+reports disks as asleep because it has not been updated to incorporate support
+for newer idle states in the ATA spec.
+
+=item B<UseSerial> B<true>|B<false>
+
+A disk's kernel name (e.g., sda) can change from one boot to the next. If this
+option is enabled, the C<smart> plugin will use the disk's serial number (e.g.,
+HGST_HUH728080ALE600_2EJ8VH8X) instead of the kernel name as the key for
+storing data. This ensures that the data for a given disk will be kept together
+even if the kernel name changes.
+
=back
=head2 Plugin C<snmp>
=over 4
-=item
+=item *
Check I</etc/uuid> (or I<UUIDFile>).
-=item
+=item *
Check for UUID from HAL (L<http://www.freedesktop.org/wiki/Software/hal>) if
present.
-=item
+=item *
Check for UUID from C<dmidecode> / SMBIOS.
-=item
+=item *
Check for UUID from Xen hypervisor.
=over 4
-=item
+=item *
Input plugins are queried periodically. They somehow acquire the current value
of whatever they where designed to work with and submit these values back to
reads the current cpu-counters of time spent in the various modes (user,
system, nice, ...) and dispatches these counters to the daemon.
-=item
+=item *
Output plugins get the dispatched values from the daemon and does something
with them. Common applications are writing to RRD-files, CSV-files or sending
void module_register (void)
{
- plugin_register_config ("conntrack", conntrack_config,
+ plugin_register_config ("conntrack", conntrack_config,
config_keys, config_keys_num);
plugin_register_read ("conntrack", conntrack_read);
} /* void module_register */
#include "common.h"
#include "plugin.h"
#include "configfile.h"
+#include "utils_curl_stats.h"
#include "utils_match.h"
#include "utils_time.h"
_Bool response_time;
_Bool response_code;
int timeout;
+ curl_stats_t *stats;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
sfree (wp->cacert);
sfree (wp->post_body);
curl_slist_free_all (wp->headers);
+ curl_stats_destroy (wp->stats);
sfree (wp->buffer);
page->response_time = 0;
page->response_code = 0;
page->timeout = -1;
+ page->stats = NULL;
page->instance = strdup (ci->values[0].value.string);
if (page->instance == NULL)
status = cf_util_get_string (child, &page->post_body);
else if (strcasecmp ("Timeout", child->key) == 0)
status = cf_util_get_int (child, &page->timeout);
+ else if (strcasecmp ("Statistics", child->key) == 0) {
+ page->stats = curl_stats_from_config (child);
+ if (page->stats == NULL)
+ status = -1;
+ }
else
{
WARNING ("curl plugin: Option `%s' not allowed here.", child->key);
status = -1;
}
- if (page->matches == NULL && !page->response_time && !page->response_code)
+ if (page->matches == NULL && page->stats == NULL
+ && !page->response_time && !page->response_code)
{
assert (page->instance != NULL);
WARNING ("curl plugin: No (valid) `Match' block "
- "or MeasureResponseTime or MeasureResponseCode within "
- "`Page' block `%s'.", page->instance);
+ "or Statistics or MeasureResponseTime or MeasureResponseCode "
+ "within `Page' block `%s'.", page->instance);
status = -1;
}
if (wp->response_time)
cc_submit_response_time (wp, cdtime() - start);
+ if (wp->stats != NULL)
+ curl_stats_dispatch (wp->stats, wp->curl, hostname_g, "curl", wp->instance);
if(wp->response_code)
{
#include "configfile.h"
#include "utils_avltree.h"
#include "utils_complain.h"
+#include "utils_curl_stats.h"
#include <sys/types.h>
#include <sys/un.h>
char *post_body;
cdtime_t interval;
int timeout;
+ curl_stats_t *stats;
CURL *curl;
char curl_errbuf[CURL_ERROR_SIZE];
sfree (db->cacert);
sfree (db->post_body);
curl_slist_free_all (db->headers);
+ curl_stats_destroy (db->stats);
sfree (db);
} /* }}} void cj_free */
status = cf_util_get_cdtime(child, &db->interval);
else if (strcasecmp ("Timeout", child->key) == 0)
status = cf_util_get_int (child, &db->timeout);
+ else if (strcasecmp ("Statistics", child->key) == 0)
+ {
+ db->stats = curl_stats_from_config (child);
+ if (db->stats == NULL)
+ status = -1;
+ }
else
{
WARNING ("curl_json plugin: Option `%s' not allowed here.", child->key);
/* }}} End of configuration handling functions */
+static const char *cj_host (cj_t *db) /* {{{ */
+{
+ if ((db->host == NULL)
+ || (strcmp ("", db->host) == 0)
+ || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
+ return hostname_g;
+ return db->host;
+} /* }}} cj_host */
+
static void cj_submit (cj_t *db, cj_key_t *key, value_t *value) /* {{{ */
{
value_list_t vl = VALUE_LIST_INIT;
- char *host;
vl.values = value;
vl.values_len = 1;
- if ((db->host == NULL)
- || (strcmp ("", db->host) == 0)
- || (strcmp (CJ_DEFAULT_HOST, db->host) == 0))
- host = hostname_g;
- else
- host = db->host;
-
if (key->instance == NULL)
{
int i, len = 0;
else
sstrncpy (vl.type_instance, key->instance, sizeof (vl.type_instance));
- sstrncpy (vl.host, host, sizeof (vl.host));
+ sstrncpy (vl.host, cj_host (db), sizeof (vl.host));
sstrncpy (vl.plugin, "curl_json", sizeof (vl.plugin));
sstrncpy (vl.plugin_instance, db->instance, sizeof (vl.plugin_instance));
sstrncpy (vl.type, key->type, sizeof (vl.type));
status, db->curl_errbuf, url);
return (-1);
}
+ if (db->stats != NULL)
+ curl_stats_dispatch (db->stats, db->curl, cj_host (db), "curl_json", db->instance);
curl_easy_getinfo(db->curl, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(db->curl, CURLINFO_RESPONSE_CODE, &rc);
}
#if HAVE_YAJL_V2
- status = yajl_complete_parse(db->yajl);
+ status = yajl_complete_parse(db->yajl);
#else
- status = yajl_parse_complete(db->yajl);
+ status = yajl_parse_complete(db->yajl);
#endif
if (status != yajl_status_ok)
{
#include "common.h"
#include "plugin.h"
#include "configfile.h"
+#include "utils_curl_stats.h"
#include "utils_llist.h"
#include <libxml/parser.h>
char *post_body;
int timeout;
struct curl_slist *headers;
+ curl_stats_t *stats;
cx_namespace_t *namespaces;
size_t namespaces_num;
return (0);
}
- if (len == 0)
+ if (len == 0)
return (len);
if ((db->buffer_fill + len) >= db->buffer_size)
sfree (db->cacert);
sfree (db->post_body);
curl_slist_free_all (db->headers);
+ curl_stats_destroy (db->stats);
for (i = 0; i < db->namespaces_num; i++)
{
sfree (db);
} /* }}} void cx_free */
+static const char *cx_host (cx_t *db) /* {{{ */
+{
+ if (db->host == NULL)
+ return hostname_g;
+ return db->host;
+} /* }}} cx_host */
+
static int cx_config_append_string (const char *name, struct curl_slist **dest, /* {{{ */
oconfig_item_t *ci)
{
vl.values_len = ds->ds_num;
sstrncpy (vl.type, xpath->type, sizeof (vl.type));
sstrncpy (vl.plugin, "curl_xml", sizeof (vl.plugin));
- sstrncpy (vl.host, (host != NULL) ? host : hostname_g, sizeof (vl.host));
+ sstrncpy (vl.host, host, sizeof (vl.host));
if (plugin_instance != NULL)
sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
ds = plugin_get_ds (xpath->type);
if ( (cx_check_type(ds, xpath) == 0) &&
- (cx_handle_base_xpath(db->instance, db->host,
+ (cx_handle_base_xpath(db->instance, cx_host (db),
xpath_ctx, ds, le->key, xpath) == 0) )
status = 0; /* we got atleast one success */
status, db->curl_errbuf, url);
return (-1);
}
+ if (db->stats != NULL)
+ curl_stats_dispatch (db->stats, db->curl, cx_host (db), "curl_xml", db->instance);
curl_easy_getinfo(curl, CURLINFO_EFFECTIVE_URL, &url);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &rc);
status = cx_config_add_namespace (db, child);
else if (strcasecmp ("Timeout", child->key) == 0)
status = cf_util_get_int (child, &db->timeout);
+ else if (strcasecmp ("Statistics", child->key) == 0)
+ {
+ db->stats = curl_stats_from_config (child);
+ if (db->stats == NULL)
+ status = -1;
+ }
else
{
WARNING ("curl_xml plugin: Option `%s' not allowed here.", child->key);
AM_CPPFLAGS += -DPKGDATADIR='"${pkgdatadir}"'
# Link to these libraries..
-COMMON_LIBS =
+COMMON_LIBS = $(PTHREAD_LIBS)
if BUILD_WITH_LIBRT
COMMON_LIBS += -lrt
endif
if BUILD_WITH_LIBRESOLV
COMMON_LIBS += -lresolv
endif
-if BUILD_WITH_LIBPTHREAD
-COMMON_LIBS += -lpthread
-endif
if BUILD_WITH_LIBKSTAT
COMMON_LIBS += -lkstat
endif
collectd_LDADD += -loconfig
endif
+LOG_COMPILER = env VALGRIND="@VALGRIND@" $(abs_top_srcdir)/testwrapper.sh
+
check_PROGRAMS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
TESTS = test_common test_meta_data test_utils_avltree test_utils_heap test_utils_time test_utils_subst
*/
char hostname_g[DATA_MAX_NAME_LEN];
cdtime_t interval_g;
-int pidfile_from_cli = 0;
int timeout_g;
#if HAVE_LIBKSTAT
kstat_ctl_t *kc;
break;
case 'T':
test_readall = 1;
- global_option_set ("ReadThreads", "-1");
+ global_option_set ("ReadThreads", "-1", 1);
#if COLLECT_DAEMON
daemonize = 0;
#endif /* COLLECT_DAEMON */
break;
#if COLLECT_DAEMON
case 'P':
- global_option_set ("PIDFile", optarg);
- pidfile_from_cli = 1;
+ global_option_set ("PIDFile", optarg, 1);
break;
case 'f':
daemonize = 0;
#endif
#ifndef PACKAGE_NAME
-#define PACKAGE_NAME "collectd"
+# define PACKAGE_NAME "collectd"
#endif
#ifndef PREFIX
-#define PREFIX "/opt/" PACKAGE_NAME
+# define PREFIX "/opt/" PACKAGE_NAME
#endif
#ifndef SYSCONFDIR
-#define SYSCONFDIR PREFIX "/etc"
+# define SYSCONFDIR PREFIX "/etc"
#endif
#ifndef CONFIGFILE
-#define CONFIGFILE SYSCONFDIR"/collectd.conf"
+# define CONFIGFILE SYSCONFDIR"/collectd.conf"
#endif
#ifndef LOCALSTATEDIR
-#define LOCALSTATEDIR PREFIX "/var"
+# define LOCALSTATEDIR PREFIX "/var"
#endif
#ifndef PKGLOCALSTATEDIR
-#define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
+# define PKGLOCALSTATEDIR PREFIX "/var/lib/" PACKAGE_NAME
#endif
#ifndef PIDFILE
-#define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
+# define PIDFILE PREFIX "/var/run/" PACKAGE_NAME ".pid"
#endif
#ifndef PLUGINDIR
-#define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
+# define PLUGINDIR PREFIX "/lib/" PACKAGE_NAME
#endif
#ifndef PKGDATADIR
-#define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
+# define PKGDATADIR PREFIX "/share/" PACKAGE_NAME
#endif
#ifndef COLLECTD_GRP_NAME
# define COLLECTD_DEFAULT_INTERVAL 10.0
#endif
- #ifndef COLLECTD_USERAGENT
- # define COLLECTD_USERAGENT PACKAGE_NAME"/"PACKAGE_VERSION
- #endif
+#ifndef COLLECTD_USERAGENT
+# define COLLECTD_USERAGENT PACKAGE_NAME "/" PACKAGE_VERSION
+#endif
/* Only enable __attribute__() for compilers known to support it. */
-#if defined(__clang__)
-# define clang_attr(x) __attribute__(x)
-# define gcc_attr(x) /**/
-#elif __GNUC__
-# define clang_attr(x) /**/
-# define gcc_attr(x) __attribute__(x)
-#else
-# define clang_attr(x) /**/
-# define gcc_attr(x) /**/
-# define __attribute__(x) /**/
+#if !defined(__clang__) && !defined(__GNUC__)
+# if !defined(__attribute__)
+# define __attribute__(x) /**/
+# endif
#endif
#if defined(COLLECT_DEBUG) && COLLECT_DEBUG && defined(__GNUC__) && __GNUC__
extern char hostname_g[];
extern cdtime_t interval_g;
-extern int pidfile_from_cli;
extern int timeout_g;
#endif /* COLLECTD_H */
#include "plugin.h"
#include "utils_cache.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
+#include <pthread.h>
#ifdef HAVE_MATH_H
# include <math.h>
ptr = (const char *) buf;
nleft = count;
+ if (fd < 0)
+ return (-1);
+
/* checking for closed peer connection */
pfd.fd = fd;
pfd.events = POLLIN | POLLHUP;
{
const char *key;
char *value;
+ _Bool from_cli; /* value set from CLI */
const char *def;
} cf_global_option_t;
static cf_global_option_t cf_global_options[] =
{
- {"BaseDir", NULL, PKGLOCALSTATEDIR},
- {"PIDFile", NULL, PIDFILE},
- {"Hostname", NULL, NULL},
- {"FQDNLookup", NULL, "true"},
- {"Interval", NULL, NULL},
- {"ReadThreads", NULL, "5"},
- {"WriteThreads", NULL, "5"},
- {"WriteQueueLimitHigh", NULL, NULL},
- {"WriteQueueLimitLow", NULL, NULL},
- {"Timeout", NULL, "2"},
- {"AutoLoadPlugin", NULL, "false"},
- {"CollectInternalStats", NULL, "false"},
- {"PreCacheChain", NULL, "PreCache"},
- {"PostCacheChain", NULL, "PostCache"},
- {"MaxReadInterval", NULL, "86400"}
+ {"BaseDir", NULL, 0, PKGLOCALSTATEDIR},
+ {"PIDFile", NULL, 0, PIDFILE},
+ {"Hostname", NULL, 0, NULL},
+ {"FQDNLookup", NULL, 0, "true"},
+ {"Interval", NULL, 0, NULL},
+ {"ReadThreads", NULL, 0, "5"},
+ {"WriteThreads", NULL, 0, "5"},
+ {"WriteQueueLimitHigh", NULL, 0, NULL},
+ {"WriteQueueLimitLow", NULL, 0, NULL},
+ {"Timeout", NULL, 0, "2"},
+ {"AutoLoadPlugin", NULL, 0, "false"},
+ {"CollectInternalStats", NULL, 0, "false"},
+ {"PreCacheChain", NULL, 0, "PreCache"},
+ {"PostCacheChain", NULL, 0, "PostCache"},
+ {"MaxReadInterval", NULL, 0, "86400"}
};
static int cf_global_options_num = STATIC_ARRAY_SIZE (cf_global_options);
if (ci->values_num != 1)
return (-1);
if (ci->values[0].type == OCONFIG_TYPE_STRING)
- return (global_option_set (ci->key, ci->values[0].value.string));
+ 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);
- return (global_option_set (ci->key, tmp));
+ return (global_option_set (ci->key, tmp, 0));
}
else if (ci->values[0].type == OCONFIG_TYPE_BOOLEAN)
{
if (ci->values[0].value.boolean)
- return (global_option_set (ci->key, "true"));
+ return (global_option_set (ci->key, "true", 0));
else
- return (global_option_set (ci->key, "false"));
+ return (global_option_set (ci->key, "false", 0));
}
return (-1);
/*
* Public functions
*/
-int global_option_set (const char *option, const char *value)
+int global_option_set (const char *option, const char *value, _Bool from_cli)
{
int i;
break;
if (i >= cf_global_options_num)
+ {
+ ERROR ("configfile: Cannot set unknown global option `%s'.", option);
return (-1);
+ }
- if (strcasecmp (option, "PIDFile") == 0 && pidfile_from_cli == 1)
+ if (cf_global_options[i].from_cli && (! from_cli))
{
- DEBUG ("Configfile: Ignoring `PIDFILE' option because "
- "command-line option `-P' take precedence.");
+ DEBUG ("configfile: Ignoring %s `%s' option because "
+ "it was overriden by a command-line option.",
+ option, value);
return (0);
}
else
cf_global_options[i].value = NULL;
+ cf_global_options[i].from_cli = from_cli;
+
return (0);
}
break;
if (i >= cf_global_options_num)
+ {
+ ERROR ("configfile: Cannot get unknown global option `%s'.", option);
return (NULL);
+ }
return ((cf_global_options[i].value != NULL)
? cf_global_options[i].value
*/
int cf_read (const char *filename);
-int global_option_set (const char *option, const char *value);
+int global_option_set (const char *option, const char *value, _Bool from_cli);
const char *global_option_get (const char *option);
long global_option_get_long (const char *option, long default_value);
long global_option_get_long_in_range (const char *option, long default_value, long min, long max);
#include "meta_data.h"
#include "utils_time.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
+#include <pthread.h>
#define PLUGIN_FLAGS_GLOBAL 0x0001
/**
* collectd - src/utils_cache.c
* Copyright (C) 2007-2010 Florian octo Forster
+ * Copyright (C) 2016 Sebastian tokkee Harl
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*
* Authors:
* Florian octo Forster <octo at collectd.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
**/
#include "collectd.h"
* (for purging old entries) */
cdtime_t last_update;
/* Interval in which the data is collected
- * (for purding old entries) */
+ * (for purging old entries) */
cdtime_t interval;
int state;
int hits;
meta_data_t *meta;
} cache_entry_t;
+struct uc_iter_s {
+ c_avl_iterator_t *iter;
+
+ char *name;
+ cache_entry_t *entry;
+};
+
static c_avl_tree_t *cache_tree = NULL;
static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER;
} /* int uc_inc_hits */
/*
+ * Iterator interface
+ */
+uc_iter_t *uc_get_iterator (void)
+{
+ uc_iter_t *iter;
+
+ iter = (uc_iter_t *) calloc(1, sizeof (*iter));
+ if (iter == NULL)
+ return (NULL);
+
+ pthread_mutex_lock (&cache_lock);
+
+ iter->iter = c_avl_get_iterator (cache_tree);
+ if (iter->iter == NULL)
+ {
+ free (iter);
+ return (NULL);
+ }
+
+ return (iter);
+} /* uc_iter_t *uc_get_iterator */
+
+int uc_iterator_next (uc_iter_t *iter, char **ret_name)
+{
+ int status;
+
+ if (iter == NULL)
+ return (-1);
+
+ while ((status = c_avl_iterator_next (iter->iter,
+ (void *) &iter->name, (void *) &iter->entry)) == 0)
+ {
+ if (iter->entry->state == STATE_MISSING)
+ continue;
+
+ break;
+ }
+ if (status != 0) {
+ iter->name = NULL;
+ iter->entry = NULL;
+ return (-1);
+ }
+
+ if (ret_name != NULL)
+ *ret_name = iter->name;
+
+ return (0);
+} /* int uc_iterator_next */
+
+void uc_iterator_destroy (uc_iter_t *iter)
+{
+ if (iter == NULL)
+ return;
+
+ c_avl_iterator_destroy (iter->iter);
+ pthread_mutex_unlock (&cache_lock);
+
+ free (iter);
+} /* void uc_iterator_destroy */
+
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time)
+{
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_time == NULL))
+ return (-1);
+
+ *ret_time = iter->entry->last_time;
+ return (0);
+} /* int uc_iterator_get_name */
+
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, size_t *ret_num)
+{
+ size_t i;
+
+ if ((iter == NULL) || (iter->entry == NULL)
+ || (ret_values == NULL) || (ret_num == NULL))
+ return (-1);
+
+ *ret_values = calloc (iter->entry->values_num, sizeof(*iter->entry->values_raw));
+ if (*ret_values == NULL)
+ return (-1);
+ for (i = 0; i < iter->entry->values_num; ++i)
+ *ret_values[i] = iter->entry->values_raw[i];
+
+ *ret_num = iter->entry->values_num;
+
+ return (0);
+} /* int uc_iterator_get_values */
+
+int uc_iterator_get_interval (uc_iter_t *iter, cdtime_t *ret_interval)
+{
+ if ((iter == NULL) || (iter->entry == NULL) || (ret_interval == NULL))
+ return (-1);
+
+ *ret_interval = iter->entry->interval;
+ return (0);
+} /* int uc_iterator_get_name */
+
+/*
* Meta data interface
*/
/* XXX: This function will acquire `cache_lock' but will not free it! */
/**
* collectd - src/utils_cache.h
* Copyright (C) 2007 Florian octo Forster
+ * Copyright (C) 2016 Sebastian tokkee Harl
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
*
* Authors:
* Florian octo Forster <octo at collectd.org>
+ * Sebastian tokkee Harl <sh at tokkee.org>
**/
#ifndef UTILS_CACHE_H
gauge_t *ret_history, size_t num_steps, size_t num_ds);
/*
+ * Iterator interface
+ */
+struct uc_iter_s;
+typedef struct uc_iter_s uc_iter_t;
+
+/*
+ * NAME
+ * uc_get_iterator
+ *
+ * DESCRIPTION
+ * Create an iterator for the cache. It will hold the cache lock until it's
+ * destroyed.
+ *
+ * RETURN VALUE
+ * An iterator object on success or NULL else.
+ */
+uc_iter_t *uc_get_iterator (void);
+
+/*
+ * NAME
+ * uc_iterator_next
+ *
+ * DESCRIPTION
+ * Advance the iterator to the next positiion and (optionally) returns the
+ * name of the entry.
+ *
+ * PARAMETERS
+ * `iter' The iterator object to advance.
+ * `ret_name' Pointer to a string where to store the name. The returned
+ * value is a copy of the value and has to be freed by the
+ * caller.
+ *
+ * RETURN VALUE
+ * Zero upon success or non-zero if the iterator ie NULL or no further
+ * values are available.
+ */
+int uc_iterator_next (uc_iter_t *iter, char **ret_name);
+void uc_iterator_destroy (uc_iter_t *iter);
+
+/* Return the timestamp of the value at the current position. */
+int uc_iterator_get_time (uc_iter_t *iter, cdtime_t *ret_time);
+/* Return the (raw) value at the current position. */
+int uc_iterator_get_values (uc_iter_t *iter, value_t **ret_values, 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);
+
+/*
* Meta data interface
*/
int uc_meta_data_exists (const value_list_t *vl, const char *key);
if (vl == NULL)
return (EINVAL);
- /* Is this lock really necessary? */
- pthread_mutex_lock (&threshold_lock);
+ /* Is this lock really necessary? */
+ pthread_mutex_lock (&threshold_lock);
t = threshold_search (vl);
if (t == NULL) {
- pthread_mutex_unlock (&threshold_lock);
+ pthread_mutex_unlock (&threshold_lock);
return (ENOENT);
- }
+ }
memcpy (ret_threshold, t, sizeof (*ret_threshold));
- pthread_mutex_unlock (&threshold_lock);
+ pthread_mutex_unlock (&threshold_lock);
ret_threshold->next = NULL;
#endif
if (ignorelist_match (ignorelist, output_name) != 0)
+ {
+#if HAVE_LIBUDEV
+ /* release udev-based alternate name, if allocated */
+ sfree (alt_name);
+#endif
continue;
+ }
if ((ds->read_bytes != 0) || (ds->write_bytes != 0))
disk_submit (output_name, "disk_octets",
#include "configfile.h"
#include "utils_dns.h"
-#include <pthread.h>
#include <poll.h>
#include <pcap.h>
#include <stddef.h>
-#if HAVE_LIBPTHREAD
-# include <pthread.h>
-#endif
-
#include <sys/un.h>
#include <sys/select.h>
for (i = 0; i < n_stats; i++)
{
- const char *stat_name;
+ char *stat_name;
stat_name = (void *) &strings->data[i * ETH_GSTRING_LEN];
+ /* Remove leading spaces in key name */
+ while (isspace ((int) *stat_name))
+ stat_name++;
+
DEBUG("ethstat plugin: device = \"%s\": %s = %"PRIu64,
device, stat_name, (uint64_t) stats->data[i]);
ethstat_submit_value (device,
#include <grp.h>
#include <signal.h>
-#include <pthread.h>
-
#define PL_NORMAL 0x01
#define PL_NOTIF_ACTION 0x02
#include "configfile.h"
#include "utils_avltree.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
--- /dev/null
+/**
+ * collectd - src/grpc.cc
+ * Copyright (C) 2015-2016 Sebastian Harl
+ *
+ * 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:
+ * Sebastian Harl <sh at tokkee.org>
+ **/
+
+#include <grpc++/grpc++.h>
+#include <google/protobuf/util/time_util.h>
+
+#include <fstream>
+#include <iostream>
+#include <vector>
+
+#include "collectd.grpc.pb.h"
+
+extern "C" {
+#include <fnmatch.h>
+#include <stdbool.h>
+#include <pthread.h>
+
+#include "collectd.h"
+#include "common.h"
+#include "configfile.h"
+#include "plugin.h"
+
+#include "daemon/utils_cache.h"
+}
+
+using collectd::Collectd;
+
+using collectd::DispatchValuesRequest;
+using collectd::DispatchValuesReply;
+using collectd::QueryValuesRequest;
+using collectd::QueryValuesReply;
+
+using google::protobuf::util::TimeUtil;
+
+/*
+ * private types
+ */
+
+struct Listener {
+ grpc::string addr;
+ grpc::string port;
+
+ grpc::SslServerCredentialsOptions *ssl;
+};
+static std::vector<Listener> listeners;
+static grpc::string default_addr("0.0.0.0:50051");
+
+/*
+ * helper functions
+ */
+
+static bool ident_matches(const value_list_t *vl, const value_list_t *matcher)
+{
+ if (fnmatch(matcher->host, vl->host, 0))
+ return false;
+
+ if (fnmatch(matcher->plugin, vl->plugin, 0))
+ return false;
+ if (fnmatch(matcher->plugin_instance, vl->plugin_instance, 0))
+ return false;
+
+ if (fnmatch(matcher->type, vl->type, 0))
+ return false;
+ if (fnmatch(matcher->type_instance, vl->type_instance, 0))
+ return false;
+
+ return true;
+} /* ident_matches */
+
+static grpc::string read_file(const char *filename)
+{
+ std::ifstream f;
+ grpc::string s, content;
+
+ f.open(filename);
+ if (!f.is_open()) {
+ ERROR("grpc: Failed to open '%s'", filename);
+ return "";
+ }
+
+ while (std::getline(f, s)) {
+ content += s;
+ content.push_back('\n');
+ }
+ f.close();
+ return content;
+} /* read_file */
+
+/*
+ * proto conversion
+ */
+
+static void marshal_ident(const value_list_t *vl, collectd::types::Identifier *msg)
+{
+ msg->set_host(vl->host);
+ msg->set_plugin(vl->plugin);
+ if (vl->plugin_instance[0] != '\0')
+ msg->set_plugin_instance(vl->plugin_instance);
+ msg->set_type(vl->type);
+ if (vl->type_instance[0] != '\0')
+ msg->set_type_instance(vl->type_instance);
+} /* marshal_ident */
+
+static grpc::Status unmarshal_ident(const collectd::types::Identifier &msg, value_list_t *vl,
+ bool require_fields)
+{
+ std::string s;
+
+ s = msg.host();
+ if (!s.length() && require_fields)
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("missing host name"));
+ sstrncpy(vl->host, s.c_str(), sizeof(vl->host));
+
+ s = msg.plugin();
+ if (!s.length() && require_fields)
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("missing plugin name"));
+ sstrncpy(vl->plugin, s.c_str(), sizeof(vl->plugin));
+
+ s = msg.type();
+ if (!s.length() && require_fields)
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("missing type name"));
+ sstrncpy(vl->type, s.c_str(), sizeof(vl->type));
+
+ s = msg.plugin_instance();
+ sstrncpy(vl->plugin_instance, s.c_str(), sizeof(vl->plugin_instance));
+
+ s = msg.type_instance();
+ sstrncpy(vl->type_instance, s.c_str(), sizeof(vl->type_instance));
+
+ return grpc::Status::OK;
+} /* unmarshal_ident() */
+
+static grpc::Status marshal_value_list(const value_list_t *vl, collectd::types::ValueList *msg)
+{
+ auto id = msg->mutable_identifier();
+ marshal_ident(vl, id);
+
+ auto ds = plugin_get_ds(vl->type);
+ if ((ds == NULL) || (ds->ds_num != vl->values_len)) {
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve data-set for values"));
+ }
+
+ auto t = TimeUtil::NanosecondsToTimestamp(CDTIME_T_TO_NS(vl->time));
+ auto d = TimeUtil::NanosecondsToDuration(CDTIME_T_TO_NS(vl->interval));
+ msg->set_allocated_time(new google::protobuf::Timestamp(t));
+ msg->set_allocated_interval(new google::protobuf::Duration(d));
+
+ for (size_t i = 0; i < vl->values_len; ++i) {
+ auto v = msg->add_value();
+ switch (ds->ds[i].type) {
+ case DS_TYPE_COUNTER:
+ v->set_counter(vl->values[i].counter);
+ break;
+ case DS_TYPE_GAUGE:
+ v->set_gauge(vl->values[i].gauge);
+ break;
+ case DS_TYPE_DERIVE:
+ v->set_derive(vl->values[i].derive);
+ break;
+ case DS_TYPE_ABSOLUTE:
+ v->set_absolute(vl->values[i].absolute);
+ break;
+ default:
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("unknown value type"));
+ }
+ }
+
+ return grpc::Status::OK;
+} /* marshal_value_list */
+
+static grpc::Status unmarshal_value_list(const collectd::types::ValueList &msg, value_list_t *vl)
+{
+ vl->time = NS_TO_CDTIME_T(TimeUtil::TimestampToNanoseconds(msg.time()));
+ vl->interval = NS_TO_CDTIME_T(TimeUtil::DurationToNanoseconds(msg.interval()));
+
+ auto status = unmarshal_ident(msg.identifier(), vl, true);
+ if (!status.ok())
+ return status;
+
+ value_t *values = NULL;
+ size_t values_len = 0;
+
+ status = grpc::Status::OK;
+ for (auto v : msg.value()) {
+ value_t *val = (value_t *)realloc(values, (values_len + 1) * sizeof(*values));
+ if (!val) {
+ status = grpc::Status(grpc::StatusCode::RESOURCE_EXHAUSTED,
+ grpc::string("failed to allocate values array"));
+ break;
+ }
+
+ values = val;
+ val = values + values_len;
+ values_len++;
+
+ switch (v.value_case()) {
+ case collectd::types::Value::ValueCase::kCounter:
+ val->counter = counter_t(v.counter());
+ break;
+ case collectd::types::Value::ValueCase::kGauge:
+ val->gauge = gauge_t(v.gauge());
+ break;
+ case collectd::types::Value::ValueCase::kDerive:
+ val->derive = derive_t(v.derive());
+ break;
+ case collectd::types::Value::ValueCase::kAbsolute:
+ val->absolute = absolute_t(v.absolute());
+ break;
+ default:
+ status = grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ grpc::string("unknown value type"));
+ break;
+ }
+
+ if (!status.ok())
+ break;
+ }
+ if (status.ok()) {
+ vl->values = values;
+ vl->values_len = values_len;
+ }
+ else if (values) {
+ free(values);
+ }
+
+ return status;
+} /* unmarshal_value_list() */
+
+/*
+ * request call-backs and call objects
+ */
+
+static grpc::Status Process(grpc::ServerContext *ctx,
+ DispatchValuesRequest request, DispatchValuesReply *reply)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ auto status = unmarshal_value_list(request.values(), &vl);
+ if (!status.ok())
+ return status;
+
+ if (plugin_dispatch_values(&vl))
+ status = grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to enqueue values for writing"));
+ return status;
+} /* Process(): DispatchValues */
+
+static grpc::Status Process(grpc::ServerContext *ctx,
+ QueryValuesRequest request, QueryValuesReply *reply)
+{
+ uc_iter_t *iter;
+ char *name = NULL;
+
+ value_list_t matcher;
+ auto status = unmarshal_ident(request.identifier(), &matcher, false);
+ if (!status.ok())
+ return status;
+
+ if ((iter = uc_get_iterator()) == NULL) {
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to query values: cannot create iterator"));
+ }
+
+ while (uc_iterator_next(iter, &name) == 0) {
+ value_list_t res;
+ if (parse_identifier_vl(name, &res) != 0)
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to parse identifier"));
+
+ if (!ident_matches(&res, &matcher))
+ continue;
+
+ if (uc_iterator_get_time(iter, &res.time) < 0)
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve value timestamp"));
+ if (uc_iterator_get_interval(iter, &res.interval) < 0)
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve value interval"));
+ if (uc_iterator_get_values(iter, &res.values, &res.values_len) < 0)
+ return grpc::Status(grpc::StatusCode::INTERNAL,
+ grpc::string("failed to retrieve values"));
+
+ auto vl = reply->add_values();
+ status = marshal_value_list(&res, vl);
+ free(res.values);
+ if (!status.ok())
+ return status;
+ }
+
+ uc_iterator_destroy(iter);
+
+ return grpc::Status::OK;
+} /* Process(): QueryValues */
+
+class Call
+{
+public:
+ Call(Collectd::AsyncService *service, grpc::ServerCompletionQueue *cq)
+ : service_(service), cq_(cq), status_(CREATE)
+ { }
+
+ virtual ~Call()
+ { }
+
+ void Handle()
+ {
+ if (status_ == CREATE) {
+ Create();
+ status_ = PROCESS;
+ }
+ else if (status_ == PROCESS) {
+ Process();
+ status_ = FINISH;
+ }
+ else {
+ GPR_ASSERT(status_ == FINISH);
+ Finish();
+ }
+ } /* Handle() */
+
+protected:
+ virtual void Create() = 0;
+ virtual void Process() = 0;
+ virtual void Finish() = 0;
+
+ Collectd::AsyncService *service_;
+ grpc::ServerCompletionQueue *cq_;
+ grpc::ServerContext ctx_;
+
+private:
+ enum CallStatus { CREATE, PROCESS, FINISH };
+ CallStatus status_;
+}; /* class Call */
+
+template<typename RequestT, typename ReplyT>
+class RpcCall final : public Call
+{
+ typedef void (Collectd::AsyncService::*CreatorT)(grpc::ServerContext *,
+ RequestT *, grpc::ServerAsyncResponseWriter<ReplyT> *,
+ grpc::CompletionQueue *, grpc::ServerCompletionQueue *, void *);
+
+public:
+ RpcCall(Collectd::AsyncService *service,
+ CreatorT creator, grpc::ServerCompletionQueue *cq)
+ : Call(service, cq), creator_(creator), responder_(&ctx_)
+ {
+ Handle();
+ } /* RpcCall() */
+
+ virtual ~RpcCall()
+ { }
+
+private:
+ void Create()
+ {
+ (service_->*creator_)(&ctx_, &request_, &responder_, cq_, cq_, this);
+ } /* Create() */
+
+ void Process()
+ {
+ // Add a new request object to the queue.
+ new RpcCall<RequestT, ReplyT>(service_, creator_, cq_);
+ grpc::Status status = ::Process(&ctx_, request_, &reply_);
+ responder_.Finish(reply_, status, this);
+ } /* Process() */
+
+ void Finish()
+ {
+ delete this;
+ } /* Finish() */
+
+ CreatorT creator_;
+
+ RequestT request_;
+ ReplyT reply_;
+
+ grpc::ServerAsyncResponseWriter<ReplyT> responder_;
+}; /* class RpcCall */
+
+/*
+ * gRPC server implementation
+ */
+
+class CollectdServer final
+{
+public:
+ void Start()
+ {
+ auto auth = grpc::InsecureServerCredentials();
+
+ grpc::ServerBuilder builder;
+
+ if (listeners.empty()) {
+ builder.AddListeningPort(default_addr, auth);
+ INFO("grpc: Listening on %s", default_addr.c_str());
+ }
+ else {
+ for (auto l : listeners) {
+ grpc::string addr = l.addr + ":" + l.port;
+
+ auto use_ssl = grpc::string("");
+ auto a = auth;
+ if (l.ssl != nullptr) {
+ use_ssl = grpc::string(" (SSL enabled)");
+ a = grpc::SslServerCredentials(*l.ssl);
+ }
+
+ builder.AddListeningPort(addr, a);
+ INFO("grpc: Listening on %s%s", addr.c_str(), use_ssl.c_str());
+ }
+ }
+
+ builder.RegisterService(&service_);
+ cq_ = builder.AddCompletionQueue();
+ server_ = builder.BuildAndStart();
+ } /* Start() */
+
+ void Shutdown()
+ {
+ server_->Shutdown();
+ cq_->Shutdown();
+ } /* Shutdown() */
+
+ void Mainloop()
+ {
+ // Register request types.
+ new RpcCall<DispatchValuesRequest, DispatchValuesReply>(&service_,
+ &Collectd::AsyncService::RequestDispatchValues, cq_.get());
+ new RpcCall<QueryValuesRequest, QueryValuesReply>(&service_,
+ &Collectd::AsyncService::RequestQueryValues, cq_.get());
+
+ while (true) {
+ void *req = NULL;
+ bool ok = false;
+
+ if (!cq_->Next(&req, &ok))
+ break; // Queue shut down.
+ if (!ok) {
+ ERROR("grpc: Failed to read from queue");
+ break;
+ }
+
+ static_cast<Call *>(req)->Handle();
+ }
+ } /* Mainloop() */
+
+private:
+ Collectd::AsyncService service_;
+
+ std::unique_ptr<grpc::Server> server_;
+ std::unique_ptr<grpc::ServerCompletionQueue> cq_;
+}; /* class CollectdServer */
+
+static CollectdServer *server = nullptr;
+
+/*
+ * collectd plugin interface
+ */
+
+extern "C" {
+ static pthread_t *workers;
+ static size_t workers_num = 5;
+
+ static void *worker_thread(void *arg)
+ {
+ CollectdServer *s = (CollectdServer *)arg;
+ s->Mainloop();
+ return NULL;
+ } /* worker_thread() */
+
+ static int c_grpc_config_listen(oconfig_item_t *ci)
+ {
+ if ((ci->values_num != 2)
+ || (ci->values[0].type != OCONFIG_TYPE_STRING)
+ || (ci->values[1].type != OCONFIG_TYPE_STRING)) {
+ ERROR("grpc: The `%s` config option needs exactly "
+ "two string argument (address and port).", ci->key);
+ return -1;
+ }
+
+ auto listener = Listener();
+ listener.addr = grpc::string(ci->values[0].value.string);
+ listener.port = grpc::string(ci->values[1].value.string);
+ listener.ssl = nullptr;
+
+ auto ssl_opts = new(grpc::SslServerCredentialsOptions);
+ grpc::SslServerCredentialsOptions::PemKeyCertPair pkcp = {};
+ bool use_ssl = false;
+
+ for (int i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *child = ci->children + i;
+
+ if (!strcasecmp("EnableSSL", child->key)) {
+ if (cf_util_get_boolean(child, &use_ssl)) {
+ ERROR("grpc: Option `%s` expects a boolean value",
+ child->key);
+ return -1;
+ }
+ }
+ else if (!strcasecmp("SSLRootCerts", child->key)) {
+ char *certs = NULL;
+ if (cf_util_get_string(child, &certs)) {
+ ERROR("grpc: Option `%s` expects a string value",
+ child->key);
+ return -1;
+ }
+ ssl_opts->pem_root_certs = read_file(certs);
+ }
+ else if (!strcasecmp("SSLServerKey", child->key)) {
+ char *key = NULL;
+ if (cf_util_get_string(child, &key)) {
+ ERROR("grpc: Option `%s` expects a string value",
+ child->key);
+ return -1;
+ }
+ pkcp.private_key = read_file(key);
+ }
+ else if (!strcasecmp("SSLServerCert", child->key)) {
+ char *cert = NULL;
+ if (cf_util_get_string(child, &cert)) {
+ ERROR("grpc: Option `%s` expects a string value",
+ child->key);
+ return -1;
+ }
+ pkcp.cert_chain = read_file(cert);
+ }
+ else {
+ WARNING("grpc: Option `%s` not allowed in <%s> block.",
+ child->key, ci->key);
+ }
+ }
+
+ ssl_opts->pem_key_cert_pairs.push_back(pkcp);
+ if (use_ssl)
+ listener.ssl = ssl_opts;
+ else
+ delete(ssl_opts);
+
+ listeners.push_back(listener);
+ return 0;
+ } /* c_grpc_config_listen() */
+
+ static int c_grpc_config(oconfig_item_t *ci)
+ {
+ int i;
+
+ for (i = 0; i < ci->children_num; i++) {
+ oconfig_item_t *child = ci->children + i;
+
+ if (!strcasecmp("Listen", child->key)) {
+ if (c_grpc_config_listen(child))
+ return -1;
+ }
+ else if (!strcasecmp("WorkerThreads", child->key)) {
+ int n;
+ if (cf_util_get_int(child, &n))
+ return -1;
+ workers_num = (size_t)n;
+ }
+ else {
+ WARNING("grpc: Option `%s` not allowed here.", child->key);
+ }
+ }
+
+ return 0;
+ } /* c_grpc_config() */
+
+ static int c_grpc_init(void)
+ {
+ server = new CollectdServer();
+ size_t i;
+
+ if (! server) {
+ ERROR("grpc: Failed to create server");
+ return -1;
+ }
+
+ workers = (pthread_t *)calloc(workers_num, sizeof(*workers));
+ if (! workers) {
+ delete server;
+ server = nullptr;
+
+ ERROR("grpc: Failed to allocate worker threads");
+ return -1;
+ }
+
+ server->Start();
+ for (i = 0; i < workers_num; i++) {
+ plugin_thread_create(&workers[i], /* attr = */ NULL,
+ worker_thread, server);
+ }
+ INFO("grpc: Started %zu workers", workers_num);
+ return 0;
+ } /* c_grpc_init() */
+
+ static int c_grpc_shutdown(void)
+ {
+ size_t i;
+
+ if (!server)
+ return -1;
+
+ server->Shutdown();
+
+ INFO("grpc: Waiting for %zu workers to terminate", workers_num);
+ for (i = 0; i < workers_num; i++)
+ pthread_join(workers[i], NULL);
+ free(workers);
+ workers = NULL;
+ workers_num = 0;
+
+ delete server;
+ server = nullptr;
+
+ return 0;
+ } /* c_grpc_shutdown() */
+
+ void module_register(void)
+ {
+ plugin_register_complex_config("grpc", c_grpc_config);
+ plugin_register_init("grpc", c_grpc_init);
+ plugin_register_shutdown("grpc", c_grpc_shutdown);
+ } /* module_register() */
+} /* extern "C" */
+
+/* vim: set sw=4 ts=4 tw=78 noexpandtab : */
#include "plugin.h"
#include "utils_ignorelist.h"
-#include <pthread.h>
-
#include <OpenIPMI/ipmiif.h>
#include <OpenIPMI/ipmi_err.h>
#include <OpenIPMI/ipmi_posix.h>
#include "common.h"
#include "filter_chain.h"
-#include <pthread.h>
#include <jni.h>
#if !defined(JNI_VERSION_1_2)
if (ret_values_names != NULL)
{
- values_names = (char **) calloc (values_num, sizeof (*values_names));
+ values_names = calloc (values_num, sizeof (*values_names));
if (values_names == NULL)
BAIL_OUT (ENOMEM);
}
#include "plugin.h"
#include <sys/types.h>
-#include <pthread.h>
#include <yajl/yajl_common.h>
#include <yajl/yajl_gen.h>
#if HAVE_YAJL_YAJL_VERSION_H
if (0 == strcasecmp (key, "LogLevel")) {
log_level = parse_log_severity(value);
- if (log_level < 0) {
- log_level = LOG_INFO;
- ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
- value);
- return 1;
- }
+ if (log_level < 0) {
+ log_level = LOG_INFO;
+ ERROR("log_logstash: invalid loglevel [%s] defaulting to 'info'",
+ value);
+ return 1;
+ }
}
else if (0 == strcasecmp (key, "File")) {
sfree (log_file);
#include "common.h"
#include "plugin.h"
-#include <pthread.h>
-
#define DEFAULT_LOGFILE LOCALSTATEDIR"/log/collectd.log"
#if COLLECT_DEBUG
#include "utils_cache.h"
#include "utils_complain.h"
-#include <pthread.h>
-
#include <mosquitto.h>
#define MQTT_MAX_TOPIC_SIZE 1024
counter_submit ("mysql_sort", "scan", val, db);
}
+ else if (strncmp (key, "Slow_queries", strlen ("Slow_queries")) == 0)
+ {
+ counter_submit ("mysql_slow_queries", NULL , val, db);
+ }
}
mysql_free_result (res); res = NULL;
#include "network.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
#if HAVE_NETDB_H
# include <netdb.h>
#endif
#endif
#if HAVE_LIBGCRYPT
-# include <pthread.h>
# if defined __APPLE__
/* default xcode compiler throws warnings even when deprecated functionality
* is not used. -Werror breaks the build because of erroneous warnings.
printed_ignore_warning = 1;
}
buffer = ((char *) buffer) + pkg_length;
+ buffer_size -= (size_t) pkg_length;
continue;
}
#endif /* HAVE_LIBGCRYPT */
printed_ignore_warning = 1;
}
buffer = ((char *) buffer) + pkg_length;
+ buffer_size -= (size_t) pkg_length;
continue;
}
#endif /* HAVE_LIBGCRYPT */
DEBUG ("network plugin: parse_packet: Unknown part"
" type: 0x%04hx", pkg_type);
buffer = ((char *) buffer) + pkg_length;
+ buffer_size -= (size_t) pkg_length;
}
} /* while (buffer_size > sizeof (part_header_t)) */
#include <auth-client.h>
#include <libesmtp.h>
-#include <pthread.h>
#define MAXSTRING 256
# include <poll.h>
#endif
+#ifndef STA_NANO
+# define STA_NANO 0x2000
+#endif
+
static const char *config_keys[] =
{
"Host",
break;
}
- memset ((void *) &res, '\0', sizeof (res));
+ memset (&res, '\0', sizeof (res));
status = recv (sd, (void *) &res, sizeof (res), 0 /* no flags */);
if ((status < 0) && ((errno == EAGAIN) || (errno == EINTR)))
if ((sd = ntpd_connect ()) < 0)
return (-1);
- memset ((void *) &req, '\0', sizeof (req));
+ memset (&req, '\0', sizeof (req));
req.rm_vn_mode = RM_VN_MODE(0, 0, 0);
req.auth_seq = AUTH_SEQ (0, 0);
req.implementation = IMPL_XNTPD;
int i;
/* On Linux, if the STA_NANO bit is set in ik->status, then ik->offset
- * is is nanoseconds, otherwise it's microseconds.
- * TODO(octo): STA_NANO is defined in the Linux specific <sys/timex.h> header. */
+ * is is nanoseconds, otherwise it's microseconds. */
double scale_loop = 1e-6;
double scale_error = 1e-6;
return (-1);
}
+ if (ntohs(ik->status) & STA_NANO) {
+ scale_loop = 1e-9;
+ scale_error = 1e-9;
+ }
+
/* kerninfo -> estimated error */
offset_loop = scale_loop * ((gauge_t) ntohl (ik->offset));
freq_loop = ntpd_read_fp (ik->freq);
#include "common.h"
#include "plugin.h"
-#include <pthread.h>
#include <upsclient.h>
#if HAVE_UPSCONN_T
* interface for collectd plugins written in perl.
*/
-/* do not automatically get the thread specific perl interpreter */
+/* do not automatically get the thread specific Perl interpreter */
#define PERL_NO_GET_CONTEXT
#define DONT_POISON_SPRINTF_YET 1
#include "filter_chain.h"
-#include <pthread.h>
-
#if !defined(USE_ITHREADS)
# error "Perl does not support ithreads!"
#endif /* !defined(USE_ITHREADS) */
typedef struct c_ithread_s {
/* the thread's Perl interpreter */
PerlInterpreter *interp;
+ _Bool running; /* thread is inside Perl interpreter */
+ _Bool shutdown;
+ pthread_t pthread;
/* double linked list of threads */
struct c_ithread_s *prev;
#endif /* COLLECT_DEBUG */
pthread_mutex_t mutex;
+ pthread_mutexattr_t mutexattr;
} c_ithread_list_t;
/* name / user_data for Perl matches / targets */
} /* static int pplugin_dispatch_notification (HV *) */
/*
+ * Call perl sub with thread locking flags handled.
+ */
+static int call_pv_locked (pTHX_ const char* sub_name)
+{
+ _Bool old_running;
+ int ret;
+
+ c_ithread_t *t = (c_ithread_t *)pthread_getspecific(perl_thr_key);
+ if (t == NULL) /* thread destroyed */
+ return 0;
+
+ old_running = t->running;
+ t->running = 1;
+
+ if (t->shutdown) {
+ t->running = old_running;
+ return 0;
+ }
+
+ ret = call_pv (sub_name, G_SCALAR);
+
+ t->running = old_running;
+ return ret;
+} /* static int call_pv_locked (pTHX, *sub_name) */
+
+/*
* Call all working functions of the given type.
*/
static int pplugin_call_all (pTHX_ int type, ...)
PUTBACK;
- retvals = call_pv ("Collectd::plugin_call_all", G_SCALAR);
+ retvals = call_pv_locked (aTHX_ "Collectd::plugin_call_all");
SPAGAIN;
if (0 < retvals) {
} /* static int pplugin_call_all (int, ...) */
/*
- * collectd's perl interpreter based thread implementation.
+ * collectd's Perl interpreter based thread implementation.
*
* This has been inspired by Perl's ithreads introduced in version 5.6.0.
*/
t->prev = perl_threads->tail;
}
+ t->pthread = pthread_self();
+ t->running = 0;
+ t->shutdown = 0;
perl_threads->tail = t;
pthread_setspecific (perl_thr_key, (const void *)t);
PUTBACK;
- retvals = call_pv ("Collectd::fc_call", G_SCALAR);
+ retvals = call_pv_locked (aTHX_ "Collectd::fc_call");
if ((FC_CB_EXEC == cb_type) && (meta != NULL)) {
assert (pmeta != NULL);
static int perl_init (void)
{
+ int status;
dTHX;
if (NULL == perl_threads)
log_debug ("perl_init: c_ithread: interp = %p (active threads: %i)",
aTHX, perl_threads->number_of_threads);
- return pplugin_call_all (aTHX_ PLUGIN_INIT);
+
+ /* Lock the base thread to avoid race conditions with c_ithread_create().
+ * See https://github.com/collectd/collectd/issues/9 and
+ * https://github.com/collectd/collectd/issues/1706 for details.
+ */
+ assert (aTHX == perl_threads->head->interp);
+ pthread_mutex_lock (&perl_threads->mutex);
+
+ status = pplugin_call_all (aTHX_ PLUGIN_INIT);
+
+ pthread_mutex_unlock (&perl_threads->mutex);
+
+ return status;
} /* static int perl_init (void) */
static int perl_read (void)
/* Lock the base thread if this is not called from one of the read threads
* to avoid race conditions with c_ithread_create(). See
- * https://github.com/collectd/collectd/issues/9 for details. */
+ * https://github.com/collectd/collectd/issues/9 for details.
+ */
+
if (aTHX == perl_threads->head->interp)
pthread_mutex_lock (&perl_threads->mutex);
t = perl_threads->tail;
while (NULL != t) {
+ struct timespec ts_wait;
c_ithread_t *thr = t;
/* the pointer has to be advanced before destroying
* the thread as this will free the memory */
t = t->prev;
+ thr->shutdown = 1;
+ if (thr->running) {
+ /* Give some time to thread to exit from Perl interpreter */
+ WARNING ("perl shutdown: Thread is running inside Perl. Waiting.");
+ ts_wait.tv_sec = 0;
+ ts_wait.tv_nsec = 500000;
+ nanosleep (&ts_wait, NULL);
+ }
+ if (thr->running) {
+ pthread_kill (thr->pthread, SIGTERM);
+ ERROR ("perl shutdown: Thread hangs inside Perl. Thread killed.");
+ }
c_ithread_destroy (thr);
}
pthread_mutex_unlock (&perl_threads->mutex);
pthread_mutex_destroy (&perl_threads->mutex);
+ pthread_mutexattr_destroy (&perl_threads->mutexattr);
sfree (perl_threads);
perl_threads = smalloc (sizeof (*perl_threads));
memset (perl_threads, 0, sizeof (c_ithread_list_t));
- pthread_mutex_init (&perl_threads->mutex, NULL);
+ pthread_mutexattr_init(&perl_threads->mutexattr);
+ pthread_mutexattr_settype(&perl_threads->mutexattr, PTHREAD_MUTEX_RECURSIVE);
+ pthread_mutex_init (&perl_threads->mutex, &perl_threads->mutexattr);
/* locking the mutex should not be necessary at this point
* but let's just do it for the sake of completeness */
pthread_mutex_lock (&perl_threads->mutex);
aTHX = perl_threads->head->interp;
- log_debug ("perl_config: loading perl plugin \"%s\"", value);
+ log_debug ("perl_config: Loading Perl plugin \"%s\"", value);
load_module (PERL_LOADMOD_NOIMPORT,
newSVpv (module_name, strlen (module_name)), Nullsv);
return 0;
#include "plugin.h"
#include "configfile.h"
-#include <pthread.h>
#include <netdb.h>
#include <poll.h>
#include "configfile.h"
#include "utils_complain.h"
-#include <pthread.h>
#include <netinet/in.h>
#if HAVE_NETDB_H
# include <netdb.h> /* NI_MAXHOST */
#include "utils_db_query.h"
#include "utils_complain.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
#include <pg_config_manual.h>
#include <libpq-fe.h>
return (0);
} /* int ps_list_match */
-static void ps_update_counter (
- _Bool init,
- derive_t *group_counter,
- derive_t *curr_counter, unsigned long *curr_value,
- derive_t new_counter, unsigned long new_value) {
- if (init)
- {
- *curr_value = new_value;
- *curr_counter += new_value;
- *group_counter += new_value;
- return;
- }
-
- if (new_counter < *curr_counter)
- {
- *curr_value = new_counter + (ULONG_MAX - *curr_counter);
- }
- else
- {
- *curr_value = new_counter - *curr_counter;
- }
- *curr_counter = new_counter;
- *group_counter += *curr_value;
+static void ps_update_counter (_Bool init, derive_t *group_counter,
+ derive_t *curr_counter, unsigned long *curr_value,
+ derive_t new_counter, unsigned long new_value)
+{
+ if (init)
+ {
+ *curr_value = new_value;
+ *curr_counter += new_value;
+ *group_counter += new_value;
+ return;
+ }
+
+ if (new_counter < *curr_counter)
+ *curr_value = new_counter + (ULONG_MAX - *curr_counter);
+ else
+ *curr_value = new_counter - *curr_counter;
+
+ *curr_counter = new_counter;
+ *group_counter += *curr_value;
}
/* add process entry to 'instances' of process 'name' (or refresh it) */
for (ps = list_head_g; ps != NULL; ps = ps->next)
{
- _Bool want_init;
+ _Bool want_init;
if ((ps_list_match (name, cmdline, ps)) == 0)
continue;
if (fclose (fh))
{
char errbuf[1024];
- WARNING ("processes: fclose: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
+ WARNING ("processes: fclose: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
}
}
closedir (dh);
#include <structmember.h>
#include <signal.h>
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
#include "collectd.h"
#include "common.h"
#include "plugin.h"
#include "configfile.h"
-#include <pthread.h>
#include <sys/time.h>
#include <hiredis/hiredis.h>
#include <rrd.h>
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
/*
* Private types
*/
#include <stdlib.h>
#include <string.h>
#include <time.h>
-#include <pthread.h>
#include <glib.h>
#include <libsigrok/libsigrok.h>
static const char *config_keys[] =
{
"Disk",
- "IgnoreSelected"
+ "IgnoreSelected",
+ "IgnoreSleepMode",
+ "UseSerial"
};
static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
static ignorelist_t *ignorelist = NULL;
+static int ignore_sleep_mode = 0;
+static int use_serial = 0;
static int smart_config (const char *key, const char *value)
{
invert = 0;
ignorelist_set_invert (ignorelist, invert);
}
+ else if (strcasecmp ("IgnoreSleepMode", key) == 0)
+ {
+ if (IS_TRUE (value))
+ ignore_sleep_mode = 1;
+ }
+ else if (strcasecmp ("UseSerial", key) == 0)
+ {
+ if (IS_TRUE (value))
+ use_serial = 1;
+ }
else
{
return (-1);
}
}
-static void smart_handle_disk (const char *dev)
+static void smart_handle_disk (const char *dev, const char *serial)
{
SkDisk *d = NULL;
SkBool awake = FALSE;
const SkSmartParsedData *spd;
uint64_t poweron, powercycles, badsectors, temperature;
- shortname = strrchr(dev, '/');
- if (!shortname) return;
- shortname++;
+ if (use_serial && serial)
+ {
+ shortname = serial;
+ }
+ else
+ {
+ shortname = strrchr(dev, '/');
+ if (!shortname) return;
+ shortname++;
+ }
if (ignorelist_match (ignorelist, shortname) != 0) {
DEBUG ("smart plugin: ignoring %s.", dev);
return;
DEBUG ("smart plugin: disk %s has no SMART support.", dev);
goto end;
}
- if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+ if (!ignore_sleep_mode)
{
- DEBUG ("smart plugin: disk %s is sleeping.", dev);
- goto end;
+ if (sk_disk_check_sleep_mode (d, &awake) < 0 || !awake)
+ {
+ DEBUG ("smart plugin: disk %s is sleeping.", dev);
+ goto end;
+ }
}
if (sk_disk_smart_read_data (d) < 0)
{
devices = udev_enumerate_get_list_entry (enumerate);
udev_list_entry_foreach (dev_list_entry, devices)
{
- const char *path, *devpath;
+ const char *path, *devpath, *serial;
path = udev_list_entry_get_name (dev_list_entry);
dev = udev_device_new_from_syspath (handle_udev, path);
devpath = udev_device_get_devnode (dev);
+ serial = udev_device_get_property_value (dev, "ID_SERIAL");
/* Query status with libatasmart */
- smart_handle_disk (devpath);
+ smart_handle_disk (devpath, serial);
udev_device_unref (dev);
}
#include "plugin.h"
#include "utils_complain.h"
-#include <pthread.h>
-
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
#include "utils_complain.h"
#include "utils_latency.h"
-#include <pthread.h>
-
#include <sys/types.h>
#include <netdb.h>
#include <poll.h>
/*
* Interpret configuration values
*/
- if (strcasecmp ("Host", key) == 0)
+ if (strcasecmp ("Host", key) == 0)
{
char *temp;
if (success == 0)
return (-1);
- return (0);
+ return (0);
} /* int tss2_read */
static int tss2_shutdown(void)
#define OK(cond) OK1(cond, #cond)
#define EXPECT_EQ_STR(expect, actual) do { \
- if (strcmp (expect, actual) != 0) { \
+ /* Evaluate 'actual' only once. */ \
+ const char *got__ = actual; \
+ if (strcmp (expect, got__) != 0) { \
printf ("not ok %i - %s = \"%s\", want \"%s\"\n", \
- ++check_count__, #actual, actual, expect); \
+ ++check_count__, #actual, got__, expect); \
return (-1); \
} \
- printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, actual); \
+ printf ("ok %i - %s = \"%s\"\n", ++check_count__, #actual, got__); \
} while (0)
#define EXPECT_EQ_INT(expect, actual) do { \
#include "utils_threshold.h"
#include <assert.h>
-#include <pthread.h>
/*
* Threshold management
ceph_rate value:DERIVE:0:U
changes_since_last_save value:GAUGE:0:U
charge value:GAUGE:0:U
+clock_last_meas value:GAUGE:0:U
+clock_last_update value:GAUGE:U:U
+clock_mode value:GAUGE:0:U
+clock_reachability value:GAUGE:0:U
+clock_skew_ppm value:GAUGE:-2:2
+clock_state value:GAUGE:0:U
+clock_stratum value:GAUGE:0:U
compression uncompressed:DERIVE:0:U, compressed:DERIVE:0:U
compression_ratio value:GAUGE:0:2
connections value:DERIVE:0:U
flow value:GAUGE:0:U
fork_rate value:DERIVE:0:U
frequency value:GAUGE:0:U
+frequency_error value:GAUGE:-2:2
frequency_offset value:GAUGE:-1000000:1000000
fscache_stat value:DERIVE:0:U
gauge value:GAUGE:U:U
mysql_sort value:DERIVE:0:U
mysql_sort_merge_passes value:DERIVE:0:U
mysql_sort_rows value:DERIVE:0:U
+mysql_slow_queries value:DERIVE:0:U
nfs_procedure value:DERIVE:0:U
nginx_connections value:GAUGE:0:U
nginx_requests value:DERIVE:0:U
requests value:GAUGE:0:U
response_code value:GAUGE:0:U
response_time value:GAUGE:0:U
+root_delay value:GAUGE:U:U
+root_dispersion value:GAUGE:U:U
route_etx value:GAUGE:0:U
route_metric value:GAUGE:0:U
routes value:GAUGE:0:U
threads value:GAUGE:0:U
time_dispersion value:GAUGE:-1000000:1000000
time_offset value:GAUGE:-1000000:1000000
+time_offset_ntp value:GAUGE:-1000000:1000000
+time_offset_rms value:GAUGE:-1000000:1000000
+time_ref value:GAUGE:0:U
timeleft value:GAUGE:0:U
total_bytes value:DERIVE:0:U
total_connections value:DERIVE:0:U
#include "utils_cmd_putval.h"
#include "utils_cmd_putnotif.h"
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
#include <sys/stat.h>
#include <sys/un.h>
} /* while (*buffer != 0) */
/* Done parsing the options. */
- if (fh!=stdout)
- print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
+ if (fh!=stdout)
+ print_to_socket (fh, "0 Success: %i %s been dispatched.\n",
values_submitted,
(values_submitted == 1) ? "value has" : "values have");
--- /dev/null
+/**
+ * collectd - src/utils_curl_stats.c
+ * Copyright (C) 2015 Sebastian 'tokkee' Harl
+ *
+ * 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:
+ * Sebastian Harl <sh@tokkee.org>
+ **/
+
+#include "collectd.h"
+#include "common.h"
+#include "utils_curl_stats.h"
+
+#include <stdbool.h>
+#include <stddef.h>
+
+struct curl_stats_s
+{
+ bool total_time;
+ bool namelookup_time;
+ bool connect_time;
+ bool pretransfer_time;
+ bool size_upload;
+ bool size_download;
+ bool speed_download;
+ bool speed_upload;
+ bool header_size;
+ bool request_size;
+ bool content_length_download;
+ bool content_length_upload;
+ bool starttransfer_time;
+ bool redirect_time;
+ bool redirect_count;
+ bool num_connects;
+ bool appconnect_time;
+};
+
+/*
+ * Private functions
+ */
+
+static int dispatch_gauge (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+ CURLcode code;
+ value_t v;
+
+ code = curl_easy_getinfo (curl, info, &v.gauge);
+ if (code != CURLE_OK)
+ return -1;
+
+ vl->values = &v;
+ vl->values_len = 1;
+
+ return plugin_dispatch_values (vl);
+} /* dispatch_gauge */
+
+/* dispatch a speed, in bytes/second */
+static int dispatch_speed (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+ CURLcode code;
+ value_t v;
+
+ code = curl_easy_getinfo (curl, info, &v.gauge);
+ if (code != CURLE_OK)
+ return -1;
+
+ v.gauge *= 8;
+
+ vl->values = &v;
+ vl->values_len = 1;
+
+ return plugin_dispatch_values (vl);
+} /* dispatch_speed */
+
+/* dispatch a size/count, reported as a long value */
+static int dispatch_size (CURL *curl, CURLINFO info, value_list_t *vl)
+{
+ CURLcode code;
+ value_t v;
+ long raw;
+
+ code = curl_easy_getinfo (curl, info, &raw);
+ if (code != CURLE_OK)
+ return -1;
+
+ v.gauge = (double)raw;
+
+ vl->values = &v;
+ vl->values_len = 1;
+
+ return plugin_dispatch_values (vl);
+} /* dispatch_size */
+
+static struct {
+ const char *name;
+ const char *config_key;
+ size_t offset;
+
+ int (*dispatcher)(CURL *, CURLINFO, value_list_t *);
+ const char *type;
+ CURLINFO info;
+} field_specs[] = {
+#define SPEC(name, config_key, dispatcher, type, info) \
+ { #name, config_key, offsetof (curl_stats_t, name), dispatcher, type, info }
+
+ SPEC (total_time, "TotalTime", dispatch_gauge, "duration", CURLINFO_TOTAL_TIME),
+ SPEC (namelookup_time, "NamelookupTime", dispatch_gauge, "duration", CURLINFO_NAMELOOKUP_TIME),
+ SPEC (connect_time, "ConnectTime", dispatch_gauge, "duration", CURLINFO_CONNECT_TIME),
+ SPEC (pretransfer_time, "PretransferTime", dispatch_gauge, "duration", CURLINFO_PRETRANSFER_TIME),
+ SPEC (size_upload, "SizeUpload", dispatch_gauge, "bytes", CURLINFO_SIZE_UPLOAD),
+ SPEC (size_download, "SizeDownload", dispatch_gauge, "bytes", CURLINFO_SIZE_DOWNLOAD),
+ SPEC (speed_download, "SpeedDownload", dispatch_speed, "bitrate", CURLINFO_SPEED_DOWNLOAD),
+ SPEC (speed_upload, "SpeedUpload", dispatch_speed, "bitrate", CURLINFO_SPEED_UPLOAD),
+ SPEC (header_size, "HeaderSize", dispatch_size, "bytes", CURLINFO_HEADER_SIZE),
+ SPEC (request_size, "RequestSize", dispatch_size, "bytes", CURLINFO_REQUEST_SIZE),
+ SPEC (content_length_download, "ContentLengthDownload", dispatch_gauge, "bytes", CURLINFO_CONTENT_LENGTH_DOWNLOAD),
+ SPEC (content_length_upload, "ContentLengthUpload", dispatch_gauge, "bytes", CURLINFO_CONTENT_LENGTH_UPLOAD),
+ SPEC (starttransfer_time, "StarttransferTime", dispatch_gauge, "duration", CURLINFO_STARTTRANSFER_TIME),
+ SPEC (redirect_time, "RedirectTime", dispatch_gauge, "duration", CURLINFO_REDIRECT_TIME),
+ SPEC (redirect_count, "RedirectCount", dispatch_size, "count", CURLINFO_REDIRECT_COUNT),
+ SPEC (num_connects, "NumConnects", dispatch_size, "count", CURLINFO_NUM_CONNECTS),
+#ifdef HAVE_CURLINFO_APPCONNECT_TIME
+ SPEC (appconnect_time, "AppconnectTime", dispatch_gauge, "duration", CURLINFO_APPCONNECT_TIME),
+#endif
+
+#undef SPEC
+};
+
+static void enable_field (curl_stats_t *s, size_t offset)
+{
+ *(bool *)((char *)s + offset) = true;
+} /* enable_field */
+
+static bool field_enabled (curl_stats_t *s, size_t offset)
+{
+ return *(bool *)((char *)s + offset);
+} /* field_enabled */
+
+/*
+ * Public API
+ */
+curl_stats_t *curl_stats_from_config (oconfig_item_t *ci)
+{
+ curl_stats_t *s;
+ int i;
+
+ if (ci == NULL)
+ return NULL;
+
+ s = calloc (1, sizeof (*s));
+ if (s == NULL)
+ return NULL;
+
+ for (i = 0; i < ci->children_num; ++i)
+ {
+ oconfig_item_t *c = ci->children + i;
+ size_t field;
+
+ _Bool enabled = 0;
+
+ for (field = 0; field < STATIC_ARRAY_SIZE (field_specs); ++field) {
+ if (! strcasecmp (c->key, field_specs[field].config_key))
+ break;
+ if (! strcasecmp (c->key, field_specs[field].name))
+ break;
+ }
+ if (field >= STATIC_ARRAY_SIZE (field_specs))
+ {
+ ERROR ("curl stats: Unknown field name %s", c->key);
+ free (s);
+ return NULL;
+ }
+
+
+ if (cf_util_get_boolean (c, &enabled) != 0) {
+ free (s);
+ return NULL;
+ }
+ if (enabled)
+ enable_field (s, field_specs[field].offset);
+ }
+
+ return s;
+} /* curl_stats_from_config */
+
+void curl_stats_destroy (curl_stats_t *s)
+{
+ if (s != NULL)
+ free (s);
+} /* curl_stats_destroy */
+
+int curl_stats_dispatch (curl_stats_t *s, CURL *curl,
+ const char *hostname, const char *plugin, const char *plugin_instance)
+{
+ value_list_t vl = VALUE_LIST_INIT;
+ size_t field;
+
+ if (s == NULL)
+ return 0;
+ if ((curl == NULL) || (hostname == 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);
+ return -1;
+ }
+
+ 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));
+
+ for (field = 0; field < STATIC_ARRAY_SIZE (field_specs); ++field)
+ {
+ int status;
+
+ if (! field_enabled (s, field_specs[field].offset))
+ continue;
+
+ sstrncpy (vl.type, field_specs[field].type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, field_specs[field].name, sizeof (vl.type_instance));
+
+ vl.values = NULL;
+ vl.values_len = 0;
+ status = field_specs[field].dispatcher (curl, field_specs[field].info, &vl);
+ if (status < 0)
+ return status;
+ }
+
+ return 0;
+} /* curl_stats_dispatch */
--- /dev/null
+/**
+ * collectd - src/utils_curl_stats.h
+ * Copyright (C) 2015 Sebastian 'tokkee' Harl
+ *
+ * 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:
+ * Sebastian Harl <sh@tokkee.org>
+ **/
+
+#ifndef UTILS_CURL_STATS_H
+#define UTILS_CURL_STATS_H 1
+
+#include "configfile.h"
+#include "plugin.h"
+
+#include <curl/curl.h>
+
+struct curl_stats_s;
+typedef struct curl_stats_s curl_stats_t;
+
+/*
+ * curl_stats_from_config allocates and constructs a cURL statistics object
+ * from the specified configuration which is expected to be a single block of
+ * boolean options named after cURL information fields. The boolean value
+ * indicates whether to collect the respective information.
+ *
+ * See http://curl.haxx.se/libcurl/c/curl_easy_getinfo.html
+ */
+curl_stats_t *curl_stats_from_config (oconfig_item_t *ci);
+
+void curl_stats_destroy (curl_stats_t *s);
+
+/*
+ * curl_stats_dispatch dispatches performance values from the the specified
+ * cURL session to the daemon.
+ */
+int curl_stats_dispatch (curl_stats_t *s, CURL *curl,
+ const char *hostname, const char *plugin, const char *plugin_instance);
+
+#endif /* UTILS_CURL_STATS_H */
char *name;
char *statement;
void *user_data;
+ char *plugin_instance_from;
unsigned int min_version;
unsigned int max_version;
char **instances_buffer;
char **values_buffer;
char **metadata_buffer;
+ char *plugin_instance;
struct udb_result_preparation_area_s *next;
}; /* }}} */
struct udb_query_preparation_area_s /* {{{ */
{
size_t column_num;
+ size_t plugin_instance_pos;
char *host;
char *plugin;
char *db_name;
sstrncpy (vl.host, q_area->host, sizeof (vl.host));
sstrncpy (vl.plugin, q_area->plugin, sizeof (vl.plugin));
- sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
sstrncpy (vl.type, r->type, sizeof (vl.type));
+ /* Set vl.plugin_instance */
+ if (q->plugin_instance_from != NULL) {
+ sstrncpy (vl.plugin_instance, r_area->plugin_instance, sizeof (vl.plugin_instance));
+ }
+ else {
+ sstrncpy (vl.plugin_instance, q_area->db_name, sizeof (vl.plugin_instance));
+ }
+
/* Set vl.type_instance {{{ */
if (r->instances_num == 0)
{
for (i = 0; i < r->metadata_num; i++)
r_area->metadata_buffer[i] = column_values[r_area->metadata_pos[i]];
+ if (q->plugin_instance_from)
+ r_area->plugin_instance = column_values[q_area->plugin_instance_pos];
+
return udb_result_submit (r, r_area, q, q_area);
} /* }}} int udb_result_handle_result */
/* }}} */
- /* Determine the position of the instance columns {{{ */
+ /* Determine the position of the plugin instance column {{{ */
for (i = 0; i < r->instances_num; i++)
{
size_t j;
}
} /* }}} for (i = 0; i < r->instances_num; i++) */
+
/* Determine the position of the value columns {{{ */
for (i = 0; i < r->values_num; i++)
{
return;
sfree (r->type);
+ sfree (r->instance_prefix);
for (i = 0; i < r->instances_num; i++)
sfree (r->instances[i]);
sfree (q->name);
sfree (q->statement);
+ sfree (q->plugin_instance_from);
udb_result_free (q->results);
}
q->min_version = 0;
q->max_version = UINT_MAX;
+ q->statement = NULL;
+ q->results = NULL;
+ q->plugin_instance_from = NULL;
status = udb_config_set_string (&q->name, ci);
if (status != 0)
status = udb_config_set_uint (&q->min_version, child);
else if (strcasecmp ("MaxVersion", child->key) == 0)
status = udb_config_set_uint (&q->max_version, child);
+ else if (strcasecmp ("PluginInstanceFrom", child->key) == 0)
+ status = udb_config_set_string (&q->plugin_instance_from, child);
/* Call custom callbacks */
else if (cb != NULL)
} while (0);
#endif
+ /* Determine the position of the PluginInstance column {{{ */
+ if (q->plugin_instance_from != NULL)
+ {
+ size_t i;
+
+ for (i = 0; i < column_num; i++)
+ {
+ if (strcasecmp (q->plugin_instance_from, column_names[i]) == 0)
+ {
+ prep_area->plugin_instance_pos = i;
+ break;
+ }
+ }
+
+ if (i >= column_num)
+ {
+ ERROR ("db query utils: udb_query_prepare_result: "
+ "Column `%s' from `PluginInstanceFrom' could not be found.",
+ q->plugin_instance_from);
+ udb_query_finish_result (q, prep_area);
+ return (-ENOENT);
+ }
+ }
+ /* }}} */
+
for (r = q->results, r_area = prep_area->result_prep_areas;
r != NULL; r = r->next, r_area = r_area->next)
{
*/
#include "collectd.h"
+#include "common.h"
#include "testing.h"
#include "utils_mount.h"
{
char line_opts[] = "foo=one,bar=two,qux=three";
char line_bool[] = "one,two,three";
-
- EXPECT_EQ_STR ("one", cu_mount_getoptionvalue (line_opts, "foo="));
- EXPECT_EQ_STR ("two", cu_mount_getoptionvalue (line_opts, "bar="));
- EXPECT_EQ_STR ("three", cu_mount_getoptionvalue (line_opts, "qux="));
- OK (NULL == cu_mount_getoptionvalue (line_opts, "unknown="));
-
- EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "one"));
- EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "two"));
- EXPECT_EQ_STR ("", cu_mount_getoptionvalue (line_bool, "three"));
- OK (NULL == cu_mount_getoptionvalue (line_bool, "four"));
+ char *v;
+
+ EXPECT_EQ_STR ("one", v = cu_mount_getoptionvalue (line_opts, "foo="));
+ sfree (v);
+ EXPECT_EQ_STR ("two", v = cu_mount_getoptionvalue (line_opts, "bar="));
+ sfree (v);
+ EXPECT_EQ_STR ("three", v = cu_mount_getoptionvalue (line_opts, "qux="));
+ sfree (v);
+ OK (NULL == (v = cu_mount_getoptionvalue (line_opts, "unknown=")));
+ sfree (v);
+
+ EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "one"));
+ sfree (v);
+ EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "two"));
+ sfree (v);
+ EXPECT_EQ_STR ("", v = cu_mount_getoptionvalue (line_bool, "three"));
+ sfree (v);
+ OK (NULL == (v = cu_mount_getoptionvalue (line_bool, "four")));
+ sfree (v);
return (0);
}
obj->cb_free_class (user_class_list->entry.user_class);
user_class_list->entry.user_class = NULL;
+#define CLEAR_FIELD(field) do { \
+ if (user_class_list->entry.match.field.is_regex) { \
+ regfree (&user_class_list->entry.match.field.regex); \
+ user_class_list->entry.match.field.is_regex = 0; \
+ } \
+} while (0)
+
+ CLEAR_FIELD (host);
+ CLEAR_FIELD (plugin);
+ CLEAR_FIELD (plugin_instance);
+ CLEAR_FIELD (type);
+ CLEAR_FIELD (type_instance);
+
+#undef CLEAR_FIELD
+
lu_destroy_user_obj (obj, user_class_list->entry.user_obj_list);
user_class_list->entry.user_obj_list = NULL;
pthread_mutex_destroy (&user_class_list->entry.lock);
--- /dev/null
+{
+ strlen_bogus_invalid_read_after_strdup
+ Memcheck:Addr4
+ fun:parse_value
+ fun:parse_values
+ fun:test_parse_values
+ fun:main
+}
continue;
}
- status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
+ status = virDomainMemoryStats (domains[i], minfo, VIR_DOMAIN_MEMORY_STAT_NR, 0);
if (status < 0) {
ERROR ("virt plugin: virDomainMemoryStats failed with status %i.",
#include "utils_complain.h"
#include "utils_format_graphite.h"
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
#include <netdb.h>
#define WG_DEFAULT_NODE "localhost"
static int wg_send_buffer (struct wg_callback *cb)
{
- ssize_t status = 0;
+ ssize_t status;
+
+ if (cb->sock_fd < 0)
+ return (-1);
status = swrite (cb->sock_fd, cb->send_buf, strlen (cb->send_buf));
if (status != 0)
#include "utils_cache.h"
#include "utils_format_json.h"
-#if HAVE_PTHREAD_H
-# include <pthread.h>
-#endif
-
#include <curl/curl.h>
#ifndef WRITE_HTTP_DEFAULT_BUFFER_SIZE
#include <stdint.h>
#include <librdkafka/rdkafka.h>
-#include <pthread.h>
#include <zlib.h>
#include <errno.h>
}
#endif
+static uint32_t kafka_hash(const char *keydata, size_t keylen)
+{
+ uint32_t hash = 5381;
+ for (; keylen > 0; keylen--)
+ hash = ((hash << 5) + hash) + keydata[keylen - 1];
+ return hash;
+}
+
static int32_t kafka_partition(const rd_kafka_topic_t *rkt,
const void *keydata, size_t keylen,
int32_t partition_cnt, void *p, void *m)
{
- uint32_t key = *((uint32_t *)keydata );
+ uint32_t key = kafka_hash(keydata, keylen);
uint32_t target = key % partition_cnt;
int32_t i = partition_cnt;
#include "utils_format_graphite.h"
-/* Folks without pthread will need to disable this plugin. */
-#include <pthread.h>
-
#include <netdb.h>
#define WL_BUF_SIZE 8192
#include "configfile.h"
#include "utils_cache.h"
-#include <pthread.h>
-
#if HAVE_STDINT_H
# define MONGO_HAVE_STDINT 1
#else
#include "common.h"
#include "configfile.h"
-#include <pthread.h>
#include <sys/time.h>
#include <hiredis/hiredis.h>
* Gergely Nagy <algernon at madhouse-project.org>
*/
-#include <riemann/riemann-client.h>
-#include <errno.h>
-#include <pthread.h>
-
#include "collectd.h"
+
+
#include "plugin.h"
#include "common.h"
#include "configfile.h"
#include "utils_complain.h"
#include "write_riemann_threshold.h"
+#include <errno.h>
+#include <riemann/riemann-client.h>
+
#define RIEMANN_HOST "localhost"
#define RIEMANN_PORT 5555
#define RIEMANN_TTL_FACTOR 2.0
* Andrés J. Díaz <ajdiaz at connectical.com>
**/
-#include <assert.h>
-#include <ltdl.h>
-#include <pthread.h>
-
#include "collectd.h"
#include "common.h"
#include "plugin.h"
#include "utils_threshold.h"
#include "write_riemann_threshold.h"
+#include <assert.h>
+#include <ltdl.h>
+#include <pthread.h>
+
/*
* Threshold management
* ====================
#include <errno.h>
#include <netdb.h>
#include <inttypes.h>
-#include <pthread.h>
#include <stddef.h>
#include <stdlib.h>
#include "utils_cache.h"
-#include <pthread.h>
#include <netdb.h>
#ifndef WT_DEFAULT_NODE
const char *host;
const char *port;
- memset ((void *) &ai_hints, '\0', sizeof (ai_hints));
+ memset (&ai_hints, '\0', sizeof (ai_hints));
ai_hints.ai_family = AF_UNSPEC;
ai_hints.ai_socktype = SOCK_STREAM;
--- /dev/null
+#! /bin/sh
+#
+# collectd -- testwrapper.sh
+#
+# A wrapper script for running tests. If valgrind is available, memory
+# checking will be enabled for all tests.
+
+set -e
+
+MEMCHECK=""
+
+if test -n "$VALGRIND"; then
+ MEMCHECK="$VALGRIND --quiet --tool=memcheck --error-exitcode=1"
+ MEMCHECK="$MEMCHECK --trace-children=yes"
+ MEMCHECK="$MEMCHECK --leak-check=full"
+ MEMCHECK="$MEMCHECK --gen-suppressions=all"
+
+ for f in "valgrind.$( uname -s ).suppress" "valgrind.suppress"; do
+ filename="$( dirname "$0" )/src/$f"
+ if test -e "$filename"; then
+ # Valgrind supports up to 100 suppression files.
+ MEMCHECK="$MEMCHECK --suppressions=$filename"
+ fi
+ done
+fi
+
+exec $MEMCHECK "$@"
+
+# vim: set tw=78 sw=4 ts=4 noexpandtab :
+