From: octo Date: Fri, 14 Apr 2006 10:53:44 +0000 (+0000) Subject: Merged `branches/log-mode' to `trunk' X-Git-Tag: collectd-3.8.6^2~44 X-Git-Url: https://git.octo.it/?a=commitdiff_plain;h=4ff510ffa41e47f31c695c83f045fd79efecf5f4;hp=bcd127b99eb16566fd2bdb687d3f7172e3cdbc27;p=collectd.git Merged `branches/log-mode' to `trunk' --- diff --git a/AUTHORS b/AUTHORS index 30e95ce3..7c0f895c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -22,6 +22,9 @@ tape module by: users module by: Sebastian Harl +vserver module by: + Sebastian Harl + PID-file patch by: Tommie Gannert diff --git a/ChangeLog b/ChangeLog index 92c421ca..1338d13a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2006-04-02, Version 3.9.0 + * A plugin to monitor the Apache webserver has been added. + + * A plugin to collect statistics about virtual servers using VServer. + Thanks to Sebastian Harl for writing + this plugin :) + * A plugin for wireless LAN cards has been added. It monitors signal + strength, link quality and noise ratio.. + * An option to compile collectd with different `step' and `hearbeat' + settings has been added. The size of RRAs is no longer static but + calculated based on the settings for `step' and `width'. + * The `ping' plugin can now be configured to use a certain TTL. + * A plugin to monitor the hardware sensors of Apple computers has been + added. + * The plugins `cpu', `memory', `processes' and `traffic' have been + ported to Mach/Darwin (Mac OS X). + 2006-04-09, Version 3.8.4 * Applied patch by Vincent Stehlé which improves the disk-name resolution in the `hddtemp' plugin for Linux systems. diff --git a/README b/README index 016a14b6..327d2ef1 100644 --- a/README +++ b/README @@ -66,6 +66,9 @@ Features - Users (Currently logged in users) + - VServer + (System ressources used by vservers) + * Performance: Running as a daemon collectd doesn't spend much time in startup. Since collectd links against libping, librrd and libsensors it doesn't need to start any other processes. diff --git a/TODO b/TODO index 1fe76c84..b8a5b33a 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,18 @@ +src/apple_sensors.c: Check for more sensor types. +src/battery.c: commend not working code. +general: build Darwin package + +Near future: +* Update the RPM specfile to + - build `collectd-apache' + - be free of syntax erros. + For version 3.*: * Port nfs module to solaris * Port tape module to Linux * Maybe look into porting the serial module + +http://developer.apple.com/documentation/DeviceDrivers/Conceptual/AccessingHardware/AH_IOKitLib_API/chapter_5_section_1.html +http://developer.apple.com/documentation/DeviceDrivers/Conceptual/IOKitFundamentals/index.html#//apple_ref/doc/uid/TP0000011 +http://www.gauchosoft.com/Software/X%20Resource%20Graph/ +http://johannes.sipsolutions.net/PowerBook/Apple_Motion_Sensor_Specification/ diff --git a/collectd.spec b/collectd.spec index 146bd98f..d06ca04c 100644 --- a/collectd.spec +++ b/collectd.spec @@ -1,6 +1,6 @@ Summary: Statistics collection daemon for filling RRD files. Name: collectd -Version: 3.8.4 +Version: 3.9.0 Release: 1 Source: http://verplant.org/collectd/%{name}-%{version}.tar.gz License: GPL @@ -79,6 +79,8 @@ rm -rf $RPM_BUILD_ROOT %attr(0444,root,root) %{_libdir}/%{name}/tape.so* %attr(0444,root,root) %{_libdir}/%{name}/traffic.so* %attr(0444,root,root) %{_libdir}/%{name}/users.so* +%attr(0444,root,root) %{_libdir}/%{name}/vserver.so* +%attr(0444,root,root) %{_libdir}/%{name}/wireless.so* %dir /var/lib/collectd %files mysql @@ -88,10 +90,7 @@ rm -rf $RPM_BUILD_ROOT %attr(0444,root,root) %{_libdir}/%{name}/sensors.so* %changelog -* Sun Apr 09 2006 Florian octo Forster 3.8.4-1 -- New upstream version - -* Sun Apr 02 2006 Florian octo Forster 3.8.3-1 +* Thu Mar 21 2006 Florian octo Forster 3.9.0-1 - New upstream version * Thu Mar 14 2006 Florian octo Forster 3.8.2-1 diff --git a/configure.in b/configure.in index dd20a8a8..a56c48b1 100644 --- a/configure.in +++ b/configure.in @@ -1,5 +1,5 @@ dnl Process this file with autoconf to produce a configure script. -AC_INIT(collectd, 3.8.4) +AC_INIT(collectd, 3.9.0-alpha1) AC_CONFIG_SRCDIR(src/collectd.c) AC_CONFIG_HEADERS(src/config.h) AM_INIT_AUTOMAKE(dist-bzip2) @@ -34,7 +34,9 @@ AC_HEADER_STDC AC_HEADER_SYS_WAIT AC_HEADER_DIRENT AC_CHECK_HEADERS(stdint.h) +AC_CHECK_HEADERS(stdio.h) AC_CHECK_HEADERS(errno.h) +AC_CHECK_HEADERS(math.h) AC_CHECK_HEADERS(syslog.h) AC_CHECK_HEADERS(fcntl.h) AC_CHECK_HEADERS(signal.h) @@ -134,10 +136,44 @@ AC_CHECK_HEADERS(netinet/icmp6.h, [], [], # For cpu modules AC_CHECK_HEADERS(sys/sysctl.h sys/dkstat.h) +AC_CHECK_HEADERS(mach/mach_init.h) +AC_CHECK_HEADERS(mach/host_priv.h) +AC_CHECK_HEADERS(mach/mach_error.h) +AC_CHECK_HEADERS(mach/mach_host.h) +AC_CHECK_HEADERS(mach/mach_port.h) +AC_CHECK_HEADERS(mach/mach_types.h) +AC_CHECK_HEADERS(mach/message.h) +AC_CHECK_HEADERS(mach/processor_set.h) +AC_CHECK_HEADERS(mach/processor.h) +AC_CHECK_HEADERS(mach/processor_info.h) +AC_CHECK_HEADERS(mach/task.h) +AC_CHECK_HEADERS(mach/thread_act.h) +AC_CHECK_HEADERS(mach/vm_region.h) +AC_CHECK_HEADERS(mach/vm_map.h) +AC_CHECK_HEADERS(mach/vm_prot.h) +AC_CHECK_HEADERS(mach/vm_statistics.h) +AC_CHECK_HEADERS(mach/kern_return.h) # For hddtemp module AC_CHECK_HEADERS(linux/major.h) +# For the apple_sensors module +AC_CHECK_HEADERS(CoreFoundation/CoreFoundation.h) +AC_CHECK_HEADERS(IOKit/IOKitLib.h) +AC_CHECK_HEADERS(IOKit/IOTypes.h) + +# For the battery plugin +AC_CHECK_HEADERS(IOKit/ps/IOPowerSources.h, [], [], +[ +#if HAVE_IOKIT_IOKITLIB_H +# include +#endif +#if HAVE_IOKIT_IOTYPES_H +# include +#endif +]) +AC_CHECK_HEADERS(IOKit/ps/IOPSKeys.h) + # For load module AC_CHECK_HEADERS(sys/loadavg.h) @@ -145,6 +181,42 @@ AC_CHECK_HEADERS(sys/loadavg.h) AC_CHECK_HEADERS(utmp.h) AC_CHECK_HEADERS(utmpx.h) +# For traffic plugin +AC_CHECK_HEADERS(ifaddrs.h) +AC_CHECK_HEADERS(net/if.h, [], [], +[ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +]) +AC_CHECK_HEADERS(linux/if.h, [], [], +[ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +]) +AC_CHECK_HEADERS(linux/netdevice.h, [], [], +[ +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif +#if HAVE_LINUX_IF_H +# include +#endif +]) + +# For apache plugin +AC_CHECK_HEADERS(curl/curl.h) + # For quota module AC_CHECK_HEADERS(grp.h pwd.h sys/ucred.h) AC_CHECK_HEADERS(ctype.h) @@ -203,6 +275,9 @@ AC_CHECK_FUNCS(statfs statvfs) # For load module AC_CHECK_FUNCS(getloadavg, [have_getloadavg="yes"], [have_getloadavg="no"]) +# For the `processes' plugin +AC_CHECK_FUNCS(thread_info) + # For users module AC_CHECK_FUNCS(getutent getutxent) @@ -210,6 +285,9 @@ AC_CHECK_FUNCS(getutent getutxent) AC_CHECK_FUNCS(quotactl) AC_CHECK_FUNCS(getgrgid getpwuid) +# For traffic module +AC_CHECK_FUNCS(getifaddrs) + # For mount interface AC_CHECK_FUNCS(getfsent getvfsent listmntent) AC_CHECK_FUNCS(getfsstat) @@ -280,14 +358,33 @@ if test "x$fu_cv_getmntent2" = "xyes"; then ) fi +# Check for structures +AC_CHECK_MEMBERS([struct if_data.ifi_ibytes, struct if_data.ifi_obytes], + [AC_DEFINE(HAVE_STRUCT_IF_DATA, 1, [Define if struct if_data exists and is usable.])], + [], + [ + #include + #include + #include + ]) +AC_CHECK_MEMBERS([struct net_device_stats.rx_bytes, struct net_device_stats.tx_bytes], + [AC_DEFINE(HAVE_STRUCT_NET_DEVICE_STATS, 1, [Define if struct net_device_stats exists and is usable.])], + [], + [ + #include + #include + #include + #include + ]) + AC_MSG_CHECKING([for kernel type ($host_os)]) case $host_os in *linux*) - AC_DEFINE([KERNEL_LINUX], [], [True if program is to be compiled for a Linux kernel]) + AC_DEFINE([KERNEL_LINUX], 1, [True if program is to be compiled for a Linux kernel]) ac_system="Linux" ;; *solaris*) - AC_DEFINE([KERNEL_SOLARIS], [], [True if program is to be compiled for a Solaris kernel]) + AC_DEFINE([KERNEL_SOLARIS], 1, [True if program is to be compiled for a Solaris kernel]) ac_system="Solaris" ;; *) @@ -311,6 +408,7 @@ AC_CHECK_LIB(resolv, res_search, [with_libresolv="no"]) AM_CONDITIONAL(BUILD_WITH_LIBRESOLV, test "x$with_libresolv" = "xyes") + m4_divert_once([HELP_WITH], [ collectd additional packages:]) @@ -396,9 +494,92 @@ AC_DEFINE_UNQUOTED(COLLECT_KSTAT, [$collect_kstat], [Wether or not to use kstat library (Solaris)]) AM_CONDITIONAL(BUILD_WITH_KSTAT, test "x$with_kstat" = "xyes") +### BEGIN of check for libcurl ### +with_curl_config="curl-config" +with_curl_prefix=0 +with_curl_libs="" +AC_ARG_WITH(libcurl, [AS_HELP_STRING([--with-libcurl@<:@=PREFIX@:>@], [Path to libcurl.])], +[ + if test "x$withval" != "xno" -a "x$withval" != "xyes" + then + if test -x "$withval/bin/curl-config" + then + with_curl_config="$withval/bin/curl-config" + with_curl_prefix=1 + fi + fi + if test "x$withval" = "xno" + then + with_libcurl="no" + else + with_libcurl="yes" + fi +], +[ + with_libcurl="yes" +]) +if test "x$with_libcurl" = "xyes" +then + with_curl_libs=`$with_curl_config --libs 2>/dev/null` + curl_config_status=$? + + if test $curl_config_status -ne 0 + then + with_libcurl="no" + else + AC_CHECK_LIB(curl, curl_easy_init, + [ + BUILD_WITH_LIBCURL_LIBS="$with_curl_libs" + AC_SUBST(BUILD_WITH_LIBCURL_LIBS) + ], + [ + with_libcurl="no" + ], + [$with_curl_libs]) + fi +fi +if test "x$with_libcurl" = "xyes" -a $with_curl_prefix -ne 0 +then + with_curl_prefix=`$with_curl_config --libs 2>/dev/null` + curl_config_status=$? + + if test $curl_config_status -ne 0 + then + with_libcurl="no" + else + if test -d "$with_curl_prefix/include" + then + CPPFLAGS="$CPPFLAGS -I$with_curl_prefix/include" + fi + fi +fi + +with_libcurl_numeric=0 +if test "x$with_libcurl" = "xyes" +then + with_libcurl_numeric=1 +fi +AC_DEFINE_UNQUOTED(HAVE_LIBCURL, [$with_libcurl_numeric], [Define to 1 if you have the 'curl' library (-lcurl).]) +AM_CONDITIONAL(BUILD_WITH_LIBCURL, test "x$with_libcurl" = "xyes") +### END of check for libcurl ### + +with_libiokit="no" +collectd_libiokit=0 +AC_CHECK_LIB(IOKit, IOServiceGetMatchingServices, +[ + with_libiokit="yes" + collectd_libiokit=1 +], +[ + with_libiokit="no" + collectd_libiokit=0 +]) +AC_DEFINE_UNQUOTED(COLLECT_LIBIOKIT, [$collect_libiokit], [Wether or not to use the IOKit library]) +AM_CONDITIONAL(BUILD_WITH_LIBIOKIT, test "x$with_libiokit" = "xyes") + AC_ARG_WITH(libstatgrab, [AS_HELP_STRING([--with-libstatgrab@<:@=PREFIX@:>@], [Path to libstatgrab.])], [ - if test "x$withval" != "xno" && test "x$withval" != "xyes" + if test "x$withval" != "xno" -a "x$withval" != "xyes" then LDFLAGS="$LDFLAGS -L$withval/lib" CPPFLAGS="$CPPFLAGS -I$withval/include" @@ -512,6 +693,42 @@ AC_DEFINE_UNQUOTED(COLLECT_LIBMYSQL, [$collect_libmysql], [Wether or not to use mysql library]) AM_CONDITIONAL(BUILD_WITH_LIBMYSQL, test "x$with_libmysql" = "xyes") +# Define `step' and `hearbeat' values.. +declare -i collectd_step=10 +declare -i collectd_heartbeat=25 +AC_ARG_WITH(step, [AS_HELP_STRING([--with-step=SECONDS], [Interval in which plugins are queried.])], +[ + if test "x$withval" != "xno" -a "x$withval" != "xyes" + then + declare -i tmp_collectd_step="$withval" + if test $tmp_collectd_step -gt 0 + then + collectd_step=$tmp_collectd_step + let "collectd_heartbeat=$collectd_step*2" + fi + fi +], []) +AC_ARG_WITH(heartbeat, [AS_HELP_STRING([--with-heartbeat=SECONDS], [Heartbeat of the DS in generated RRD files.])], +[ + if test "x$withval" != "xno" -a "x$withval" != "xyes" + then + declare -i tmp_collectd_heartbeat="$withval" + if test $tmp_collectd_heartbeat -gt 0 + then + collectd_heartbeat=$tmp_collectd_heartbeat + fi + fi +], []) + +if test $collectd_step -ne 10 +then + AC_DEFINE_UNQUOTED(COLLECTD_STEP, "$collectd_step", [Interval in which plugins are queried.]) +fi +if test $collectd_heartbeat -ne 25 +then + AC_DEFINE_UNQUOTED(COLLECTD_HEARTBEAT, "$collectd_heartbeat", [Interval in which plugins are queried.]) +fi + # # Check for enabled/disabled features # @@ -583,6 +800,8 @@ AC_COLLECTD([daemon], [disable], [feature], [daemon mode]) m4_divert_once([HELP_ENABLE], [ collectd modules:]) +AC_COLLECTD([apache], [disable], [module], [Apache httpd statistics]) +AC_COLLECTD([apple_sensors], [disable], [module], [Apple's hardware sensors]) AC_COLLECTD([battery], [disable], [module], [battery statistics]) AC_COLLECTD([cpu], [disable], [module], [cpu usage statistics]) AC_COLLECTD([cpufreq], [disable], [module], [system cpu frequency statistics]) @@ -602,6 +821,7 @@ AC_COLLECTD([swap], [disable], [module], [swap statistics]) AC_COLLECTD([tape], [disable], [module], [tape statistics]) AC_COLLECTD([traffic], [disable], [module], [system traffic statistics]) AC_COLLECTD([users], [disable], [module], [user count statistics]) +AC_COLLECTD([vserver], [disable], [module], [vserver statistics]) AC_COLLECTD([wireless], [disable], [module], [wireless link statistics]) #m4_divert_once([HELP_ENABLE], [ @@ -826,6 +1046,8 @@ cat < +# URL http://localhost/status?auto +# User www-user +# Password secret +# # # Host host.foo.bar diff --git a/contrib/collection.cgi b/contrib/collection.cgi index 5684475e..51e187de 100755 --- a/contrib/collection.cgi +++ b/contrib/collection.cgi @@ -53,6 +53,47 @@ our $GraphDefs; $GraphDefs = { + apache_bytes => ['DEF:min_raw={file}:count:MIN', + 'DEF:avg_raw={file}:count:AVERAGE', + 'DEF:max_raw={file}:count:MAX', + 'CDEF:min=min_raw,8,*', + 'CDEF:avg=avg_raw,8,*', + 'CDEF:max=max_raw,8,*', + 'CDEF:mytime=avg_raw,TIME,TIME,IF', + 'CDEF:sample_len_raw=mytime,PREV(mytime),-', + 'CDEF:sample_len=sample_len_raw,UN,0,sample_len_raw,IF', + 'CDEF:avg_sample=avg_raw,UN,0,avg_raw,IF,sample_len,*', + 'CDEF:avg_sum=PREV,UN,0,PREV,IF,avg_sample,+', + "AREA:avg#$HalfBlue", + "LINE1:avg#$FullBlue:Bit/s", + 'GPRINT:min:MIN:%5.1lf%s Min,', + 'GPRINT:avg:AVERAGE:%5.1lf%s Avg,', + 'GPRINT:max:MAX:%5.1lf%s Max,', + 'GPRINT:avg:LAST:%5.1lf%s Last', + 'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l' + ], + apache_requests => ['DEF:min={file}:count:MIN', + 'DEF:avg={file}:count:AVERAGE', + 'DEF:max={file}:count:MAX', + "AREA:max#$HalfBlue", + "AREA:min#$Canvas", + "LINE1:avg#$FullBlue:Requests/s", + 'GPRINT:min:MIN:%6.2lf Min,', + 'GPRINT:avg:AVERAGE:%6.2lf Avg,', + 'GPRINT:max:MAX:%6.2lf Max,', + 'GPRINT:avg:LAST:%6.2lf Last' + ], + apache_scoreboard => ['DEF:min={file}:count:MIN', + 'DEF:avg={file}:count:AVERAGE', + 'DEF:max={file}:count:MAX', + "AREA:max#$HalfBlue", + "AREA:min#$Canvas", + "LINE1:avg#$FullBlue:Processes", + 'GPRINT:min:MIN:%6.2lf Min,', + 'GPRINT:avg:AVERAGE:%6.2lf Avg,', + 'GPRINT:max:MAX:%6.2lf Max,', + 'GPRINT:avg:LAST:%6.2lf Last' + ], charge => [ 'DEF:avg={file}:charge:AVERAGE', 'DEF:min={file}:charge:MIN', @@ -262,8 +303,10 @@ our $GraphDefs; 'DEF:free_max={file}:free:MAX', 'DEF:buffers_max={file}:buffers:MAX', 'DEF:cached_max={file}:cached:MAX', - 'CDEF:free_cached_buffers_used=free_avg,cached_avg,+,buffers_avg,+,used_avg,+', - 'CDEF:cached_buffers_used=cached_avg,buffers_avg,+,used_avg,+', + 'CDEF:cached_avg_nn=cached_avg,UN,0,cached_avg,IF', + 'CDEF:buffers_avg_nn=buffers_avg,UN,0,buffers_avg,IF', + 'CDEF:free_cached_buffers_used=free_avg,cached_avg_nn,+,buffers_avg_nn,+,used_avg,+', + 'CDEF:cached_buffers_used=cached_avg,buffers_avg_nn,+,used_avg,+', 'CDEF:buffers_used=buffers_avg,used_avg,+', "AREA:free_cached_buffers_used#$HalfGreen", "AREA:cached_buffers_used#$HalfBlue", @@ -718,7 +761,87 @@ our $GraphDefs; 'GPRINT:avg:AVERAGE:%5.1lf%sV Avg,', 'GPRINT:max:MAX:%5.1lf%sV Max,', 'GPRINT:avg:LAST:%5.1lf%sV Last\l' - ] + ], + threads => [ + "DEF:total_avg={file}:total:AVERAGE", + "DEF:total_min={file}:total:MIN", + "DEF:total_max={file}:total:MAX", + "DEF:running_avg={file}:running:AVERAGE", + "DEF:running_min={file}:running:MIN", + "DEF:running_max={file}:running:MAX", + "DEF:uninterruptible_avg={file}:uninterruptible:AVERAGE", + "DEF:uninterruptible_min={file}:uninterruptible:MIN", + "DEF:uninterruptible_max={file}:uninterruptible:MAX", + "DEF:onhold_avg={file}:onhold:AVERAGE", + "DEF:onhold_min={file}:onhold:MIN", + "DEF:onhold_max={file}:onhold:MAX", + "LINE1:total_avg#$FullYellow:Total ", + 'GPRINT:total_min:MIN:%5.1lf Min,', + 'GPRINT:total_avg:AVERAGE:%5.1lf Avg.,', + 'GPRINT:total_max:MAX:%5.1lf Max,', + 'GPRINT:total_avg:LAST:%5.1lf Last\l', + "LINE1:running_avg#$FullRed:Running ", + 'GPRINT:running_min:MIN:%5.1lf Min,', + 'GPRINT:running_avg:AVERAGE:%5.1lf Avg.,', + 'GPRINT:running_max:MAX:%5.1lf Max,', + 'GPRINT:running_avg:LAST:%5.1lf Last\l', + "LINE1:uninterruptible_avg#$FullGreen:Unintr ", + 'GPRINT:uninterruptible_min:MIN:%5.1lf Min,', + 'GPRINT:uninterruptible_avg:AVERAGE:%5.1lf Avg.,', + 'GPRINT:uninterruptible_max:MAX:%5.1lf Max,', + 'GPRINT:uninterruptible_avg:LAST:%5.1lf Last\l', + "LINE1:onhold_avg#$FullBlue:Onhold ", + 'GPRINT:onhold_min:MIN:%5.1lf Min,', + 'GPRINT:onhold_avg:AVERAGE:%5.1lf Avg.,', + 'GPRINT:onhold_max:MAX:%5.1lf Max,', + 'GPRINT:onhold_avg:LAST:%5.1lf Last\l' + ], + vs_memory => [ + 'DEF:vm_avg={file}:vm:AVERAGE', + 'DEF:vm_min={file}:vm:MIN', + 'DEF:vm_max={file}:vm:MAX', + 'DEF:vml_avg={file}:vml:AVERAGE', + 'DEF:vml_min={file}:vml:MIN', + 'DEF:vml_max={file}:vml:MAX', + 'DEF:rss_avg={file}:rss:AVERAGE', + 'DEF:rss_min={file}:rss:MIN', + 'DEF:rss_max={file}:rss:MAX', + 'DEF:anon_avg={file}:anon:AVERAGE', + 'DEF:anon_min={file}:anon:MIN', + 'DEF:anon_max={file}:anon:MAX', + "LINE1:vm_avg#$FullYellow:VM ", + 'GPRINT:vm_min:MIN:%5.1lf%s Min,', + 'GPRINT:vm_avg:AVERAGE:%5.1lf%s Avg.,', + 'GPRINT:vm_max:MAX:%5.1lf%s Avg.,', + 'GPRINT:vm_avg:LAST:%5.1lf%s Last\l', + "LINE1:vml_avg#$FullRed:Locked ", + 'GPRINT:vml_min:MIN:%5.1lf%s Min,', + 'GPRINT:vml_avg:AVERAGE:%5.1lf%s Avg.,', + 'GPRINT:vml_max:MAX:%5.1lf%s Avg.,', + 'GPRINT:vml_avg:LAST:%5.1lf%s Last\l', + "LINE1:rss_avg#$FullGreen:RSS ", + 'GPRINT:rss_min:MIN:%5.1lf%s Min,', + 'GPRINT:rss_avg:AVERAGE:%5.1lf%s Avg.,', + 'GPRINT:rss_max:MAX:%5.1lf%s Avg.,', + 'GPRINT:rss_avg:LAST:%5.1lf%s Last\l', + "LINE1:anon_avg#$FullBlue:Anon. ", + 'GPRINT:anon_min:MIN:%5.1lf%s Min,', + 'GPRINT:anon_avg:AVERAGE:%5.1lf%s Avg.,', + 'GPRINT:anon_max:MAX:%5.1lf%s Avg.,', + 'GPRINT:anon_avg:LAST:%5.1lf%s Last\l', + ], + vs_processes => [ + 'DEF:proc_avg={file}:total:AVERAGE', + 'DEF:proc_min={file}:total:MIN', + 'DEF:proc_max={file}:total:MAX', + "AREA:proc_max#$HalfBlue", + "AREA:proc_min#$Canvas", + "LINE1:proc_avg#$FullBlue:Processes", + 'GPRINT:proc_min:MIN:%4.1lf Min,', + 'GPRINT:proc_avg:AVERAGE:%4.1lf Avg.,', + 'GPRINT:proc_max:MAX:%4.1lf Max,', + 'GPRINT:proc_avg:LAST:%4.1lf Last\l' + ], }; $GraphDefs->{'disk'} = $GraphDefs->{'partition'}; $GraphDefs->{'meminfo'} = $GraphDefs->{'memory'}; @@ -726,6 +849,9 @@ our $GraphDefs; our $GraphArgs = { + apache_bytes => ['-t', 'apache traffic', '-v', 'Bit/s'], + apache_requests => ['-t', 'apache requests', '-v', 'Requests/s'], + apache_scoreboard => ['-t', 'apache scoreboard {inst}', '-v', 'Processes'], charge => ['-t', '{host} charge', '-v', 'Ampere hours'], cpu => ['-t', '{host} cpu{inst} usage', '-v', 'Percent', '-l', '0'], cpufreq => ['-t', '{host} cpu{inst} usage', '-v', 'Mhz'], @@ -749,11 +875,15 @@ our $GraphArgs = swap => ['-t', '{host} swap usage', '-v', 'Bytes', '-b', '1024', '-l', '0'], traffic => ['-t', '{host} {inst} traffic', '-v', 'Bit/s'], users => ['-t', '{host} users', '-v', 'Users'], - voltage => ['-t', '{host} voltage', '-v', 'Volts'] + voltage => ['-t', '{host} voltage', '-v', 'Volts'], + threads => ['-t', '{host} threads', '-v', 'Threads'], + vs_memory => ['-t', '{host} memory usage', '-v', 'Bytes'], + vs_processes => ['-t', '{host} processes', '-v', 'Processes'], }; our $GraphMulti = { + apache_scoreboard => \&output_graph_apache_scoreboard, cpu => \&output_graph_cpu, cpufreq => 1, disk => 1, @@ -856,6 +986,49 @@ sub output_graph_cpu return (@ret); } +sub output_graph_apache_scoreboard +{ + my @inst = @_; + my @ret = (); + + die if (@inst < 2); + + my @colors = get_n_colors (scalar (@inst)); + + for (my $i = 0; $i < scalar (@inst); $i++) + { + my $inst = $inst[$i]; + push (@ret, + "DEF:avg_$i=$AbsDir/apache_scoreboard-$inst.rrd:count:AVERAGE", + "DEF:min_$i=$AbsDir/apache_scoreboard-$inst.rrd:count:MIN", + "DEF:max_$i=$AbsDir/apache_scoreboard-$inst.rrd:count:MAX"); + } + + for (my $i = 0; $i < scalar (@inst); $i++) + { + my $inst = $inst[$i]; + my $color = $colors[$i]; + + if (length ($inst) > 15) + { + $inst = substr ($inst, 0, 12) . '...'; + } + else + { + $inst = sprintf ('%-15s', $inst); + } + + push (@ret, + "LINE1:avg_$i#$color:$inst", + "GPRINT:min_$i:MIN:%6.2lf Min,", + "GPRINT:avg_$i:AVERAGE:%6.2lf Avg,", + "GPRINT:max_$i:MAX:%6.2lf Max,", + "GPRINT:avg_$i:LAST:%6.2lf Last\\l"); + } + + return (@ret); +} + sub output_graph_ping { my @inst = @_; @@ -1025,6 +1198,7 @@ sub output_graph $Inst = $files->{$Type}[0]; } + #push (@cmd, '-', '-a', 'PNG', '-s', $TimeSpan, '-w', 800, '-h', 150); push (@cmd, '-', '-a', 'PNG', '-s', $TimeSpan); push (@cmd, @{$GraphArgs->{$Type}}) if (defined ($GraphArgs->{$Type})); @@ -1119,6 +1293,8 @@ HEADER print < +

Hourly

+

Daily

Weekly

@@ -1143,6 +1319,8 @@ HTML } print <Hourly +

Daily

Weekly

diff --git a/debian/changelog b/debian/changelog index 29cfedaa..d35c75f0 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,14 +1,8 @@ -collectd (3.8.4-1) unstable; urgency=low +collectd (3.9.0-1) unstable; urgency=low * New upstream version - -- Florian Forster Sun, 9 Apr 2006 16:01:11 +0200 - -collectd (3.8.3-1) unstable; urgency=low - - * New upstream version - - -- Florian Forster Sun, 2 Apr 2006 10:34:05 +0200 + -- Florian Forster Tue, 21 Mar 2006 22:52:54 +0200 collectd (3.8.2-1) unstable; urgency=low diff --git a/debian/collectd-apache.files b/debian/collectd-apache.files new file mode 100644 index 00000000..f983e900 --- /dev/null +++ b/debian/collectd-apache.files @@ -0,0 +1 @@ +usr/lib/collectd/apache.so* diff --git a/debian/control b/debian/control index 9b3b9cae..69918a51 100644 --- a/debian/control +++ b/debian/control @@ -2,7 +2,7 @@ Source: collectd Section: utils Priority: optional Maintainer: Florian Forster -Build-Depends: debhelper (>= 4.0.0), autotools-dev, librrd0-dev | librrd2-dev, libsensors-dev, libmysqlclient14-dev +Build-Depends: debhelper (>= 4.0.0), autotools-dev, librrd0-dev | librrd2-dev, libsensors-dev, libmysqlclient14-dev, libcurl3-dev Standards-Version: 3.6.1 Package: collectd @@ -16,6 +16,13 @@ Description: Statistics collection daemon for filling RRD files. it's very fast and easy on the system. Also, the statistics are very fine grained since the files are updated every 10 seconds. +Package: collectd-apache +Architecture: any +Depends: collectd (= ${Source-Version}), apache2 | apache, libcurl3 +Description: collectd plugin for Apache-statistics + collectd module to collect Apache statistics. It reads the page generated by + `mod_status' and writes it's content into RRD files. + Package: collectd-mysql Architecture: any Depends: collectd (= ${Source-Version}), libmysqlclient14 diff --git a/debian/rules b/debian/rules index d64075d7..5ae57619 100755 --- a/debian/rules +++ b/debian/rules @@ -18,7 +18,7 @@ DEB_BUILD_GNU_TYPE ?= $(shell dpkg-architecture -qDEB_BUILD_GNU_TYPE) CFLAGS = -Wall -g -PLUGINS = mysql sensors +PLUGINS = apache mysql sensors ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CFLAGS += -O0 diff --git a/src/Makefile.am b/src/Makefile.am index 25634629..c554abe9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -44,17 +44,42 @@ collectd_DEPENDENCIES = $(LIBLTDL) libconfig/libconfig.la pkglib_LTLIBRARIES = +if BUILD_MODULE_APACHE +pkglib_LTLIBRARIES += apache.la +apache_la_SOURCES = apache.c +apache_la_LDFLAGS = -module -avoid-version +if BUILD_WITH_LIBCURL +apache_la_LDFLAGS += $(BUILD_WITH_LIBCURL_LIBS) +endif +collectd_LDADD += "-dlopen" apache.la +collectd_DEPENDENCIES += apache.la +endif + +if BUILD_MODULE_APPLE_SENSORS +pkglib_LTLIBRARIES += apple_sensors.la +apple_sensors_la_SOURCES = apple_sensors.c +apple_sensors_la_LDFLAGS = -module -avoid-version +if BUILD_WITH_LIBIOKIT +apple_sensors_la_LDFLAGS += -lIOKit +endif +collectd_LDADD += "-dlopen" apple_sensors.la +collectd_DEPENDENCIES += apple_sensors.la +endif + if BUILD_MODULE_BATTERY pkglib_LTLIBRARIES += battery.la battery_la_SOURCES = battery.c battery_la_LDFLAGS = -module -avoid-version +if BUILD_WITH_LIBIOKIT +battery_la_LDFLAGS += -lIOKit +endif collectd_LDADD += "-dlopen" battery.la collectd_DEPENDENCIES += battery.la endif if BUILD_MODULE_CPU pkglib_LTLIBRARIES += cpu.la -cpu_la_SOURCES = cpu.c cpu.h +cpu_la_SOURCES = cpu.c cpu_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" cpu.la collectd_DEPENDENCIES += cpu.la @@ -62,7 +87,7 @@ endif if BUILD_MODULE_CPUFREQ pkglib_LTLIBRARIES += cpufreq.la -cpufreq_la_SOURCES = cpufreq.c cpufreq.h +cpufreq_la_SOURCES = cpufreq.c cpufreq_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" cpufreq.la collectd_DEPENDENCIES += cpufreq.la @@ -78,7 +103,7 @@ endif if BUILD_MODULE_DISK pkglib_LTLIBRARIES += disk.la -disk_la_SOURCES = disk.c disk.h +disk_la_SOURCES = disk.c disk_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" disk.la collectd_DEPENDENCIES += disk.la @@ -97,7 +122,7 @@ endif if BUILD_MODULE_HDDTEMP pkglib_LTLIBRARIES += hddtemp.la -hddtemp_la_SOURCES = hddtemp.c hddtemp.h +hddtemp_la_SOURCES = hddtemp.c hddtemp_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" hddtemp.la collectd_DEPENDENCIES += hddtemp.la @@ -105,7 +130,7 @@ endif if BUILD_MODULE_LOAD pkglib_LTLIBRARIES += load.la -load_la_SOURCES = load.c load.h +load_la_SOURCES = load.c load_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" load.la collectd_DEPENDENCIES += load.la @@ -113,7 +138,7 @@ endif if BUILD_MODULE_MEMORY pkglib_LTLIBRARIES += memory.la -memory_la_SOURCES = memory.c memory.h +memory_la_SOURCES = memory.c memory_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" memory.la collectd_DEPENDENCIES += memory.la @@ -132,7 +157,7 @@ endif if BUILD_MODULE_NFS pkglib_LTLIBRARIES += nfs.la -nfs_la_SOURCES = nfs.c nfs.h +nfs_la_SOURCES = nfs.c nfs_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" nfs.la collectd_DEPENDENCIES += nfs.la @@ -140,7 +165,7 @@ endif if BUILD_MODULE_PING pkglib_LTLIBRARIES += ping.la -ping_la_SOURCES = ping.c ping.h +ping_la_SOURCES = ping.c ping_la_LDFLAGS = -module -avoid-version ping_la_LIBADD = liboping/liboping.la ping_la_DEPENDENCIES = liboping/liboping.la @@ -150,7 +175,7 @@ endif if BUILD_MODULE_PROCESSES pkglib_LTLIBRARIES += processes.la -processes_la_SOURCES = processes.c processes.h +processes_la_SOURCES = processes.c processes_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" processes.la collectd_DEPENDENCIES += processes.la @@ -158,7 +183,7 @@ endif if BUILD_MODULE_SENSORS pkglib_LTLIBRARIES += sensors.la -sensors_la_SOURCES = sensors.c sensors.h +sensors_la_SOURCES = sensors.c sensors_la_LDFLAGS = -module -avoid-version if BUILD_WITH_LM_SENSORS sensors_la_LDFLAGS += -lsensors @@ -169,7 +194,7 @@ endif if BUILD_MODULE_SERIAL pkglib_LTLIBRARIES += serial.la -serial_la_SOURCES = serial.c serial.h +serial_la_SOURCES = serial.c serial_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" serial.la collectd_DEPENDENCIES += serial.la @@ -177,7 +202,7 @@ endif if BUILD_MODULE_SWAP pkglib_LTLIBRARIES += swap.la -swap_la_SOURCES = swap.c swap.h +swap_la_SOURCES = swap.c swap_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" swap.la collectd_DEPENDENCIES += swap.la @@ -185,7 +210,7 @@ endif if BUILD_MODULE_TAPE pkglib_LTLIBRARIES += tape.la -tape_la_SOURCES = tape.c tape.h +tape_la_SOURCES = tape.c tape_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" tape.la collectd_DEPENDENCIES += tape.la @@ -193,7 +218,7 @@ endif if BUILD_MODULE_TRAFFIC pkglib_LTLIBRARIES += traffic.la -traffic_la_SOURCES = traffic.c traffic.h +traffic_la_SOURCES = traffic.c traffic_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" traffic.la collectd_DEPENDENCIES += traffic.la @@ -201,18 +226,24 @@ endif if BUILD_MODULE_USERS pkglib_LTLIBRARIES += users.la -users_la_SOURCES = users.c users.h +users_la_SOURCES = users.c users_la_LDFLAGS = -module -avoid-version collectd_LDADD += "-dlopen" users.la collectd_DEPENDENCIES += users.la endif +if BUILD_MODULE_VSERVER +pkglib_LTLIBRARIES += vserver.la +vserver_la_SOURCES = vserver.c +vserver_la_LDFLAGS = -module -avoid-version +collectd_LDADD += "-dlopen" vserver.la +collectd_DEPENDENCIES += vserver.la +endif + if BUILD_MODULE_WIRELESS pkglib_LTLIBRARIES += wireless.la wireless_la_SOURCES = wireless.c wireless_la_LDFLAGS = -module -avoid-version -# FIXME Make `-lm' conditional -wireless_la_LDFLAGS += -lm collectd_LDADD += "-dlopen" wireless.la collectd_DEPENDENCIES += wireless.la endif diff --git a/src/apache.c b/src/apache.c new file mode 100644 index 00000000..c410dc43 --- /dev/null +++ b/src/apache.c @@ -0,0 +1,328 @@ +/** + * collectd - src/apache.c + * Copyright (C) 2006 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "configfile.h" + +#define MODULE_NAME "apache" + +#if HAVE_LIBCURL && HAVE_CURL_CURL_H +# define APACHE_HAVE_READ 1 +# include +#else +# define APACHE_HAVE_READ 0 +#endif + +static char *url = NULL; +static char *user = NULL; +static char *pass = NULL; + +#if APACHE_HAVE_READ +static CURL *curl = NULL; + +static char apache_buffer[4096]; +static int apache_buffer_len = 0; +static char apache_curl_error[CURL_ERROR_SIZE]; +#endif + +/* Limit to 2^27 bytes/s. That's what a gigabit-ethernet link can handle, in + * theory. */ +static char *bytes_file = "apache/apache_bytes.rrd"; +static char *bytes_ds_def[] = +{ + "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:134217728", + NULL +}; +static int bytes_ds_num = 1; + +/* Limit to 2^20 requests/s */ +static char *requests_file = "apache/apache_requests.rrd"; +static char *requests_ds_def[] = +{ + "DS:count:COUNTER:"COLLECTD_HEARTBEAT":0:1048576", + NULL +}; +static int requests_ds_num = 1; + +static char *scoreboard_file = "apache/apache_scoreboard-%s.rrd"; +static char *scoreboard_ds_def[] = +{ + "DS:count:GAUGE:"COLLECTD_HEARTBEAT":0:U", + NULL +}; +static int scoreboard_ds_num = 1; + +static char *config_keys[] = +{ + "URL", + "User", + "Password", + NULL +}; +static int config_keys_num = 3; + + +static size_t apache_curl_callback (void *buf, size_t size, size_t nmemb, void *stream) +{ + size_t len = size * nmemb; + + if ((apache_buffer_len + len) >= 4096) + { + len = 4095 - apache_buffer_len; + } + + if (len <= 0) + return (len); + + memcpy (apache_buffer + apache_buffer_len, (char *) buf, len); + apache_buffer_len += len; + apache_buffer[apache_buffer_len] = '\0'; + + return (len); +} + +static int config_set (char **var, char *value) +{ + if (*var != NULL) + { + free (*var); + *var = NULL; + } + + if ((*var = strdup (value)) == NULL) + return (1); + else + return (0); +} + +static int config (char *key, char *value) +{ + if (strcasecmp (key, "url") == 0) + return (config_set (&url, value)); + else if (strcasecmp (key, "user") == 0) + return (config_set (&user, value)); + else if (strcasecmp (key, "password") == 0) + return (config_set (&pass, value)); + else + return (-1); +} + +static void init (void) +{ +#if APACHE_HAVE_READ + static char credentials[1024]; + + if (curl != NULL) + { + curl_easy_cleanup (curl); + } + + if ((curl = curl_easy_init ()) == NULL) + { + syslog (LOG_ERR, "apache: `curl_easy_init' failed."); + return; + } + + curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, apache_curl_callback); + curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION); + curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, apache_curl_error); + + if (user != NULL) + { + if (snprintf (credentials, 1024, "%s:%s", user, pass == NULL ? "" : pass) >= 1024) + { + syslog (LOG_ERR, "apache: Credentials would have been truncated."); + return; + } + + curl_easy_setopt (curl, CURLOPT_USERPWD, credentials); + } + + if (url != NULL) + { + curl_easy_setopt (curl, CURLOPT_URL, url); + } +#endif /* APACHE_HAVE_READ */ +} + +static void bytes_write (char *host, char *inst, char *val) +{ + rrd_update_file (host, bytes_file, val, bytes_ds_def, bytes_ds_num); +} + +static void requests_write (char *host, char *inst, char *val) +{ + rrd_update_file (host, requests_file, val, requests_ds_def, requests_ds_num); +} + +static void scoreboard_write (char *host, char *inst, char *val) +{ + char buf[1024]; + + if (snprintf (buf, 1024, scoreboard_file, inst) >= 1024) + return; + + rrd_update_file (host, buf, val, scoreboard_ds_def, scoreboard_ds_num); +} + +#if APACHE_HAVE_READ +static void submit (char *type, char *inst, long long value) +{ + char buf[1024]; + int status; + + status = snprintf (buf, 1024, "%u:%lli", (unsigned int) curtime, value); + if (status < 0) + { + syslog (LOG_ERR, "apache: bytes_submit: snprintf failed"); + return; + } + else if (status >= 1024) + { + syslog (LOG_WARNING, "apache: bytes_submit: snprintf was truncated"); + return; + } + + plugin_submit (type, inst, buf); +} + +static void submit_scoreboard (char *buf) +{ + /* + * Scoreboard Key: + * "_" Waiting for Connection, "S" Starting up, "R" Reading Request, + * "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup, + * "C" Closing connection, "L" Logging, "G" Gracefully finishing, + * "I" Idle cleanup of worker, "." Open slot with no current process + */ + long long open = 0LL; + long long waiting = 0LL; + long long starting = 0LL; + long long reading = 0LL; + long long sending = 0LL; + long long keepalive = 0LL; + long long dnslookup = 0LL; + long long closing = 0LL; + long long logging = 0LL; + long long finishing = 0LL; + long long idle_cleanup = 0LL; + + int i; + + for (i = 0; buf[i] != '\0'; i++) + { + if (buf[i] == '.') open++; + else if (buf[i] == '_') waiting++; + else if (buf[i] == 'S') starting++; + else if (buf[i] == 'R') reading++; + else if (buf[i] == 'W') sending++; + else if (buf[i] == 'K') keepalive++; + else if (buf[i] == 'D') dnslookup++; + else if (buf[i] == 'C') closing++; + else if (buf[i] == 'L') logging++; + else if (buf[i] == 'G') finishing++; + else if (buf[i] == 'I') idle_cleanup++; + } + + submit ("apache_scoreboard", "open" , open); + submit ("apache_scoreboard", "waiting" , waiting); + submit ("apache_scoreboard", "starting" , starting); + submit ("apache_scoreboard", "reading" , reading); + submit ("apache_scoreboard", "sending" , sending); + submit ("apache_scoreboard", "keepalive", keepalive); + submit ("apache_scoreboard", "dnslookup", dnslookup); + submit ("apache_scoreboard", "closing" , closing); + submit ("apache_scoreboard", "logging" , logging); + submit ("apache_scoreboard", "finishing", finishing); + submit ("apache_scoreboard", "idle_cleanup", idle_cleanup); +} + +static void apache_read (void) +{ + int i; + + char *ptr; + char *lines[16]; + int lines_num = 0; + + char *fields[4]; + int fields_num; + + if (curl == NULL) + return; + if (url == NULL) + return; + + if (curl_easy_perform (curl) != 0) + { + syslog (LOG_WARNING, "apache: curl_easy_perform failed: %s", apache_curl_error); + return; + } + + ptr = apache_buffer; + while ((lines[lines_num] = strtok (ptr, "\n\r")) != NULL) + { + ptr = NULL; + lines_num++; + + if (lines_num >= 16) + break; + } + + for (i = 0; i < lines_num; i++) + { + fields_num = strsplit (lines[i], fields, 4); + + if (fields_num == 3) + { + if ((strcmp (fields[0], "Total") == 0) + && (strcmp (fields[1], "Accesses:") == 0)) + submit ("apache_requests", NULL, atoll (fields[2])); + else if ((strcmp (fields[0], "Total") == 0) + && (strcmp (fields[1], "kBytes:") == 0)) + submit ("apache_bytes", NULL, 1024LL * atoll (fields[2])); + } + else if (fields_num == 2) + { + if (strcmp (fields[0], "Scoreboard:") == 0) + submit_scoreboard (fields[1]); + } + } + + apache_buffer_len = 0; +} +#else +# define apache_read NULL +#endif /* APACHE_HAVE_READ */ + +void module_register (void) +{ + plugin_register (MODULE_NAME, init, apache_read, NULL); + plugin_register ("apache_requests", NULL, NULL, requests_write); + plugin_register ("apache_bytes", NULL, NULL, bytes_write); + plugin_register ("apache_scoreboard", NULL, NULL, scoreboard_write); + cf_register (MODULE_NAME, config, config_keys, config_keys_num); +} + +#undef MODULE_NAME diff --git a/src/apple_sensors.c b/src/apple_sensors.c new file mode 100644 index 00000000..24e8f977 --- /dev/null +++ b/src/apple_sensors.c @@ -0,0 +1,268 @@ +/** + * collectd - src/apple_sensors.c + * Copyright (C) 2006 Florian octo Forster + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Florian octo Forster + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" +#include "utils_debug.h" + +#define MODULE_NAME "apple_sensors" + +#if HAVE_CTYPE_H +# include +#endif + +#if HAVE_MACH_MACH_TYPES_H +# include +#endif +#if HAVE_MACH_MACH_INIT_H +# include +#endif +#if HAVE_MACH_MACH_ERROR_H +# include +#endif +#if HAVE_MACH_MACH_PORT_H +# include +#endif +#if HAVE_COREFOUNDATION_COREFOUNDATION_H +# include +#endif +#if HAVE_IOKIT_IOKITLIB_H +# include +#endif +#if HAVE_IOKIT_IOTYPES_H +# include +#endif + +#if HAVE_IOKIT_IOKITLIB_H +# define IOKIT_HAVE_READ 1 +#else +# define IOKIT_HAVE_READ 0 +#endif + +#if HAVE_IOKIT_IOKITLIB_H +static mach_port_t io_master_port = MACH_PORT_NULL; +#endif + +static char *temperature_file = "apple_sensors/temperature-%s.rrd"; +static char *fanspeed_file = "apple_sensors/fanspeed-%s.rrd"; + +static char *ds_def[] = +{ + "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U", + NULL +}; +static int ds_num = 1; + +static void as_init (void) +{ +#if IOKIT_HAVE_READ + kern_return_t status; + + if (io_master_port != MACH_PORT_NULL) + { + mach_port_deallocate (mach_task_self (), + io_master_port); + io_master_port = MACH_PORT_NULL; + } + + status = IOMasterPort (MACH_PORT_NULL, &io_master_port); + if (status != kIOReturnSuccess) + { + syslog (LOG_ERR, "IOMasterPort failed: %s", + mach_error_string (status)); + io_master_port = MACH_PORT_NULL; + return; + } +#endif /* IOKIT_HAVE_READ */ + + return; +} + +static void as_write (char *host, char *inst, char *val, const char *template) +{ + char filename[256]; + int status; + + status = snprintf (filename, 256, template, inst); + if ((status < 1) || (status >= 256)) + return; + + rrd_update_file (host, filename, val, ds_def, ds_num); +} + +static void temperature_write (char *host, char *inst, char *val) +{ + as_write (host, inst, val, temperature_file); +} + +static void fanspeed_write (char *host, char *inst, char *val) +{ + as_write (host, inst, val, fanspeed_file); +} + +#if IOKIT_HAVE_READ +static void as_submit (char *type, char *inst, double value) +{ + char buf[128]; + + if (snprintf (buf, 1024, "%u:%f", (unsigned int) curtime, + value) >= 128) + return; + + plugin_submit (type, inst, buf); +} + +static void as_read (void) +{ + kern_return_t status; + io_iterator_t iterator; + io_object_t io_obj; + CFMutableDictionaryRef prop_dict; + CFTypeRef property; + + char type[128]; + char inst[128]; + int value_int; + double value_double; + int i; + + if (!io_master_port || (io_master_port == MACH_PORT_NULL)) + return; + + status = IOServiceGetMatchingServices (io_master_port, + IOServiceNameMatching("IOHWSensor"), + &iterator); + if (status != kIOReturnSuccess) + { + syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s", + mach_error_string (status)); + return; + } + + while ((io_obj = IOIteratorNext (iterator))) + { + prop_dict = NULL; + status = IORegistryEntryCreateCFProperties (io_obj, + &prop_dict, + kCFAllocatorDefault, + kNilOptions); + if (status != kIOReturnSuccess) + { + DBG ("IORegistryEntryCreateCFProperties failed: %s", + mach_error_string (status)); + continue; + } + + /* Copy the sensor type. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent (prop_dict, + CFSTR ("type"), + &property)) + continue; + if (CFGetTypeID (property) != CFStringGetTypeID ()) + continue; + if (!CFStringGetCString (property, + type, 128, + kCFStringEncodingASCII)) + continue; + type[127] = '\0'; + + /* Copy the sensor location. This will be used as `instance'. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent (prop_dict, + CFSTR ("location"), + &property)) + continue; + if (CFGetTypeID (property) != CFStringGetTypeID ()) + continue; + if (!CFStringGetCString (property, + inst, 128, + kCFStringEncodingASCII)) + continue; + inst[127] = '\0'; + for (i = 0; i < 128; i++) + { + if (inst[i] == '\0') + break; + else if (isalnum (inst[i])) + inst[i] = (char) tolower (inst[i]); + else + inst[i] = '_'; + } + + /* Get the actual value. Some computation, based on the `type' + * is neccessary. */ + property = NULL; + if (!CFDictionaryGetValueIfPresent (prop_dict, + CFSTR ("current-value"), + &property)) + continue; + if (CFGetTypeID (property) != CFNumberGetTypeID ()) + continue; + if (!CFNumberGetValue (property, + kCFNumberIntType, + &value_int)) + continue; + + if (strcmp (type, "temperature") == 0) + { + value_double = ((double) value_int) / 65536.0; + strncpy (type, "apple_temperature", 128); + } + else if (strcmp (type, "fanspeed") == 0) + { + value_double = ((double) value_int) / 65536.0; + strncpy (type, "apple_fanspeed", 128); + } + else if (strcmp (type, "voltage") == 0) + { + /* Leave this to the battery plugin. */ + continue; + } + else + { + DBG ("apple_sensors: Read unknown sensor type: %s", + type); + value_double = (double) value_int; + } + + as_submit (type, inst, value_double); + + CFRelease (prop_dict); + IOObjectRelease (io_obj); + } /* while (iterator) */ + + IOObjectRelease (iterator); +} +#else +# define as_read NULL +#endif /* IOKIT_HAVE_READ */ + +void module_register (void) +{ + plugin_register (MODULE_NAME, as_init, as_read, NULL); + plugin_register ("apple_temperature", NULL, NULL, temperature_write); + plugin_register ("apple_fanspeed", NULL, NULL, fanspeed_write); +} + +#undef MODULE_NAME diff --git a/src/battery.c b/src/battery.c index 21b19bb7..61379e02 100644 --- a/src/battery.c +++ b/src/battery.c @@ -23,11 +23,37 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_debug.h" #define MODULE_NAME "battery" #define BUFSIZE 512 -#if defined(KERNEL_LINUX) +#if HAVE_MACH_MACH_TYPES_H +# include +#endif +#if HAVE_MACH_MACH_INIT_H +# include +#endif +#if HAVE_MACH_MACH_ERROR_H +# include +#endif +#if HAVE_COREFOUNDATION_COREFOUNDATION_H +# include +#endif +#if HAVE_IOKIT_IOKITLIB_H +# include +#endif +#if HAVE_IOKIT_IOTYPES_H +# include +#endif +#if HAVE_IOKIT_PS_IOPOWERSOURCES_H +# include +#endif +#if HAVE_IOKIT_PS_IOPSKEYS_H +# include +#endif + +#if HAVE_IOKIT_PS_IOPOWERSOURCES_H || KERNEL_LINUX # define BATTERY_HAVE_READ 1 #else # define BATTERY_HAVE_READ 0 @@ -41,33 +67,41 @@ static char *battery_charge_file = "battery-%s/charge.rrd"; static char *ds_def_current[] = { - "DS:current:GAUGE:25:U:U", + "DS:current:GAUGE:"COLLECTD_HEARTBEAT":U:U", NULL }; static int ds_num_current = 1; static char *ds_def_voltage[] = { - "DS:voltage:GAUGE:25:U:U", + "DS:voltage:GAUGE:"COLLECTD_HEARTBEAT":U:U", NULL }; static int ds_num_voltage = 1; static char *ds_def_charge[] = { - "DS:charge:GAUGE:25:0:U", + "DS:charge:GAUGE:"COLLECTD_HEARTBEAT":0:U", NULL }; static int ds_num_charge = 1; -#if BATTERY_HAVE_READ +#if HAVE_IOKIT_PS_IOPOWERSOURCES_H + /* No global variables */ +/* #endif HAVE_IOKIT_PS_IOPOWERSOURCES_H */ + +#elif KERNEL_LINUX static int battery_pmu_num = 0; static char *battery_pmu_file = "/proc/pmu/battery_%i"; -#endif +#endif /* KERNEL_LINUX */ static void battery_init (void) { -#if BATTERY_HAVE_READ +#if HAVE_IOKIT_PS_IOPOWERSOURCES_H + /* No init neccessary */ +/* #endif HAVE_IOKIT_PS_IOPOWERSOURCES_H */ + +#elif KERNEL_LINUX int len; char filename[BUFSIZE]; @@ -81,7 +115,7 @@ static void battery_init (void) if (access (filename, R_OK)) break; } -#endif +#endif /* KERNEL_LINUX */ return; } @@ -170,7 +204,134 @@ static void battery_submit (char *inst, double current, double voltage, double c static void battery_read (void) { -#ifdef KERNEL_LINUX +#if HAVE_IOKIT_PS_IOPOWERSOURCES_H + CFTypeRef ps_raw; + CFArrayRef ps_array; + int ps_array_len; + CFDictionaryRef ps_dict; + CFTypeRef ps_obj; + CFTypeRef ps_value; + + int i; + + char name[128]; + double charge = INVALID_VALUE; + double current = INVALID_VALUE; + double voltage = INVALID_VALUE; + + ps_raw = IOPSCopyPowerSourcesInfo (); + ps_array = IOPSCopyPowerSourcesList (ps_raw); + ps_array_len = CFArrayGetCount (ps_array); + + DBG ("ps_array_len == %i", ps_array_len); + + for (i = 0; i < ps_array_len; i++) + { + ps_obj = CFArrayGetValueAtIndex (ps_array, i); + ps_dict = IOPSGetPowerSourceDescription (ps_raw, ps_obj); + + if (CFGetTypeID (ps_dict) != CFDictionaryGetTypeID ()) + { + DBG ("IOPSGetPowerSourceDescription did not return a CFDictionaryRef"); + continue; + } + + if (ps_dict != NULL) + { + /* Get the current capacity/charge */ + ps_value = NULL; + charge = INVALID_VALUE; + if (CFDictionaryGetValueIfPresent (ps_dict, + CFSTR (kIOPSCurrentCapacityKey), + &ps_value)) + { + if (CFGetTypeID (ps_value) != CFNumberGetTypeID ()) + CFNumberGetValue (ps_value, + kCFNumberDoubleType, + &charge); + else + DBG ("kIOPSCurrentCapacityKey: Not a CFNumber"); + + DBG ("charge = %f", charge); + } + else + DBG ("`%s' does not exist", kIOPSCurrentCapacityKey); + + /* Get the current */ + ps_value = NULL; + current = INVALID_VALUE; + if (CFDictionaryGetValueIfPresent (ps_dict, + CFSTR (kIOPSCurrentKey), + &ps_value)) + { + if (CFGetTypeID (ps_value) != CFNumberGetTypeID ()) + CFNumberGetValue (ps_value, + kCFNumberDoubleType, + ¤t); + else + DBG ("kIOPSCurrentKey: Not a CFNumber"); + DBG ("current = %f", current); + } + else + DBG ("`%s' does not exist", kIOPSCurrentKey); + + /* Get the voltage */ + ps_value = NULL; + voltage = INVALID_VALUE; + if (CFDictionaryGetValueIfPresent (ps_dict, + CFSTR (kIOPSVoltageKey), + &ps_value)) + { + if (CFGetTypeID (ps_value) != CFNumberGetTypeID ()) + CFNumberGetValue (ps_value, + kCFNumberDoubleType, + &voltage); + else + DBG ("kIOPSVoltageKey: Not a CFNumber"); + DBG ("voltage = %f", voltage); + } + else + DBG ("`%s' does not exist", kIOPSVoltageKey); + + /* Get the name of the device.. */ + ps_value = NULL; + if (CFDictionaryGetValueIfPresent (ps_dict, + CFSTR (kIOPSNameKey), + &ps_value)) + { + if (CFGetTypeID (ps_value) != CFStringGetTypeID ()) + if (!CFStringGetCString (ps_value, + name, 128, + kCFStringEncodingASCII)) + continue; + else + DBG ("kIOPSNameKey: Not a CFStringGetTypeID"); + DBG ("Original string: `%s'", name); + } + else + { + strncpy (name, "unknown", 128); + } + name[127] = '\0'; + for (i = 0; i < 128; i++) + { + if (name[i] == '\0') + break; + else if (isalnum (name[i])) + name[i] = (char) tolower (name[i]); + else + name[i] = '_'; + } + + battery_submit (name, current, voltage, charge); + } + } + + CFRelease(ps_array); + CFRelease(ps_raw); +/* #endif HAVE_IOKIT_PS_IOPOWERSOURCES_H */ + +#elif KERNEL_LINUX FILE *fh; char buffer[BUFSIZE]; char filename[BUFSIZE]; diff --git a/src/collectd.c b/src/collectd.c index 7b264e83..0c803655 100644 --- a/src/collectd.c +++ b/src/collectd.c @@ -29,8 +29,6 @@ #include "plugin.h" #include "configfile.h" -#include "ping.h" - static int loop = 0; #if HAVE_LIBKSTAT @@ -135,6 +133,8 @@ static void exit_usage (char *name) #if COLLECT_DEBUG " Log-File "LOGFILE"\n" #endif + " Step "COLLECTD_STEP" seconds\n" + " Heartbeat "COLLECTD_HEARTBEAT" seconds\n" "\n"PACKAGE" "VERSION", http://verplant.org/collectd/\n" "by Florian octo Forster \n" "for contributions see `AUTHORS'\n"); @@ -143,7 +143,15 @@ static void exit_usage (char *name) static int start_client (void) { - int sleepingtime; + int step; + + struct timeval tv_now; + struct timeval tv_next; + struct timespec ts_wait; + + step = atoi (COLLECTD_STEP); + if (step <= 0) + step = 10; #if HAVE_LIBKSTAT kc = NULL; @@ -168,18 +176,42 @@ static int start_client (void) while (loop == 0) { - curtime = time (NULL); + if (gettimeofday (&tv_next, NULL) < 0) + { + syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno)); + return (-1); + } + tv_next.tv_sec += step; + #if HAVE_LIBKSTAT update_kstat (); #endif + /* `curtime' is used by many (all?) plugins as the + * data-sample-time passed to RRDTool */ + curtime = time (NULL); + + /* Issue all plugins */ plugin_read_all (); - sleepingtime = 10; - while (sleepingtime != 0) + if (gettimeofday (&tv_now, NULL) < 0) { - if (loop != 0) + syslog (LOG_ERR, "gettimeofday failed: %s", strerror (errno)); + return (-1); + } + + if (timeval_sub_timespec (&tv_next, &tv_now, &ts_wait) != 0) + { + syslog (LOG_WARNING, "No sleeping because `timeval_sub_timespec' returned non-zero!"); + continue; + } + + while (nanosleep (&ts_wait, &ts_wait) == -1) + { + if (errno != EINTR) + { + syslog (LOG_ERR, "nanosleep failed: %s", strerror (errno)); break; - sleepingtime = sleep (sleepingtime); + } } } diff --git a/src/collectd.conf.pod b/src/collectd.conf.pod index 5852b6dc..a00bbb21 100644 --- a/src/collectd.conf.pod +++ b/src/collectd.conf.pod @@ -104,6 +104,26 @@ operating systems. Some Plugins may register own options. These options must be inclosed in a C-Section. Which options exist depends on the plugin used: +=head2 Plugin C + +=over 4 + +=item B I + +Sets the URL of the C output. This needs to be the output generated +by C and it needs to be the machine readable output +generated by appending the C argument. + +=item B I + +Optional user name needed for authentication. + +=item B I + +Optional password needed for authentication. + +=back + =head2 Plugin C =over 4 @@ -150,6 +170,10 @@ option for what this plugin does. Host to ping periodically. This option may be repeated several times to ping multiple hosts. +=item B I<0-255> + +Sets the Time-To-Live of generated ICMP packets. + =back =head1 SEE ALSO diff --git a/src/collectd.h b/src/collectd.h index 0221a59b..9781bdc1 100644 --- a/src/collectd.h +++ b/src/collectd.h @@ -200,6 +200,22 @@ #define MODE_LOCAL 0x04 #define MODE_LOG 0x08 +#ifndef COLLECTD_STEP +# define COLLECTD_STEP "10" +#endif + +#ifndef COLLECTD_HEARTBEAT +# define COLLECTD_HEARTBEAT "25" +#endif + +#ifndef COLLECTD_ROWS +# define COLLECTD_ROWS "1200" +#endif + +#ifndef COLLECTD_XFF +# define COLLECTD_XFF 0.1 +#endif + extern time_t curtime; #ifdef HAVE_LIBRRD diff --git a/src/collectd.pod b/src/collectd.pod index 6d572000..1eef525f 100644 --- a/src/collectd.pod +++ b/src/collectd.pod @@ -82,6 +82,10 @@ Network traffic (I) Number of users logged into the system (I) +=item + +System ressources used by VServers (I) + =back =head1 OPTIONS @@ -133,12 +137,29 @@ values. =head1 SPECIAL PLUGINS +=head2 apache + +This module connects to an Apache webserver and expects the output produced by +B. If requires B to set up the HTTP connection and issue +the request(s). The following is a sample config for the Apache webserver. The +use of C is mandatory. + + ExtendedStatus on + + + SetHandler server-status + + + +This plugin requires further configuration. Please read L. + =head2 cpufreq This module reads F
(for the first CPU installed) to get the current CPU frequency. If this file does not exist make sure B (L) or a -similar tool is installed. +similar tool is installed and an "cpu governor" (that's kernel module) is +loaded. =head2 mysql @@ -175,28 +196,45 @@ which may interfere with other statistics.. The B homepage can be found at L. -=head1 RRD FILES +=head2 vserver -The RRD files are created automatically with the following RRAs: +B support is only available for Linux. It cannot yet be found in a +vanilla kernel, though. To make use of this plugin you need a kernel that has +B support built in, i.e. you need to apply the patches and compile +your own kernel, which will then provide the /proc/virtual filesystem that is +required by this plugin. - RRA:AVERAGE:0.2:6:1500 - RRA:AVERAGE:0.1:180:1680 - RRA:AVERAGE:0.1:2160:1520 - RRA:MIN:0.2:6:1500 - RRA:MIN:0.1:180:1680 - RRA:MIN:0.1:2160:1520 - RRA:MAX:0.2:6:1500 - RRA:MAX:0.1:180:1680 - RRA:MAX:0.1:2160:1520 +The B homepage can be found at L. -Since collectd uses a 10 second I the RRAs contain the following -timespans: +=head1 RRD FILES - Resolution | Data points | Timespan - -----------+-------------+---------- - 60 seconds | 1500 | 25 hours - 30 minutes | 1680 | 35 days - 6 hours | 1520 | 380 days +The RRD files are created automatically. The size of the RRAs depend on the +compile time settings of I and I. With the default values (I += B<10>, I = B<1200>) the following RRAs are created: + + RRA:AVERAGE:0.1:1:8640 + RRA:AVERAGE:0.1:50:1210 + RRA:AVERAGE:0.1:223:1202 + RRA:AVERAGE:0.1:2635:1201 + RRA:MIN:0.1:1:8640 + RRA:MIN:0.1:50:1210 + RRA:MIN:0.1:223:1202 + RRA:MIN:0.1:2635:1201 + RRA:MAX:0.1:1:8640 + RRA:MAX:0.1:50:1210 + RRA:MAX:0.1:223:1202 + RRA:MAX:0.1:2635:1201 + +By default collectd uses a 10 second I. Thus the RRAs contain the +following timespans. If you've changed the I at compile time you will +have calculate resolution and timespan yourself. + + PDP per CDP | Resolution | Data points | Timespan + ------------+--------------+-------------+--------- + 1 | 10.0 seconds ! 8640 ! 1 day + 50 | 8.3 minutes | 1210 | 1 week + 223 | 37.2 minutes | 1202 | 1 month + 2635 | 7.3 hours | 1201 | 1 year The DS'es depend on the module creating the RRD files: @@ -376,6 +414,36 @@ The DS'es depend on the module creating the RRD files: DS:users:GAUGE:25:0:65535 +=item VServer load (FxidE>/load.rrd>) + + DS:shortterm:GAUGE:25:0:100 + DS:midterm:GAUGE:25:0:100 + DS:longterm:GAUGE:25:0:100 + +=item VServer threads (FxidE>/threads.rrd>) + + DS:total:GAUGE:25:0:65535 + DS:running:GAUGE:25:0:65535 + DS:uninterruptible:GAUGE:25:0:65535 + DS:onhold:GAUGE:25:0:65535 + +=item VServer network traffic (FxidE>/traffic-InameE>.rrd>) + + DS:incoming:COUNTER:25:0:9223372036854775807 + DS:outgoing:COUNTER:25:0:9223372036854775807 + DS:failed:COUNTER:25:0:9223372036854775807 + +=item VServer processes (FxidE>/vs_processes.rrd>) + + DS:total:GAUGE:25:0:65535 + +=item VServer memory usage (FxidE>/vs_memory.rrd>) + + DS:vm:GAUGE:25:0:9223372036854775807 + DS:vml:GAUGE:25:0:9223372036854775807 + DS:rss:GAUGE:25:0:9223372036854775807 + DS:anon:GAUGE:25:0:9223372036854775807 + =back =head1 SEE ALSO diff --git a/src/common.c b/src/common.c index 56ae326a..a4b718cb 100644 --- a/src/common.c +++ b/src/common.c @@ -25,6 +25,10 @@ #include "common.h" #include "utils_debug.h" +#ifdef HAVE_MATH_H +# include +#endif + extern int operating_mode; #ifdef HAVE_LIBKSTAT @@ -32,20 +36,45 @@ extern kstat_ctl_t *kc; #endif #ifdef HAVE_LIBRRD +#if 0 static char *rra_def[] = { + "RRA:AVERAGE:0.0:1:1500", "RRA:AVERAGE:0.2:6:1500", "RRA:AVERAGE:0.1:180:1680", "RRA:AVERAGE:0.1:2160:1520", + "RRA:MIN:0.0:1:1500", "RRA:MIN:0.2:6:1500", "RRA:MIN:0.1:180:1680", "RRA:MIN:0.1:2160:1520", + "RRA:MAX:0.0:1:1500", "RRA:MAX:0.2:6:1500", "RRA:MAX:0.1:180:1680", "RRA:MAX:0.1:2160:1520", NULL }; -static int rra_num = 9; +static int rra_num = 12; +#endif + +static int rra_timespans[] = +{ + 3600, + 86400, + 604800, + 2678400, + 31622400, + 0 +}; +static int rra_timespans_num = 5; + +static char *rra_types[] = +{ + "AVERAGE", + "MIN", + "MAX", + NULL +}; +static int rra_types_num = 3; #endif /* HAVE_LIBRRD */ void sstrncpy (char *d, const char *s, int len) @@ -204,6 +233,29 @@ int escape_slashes (char *buf, int buf_len) return (0); } +int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret) +{ + if ((tv0 == NULL) || (tv1 == NULL) || (ret == NULL)) + return (-2); + + if ((tv0->tv_sec < tv1->tv_sec) + || ((tv0->tv_sec == tv1->tv_sec) && (tv0->tv_usec < tv1->tv_usec))) + return (-1); + + ret->tv_sec = tv0->tv_sec - tv1->tv_sec; + ret->tv_nsec = 1000 * ((long) (tv0->tv_usec - tv1->tv_usec)); + + if (ret->tv_nsec < 0) + { + assert (ret->tv_sec > 0); + + ret->tv_nsec += 1000000000; + ret->tv_sec -= 1; + } + + return (0); +} + static int check_create_dir (const char *file_orig) { struct stat statbuf; @@ -308,6 +360,87 @@ static int check_create_dir (const char *file_orig) return (0); } +/* * * * * + * Magic * + * * * * */ +int rra_get (char ***ret) +{ + static char **rra_def = NULL; + static int rra_num = 0; + + int rra_max = rra_timespans_num * rra_types_num; + + int step; + int rows; + int span; + + int cdp_num; + int cdp_len; + int i, j; + + char buffer[64]; + + if ((rra_num != 0) && (rra_def != NULL)) + { + *ret = rra_def; + return (rra_num); + } + + if ((rra_def = (char **) malloc ((rra_max + 1) * sizeof (char *))) == NULL) + return (-1); + memset (rra_def, '\0', (rra_max + 1) * sizeof (char *)); + + step = atoi (COLLECTD_STEP); + rows = atoi (COLLECTD_ROWS); + + if ((step <= 0) || (rows <= 0)) + { + *ret = NULL; + return (-1); + } + + cdp_len = 0; + for (i = 0; i < rra_timespans_num; i++) + { + span = rra_timespans[i]; + + if ((span / step) < rows) + continue; + + if (cdp_len == 0) + cdp_len = 1; + else + cdp_len = (int) floor (((double) span) / ((double) (rows * step))); + + cdp_num = (int) ceil (((double) span) / ((double) (cdp_len * step))); + + for (j = 0; j < rra_types_num; j++) + { + if (rra_num >= rra_max) + break; + + if (snprintf (buffer, sizeof(buffer), "RRA:%s:%3.1f:%u:%u", + rra_types[j], COLLECTD_XFF, + cdp_len, cdp_num) >= sizeof (buffer)) + { + syslog (LOG_ERR, "rra_get: Buffer would have been truncated."); + continue; + } + + rra_def[rra_num++] = sstrdup (buffer); + } + } + +#if COLLECT_DEBUG + DBG ("rra_num = %i", rra_num); + for (i = 0; i < rra_num; i++) + DBG (" %s", rra_def[i]); +#endif + + *ret = rra_def; + return (rra_num); +} + static int log_create_file (char *filename, char **ds_def, int ds_num) { FILE *log; @@ -443,12 +576,20 @@ static int rrd_create_file (char *filename, char **ds_def, int ds_num) { char **argv; int argc; + char **rra_def; + int rra_num; int i, j; int status = 0; if (check_create_dir (filename)) return (-1); + if ((rra_num = rra_get (&rra_def)) < 1) + { + syslog (LOG_ERR, "rra_create failed: Could not calculate RRAs"); + return (-1); + } + argc = ds_num + rra_num + 4; if ((argv = (char **) malloc (sizeof (char *) * (argc + 1))) == NULL) @@ -460,7 +601,7 @@ static int rrd_create_file (char *filename, char **ds_def, int ds_num) argv[0] = "create"; argv[1] = filename; argv[2] = "-s"; - argv[3] = "10"; + argv[3] = COLLECTD_STEP; j = 4; for (i = 0; i < ds_num; i++) diff --git a/src/common.h b/src/common.h index ae93635f..bbc182b8 100644 --- a/src/common.h +++ b/src/common.h @@ -103,6 +103,9 @@ int strjoin (char *dst, size_t dst_len, char **fields, size_t fields_num, const */ int escape_slashes (char *buf, int buf_len); +/* FIXME: `timeval_sub_timespec' needs a description */ +int timeval_sub_timespec (struct timeval *tv0, struct timeval *tv1, struct timespec *ret); + int rrd_update_file (char *host, char *file, char *values, char **ds_def, int ds_num); diff --git a/src/configfile.c b/src/configfile.c index 45fe6845..91bef48c 100644 --- a/src/configfile.c +++ b/src/configfile.c @@ -106,7 +106,7 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value if ((cf_cb = cf_search (type)) == NULL) { - syslog (LOG_WARNING, "Plugin `%s' did not register a callback.\n", type); + syslog (LOG_WARNING, "Plugin `%s' did not register a callback.", type); return (-1); } @@ -130,11 +130,13 @@ static int cf_dispatch (char *type, const char *orig_key, const char *orig_value } if (i >= cf_cb->keys_num) - syslog (LOG_WARNING, "Plugin `%s' did not register for value `%s'.\n", type, key); + syslog (LOG_WARNING, "Plugin `%s' did not register for value `%s'.", type, key); free (key); free (value); + DBG ("return (%i)", ret); + return (ret); } diff --git a/src/cpu.c b/src/cpu.c index 28e62338..eacc590b 100644 --- a/src/cpu.c +++ b/src/cpu.c @@ -23,9 +23,32 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_debug.h" #define MODULE_NAME "cpu" +#ifdef HAVE_MACH_KERN_RETURN_H +# include +#endif +#ifdef HAVE_MACH_MACH_INIT_H +# include +#endif +#ifdef HAVE_MACH_HOST_PRIV_H +# include +#endif +#if HAVE_MACH_MACH_ERROR_H +# include +#endif +#ifdef HAVE_MACH_PROCESSOR_INFO_H +# include +#endif +#ifdef HAVE_MACH_PROCESSOR_H +# include +#endif +#ifdef HAVE_MACH_VM_MAP_H +# include +#endif + #ifdef HAVE_LIBKSTAT # include #endif /* HAVE_LIBKSTAT */ @@ -49,21 +72,31 @@ # endif #endif /* HAVE_SYSCTLBYNAME */ -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME) +#if defined(PROCESSOR_CPU_LOAD_INFO) || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME) # define CPU_HAVE_READ 1 #else # define CPU_HAVE_READ 0 #endif -#ifdef HAVE_LIBKSTAT +#ifdef PROCESSOR_CPU_LOAD_INFO +static mach_port_t port_host; +static processor_port_array_t cpu_list; +static mach_msg_type_number_t cpu_list_len; +/* #endif PROCESSOR_CPU_LOAD_INFO */ + +#elif defined(KERNEL_LINUX) +/* no variables needed */ +/* #endif KERNEL_LINUX */ + +#elif defined(HAVE_LIBKSTAT) /* colleague tells me that Sun doesn't sell systems with more than 100 or so CPUs.. */ # define MAX_NUMCPU 256 extern kstat_ctl_t *kc; static kstat_t *ksp[MAX_NUMCPU]; static int numcpu; -#endif /* HAVE_LIBKSTAT */ +/* #endif HAVE_LIBKSTAT */ -#ifdef HAVE_SYSCTLBYNAME +#elif defined(HAVE_SYSCTLBYNAME) static int numcpu; #endif /* HAVE_SYSCTLBYNAME */ @@ -71,18 +104,35 @@ static char *cpu_filename = "cpu-%s.rrd"; static char *ds_def[] = { - "DS:user:COUNTER:25:0:U", - "DS:nice:COUNTER:25:0:U", - "DS:syst:COUNTER:25:0:U", - "DS:idle:COUNTER:25:0:U", - "DS:wait:COUNTER:25:0:U", + "DS:user:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:nice:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:syst:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:idle:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wait:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int ds_num = 5; static void cpu_init (void) { -#ifdef HAVE_LIBKSTAT +#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE + kern_return_t status; + + port_host = mach_host_self (); + + /* FIXME: Free `cpu_list' if it's not NULL */ + if ((status = host_processors (port_host, &cpu_list, &cpu_list_len)) != KERN_SUCCESS) + { + syslog (LOG_ERR, "cpu-plugin: host_processors returned %i\n", (int) status); + cpu_list_len = 0; + return; + } + + DBG ("host_processors returned %i %s", (int) cpu_list_len, cpu_list_len == 1 ? "processor" : "processors"); + syslog (LOG_INFO, "cpu-plugin: Found %i processor%s.", (int) cpu_list_len, cpu_list_len == 1 ? "" : "s"); +/* #endif PROCESSOR_CPU_LOAD_INFO */ + +#elif defined(HAVE_LIBKSTAT) kstat_t *ksp_chain; numcpu = 0; @@ -150,8 +200,76 @@ static void cpu_submit (int cpu_num, unsigned long long user, static void cpu_read (void) { -#ifdef KERNEL_LINUX -#define BUFSIZE 1024 +#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE + int cpu; + + kern_return_t status; + +#if PROCESSOR_CPU_LOAD_INFO + processor_cpu_load_info_data_t cpu_info; + mach_msg_type_number_t cpu_info_len; +#endif +#if PROCESSOR_TEMPERATURE + processor_info_data_t cpu_temp; + mach_msg_type_number_t cpu_temp_len; +#endif + + host_t cpu_host; + + for (cpu = 0; cpu < cpu_list_len; cpu++) + { +#if PROCESSOR_CPU_LOAD_INFO + cpu_host = 0; + cpu_info_len = PROCESSOR_BASIC_INFO_COUNT; + + if ((status = processor_info (cpu_list[cpu], + PROCESSOR_CPU_LOAD_INFO, &cpu_host, + (processor_info_t) &cpu_info, &cpu_info_len)) != KERN_SUCCESS) + { + syslog (LOG_ERR, "processor_info failed with status %i\n", (int) status); + continue; + } + + if (cpu_info_len < CPU_STATE_MAX) + { + syslog (LOG_ERR, "processor_info returned only %i elements..\n", cpu_info_len); + continue; + } + + cpu_submit (cpu, cpu_info.cpu_ticks[CPU_STATE_USER], + cpu_info.cpu_ticks[CPU_STATE_NICE], + cpu_info.cpu_ticks[CPU_STATE_SYSTEM], + cpu_info.cpu_ticks[CPU_STATE_IDLE], + 0ULL); +#endif /* PROCESSOR_CPU_LOAD_INFO */ +#if PROCESSOR_TEMPERATURE + cpu_temp_len = PROCESSOR_INFO_MAX; + + status = processor_info (cpu_list[cpu], + PROCESSOR_TEMPERATURE, + &cpu_host, + cpu_temp, &cpu_temp_len); + if (status != KERN_SUCCESS) + { + syslog (LOG_ERR, "processor_info failed: %s", + mach_error_string (status)); + continue; + } + + if (cpu_temp_len != 1) + { + DBG ("processor_info (PROCESSOR_TEMPERATURE) returned %i elements..?", + (int) cpu_temp_len); + continue; + } + + DBG ("cpu_temp = %i", (int) cpu_temp); +#endif /* PROCESSOR_TEMPERATURE */ + } +/* #endif PROCESSOR_CPU_LOAD_INFO */ + +#elif defined(KERNEL_LINUX) +# define BUFSIZE 1024 int cpu; unsigned long long user, nice, syst, idle; unsigned long long wait, intr, sitr; /* sitr == soft interrupt */ diff --git a/src/cpu.h b/src/cpu.h deleted file mode 100644 index fa5a7101..00000000 --- a/src/cpu.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * collectd - src/cpu.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef CPU_H -#define CPU_H - -#include "collectd.h" - -#ifndef COLLECT_CPU -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_SYSCTLBYNAME) -#define COLLECT_CPU 1 -#else -#define COLLECT_CPU 0 -#endif -#endif /* !defined(COLLECT_CPU) */ - -#if COLLECT_CPU - -void cpu_init (void); -void cpu_read (void); - -#endif /* COLLECT_CPU */ -#endif /* CPU_H */ diff --git a/src/cpufreq.c b/src/cpufreq.c index 22877b4d..797bee70 100644 --- a/src/cpufreq.c +++ b/src/cpufreq.c @@ -36,7 +36,7 @@ static char *cpufreq_file = "cpufreq-%s.rrd"; static char *ds_def[] = { - "DS:value:GAUGE:25:0:U", + "DS:value:GAUGE:"COLLECTD_HEARTBEAT":0:U", NULL }; static int ds_num = 1; diff --git a/src/cpufreq.h b/src/cpufreq.h deleted file mode 100644 index 9c0d41e3..00000000 --- a/src/cpufreq.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/cpufreq.c - * Copyright (C) 2005 Peter Holik - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Peter Holik - **/ - -#ifndef CPUFREQ_H -#define CPUFREQ_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_CPUFREQ -#if defined(KERNEL_LINUX) -#define COLLECT_CPUFREQ 1 -#else -#define COLLECT_CPUFREQ 0 -#endif -#endif /* !defined(COLLECT_CPUFREQ) */ - -#endif /* CPUFREQ_H */ diff --git a/src/df.c b/src/df.c index 6b7df311..51dff31f 100644 --- a/src/df.c +++ b/src/df.c @@ -51,8 +51,8 @@ static char *filename_template = "df-%s.rrd"; static char *ds_def[] = { - "DS:used:GAUGE:25:0:U", - "DS:free:GAUGE:25:0:U", + "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:U", + "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:U", NULL }; static int ds_num = 2; @@ -110,10 +110,7 @@ static void df_read (void) mnt_list = NULL; if (cu_mount_getlist (&mnt_list) == NULL) - { - syslog (LOG_WARNING, "cu_mount_getlist returned `NULL'"); return; - } for (mnt_ptr = mnt_list; mnt_ptr != NULL; mnt_ptr = mnt_ptr->next) { diff --git a/src/disk.c b/src/disk.c index ea497175..992c2d2c 100644 --- a/src/disk.c +++ b/src/disk.c @@ -38,24 +38,24 @@ static char *part_filename_template = "partition-%s.rrd"; /* 104857600 == 100 MB */ static char *disk_ds_def[] = { - "DS:rcount:COUNTER:25:0:U", - "DS:rmerged:COUNTER:25:0:U", - "DS:rbytes:COUNTER:25:0:104857600", - "DS:rtime:COUNTER:25:0:U", - "DS:wcount:COUNTER:25:0:U", - "DS:wmerged:COUNTER:25:0:U", - "DS:wbytes:COUNTER:25:0:104857600", - "DS:wtime:COUNTER:25:0:U", + "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", + "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", + "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int disk_ds_num = 8; static char *part_ds_def[] = { - "DS:rcount:COUNTER:25:0:U", - "DS:rbytes:COUNTER:25:0:104857600", - "DS:wcount:COUNTER:25:0:U", - "DS:wbytes:COUNTER:25:0:104857600", + "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", + "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:104857600", NULL }; static int part_ds_num = 4; diff --git a/src/disk.h b/src/disk.h deleted file mode 100644 index f9469638..00000000 --- a/src/disk.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/disk.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef DISKSTATS_H -#define DISKSTATS_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_DISK -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) -#define COLLECT_DISK 1 -#else -#define COLLECT_DISK 0 -#endif -#endif /* !defined(COLLECT_DISK) */ - -#endif /* DISKSTATS_H */ diff --git a/src/hddtemp.c b/src/hddtemp.c index bfb2621b..d3772b8c 100644 --- a/src/hddtemp.c +++ b/src/hddtemp.c @@ -55,7 +55,7 @@ static char *filename_format = "hddtemp-%s.rrd"; static char *ds_def[] = { - "DS:value:GAUGE:25:U:U", + "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U", NULL }; static int ds_num = 1; @@ -233,7 +233,7 @@ static int hddtemp_config (char *key, char *value) * operating-systems, it's not done at all. */ static void hddtemp_init (void) { -#if defined(KERNEL_LINUX) +#if KERNEL_LINUX FILE *fh; char buf[BUFFER_SIZE]; int buflen; diff --git a/src/hddtemp.h b/src/hddtemp.h deleted file mode 100644 index aaf01915..00000000 --- a/src/hddtemp.h +++ /dev/null @@ -1,34 +0,0 @@ -/** - * collectd - src/hddtemp.c - * Copyright (C) 2005 Vincent Stehlé - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Vincent Stehlé - * Florian octo Forster - **/ - -#ifndef HDDTEMP_H -#define HDDTEMP_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_HDDTEMP -#define COLLECT_HDDTEMP 1 -#endif - -#endif /* HDDTEMP_H */ diff --git a/src/liboping/Makefile.am b/src/liboping/Makefile.am index 9ad4d665..14bd3ed6 100644 --- a/src/liboping/Makefile.am +++ b/src/liboping/Makefile.am @@ -1,5 +1,9 @@ AUTOMAKE_OPTIONS = foreign no-dependencies +if COMPILER_IS_GCC +AM_CFLAGS = -Wall -Werror +endif + noinst_LTLIBRARIES = liboping.la #liboping_la_CFLAGS = diff --git a/src/liboping/liboping.c b/src/liboping/liboping.c index b57f8e22..43d5fd50 100644 --- a/src/liboping/liboping.c +++ b/src/liboping/liboping.c @@ -92,6 +92,21 @@ /* * private (static) functions */ +static int ping_timeval_add (struct timeval *tv1, struct timeval *tv2, + struct timeval *res) +{ + res->tv_sec = tv1->tv_sec + tv2->tv_sec; + res->tv_usec = tv1->tv_usec + tv2->tv_usec; + + while (res->tv_usec > 1000000) + { + res->tv_usec -= 1000000; + res->tv_sec++; + } + + return (0); +} + static int ping_timeval_sub (struct timeval *tv1, struct timeval *tv2, struct timeval *res) { @@ -350,12 +365,13 @@ static int ping_receive_one (int fd, pinghost_t *ph, struct timeval *now) return (0); } -static int ping_receive_all (pinghost_t *ph) +static int ping_receive_all (pingobj_t *obj) { fd_set readfds; int num_readfds; int max_readfds; + pinghost_t *ph; pinghost_t *ptr; struct timeval endtime; @@ -365,14 +381,24 @@ static int ping_receive_all (pinghost_t *ph) int ret; + ph = obj->head; ret = 0; for (ptr = ph; ptr != NULL; ptr = ptr->next) ptr->latency = -1.0; - if (gettimeofday (&endtime, NULL) == -1) + if (gettimeofday (&nowtime, NULL) == -1) return (-1); - endtime.tv_sec += 1; + + /* Set up timeout */ + timeout.tv_sec = (time_t) obj->timeout; + timeout.tv_usec = (suseconds_t) (1000000 * (obj->timeout - ((double) timeout.tv_sec))); + + dprintf ("Set timeout to %i.%06i seconds\n", + (int) timeout.tv_sec, + (int) timeout.tv_usec); + + ping_timeval_add (&nowtime, &timeout, &endtime); while (1) { @@ -598,6 +624,25 @@ static int ping_send_all (pinghost_t *ph) return (0); } +/* + * Set the TTL of a socket protocol independently. + */ +static int ping_set_ttl (pinghost_t *ph, int ttl) +{ + int ret = -2; + + if (ph->addrfamily == AF_INET) + { + ret = setsockopt (ph->fd, IPPROTO_IP, IP_TTL, &ttl, sizeof (ttl)); + } + else if (ph->addrfamily == AF_INET6) + { + ret = setsockopt (ph->fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &ttl, sizeof (ttl)); + } + + return (ret); +} + static int ping_get_ident (void) { int fd; @@ -751,7 +796,7 @@ int ping_send (pingobj_t *obj) if (ping_send_all (obj->head) < 0) return (-1); - if ((ret = ping_receive_all (obj->head)) < 0) + if ((ret = ping_receive_all (obj)) < 0) return (-2); return (ret); @@ -791,7 +836,7 @@ int ping_host_add (pingobj_t *obj, const char *host) #ifdef AI_ADDRCONFIG ai_hints.ai_flags |= AI_ADDRCONFIG; #endif - ai_hints.ai_family = PF_UNSPEC; + ai_hints.ai_family = obj->addrfamily; ai_hints.ai_socktype = SOCK_RAW; if ((ph = ping_alloc ()) == NULL) @@ -885,6 +930,8 @@ int ping_host_add (pingobj_t *obj, const char *host) ph->next = obj->head; obj->head = ph; + ping_set_ttl (ph, obj->ttl); + return (0); } diff --git a/src/load.c b/src/load.c index 913eb538..fbe6c4de 100644 --- a/src/load.c +++ b/src/load.c @@ -48,9 +48,9 @@ static char *load_file = "load.rrd"; static char *ds_def[] = { - "DS:shortterm:GAUGE:25:0:100", - "DS:midterm:GAUGE:25:0:100", - "DS:longterm:GAUGE:25:0:100", + "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100", + "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100", + "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100", NULL }; static int ds_num = 3; diff --git a/src/load.h b/src/load.h deleted file mode 100644 index 651d1d6e..00000000 --- a/src/load.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/load.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef LOAD_H -#define LOAD_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_LOAD -#if defined(HAVE_GETLOADAVG) || defined(KERNEL_LINUX) || defined(HAVE_LIBSTATGRAB) -#define COLLECT_LOAD 1 -#else -#define COLLECT_LOAD 0 -#endif -#endif /* !defined(COLLECT_LOAD) */ - -#endif /* LOAD_H */ diff --git a/src/memory.c b/src/memory.c index 3ab19e65..77a6dacc 100644 --- a/src/memory.c +++ b/src/memory.c @@ -24,7 +24,23 @@ #include "common.h" #include "plugin.h" -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) +#ifdef HAVE_MACH_KERN_RETURN_H +# include +#endif +#ifdef HAVE_MACH_MACH_INIT_H +# include +#endif +#ifdef HAVE_MACH_MACH_HOST_H +# include +#endif +#ifdef HAVE_MACH_HOST_PRIV_H +# include +#endif +#ifdef MACH_VM_STATISTICS_H +# include +#endif + +#if defined (HOST_VM_INFO) || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) # define MEMORY_HAVE_READ 1 #else # define MEMORY_HAVE_READ 0 @@ -37,22 +53,41 @@ static char *memory_file = "memory.rrd"; /* 9223372036854775807 == LLONG_MAX */ static char *ds_def[] = { - "DS:used:GAUGE:25:0:9223372036854775807", - "DS:free:GAUGE:25:0:9223372036854775807", - "DS:buffers:GAUGE:25:0:9223372036854775807", - "DS:cached:GAUGE:25:0:9223372036854775807", + "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:buffers:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", NULL }; static int ds_num = 4; -#ifdef HAVE_LIBKSTAT +/* vm_statistics_data_t */ +#if defined(HOST_VM_INFO) +static mach_port_t port_host; +static vm_size_t pagesize; +/* #endif HOST_VM_INFO */ + +#elif defined(KERNEL_LINUX) +/* no global variables */ +/* #endif KERNEL_LINUX */ + +#elif defined(HAVE_LIBKSTAT) static int pagesize; static kstat_t *ksp; #endif /* HAVE_LIBKSTAT */ static void memory_init (void) { -#ifdef HAVE_LIBKSTAT +#if defined(HOST_VM_INFO) + port_host = mach_host_self (); + host_page_size (port_host, &pagesize); +/* #endif HOST_VM_INFO */ + +#elif defined(KERNEL_LINUX) +/* no init stuff */ +/* #endif KERNEL_LINUX */ + +#elif defined(HAVE_LIBKSTAT) /* getpagesize(3C) tells me this does not fail.. */ pagesize = getpagesize (); if (get_kstat (&ksp, "unix", 0, "system_pages")) @@ -85,7 +120,57 @@ static void memory_submit (long long mem_used, long long mem_buffered, static void memory_read (void) { -#ifdef KERNEL_LINUX +#if defined(HOST_VM_INFO) + kern_return_t status; + vm_statistics_data_t vm_data; + mach_msg_type_number_t vm_data_len; + + long long wired; + long long active; + long long inactive; + long long free; + + if (!port_host || !pagesize) + return; + + vm_data_len = sizeof (vm_data) / sizeof (natural_t); + if ((status = host_statistics (port_host, HOST_VM_INFO, + (host_info_t) &vm_data, + &vm_data_len)) != KERN_SUCCESS) + { + syslog (LOG_ERR, "memory-plugin: host_statistics failed and returned the value %i", (int) status); + return; + } + + /* + * From : + * + * Wired memory + * This information can't be cached to disk, so it must stay in RAM. + * The amount depends on what applications you are using. + * + * Active memory + * This information is currently in RAM and actively being used. + * + * Inactive memory + * This information is no longer being used and has been cached to + * disk, but it will remain in RAM until another application needs + * the space. Leaving this information in RAM is to your advantage if + * you (or a client of your computer) come back to it later. + * + * Free memory + * This memory is not being used. + */ + + wired = vm_data.wire_count * pagesize; + active = vm_data.active_count * pagesize; + inactive = vm_data.inactive_count * pagesize; + free = vm_data.free_count * pagesize; + + memory_submit (wired + active, -1, inactive, free); +/* #endif HOST_VM_INFO */ + +#elif defined(KERNEL_LINUX) FILE *fh; char buffer[1024]; diff --git a/src/memory.h b/src/memory.h deleted file mode 100644 index c4571102..00000000 --- a/src/memory.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/memory.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef MEMINFO_H -#define MEMINFO_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_MEMORY -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB) -#define COLLECT_MEMORY 1 -#else -#define COLLECT_MEMORY 0 -#endif -#endif /* !defined(COLLECT_MEMORY) */ - -#endif /* MEMINFO_H */ diff --git a/src/mysql.c b/src/mysql.c index 4342dea0..822c6cce 100644 --- a/src/mysql.c +++ b/src/mysql.c @@ -60,43 +60,43 @@ static char *traffic_file = "traffic-mysql.rrd"; static char *commands_ds_def[] = { - "DS:value:COUNTER:25:0:U", + "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int commands_ds_num = 1; static char *handler_ds_def[] = { - "DS:value:COUNTER:25:0:U", + "DS:value:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int handler_ds_num = 1; static char *qcache_ds_def[] = { - "DS:hits:COUNTER:25:0:U", - "DS:inserts:COUNTER:25:0:U", - "DS:not_cached:COUNTER:25:0:U", - "DS:lowmem_prunes:COUNTER:25:0:U", - "DS:queries_in_cache:GAUGE:25:0:U", + "DS:hits:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:inserts:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:not_cached:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:lowmem_prunes:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:queries_in_cache:GAUGE:"COLLECTD_HEARTBEAT":0:U", NULL }; static int qcache_ds_num = 5; static char *threads_ds_def[] = { - "DS:running:GAUGE:25:0:U", - "DS:connected:GAUGE:25:0:U", - "DS:cached:GAUGE:25:0:U", - "DS:created:COUNTER:25:0:U", + "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:U", + "DS:connected:GAUGE:"COLLECTD_HEARTBEAT":0:U", + "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:U", + "DS:created:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int threads_ds_num = 4; static char *traffic_ds_def[] = { - "DS:incoming:COUNTER:25:0:U", - "DS:outgoing:COUNTER:25:0:U", + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int traffic_ds_num = 2; diff --git a/src/network.c b/src/network.c index f6bb6e82..a2cb6f5e 100644 --- a/src/network.c +++ b/src/network.c @@ -512,8 +512,6 @@ int network_send (char *type, char *inst, char *value) if (se->mode != operating_mode) continue; - DBG ("fd = %i", se->fd); - while (1) { status = sendto (se->fd, buf, buflen, 0, diff --git a/src/nfs.c b/src/nfs.c index 1592c911..3c7b8cf8 100644 --- a/src/nfs.c +++ b/src/nfs.c @@ -83,52 +83,52 @@ Number Procedures Procedures static char *nfs2_procedures_ds_def[] = { - "DS:null:COUNTER:25:0:U", - "DS:getattr:COUNTER:25:0:U", - "DS:setattr:COUNTER:25:0:U", - "DS:root:COUNTER:25:0:U", - "DS:lookup:COUNTER:25:0:U", - "DS:readlink:COUNTER:25:0:U", - "DS:read:COUNTER:25:0:U", - "DS:wrcache:COUNTER:25:0:U", - "DS:write:COUNTER:25:0:U", - "DS:create:COUNTER:25:0:U", - "DS:remove:COUNTER:25:0:U", - "DS:rename:COUNTER:25:0:U", - "DS:link:COUNTER:25:0:U", - "DS:symlink:COUNTER:25:0:U", - "DS:mkdir:COUNTER:25:0:U", - "DS:rmdir:COUNTER:25:0:U", - "DS:readdir:COUNTER:25:0:U", - "DS:fsstat:COUNTER:25:0:U", + "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:root:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wrcache:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int nfs2_procedures_ds_num = 18; static char *nfs3_procedures_ds_def[] = { - "DS:null:COUNTER:25:0:U", - "DS:getattr:COUNTER:25:0:U", - "DS:setattr:COUNTER:25:0:U", - "DS:lookup:COUNTER:25:0:U", - "DS:access:COUNTER:25:0:U", - "DS:readlink:COUNTER:25:0:U", - "DS:read:COUNTER:25:0:U", - "DS:write:COUNTER:25:0:U", - "DS:create:COUNTER:25:0:U", - "DS:mkdir:COUNTER:25:0:U", - "DS:symlink:COUNTER:25:0:U", - "DS:mknod:COUNTER:25:0:U", - "DS:remove:COUNTER:25:0:U", - "DS:rmdir:COUNTER:25:0:U", - "DS:rename:COUNTER:25:0:U", - "DS:link:COUNTER:25:0:U", - "DS:readdir:COUNTER:25:0:U", - "DS:readdirplus:COUNTER:25:0:U", - "DS:fsstat:COUNTER:25:0:U", - "DS:fsinfo:COUNTER:25:0:U", - "DS:pathconf:COUNTER:25:0:U", - "DS:commit:COUNTER:25:0:U", + "DS:null:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:getattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:setattr:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:lookup:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:access:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:readlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:read:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:write:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:create:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:mkdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:symlink:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:mknod:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:remove:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rmdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rename:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:link:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:readdir:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:readdirplus:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:fsstat:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:fsinfo:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:pathconf:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:commit:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int nfs3_procedures_ds_num = 22; diff --git a/src/nfs.h b/src/nfs.h deleted file mode 100644 index ae752be0..00000000 --- a/src/nfs.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/nfs.h - * Copyright (C) 2005 Jason Pepas - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Jason Pepas - * Florian octo Forster - **/ - -#ifndef NFS_H -#define NFS_H - -#include "collectd.h" - -#ifndef COLLECT_NFS -#if defined(KERNEL_LINUX) -#define COLLECT_NFS 1 -#else -#define COLLECT_NFS 0 -#endif -#endif /* !defined(COLLECT_NFS) */ - -#endif /* NFS_H */ diff --git a/src/ping.c b/src/ping.c index fb2f8c1d..69661708 100644 --- a/src/ping.c +++ b/src/ping.c @@ -37,7 +37,7 @@ static char *file_template = "ping-%s.rrd"; static char *ds_def[] = { - "DS:ping:GAUGE:25:0:65535", + "DS:ping:GAUGE:"COLLECTD_HEARTBEAT":0:65535", NULL }; static int ds_num = 1; @@ -45,9 +45,10 @@ static int ds_num = 1; static char *config_keys[] = { "Host", + "TTL", NULL }; -static int config_keys_num = 1; +static int config_keys_num = 2; static void ping_init (void) { @@ -56,23 +57,34 @@ static void ping_init (void) static int ping_config (char *key, char *value) { - if (strcasecmp (key, "host")) - { - return (-1); - } - if (pingobj == NULL) { if ((pingobj = ping_construct ()) == NULL) { syslog (LOG_ERR, "ping: `ping_construct' failed.\n"); - return (-1); + return (1); } } - if (ping_host_add (pingobj, value) < 0) + if (strcasecmp (key, "host") == 0) + { + if (ping_host_add (pingobj, value) < 0) + { + syslog (LOG_WARNING, "ping: `ping_host_add' failed."); + return (1); + } + } + else if (strcasecmp (key, "ttl") == 0) + { + int ttl = atoi (value); + if (ping_setopt (pingobj, PING_DEF_TIMEOUT, (void *) &ttl)) + { + syslog (LOG_WARNING, "ping: liboping did not accept the TTL value %i", ttl); + return (1); + } + } + else { - syslog (LOG_ERR, "ping: `ping_host_add' failed.\n"); return (-1); } diff --git a/src/ping.h b/src/ping.h deleted file mode 100644 index c5f26c44..00000000 --- a/src/ping.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * collectd - src/ping.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef COLLECTD_PING_H -#define COLLECTD_PING_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_PING -#if defined(HAVE_NETINET_IN_H) -#define COLLECT_PING 1 -#else -#define COLLECT_PING 0 -#endif /* defined(HAVE_NETINET_IN_H) */ -#endif /* !defined(COLLECT_PING) */ - -#if COLLECT_PING - -#define MAX_PINGHOSTS 32 - -#endif /* COLLECT_PING */ -#endif diff --git a/src/plugin.c b/src/plugin.c index 54f57af2..e991c78d 100644 --- a/src/plugin.c +++ b/src/plugin.c @@ -26,6 +26,7 @@ #include "plugin.h" #include "network.h" +#include "utils_debug.h" typedef struct plugin { @@ -114,11 +115,19 @@ int plugin_load_file (char *file) lt_dlhandle dlh; void (*reg_handle) (void); + DBG ("file = %s", file); + lt_dlinit (); lt_dlerror (); /* clear errors */ if ((dlh = lt_dlopen (file)) == NULL) + { + const char *error = lt_dlerror (); + + syslog (LOG_ERR, "lt_dlopen failed: %s", error); + DBG ("lt_dlopen failed: %s", error); return (1); + } if ((reg_handle = lt_dlsym (dlh, "module_register")) == NULL) { @@ -145,6 +154,8 @@ int plugin_load (const char *type) struct stat statbuf; struct dirent *de; + DBG ("type = %s", type); + dir = plugin_get_dir (); ret = 1; diff --git a/src/processes.c b/src/processes.c index 3a731890..fae1c2d0 100644 --- a/src/processes.c +++ b/src/processes.c @@ -1,6 +1,7 @@ /** * collectd - src/processes.c * Copyright (C) 2005 Lyonel Vincent + * Copyright (C) 2006 Florian Forster (Mach code) * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the @@ -24,10 +25,52 @@ #include "collectd.h" #include "common.h" #include "plugin.h" +#include "utils_debug.h" + +/* Include header files for the mach system, if they exist.. */ +#if HAVE_MACH_MACH_INIT_H +# include +#endif +#if HAVE_MACH_HOST_PRIV_H +# include +#endif +#if HAVE_MACH_MACH_ERROR_H +# include +#endif +#if HAVE_MACH_MACH_HOST_H +# include +#endif +#if HAVE_MACH_MACH_PORT_H +# include +#endif +#if HAVE_MACH_MACH_TYPES_H +# include +#endif +#if HAVE_MACH_MESSAGE_H +# include +#endif +#if HAVE_MACH_PROCESSOR_SET_H +# include +#endif +#if HAVE_MACH_TASK_H +# include +#endif +#if HAVE_MACH_THREAD_ACT_H +# include +#endif +#if HAVE_MACH_VM_REGION_H +# include +#endif +#if HAVE_MACH_VM_MAP_H +# include +#endif +#if HAVE_MACH_VM_PROT_H +# include +#endif #define MODULE_NAME "processes" -#ifdef KERNEL_LINUX +#if HAVE_THREAD_INFO || KERNEL_LINUX # define PROCESSES_HAVE_READ 1 #else # define PROCESSES_HAVE_READ 0 @@ -39,18 +82,62 @@ static char *ps_file = "processes.rrd"; static char *ds_def[] = { - "DS:running:GAUGE:25:0:65535", - "DS:sleeping:GAUGE:25:0:65535", - "DS:zombies:GAUGE:25:0:65535", - "DS:stopped:GAUGE:25:0:65535", - "DS:paging:GAUGE:25:0:65535", - "DS:blocked:GAUGE:25:0:65535", + "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:sleeping:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:zombies:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:stopped:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:paging:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:blocked:GAUGE:"COLLECTD_HEARTBEAT":0:65535", NULL }; static int ds_num = 6; +#if HAVE_THREAD_INFO +static mach_port_t port_host_self; +static mach_port_t port_task_self; + +static processor_set_name_array_t pset_list; +static mach_msg_type_number_t pset_list_len; +/* #endif HAVE_THREAD_INFO */ + +#elif KERNEL_LINUX +/* No global variables */ +#endif /* KERNEL_LINUX */ + static void ps_init (void) { +#if HAVE_THREAD_INFO + kern_return_t status; + + port_host_self = mach_host_self (); + port_task_self = mach_task_self (); + + if (pset_list != NULL) + { + vm_deallocate (port_task_self, + (vm_address_t) pset_list, + pset_list_len * sizeof (processor_set_t)); + pset_list = NULL; + pset_list_len = 0; + } + + if ((status = host_processor_sets (port_host_self, + &pset_list, + &pset_list_len)) != KERN_SUCCESS) + { + syslog (LOG_ERR, "host_processor_sets failed: %s\n", + mach_error_string (status)); + pset_list = NULL; + pset_list_len = 0; + return; + } +/* #endif HAVE_THREAD_INFO */ + +#elif KERNEL_LINUX + /* No init */ +#endif /* KERNEL_LINUX */ + + return; } static void ps_write (char *host, char *inst, char *val) @@ -59,16 +146,16 @@ static void ps_write (char *host, char *inst, char *val) } #if PROCESSES_HAVE_READ -static void ps_submit (unsigned int running, - unsigned int sleeping, - unsigned int zombies, - unsigned int stopped, - unsigned int paging, - unsigned int blocked) +static void ps_submit (int running, + int sleeping, + int zombies, + int stopped, + int paging, + int blocked) { char buf[BUFSIZE]; - if (snprintf (buf, BUFSIZE, "%u:%u:%u:%u:%u:%u:%u", + if (snprintf (buf, BUFSIZE, "%u:%i:%i:%i:%i:%i:%i", (unsigned int) curtime, running, sleeping, zombies, stopped, paging, blocked) >= BUFSIZE) @@ -79,8 +166,182 @@ static void ps_submit (unsigned int running, static void ps_read (void) { -#ifdef KERNEL_LINUX - unsigned int running, sleeping, zombies, stopped, paging, blocked; +#if HAVE_THREAD_INFO + kern_return_t status; + + int pset; + processor_set_t port_pset_priv; + + int task; + task_array_t task_list; + mach_msg_type_number_t task_list_len; + + int thread; + thread_act_array_t thread_list; + mach_msg_type_number_t thread_list_len; + thread_basic_info_data_t thread_data; + mach_msg_type_number_t thread_data_len; + + int running = 0; + int sleeping = 0; + int zombies = 0; + int stopped = 0; + int blocked = 0; + + /* + * The Mach-concept is a little different from the traditional UNIX + * concept: All the work is done in threads. Threads are contained in + * `tasks'. Therefore, `task status' doesn't make much sense, since + * it's actually a `thread status'. + * Tasks are assigned to sets of processors, so that's where you go to + * get a list. + */ + for (pset = 0; pset < pset_list_len; pset++) + { + if ((status = host_processor_set_priv (port_host_self, + pset_list[pset], + &port_pset_priv)) != KERN_SUCCESS) + { + syslog (LOG_ERR, "host_processor_set_priv failed: %s\n", + mach_error_string (status)); + continue; + } + + if ((status = processor_set_tasks (port_pset_priv, + &task_list, + &task_list_len)) != KERN_SUCCESS) + { + syslog (LOG_ERR, "processor_set_tasks failed: %s\n", + mach_error_string (status)); + mach_port_deallocate (port_task_self, port_pset_priv); + continue; + } + + for (task = 0; task < task_list_len; task++) + { + status = task_threads (task_list[task], &thread_list, + &thread_list_len); + if (status != KERN_SUCCESS) + { + /* Apple's `top' treats this case a zombie. It + * makes sense to some extend: A `zombie' + * thread is nonsense, since the task/process + * is dead. */ + zombies++; + DBG ("task_threads failed: %s", + mach_error_string (status)); + if (task_list[task] != port_task_self) + mach_port_deallocate (port_task_self, + task_list[task]); + continue; /* with next task_list */ + } + + for (thread = 0; thread < thread_list_len; thread++) + { + thread_data_len = THREAD_BASIC_INFO_COUNT; + status = thread_info (thread_list[thread], + THREAD_BASIC_INFO, + (thread_info_t) &thread_data, + &thread_data_len); + if (status != KERN_SUCCESS) + { + syslog (LOG_ERR, "thread_info failed: %s\n", + mach_error_string (status)); + if (task_list[task] != port_task_self) + mach_port_deallocate (port_task_self, + thread_list[thread]); + continue; /* with next thread_list */ + } + + switch (thread_data.run_state) + { + case TH_STATE_RUNNING: + running++; + break; + case TH_STATE_STOPPED: + /* What exactly is `halted'? */ + case TH_STATE_HALTED: + stopped++; + break; + case TH_STATE_WAITING: + sleeping++; + break; + case TH_STATE_UNINTERRUPTIBLE: + blocked++; + break; + /* There is no `zombie' case here, + * since there are no zombie-threads. + * There's only zombie tasks, which are + * handled above. */ + default: + syslog (LOG_WARNING, + "Unknown thread status: %s", + thread_data.run_state); + break; + } /* switch (thread_data.run_state) */ + + if (task_list[task] != port_task_self) + { + status = mach_port_deallocate (port_task_self, + thread_list[thread]); + if (status != KERN_SUCCESS) + syslog (LOG_ERR, "mach_port_deallocate failed: %s", + mach_error_string (status)); + } + } /* for (thread_list) */ + + if ((status = vm_deallocate (port_task_self, + (vm_address_t) thread_list, + thread_list_len * sizeof (thread_act_t))) + != KERN_SUCCESS) + { + syslog (LOG_ERR, "vm_deallocate failed: %s", + mach_error_string (status)); + } + thread_list = NULL; + thread_list_len = 0; + + /* Only deallocate the task port, if it isn't our own. + * Don't know what would happen in that case, but this + * is what Apple's top does.. ;) */ + if (task_list[task] != port_task_self) + { + status = mach_port_deallocate (port_task_self, + task_list[task]); + if (status != KERN_SUCCESS) + syslog (LOG_ERR, "mach_port_deallocate failed: %s", + mach_error_string (status)); + } + } /* for (task_list) */ + + if ((status = vm_deallocate (port_task_self, + (vm_address_t) task_list, + task_list_len * sizeof (task_t))) != KERN_SUCCESS) + { + syslog (LOG_ERR, "vm_deallocate failed: %s", + mach_error_string (status)); + } + task_list = NULL; + task_list_len = 0; + + if ((status = mach_port_deallocate (port_task_self, port_pset_priv)) + != KERN_SUCCESS) + { + syslog (LOG_ERR, "mach_port_deallocate failed: %s", + mach_error_string (status)); + } + } /* for (pset_list) */ + + ps_submit (running, sleeping, zombies, stopped, -1, blocked); +/* #endif HAVE_THREAD_INFO */ + +#elif KERNEL_LINUX + int running = 0; + int sleeping = 0; + int zombies = 0; + int stopped = 0; + int paging = 0; + int blocked = 0; char buf[BUFSIZE]; char filename[20]; /* need 17 bytes */ @@ -137,7 +398,7 @@ static void ps_read (void) closedir(proc); ps_submit (running, sleeping, zombies, stopped, paging, blocked); -#endif /* defined(KERNEL_LINUX) */ +#endif /* KERNEL_LINUX */ } #else # define ps_read NULL diff --git a/src/processes.h b/src/processes.h deleted file mode 100644 index db8446a0..00000000 --- a/src/processes.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * collectd - src/processes.h - * Copyright (C) 2005 Lyonel Vincent - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Lyonel Vincent - * Florian octo Forster - **/ - -#ifndef PROCESSES_H -#define PROCESSES_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_PROCESSES -#if defined(KERNEL_LINUX) -#define COLLECT_PROCESSES 1 -#else -#define COLLECT_PROCESSES 0 -#endif -#endif /* !defined(COLLECT_PROCESSES) */ - -#endif /* PROCESSES_H */ diff --git a/src/sensors.c b/src/sensors.c index 75981e84..05973ba3 100644 --- a/src/sensors.c +++ b/src/sensors.c @@ -44,7 +44,7 @@ static char *filename_format = "sensors-%s.rrd"; static char *ds_def[] = { - "DS:value:GAUGE:25:U:U", + "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U", NULL }; static int ds_num = 1; diff --git a/src/sensors.h b/src/sensors.h deleted file mode 100644 index 9fb17676..00000000 --- a/src/sensors.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * collectd - src/sensors.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef SENSORS_H -#define SENSORS_H - -#include "collectd.h" -#include "common.h" - -/* Won't compile without header file */ -#ifndef HAVE_SENSORS_SENSORS_H -#undef HAVE_LIBSENSORS -#endif - -#ifndef COLLECT_SENSORS -#ifdef HAVE_LIBSENSORS -#define COLLECT_SENSORS 1 -#else -#define COLLECT_SENSORS 0 -#endif -#endif /* !defined(COLLECT_SENSORS) */ - -#endif /* SENSORS_H */ diff --git a/src/serial.c b/src/serial.c index 31b6148e..a95eb2d0 100644 --- a/src/serial.c +++ b/src/serial.c @@ -37,8 +37,8 @@ static char *serial_filename_template = "serial-%s.rrd"; static char *ds_def[] = { - "DS:incoming:COUNTER:25:0:U", - "DS:outgoing:COUNTER:25:0:U", + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int ds_num = 2; diff --git a/src/serial.h b/src/serial.h deleted file mode 100644 index 83372801..00000000 --- a/src/serial.h +++ /dev/null @@ -1,42 +0,0 @@ -/** - * collectd - src/serial.h - * Copyright (C) 2005 David Bacher - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * David Bacher - * Florian octo Forster - **/ - -#ifndef SERIAL_H -#define SERIAL_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_SERIAL -#if defined(KERNEL_LINUX) -#define COLLECT_SERIAL 1 -#else -#define COLLECT_SERIAL 0 -#endif -#endif /* !defined(COLLECT_SERIAL) */ - -#endif /* SERIAL_H */ - - - - diff --git a/src/swap.c b/src/swap.c index 8ffa4536..a6a4e365 100644 --- a/src/swap.c +++ b/src/swap.c @@ -44,10 +44,10 @@ static char *swap_file = "swap.rrd"; /* 1099511627776 == 1TB ought to be enough for anyone ;) */ static char *ds_def[] = { - "DS:used:GAUGE:25:0:1099511627776", - "DS:free:GAUGE:25:0:1099511627776", - "DS:cached:GAUGE:25:0:1099511627776", - "DS:resv:GAUGE:25:0:1099511627776", + "DS:used:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776", + "DS:free:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776", + "DS:cached:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776", + "DS:resv:GAUGE:"COLLECTD_HEARTBEAT":0:1099511627776", NULL }; static int ds_num = 4; diff --git a/src/swap.h b/src/swap.h deleted file mode 100644 index dfe5d36d..00000000 --- a/src/swap.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/swap.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef SWAP_H -#define SWAP_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_SWAP -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB) -#define COLLECT_SWAP 1 -#else -#define COLLECT_SWAP 0 -#endif -#endif /* !defined(COLLECT_SWAP) */ - -#endif /* SWAP_H */ diff --git a/src/tape.c b/src/tape.c index 4671ed46..f6aeb93b 100644 --- a/src/tape.c +++ b/src/tape.c @@ -37,14 +37,14 @@ static char *tape_filename_template = "tape-%s.rrd"; /* 104857600 == 100 MB */ static char *tape_ds_def[] = { - "DS:rcount:COUNTER:25:0:U", - "DS:rmerged:COUNTER:25:0:U", - "DS:rbytes:COUNTER:25:0:U", - "DS:rtime:COUNTER:25:0:U", - "DS:wcount:COUNTER:25:0:U", - "DS:wmerged:COUNTER:25:0:U", - "DS:wbytes:COUNTER:25:0:U", - "DS:wtime:COUNTER:25:0:U", + "DS:rcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:rtime:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wcount:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wmerged:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wbytes:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:wtime:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int tape_ds_num = 8; diff --git a/src/tape.h b/src/tape.h deleted file mode 100644 index acf03a37..00000000 --- a/src/tape.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/tape.h - * Copyright (C) 2005 Scott Garrett - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Scott Garrett - **/ - -#ifndef TAPESTATS_H -#define TAPESTATS_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_TAPE -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) -#define COLLECT_TAPE 1 -#else -#define COLLECT_TAPE 0 -#endif -#endif /* !defined(COLLECT_TAPE) */ - -#endif /* TAPESTATS_H */ diff --git a/src/traffic.c b/src/traffic.c index f7a9f8f4..b5e7887f 100644 --- a/src/traffic.c +++ b/src/traffic.c @@ -24,9 +24,30 @@ #include "common.h" #include "plugin.h" +#if HAVE_SYS_TYPES_H +# include +#endif +#if HAVE_SYS_SOCKET_H +# include +#endif + +/* One cannot include both. This sucks. */ +#if HAVE_LINUX_IF_H +# include +#elif HAVE_NET_IF_H +# include +#endif + +#if HAVE_LINUX_NETDEVICE_H +# include +#endif +#if HAVE_IFADDRS_H +# include +#endif + #define MODULE_NAME "traffic" -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB) +#if HAVE_GETIFADDRS || defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB) # define TRAFFIC_HAVE_READ 1 #else # define TRAFFIC_HAVE_READ 0 @@ -38,8 +59,8 @@ static char *traffic_filename_template = "traffic-%s.rrd"; static char *ds_def[] = { - "DS:incoming:COUNTER:25:0:U", - "DS:outgoing:COUNTER:25:0:U", + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:U", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:U", NULL }; static int ds_num = 2; @@ -53,7 +74,15 @@ static int numif = 0; static void traffic_init (void) { -#ifdef HAVE_LIBKSTAT +#if HAVE_GETIFADDRS + /* nothing */ +/* #endif HAVE_GETIFADDRS */ + +#elif KERNEL_LINUX + /* nothing */ +/* #endif KERNEL_LINUX */ + +#elif HAVE_LIBKSTAT kstat_t *ksp_chain; unsigned long long val; @@ -76,7 +105,13 @@ static void traffic_init (void) continue; ksp[numif++] = ksp_chain; } -#endif /* HAVE_LIBKSTAT */ +/* #endif HAVE_LIBKSTAT */ + +#elif HAVE_LIBSTATG + /* nothing */ +#endif /* HAVE_LIBSTATG */ + + return; } static void traffic_write (char *host, char *inst, char *val) @@ -108,7 +143,41 @@ static void traffic_submit (char *device, static void traffic_read (void) { -#ifdef KERNEL_LINUX +#if HAVE_GETIFADDRS + struct ifaddrs *if_list; + struct ifaddrs *if_ptr; + +#if HAVE_STRUCT_IF_DATA +# define IFA_DATA if_data +# define IFA_INCOMING ifi_ibytes +# define IFA_OUTGOING ifi_obytes +#elif HAVE_STRUCT_NET_DEVICE_STATS +# define IFA_DATA net_device_stats +# define IFA_INCOMING rx_bytes +# define IFA_OUTGOING tx_bytes +#else +# error "No suitable type for `struct ifaddrs->ifa_data' found." +#endif + + struct IFA_DATA *if_data; + + if (getifaddrs (&if_list) != 0) + return; + + for (if_ptr = if_list; if_ptr != NULL; if_ptr = if_ptr->ifa_next) + { + if ((if_data = (struct IFA_DATA *) if_ptr->ifa_data) == NULL) + continue; + + traffic_submit (if_ptr->ifa_name, + if_data->IFA_INCOMING, + if_data->IFA_OUTGOING); + } + + freeifaddrs (if_list); +/* #endif HAVE_GETIFADDRS */ + +#elif KERNEL_LINUX FILE *fh; char buffer[1024]; unsigned long long incoming, outgoing; diff --git a/src/traffic.h b/src/traffic.h deleted file mode 100644 index 3b95927a..00000000 --- a/src/traffic.h +++ /dev/null @@ -1,37 +0,0 @@ -/** - * collectd - src/traffic.h - * Copyright (C) 2005 Florian octo Forster - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Florian octo Forster - **/ - -#ifndef TRAFFIC_H -#define TRAFFIC_H - -#include "collectd.h" -#include "common.h" - -#ifndef COLLECT_TRAFFIC -#if defined(KERNEL_LINUX) || defined(HAVE_LIBKSTAT) || defined(HAVE_LIBSTATGRAB) -#define COLLECT_TRAFFIC 1 -#else -#define COLLECT_TRAFFIC 0 -#endif -#endif /* !defined(COLLECT_TRAFFIC) */ - -#endif /* TRAFFIC_H */ diff --git a/src/users.c b/src/users.c index 5fe1b711..4041a1c8 100644 --- a/src/users.c +++ b/src/users.c @@ -43,7 +43,7 @@ static char *rrd_file = "users.rrd"; static char *ds_def[] = { - "DS:users:GAUGE:25:0:65535", + "DS:users:GAUGE:"COLLECTD_HEARTBEAT":0:65535", NULL }; static int ds_num = 1; diff --git a/src/users.h b/src/users.h deleted file mode 100644 index c5140941..00000000 --- a/src/users.h +++ /dev/null @@ -1,29 +0,0 @@ -/** - * collectd - src/users.h - * Copyright (C) 2005 Sebastian Harl - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * This program is distributed in the hope that it will be useful, but - * WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA - * - * Authors: - * Sebastian Harl - **/ - -#if !COLLECTD_USERS_H -#define COLLECTD_USERS_H 1 - -void module_register(void); - -#endif /* !COLLECTD_USERS_H */ - diff --git a/src/utils_mount.c b/src/utils_mount.c index 176040aa..30a155f4 100644 --- a/src/utils_mount.c +++ b/src/utils_mount.c @@ -429,15 +429,21 @@ static cu_mount_t *cu_mount_getfsstat (void) /* Get the number of mounted file systems */ if ((bufsize = getfsstat (NULL, 0, MNT_NOWAIT)) < 1) + { + DBG ("getfsstat failed: %s", strerror (errno)); return (NULL); + } - if ((buf = (struct statfs *) malloc (bufsize * sizeof (struct statfs))) == NULL) + if ((buf = (struct statfs *) malloc (bufsize * sizeof (struct statfs))) + == NULL) return (NULL); memset (buf, '\0', bufsize * sizeof (struct statfs)); - /* FIXME: If `bufsize' in bytes or structures? */ - if ((num = getfsstat (buf, bufsize, MNT_NOWAIT)) < 1) + /* The bufsize needs to be passed in bytes. Really. This is not in the + * manpage.. -octo */ + if ((num = getfsstat (buf, bufsize * sizeof (struct statfs), MNT_NOWAIT)) < 1) { + DBG ("getfsstat failed: %s", strerror (errno)); free (buf); return (NULL); } diff --git a/src/vserver.c b/src/vserver.c new file mode 100644 index 00000000..694b6d02 --- /dev/null +++ b/src/vserver.c @@ -0,0 +1,528 @@ +/** + * collectd - src/vserver.c + * Copyright (C) 2006 Sebastian Harl + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + * + * Authors: + * Sebastian Harl + **/ + +#include "collectd.h" +#include "common.h" +#include "plugin.h" + +#include +#include +#include +#include +#include +#include +#include + +#define BUFSIZE 512 + +#define MODULE_NAME "vserver" +#define PROCDIR "/proc/virtual" + +#if defined(KERNEL_LINUX) +# define VSERVER_HAVE_READ 1 +#else +# define VSERVER_HAVE_READ 0 +#endif /* defined(KERNEL_LINUX) */ + +static char *rrd_unix = "vserver-%s/traffic-unix.rrd"; +static char *rrd_inet = "vserver-%s/traffic-inet.rrd"; +static char *rrd_inet6 = "vserver-%s/traffic-inet6.rrd"; +static char *rrd_other = "vserver-%s/traffic-other.rrd"; +static char *rrd_unspec = "vserver-%s/traffic-unspec.rrd"; + +static char *rrd_thread = "vserver-%s/vs_threads.rrd"; + +static char *rrd_load = "vserver-%s/load.rrd"; + +static char *rrd_procs = "vserver-%s/vs_processes.rrd"; +static char *rrd_memory = "vserver-%s/vs_memory.rrd"; + +/* 9223372036854775807 == LLONG_MAX */ +/* bytes transferred */ +static char *ds_def_unix[] = +{ + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + NULL +}; +static int ds_num_unix = 3; + +static char *ds_def_inet[] = +{ + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + NULL +}; +static int ds_num_inet = 3; + +static char *ds_def_inet6[] = +{ + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + NULL +}; +static int ds_num_inet6 = 3; + +static char *ds_def_other[] = +{ + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + NULL +}; +static int ds_num_other = 3; + +static char *ds_def_unspec[] = +{ + "DS:incoming:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:outgoing:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:failed:COUNTER:"COLLECTD_HEARTBEAT":0:9223372036854775807", + NULL +}; +static int ds_num_unspec = 3; + +static char *ds_def_threads[] = +{ + "DS:total:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:running:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:uninterruptible:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + "DS:onhold:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + NULL +}; +static int ds_num_threads = 4; + +static char *ds_def_load[] = +{ + "DS:shortterm:GAUGE:"COLLECTD_HEARTBEAT":0:100", + "DS:midterm:GAUGE:"COLLECTD_HEARTBEAT":0:100", + "DS:longterm:GAUGE:"COLLECTD_HEARTBEAT":0:100", + NULL +}; +static int ds_num_load = 3; + +static char *ds_def_procs[] = +{ + "DS:total:GAUGE:"COLLECTD_HEARTBEAT":0:65535", + NULL +}; +static int ds_num_procs = 1; + +/* 9223372036854775807 == LLONG_MAX */ +/* bytes */ +static char *ds_def_memory[] = +{ + "DS:vm:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:vml:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:rss:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + "DS:anon:GAUGE:"COLLECTD_HEARTBEAT":0:9223372036854775807", + NULL +}; +static int ds_num_memory = 4; + +static int pagesize = 0; + +static void vserver_init (void) +{ + /* XXX Should we check for getpagesize () in configure? + * What's the right thing to do, if there is no getpagesize ()? */ + pagesize = getpagesize (); + return; +} /* static void vserver_init(void) */ + +static void vserver_unix_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_unix, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_unix, ds_num_unix); + return; +} /* static void vserver_unix_write(char *host, char *inst, char *val) */ + +static void vserver_inet_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_inet, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_inet, ds_num_inet); + return; +} /* static void vserver_inet_write(char *host, char *inst, char *val) */ + +static void vserver_inet6_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_inet6, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_inet6, ds_num_inet6); + return; +} /* static void vserver_inet6_write(char *host, char *inst, char *val) */ + +static void vserver_other_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_other, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_other, ds_num_other); + return; +} /* static void vserver_other_write(char *host, char *inst, char *val) */ + +static void vserver_unspec_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_unspec, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_unspec, ds_num_unspec); + return; +} /* static void vserver_unspec_write(char *host, char *inst, char *val) */ + +static void vserver_threads_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_thread, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_threads, ds_num_threads); + return; +} /* static void vserver_threads_write(char *host, char *inst, char *val) */ + +static void vserver_load_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_load, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_load, ds_num_load); + return; +} /* static void vserver_load_write(char *host, char *inst, char *val) */ + +static void vserver_procs_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_procs, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_procs, ds_num_procs); + return; +} /* static void vserver_procs_write(char *host, char *inst, char *val) */ + +static void vserver_memory_write (char *host, char *inst, char *val) +{ + int len; + char filename[BUFSIZE]; + + len = snprintf (filename, BUFSIZE, rrd_memory, inst); + if ((len > 0) && (len < BUFSIZE)) + rrd_update_file (host, filename, val, ds_def_memory, ds_num_memory); + return; +} /* static void vserver_memory_write(char *host, char *inst, char *val) */ + +#if VSERVER_HAVE_READ +static void vserver_submit (char *inst, long long unix_in, long long unix_out, + long long unix_failed, long long inet_in, long long inet_out, + long long inet_failed, long long inet6_in, long long inet6_out, + long long inet6_failed, long long other_in, long long other_out, + long long other_failed, long long unspec_in, long long unspec_out, + long long unspec_failed, int t_total, int t_running, + int t_uninterruptible, int t_onhold, double avg1, double avg5, + double avg15, int p_total, long long vm, long long vml, long long rss, + long long anon) +{ + int len; + char buffer[BUFSIZE]; + + len = snprintf (buffer, BUFSIZE, + "N:%lld:%lld:%lld", unix_in, unix_out, unix_failed); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_unix", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, + "N:%lld:%lld:%lld", inet_in, inet_out, inet_failed); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_inet", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, + "N:%lld:%lld:%lld", inet6_in, inet6_out, inet6_failed); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_inet6", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, + "N:%lld:%lld:%lld", other_in, other_out, other_failed); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_other", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, + "N:%lld:%lld:%lld", unspec_in, unspec_out, unspec_failed); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_unspec", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, "N:%d:%d:%d:%d", + t_total, t_running, t_uninterruptible, t_onhold); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_threads", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, "N:%.2f:%.2f:%.2f", + avg1, avg5, avg15); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_load", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, "N:%d", + p_total); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_procs", inst, buffer); + + + len = snprintf (buffer, BUFSIZE, "N:%lld:%lld:%lld:%lld", + vm, vml, rss, anon); + + if ((len > 0) && (len < BUFSIZE)) + plugin_submit ("vserver_memory", inst, buffer); + return; +} /* static void vserver_submit() */ + +static inline long long __get_sock_bytes(const char *s) +{ + while (s[0] != '/') + ++s; + + /* Remove '/' */ + ++s; + return atoll(s); +} + +static void vserver_read (void) +{ + DIR *proc; + struct dirent *dent; /* 42 */ + + errno = 0; + if (NULL == (proc = opendir (PROCDIR))) { + syslog (LOG_ERR, "Cannot open '%s': %s", PROCDIR, strerror (errno)); + return; + } + + while (NULL != (dent = readdir (proc))) { + int len; + char file[BUFSIZE]; + + FILE *fh; + char buffer[BUFSIZE]; + + char *cols[4]; + + long long unix_s[3] = {-1, -1, -1}; + long long inet[3] = {-1, -1, -1}; + long long inet6[3] = {-1, -1, -1}; + long long other[3] = {-1, -1, -1}; + long long unspec[3] = {-1, -1, -1}; + int threads[4] = {-1, -1, -1, -1}; + double load[3] = {-1, -1, -1}; + /* Just to be consistent ;-) */ + int procs[1] = {-1}; + long long memory[4] = {-1, -1, -1, -1}; + + if (dent->d_name[0] == '.') + continue; + + /* XXX This check is just the result of a trial-and-error test. + * I did not find any documentation describing the d_type field. */ + if (!(dent->d_type & 0x4)) + /* This is not a directory */ + continue; + + /* socket message accounting */ + len = snprintf (file, BUFSIZE, PROCDIR "/%s/cacct", dent->d_name); + if ((len < 0) || (len >= BUFSIZE)) + continue; + + if (NULL == (fh = fopen (file, "r"))) { + syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno)); + continue; + } + + while (NULL != fgets (buffer, BUFSIZE, fh)) { + if (strsplit (buffer, cols, 4) < 4) + continue; + + if (0 == strcmp (cols[0], "UNIX:")) { + unix_s[0] = __get_sock_bytes (cols[1]); + unix_s[1] = __get_sock_bytes (cols[2]); + unix_s[2] = __get_sock_bytes (cols[3]); + } + else if (0 == strcmp (cols[0], "INET:")) { + inet[0] = __get_sock_bytes (cols[1]); + inet[1] = __get_sock_bytes (cols[2]); + inet[2] = __get_sock_bytes (cols[3]); + } + else if (0 == strcmp (cols[0], "INET6:")) { + inet6[0] = __get_sock_bytes (cols[1]); + inet6[1] = __get_sock_bytes (cols[2]); + inet6[2] = __get_sock_bytes (cols[3]); + } + else if (0 == strcmp (cols[0], "OTHER:")) { + other[0] = __get_sock_bytes (cols[1]); + other[1] = __get_sock_bytes (cols[2]); + other[2] = __get_sock_bytes (cols[3]); + } + else if (0 == strcmp (cols[0], "UNSPEC:")) { + unspec[0] = __get_sock_bytes (cols[1]); + unspec[1] = __get_sock_bytes (cols[2]); + unspec[2] = __get_sock_bytes (cols[3]); + } + } + + fclose (fh); + + /* thread information and load */ + len = snprintf (file, BUFSIZE, PROCDIR "/%s/cvirt", dent->d_name); + if ((len < 0) || (len >= BUFSIZE)) + continue; + + if (NULL == (fh = fopen (file, "r"))) { + syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno)); + continue; + } + + while (NULL != fgets (buffer, BUFSIZE, fh)) { + int n = strsplit (buffer, cols, 4); + + if (2 == n) { + if (0 == strcmp (cols[0], "nr_threads:")) { + threads[0] = atoi (cols[1]); + } + else if (0 == strcmp (cols[0], "nr_running:")) { + threads[1] = atoi (cols[1]); + } + else if (0 == strcmp (cols[0], "nr_unintr:")) { + threads[2] = atoi (cols[1]); + } + else if (0 == strcmp (cols[0], "nr_onhold:")) { + threads[3] = atoi (cols[1]); + } + } + else if (4 == n) { + if (0 == strcmp (cols[0], "loadavg:")) { + load[0] = atof (cols[1]); + load[1] = atof (cols[2]); + load[2] = atof (cols[3]); + } + } + } + + fclose (fh); + + /* processes and memory usage */ + len = snprintf (file, BUFSIZE, PROCDIR "/%s/limit", dent->d_name); + if ((len < 0) || (len >= BUFSIZE)) + continue; + + if (NULL == (fh = fopen (file, "r"))) { + syslog (LOG_ERR, "Cannot open '%s': %s", file, strerror (errno)); + continue; + } + + while (NULL != fgets (buffer, BUFSIZE, fh)) { + if (strsplit (buffer, cols, 2) < 2) + continue; + + if (0 == strcmp (cols[0], "PROC:")) { + procs[0] = atoi (cols[1]); + } + else if (0 == strcmp (cols[0], "VM:")) { + memory[0] = atoll (cols[1]) * pagesize; + } + else if (0 == strcmp (cols[0], "VML:")) { + memory[1] = atoll (cols[1]) * pagesize; + } + else if (0 == strcmp (cols[0], "RSS:")) { + memory[2] = atoll (cols[1]) * pagesize; + } + else if (0 == strcmp (cols[0], "ANON:")) { + memory[3] = atoll (cols[1]) * pagesize; + } + } + + fclose (fh); + + /* XXX What to do in case of an error (i.e. some value is + * still -1)? */ + + vserver_submit (dent->d_name, unix_s[0], unix_s[1], unix_s[2], + inet[0], inet[1], inet[2], inet6[0], inet6[1], inet6[2], + other[0], other[1], other[2], unspec[0], unspec[1], unspec[2], + threads[0], threads[1], threads[2], threads[3], load[0], + load[1], load[2], procs[0], memory[0], memory[1], memory[2], + memory[3]); + } + + closedir (proc); + return; +} /* static void vserver_read(void) */ +#else +# define vserver_read NULL +#endif /* VSERVER_HAVE_READ */ + +void module_register (void) +{ + plugin_register (MODULE_NAME, vserver_init, vserver_read, NULL); + plugin_register ("vserver_unix", NULL, NULL, vserver_unix_write); + plugin_register ("vserver_inet", NULL, NULL, vserver_inet_write); + plugin_register ("vserver_inet6", NULL, NULL, vserver_inet6_write); + plugin_register ("vserver_other", NULL, NULL, vserver_other_write); + plugin_register ("vserver_unspec", NULL, NULL, vserver_unspec_write); + plugin_register ("vserver_threads", NULL, NULL, vserver_threads_write); + plugin_register ("vserver_load", NULL, NULL, vserver_load_write); + plugin_register ("vserver_procs", NULL, NULL, vserver_procs_write); + plugin_register ("vserver_memory", NULL, NULL, vserver_memory_write); + return; +} /* void module_register(void) */ + +/* vim: set ts=4 sw=4 noexpandtab : */ diff --git a/src/wireless.c b/src/wireless.c index be366c48..f0b9b01a 100644 --- a/src/wireless.c +++ b/src/wireless.c @@ -24,8 +24,6 @@ #include "common.h" #include "plugin.h" -#include - #define MODULE_NAME "wireless" #define BUFSIZE 1024 @@ -41,9 +39,9 @@ static char *filename_template = "wireless-%s.rrd"; static char *ds_def[] = { - "DS:quality:GAUGE:25:0:U", - "DS:power:GAUGE:25:0:U", - "DS:noise:GAUGE:25:0:U", + "DS:quality:GAUGE:"COLLECTD_HEARTBEAT":0:U", + "DS:power:GAUGE:"COLLECTD_HEARTBEAT":U:0", + "DS:noise:GAUGE:"COLLECTD_HEARTBEAT":U:0", NULL }; static int ds_num = 3; @@ -79,6 +77,7 @@ static void wireless_write (char *host, char *inst, char *val) } #if WIRELESS_HAVE_READ +#if 0 static double wireless_dbm_to_watt (double dbm) { double watt; @@ -92,6 +91,7 @@ static double wireless_dbm_to_watt (double dbm) return (watt); } +#endif static void wireless_submit (char *device, double quality, double power, double noise) @@ -154,18 +154,15 @@ static void wireless_read (void) power = atof (fields[3]); noise = atof (fields[4]); + /* Fill in invalid values when conversion failed.. */ if (quality == 0.0) - quality = -1.0; + quality = -1.0; /* quality >= 0 */ - if (power >= 0.0) - power = -1.0; - else - power = wireless_dbm_to_watt (power); + if (power == 0.0) + power = 1.0; /* power <= 0 */ - if (noise >= 0.0) - noise = -1.0; - else - noise = wireless_dbm_to_watt (noise); + if (noise == 0.0) + noise = 1.0; /* noise <= 0 */ wireless_submit (device, quality, power, noise); } @@ -179,7 +176,7 @@ static void wireless_read (void) void module_register (void) { - plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write); + plugin_register (MODULE_NAME, wireless_init, wireless_read, wireless_write); } #undef BUFSIZE