src/collectdmon
src/*.1
src/*.5
+src/.pod2man.tmp.*
src/libcollectdclient/collectd/lcc_features.h
+src/utils_vl_lookup_test
# patch stuff
*.rej
bindings/perl/Collectd/pm_to_blib
bindings/perl/blib/
bindings/perl/pm_to_blib
+bindings/buildperl
# java stuff
bindings/java/java-build-stamp
* A POSIX-threads (pthread) implementation.
Since gathering some statistics is slow (network connections, slow devices,
- etc) the collectd is parallelized. The POSIX threads interface is being
+ etc) collectd is parallelized. The POSIX threads interface is being
used and should be found in various implementations for hopefully all
platforms.
environment = new HashMap ();
environment.put (JMXConnector.CREDENTIALS, credentials);
+ environment.put(JMXConnectorFactory.PROTOCOL_PROVIDER_CLASS_LOADER, this.getClass().getClassLoader());
}
try
AC_MSG_ERROR([Didn't find out how doubles are stored in memory. Sorry.])
fi; fi; fi
+# --with-useragent {{{
+AC_ARG_WITH(useragent, [AS_HELP_STRING([--with-useragent@<:@=AGENT@:>@], [User agent to use on http requests])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ AC_DEFINE_UNQUOTED(COLLECTD_USERAGENT, ["$withval"], [User agent for http requests])
+ fi
+])
+
+# }}}
+
have_getfsstat="no"
AC_CHECK_FUNCS(getfsstat, [have_getfsstat="yes"])
have_getvfsstat="no"
fi
if test "x$with_libmnl" = "xyes"
then
+ AC_CHECK_MEMBERS([struct rtnl_link_stats64.tx_window_errors],
+ [AC_DEFINE(HAVE_RTNL_LINK_STATS64, 1, [Define if struct rtnl_link_stats64 exists and is usable.])],
+ [],
+ [
+ #include <linux/if_link.h>
+ ])
+fi
+if test "x$with_libmnl" = "xyes"
+then
AC_CHECK_LIB(mnl, mnl_nlmsg_get_payload,
[with_libmnl="yes"],
[with_libmnl="no (symbol 'mnl_nlmsg_get_payload' not found)"],
#!/usr/bin/perl
+# Copyright (c) 2006-2010 Florian Forster <octo at collectd.org>
+# Copyright (c) 2006-2008 Sebastian Harl <sh at tokkee.org>
+# Copyright (c) 2008 Mirko Buffoni <briareos at eswat.org>
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in
+# all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+# THE SOFTWARE.
use strict;
use warnings;
{
my $array_ref = shift;
my $array_sort = shift;
+ my $unknown_first = shift || 0;
my %elements = map { $_ => 1 } (@$array_ref);
splice (@$array_ref, 0);
push (@$array_ref, $_);
delete ($elements{$_});
}
- push (@$array_ref, sort (keys %elements));
+ if ($unknown_first) {
+ unshift (@$array_ref, sort (keys %elements));
+ }
+ else {
+ push (@$array_ref, sort (keys %elements));
+ }
} # _custom_sort_arrayref
sub action_show_host
$GraphDefs =
{
- apache_bytes => ['DEF:min_raw={file}:count:MIN',
- 'DEF:avg_raw={file}:count:AVERAGE',
- 'DEF:max_raw={file}:count:MAX',
+ apache_bytes => ['DEF:min_raw={file}:value:MIN',
+ 'DEF:avg_raw={file}:value:AVERAGE',
+ 'DEF:max_raw={file}:value:MAX',
'CDEF:min=min_raw,8,*',
'CDEF:avg=avg_raw,8,*',
'CDEF:max=max_raw,8,*',
'GPRINT:avg:LAST:%5.1lf%s Last',
'GPRINT:avg_sum:LAST:(ca. %5.1lf%sB Total)\l'
],
- apache_connections => ['DEF:min={file}:count:MIN',
- 'DEF:avg={file}:count:AVERAGE',
- 'DEF:max={file}:count:MAX',
+ apache_connections => ['DEF:min={file}:value:MIN',
+ 'DEF:avg={file}:value:AVERAGE',
+ 'DEF:max={file}:value:MAX',
"AREA:max#$HalfBlue",
"AREA:min#$Canvas",
"LINE1:avg#$FullBlue:Connections",
'GPRINT:max:MAX:%6.2lf Max,',
'GPRINT:avg:LAST:%6.2lf Last'
],
- apache_idle_workers => ['DEF:min={file}:count:MIN',
- 'DEF:avg={file}:count:AVERAGE',
- 'DEF:max={file}:count:MAX',
+ apache_idle_workers => ['DEF:min={file}:value:MIN',
+ 'DEF:avg={file}:value:AVERAGE',
+ 'DEF:max={file}:value:MAX',
"AREA:max#$HalfBlue",
"AREA:min#$Canvas",
"LINE1:avg#$FullBlue:Idle Workers",
'GPRINT:max:MAX:%6.2lf Max,',
'GPRINT:avg:LAST:%6.2lf Last'
],
- apache_requests => ['DEF:min={file}:count:MIN',
- 'DEF:avg={file}:count:AVERAGE',
- 'DEF:max={file}:count:MAX',
+ apache_requests => ['DEF:min={file}:value:MIN',
+ 'DEF:avg={file}:value:AVERAGE',
+ 'DEF:max={file}:value:MAX',
"AREA:max#$HalfBlue",
"AREA:min#$Canvas",
"LINE1:avg#$FullBlue:Requests/s",
'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',
+ apache_scoreboard => ['DEF:min={file}:value:MIN',
+ 'DEF:avg={file}:value:AVERAGE',
+ 'DEF:max={file}:value:MAX',
"AREA:max#$HalfBlue",
"AREA:min#$Canvas",
"LINE1:avg#$FullBlue:Processes",
$GraphDefs->{'virt_cpu_total'} = $GraphDefs->{'virt_cpu_total'};
$MetaGraphDefs->{'cpu'} = \&meta_graph_cpu;
+ $MetaGraphDefs->{'df_complex'} = \&meta_graph_df;
$MetaGraphDefs->{'dns_qtype'} = \&meta_graph_dns;
$MetaGraphDefs->{'dns_rcode'} = \&meta_graph_dns;
$MetaGraphDefs->{'if_rx_errors'} = \&meta_graph_if_rx_errors;
return (meta_graph_generic_stack ($opts, $sources));
} # meta_graph_cpu
+sub meta_graph_df
+{
+ confess ("Wrong number of arguments") if (@_ != 5);
+
+ my $host = shift;
+ my $plugin = shift;
+ my $plugin_instance = shift;
+ my $type = shift;
+ my $type_instances = shift;
+
+ my $opts = {};
+ my $sources = [];
+
+ my $prefix = "$host/$plugin"
+ . (defined ($plugin_instance) ? "-$plugin_instance" : '') . "/$type";
+
+ $opts->{'title'} = "Disk usage $prefix";
+
+ $opts->{'number_format'} = '%5.1lf%s';
+ $opts->{'rrd_opts'} = ['-l', 0, '-b', '1024', '-v', 'Bytes'];
+
+ my @files = ();
+
+ $opts->{'colors'} =
+ {
+ 'used' => 'ff0000',
+ 'snap_normal_used' => 'c10640',
+ 'snap_reserve_used' => '820c81',
+ 'snap_reserved' => 'f15aef',
+ 'reserved' => 'ffb000',
+ 'free' => '00ff00',
+ 'sis_saved' => '00e0e0',
+ 'dedup_saved' => '00c1c1',
+ 'compression_saved' => '00a2a2'
+ };
+
+ # LVM uses LV names as type-instance; they should sort first
+ _custom_sort_arrayref ($type_instances,
+ [qw(compression_saved dedup_saved sis_saved free reserved snap_reserved
+ snap_reserve_used snap_normal_used used)], 1);
+
+ for (@$type_instances)
+ {
+ my $inst = $_;
+ my $file = '';
+
+ for (@DataDirs)
+ {
+ if (-e "$_/$prefix-$inst.rrd")
+ {
+ $file = "$_/$prefix-$inst.rrd";
+ last;
+ }
+ }
+ confess ("No file found for $prefix") if ($file eq '');
+
+ push (@$sources,
+ {
+ name => $inst,
+ file => $file
+ }
+ );
+ } # for (@$type_instances)
+
+ return (meta_graph_generic_stack ($opts, $sources));
+} # meta_graph_df
+
sub meta_graph_dns
{
confess ("Wrong number of arguments") if (@_ != 5);
vl.time = time (NULL);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "myplugin", sizeof (vl.plugin));
+
+ /* it is strongly recommended to use a type defined in the types.db file
+ * instead of a custom type */
+ sstrncpy (vl.type, "myplugin", sizeof (vl.plugin));
/* optionally set vl.plugin_instance and vl.type_instance to reasonable
* values (default: "") */
/* dispatch the values to collectd which passes them on to all registered
- * write functions - the first argument is used to lookup the data set
- * definition (it is strongly recommended to use a type defined in the
- * types.db file) */
- plugin_dispatch_values ("myplugin", &vl);
+ * write functions */
+ plugin_dispatch_values (&vl);
/* A return value != 0 indicates an error and the plugin will be skipped
* for an increasing amount of time. */
/*
* This function is called after values have been dispatched to collectd.
*/
-static int my_write (const data_set_t *ds, const value_list_t *vl)
+static int my_write (const data_set_t *ds, const value_list_t *vl,
+ user_data_t *ud)
{
char name[1024] = "";
int i = 0;
/*
* This function is called when plugin_log () has been used.
*/
-static void my_log (int severity, const char *msg)
+static void my_log (int severity, const char *msg, user_data_t *ud)
{
printf ("LOG: %i - %s\n", severity, msg);
return;
/*
* This function is called when plugin_dispatch_notification () has been used.
*/
-static int my_notify (const notification_t *notif)
+static int my_notify (const notification_t *notif, user_data_t *ud)
{
char time_str[32] = "";
struct tm *tm = NULL;
*/
void module_register (void)
{
- plugin_register_log ("myplugin", my_log);
- plugin_register_notification ("myplugin", my_notify);
+ plugin_register_log ("myplugin", my_log, /* user data */ NULL);
+ plugin_register_notification ("myplugin", my_notify,
+ /* user data */ NULL);
plugin_register_data_set (&ds);
plugin_register_read ("myplugin", my_read);
plugin_register_init ("myplugin", my_init);
- plugin_register_write ("myplugin", my_write);
+ plugin_register_write ("myplugin", my_write, /* user data */ NULL);
plugin_register_shutdown ("myplugin", my_shutdown);
return;
} /* void module_register (void) */
/* subscribe only */
char *exchange_type;
char *queue;
+ _Bool queue_durable;
+ _Bool queue_auto_delete;
amqp_connection_state_t connection;
pthread_mutex_t lock;
? amqp_cstring_bytes (conf->queue)
: AMQP_EMPTY_BYTES,
/* passive = */ 0,
- /* durable = */ 0,
+ /* durable = */ conf->queue_durable,
/* exclusive = */ 0,
- /* auto_delete = */ 1,
+ /* auto_delete = */ conf->queue_auto_delete,
/* arguments = */ AMQP_EMPTY_TABLE);
if (qd_ret == NULL)
{
{
camqp_config_t *conf = user_data->data;
char routing_key[6 * DATA_MAX_NAME_LEN];
- char buffer[4096];
+ char buffer[8192];
int status;
if ((ds == NULL) || (vl == NULL) || (conf == NULL))
/* subscribe only */
conf->exchange_type = NULL;
conf->queue = NULL;
+ conf->queue_durable = 0;
+ conf->queue_auto_delete = 1;
/* general */
conf->connection = NULL;
pthread_mutex_init (&conf->lock, /* attr = */ NULL);
status = cf_util_get_string (child, &conf->exchange_type);
else if ((strcasecmp ("Queue", child->key) == 0) && !publish)
status = cf_util_get_string (child, &conf->queue);
+ else if (strcasecmp ("QueueDurable", child->key) == 0)
+ status = cf_util_get_boolean (child, &conf->queue_durable);
+ else if (strcasecmp ("QueueAutoDelete", child->key) == 0)
+ status = cf_util_get_boolean (child, &conf->queue_auto_delete);
else if (strcasecmp ("RoutingKey", child->key) == 0)
status = cf_util_get_string (child, &conf->routing_key);
else if ((strcasecmp ("Persistent", child->key) == 0) && publish)
curl_easy_setopt (st->curl, CURLOPT_WRITEHEADER, st);
}
- curl_easy_setopt (st->curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (st->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (st->curl, CURLOPT_ERRORBUFFER, st->apache_curl_error);
if (st->user != NULL)
curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, ascent_curl_callback);
- curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, ascent_curl_error);
if (user != NULL)
curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, bind_curl_callback);
- curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, bind_curl_error);
curl_easy_setopt (curl, CURLOPT_URL, (url != NULL) ? url : BIND_DEFAULT_URL);
curl_easy_setopt (curl, CURLOPT_FOLLOWLOCATION, 1L);
Community "another_string"
Collect "std_traffic" "hr_users"
</Host>
+ <Host "secure.router.mydomain.org">
+ Address "192.168.0.7"
+ Version 3
+ SecurityLevel "authPriv"
+ Username "cosmo"
+ AuthProtocol "SHA"
+ AuthPassphrase "setec_astronomy"
+ PrivacyProtocol "AES"
+ PrivacyPassphrase "too_many_secrets"
+ Collect "std_traffic"
+ </Host>
<Host "some.ups.mydomain.org">
Address "192.168.0.3"
Version 1
This value is not applied to counter-values.
+=item B<Ignore> I<Value> [, I<Value> ...]
+
+The ignore values allows to ignore Instances based on their name and the patterns
+specified by the various values you've entered. The match is a glob-type shell
+matching.
+
+=item B<InvertMatch> I<true|false(default)>
+
+The invertmatch value should be use in combination of the Ignore option.
+It changes the behaviour of the Ignore option, from a blacklist behaviour
+when InvertMatch is set to false, to a whitelist when specified to true.
+
=back
=head2 The Host block
Set the address to connect to.
-=item B<Version> B<1>|B<2>
+=item B<Version> B<1>|B<2>|B<3>
Set the SNMP version to use. When giving B<2> version C<2c> is actually used.
-Version 3 is not supported by this plugin.
=item B<Community> I<Community>
-Pass I<Community> to the host.
+Pass I<Community> to the host. (Ignored for SNMPv3).
+
+=item B<Username> I<Username>
+
+Sets the I<Username> to use for SNMPv3 security.
+
+=item B<SecurityLevel> I<authPriv>|I<authNoPriv>|I<noAuthNoPriv>
+
+Selects the security level for SNMPv3 security.
+
+=item B<Context> I<Context>
+
+Sets the I<Context> for SNMPv3 security.
+
+=item B<AuthProtocol> I<MD5>|I<SHA>
+
+Selects the authentication protocol for SNMPv3 security.
+
+=item B<AuthPassphrase> I<Passphrase>
+
+Sets the authentication passphrase for SNMPv3 security.
+
+=item B<PrivacyProtocol> I<AES>|I<DES>
+
+Selects the privacy (encryption) protocol for SNMPv3 security.
+
+=item B<PrivacyPassphrase> I<Passphrase>
+
+Sets the privacy (encryption) passphrase for SNMPv3 security.
=item B<Collect> I<Data> [I<Data> ...]
L<variables(5)>,
L<unix(7)>
-=head1 AUTHOR
+=head1 AUTHORS
Florian Forster E<lt>octo@verplant.orgE<gt>
+Michael Pilat E<lt>mike@mikepilat.comE<gt>
=cut
# ription of those options is available in the collectd.conf(5) manual page. #
##############################################################################
-#<Plugin "aggregation">
+#<Plugin aggregation>
# <Aggregation>
# #Host "unspecified"
# Plugin "cpu"
# </Aggregation>
#</Plugin>
-#<Plugin "amqp">
+#<Plugin amqp>
# <Publish "name">
# Host "localhost"
# Port "5672"
# CACert "/etc/ssl/ca.crt"
#</Plugin>
-#<Plugin "bind">
+#<Plugin bind>
# URL "http://localhost:8053/"
# ParseTime false
# OpCodes true
# IgnoreSelected false
#</Plugin>
+#<Plugin cpu>
+# ReportActive false
+# ReportByCpu true
+# ValuesPercentage false
+#</Plugin>
+#
#<Plugin csv>
# DataDir "@localstatedir@/lib/@PACKAGE_NAME@/csv"
# StoreRates false
# </URL>
#</Plugin>
-#<Plugin "curl_xml">
+#<Plugin curl_xml>
# <URL "http://localhost/stats.xml">
# Host "my_host"
# Instance "some_instance"
# </Directory>
#</Plugin>
-#<Plugin "gmond">
+#<Plugin gmond>
# MCReceiveFrom "239.2.11.71" "8649"
# <Metric "swap_total">
# Type "swap"
# IgnoreSelected true
#</Plugin>
-#<Plugin "java">
+#<Plugin java>
# JVMArg "-verbose:jni"
# JVMArg "-Djava.class.path=@prefix@/share/collectd/java/collectd-api.jar"
#
# InterfaceFormat name
#</Plugin>
+#<Plugin load>
+# ReportRelative true
+#</Plugin>
+
#<Plugin lpar>
# CpuPoolStats false
# ReportBySerial false
# </Instance>
#</Plugin>
+#<Plugin memory>
+# ValuesAbsolute true
+# ValuesPercentage false
+#</Plugin>
+
#<Plugin modbus>
# <Data "data_name">
# RegisterBase 1234
# TimerPercentile 90.0
#</Plugin>
-#<Plugin "swap">
+#<Plugin swap>
# ReportByDevice false
# ReportBytes true
+# ValuesAbsolute true
+# ValuesPercentage false
#</Plugin>
-#<Plugin "table">
+#<Plugin table>
# <Table "/proc/slabinfo">
# Instance "slabinfo"
# Separator " "
# </Table>
#</Plugin>
-#<Plugin "tail">
+#<Plugin tail>
# <File "/var/log/exim4/mainlog">
# Instance "exim"
+# Interval 60
# <Match>
# Regex "S=([1-9][0-9]*)"
# DSType "CounterAdd"
# </File>
#</Plugin>
-#<Plugin "tail_csv">
+#<Plugin tail_csv>
# <Metric "dropped">
# Type "percent"
# Instance "dropped"
# TTLFactor 2.0
# </Node>
# Tag "foobar"
+# Attribute "foo" "bar"
#</Plugin>
##############################################################################
##############################################################################
#@BUILD_PLUGIN_THRESHOLD_TRUE@LoadPlugin "threshold"
-#<Plugin "threshold">
+#<Plugin threshold>
# <Type "foo">
# WarningMin 0.00
# WarningMax 1000.00
BaseDir "/path/to/data/"
PIDFile "/path/to/pidfile/collectd.pid"
Server "123.123.123.123" 12345
-
+
LoadPlugin cpu
LoadPlugin load
-
+
<LoadPlugin df>
Interval 3600
</LoadPlugin>
-
+
LoadPlugin ping
<Plugin ping>
Host "example.org"
<Aggregation>
Plugin "cpu"
Type "cpu"
-
+
GroupBy "Host"
GroupBy "TypeInstance"
-
+
CalculateSum true
CalculateAverage true
</Aggregation>
Plugin "cpu"
PluginInstance "/[0,2,4,6,8]$/"
Type "cpu"
-
+
SetPlugin "cpu"
SetPluginInstance "even-%{aggregation}"
-
+
GroupBy "Host"
GroupBy "TypeInstance"
-
+
CalculateAverage true
</Aggregation>
</Plugin>
# GraphitePrefix "collectd."
# GraphiteEscapeChar "_"
</Publish>
-
+
# Receive values from an AMQP broker
<Subscribe "some_name">
Host "localhost"
ParseTime false
OpCodes true
QTypes true
-
+
ServerStats true
ZoneMaintStats true
ResolverStats false
MemoryStats true
-
+
<View "_default">
QTypes true
ResolverStats true
CacheRRSets true
-
+
Zone "127.in-addr.arpa/IN"
</View>
</Plugin>
=back
+=head2 Plugin C<cpu>
+
+The I<CPU plugin> collects CPU usage metrics.
+
+The following configuration options are available:
+
+=over 4
+
+=item B<ReportActive> B<false>|B<true>
+
+Reports non-idle CPU usage as the "active" value. Defaults to false.
+
+=item B<ReportByCpu> B<false>|B<true>
+
+When true reports usage for all cores. When false, reports cpu usage
+aggregated over all cores. Implies ValuesPercentage when false.
+Defaults to true.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+When true report percentage usage instead of tick values. Defaults to false.
+
+=back
+
+
=head2 Plugin C<cpufreq>
This plugin doesn't have any options. It reads
Password to use if authorization is required to read the page.
+=item B<Digest> B<true>|B<false>
+
+Enable HTTP digest authentication.
+
=item B<VerifyPeer> B<true>|B<false>
Enable or disable peer SSL certificate verification. See
Sets the plugin instance to I<Instance>.
=item B<User> I<Name>
+
=item B<Password> I<Password>
+
+=item B<Digest> B<true>|B<false>
+
=item B<VerifyPeer> B<true>|B<false>
+
=item B<VerifyHost> B<true>|B<false>
+
=item B<CACert> I<file>
+
=item B<Header> I<Header>
+
=item B<Post> I<Body>
These options behave exactly equivalent to the appropriate options of the
=item B<Password> I<Password>
+=item B<Digest> B<true>|B<false>
+
=item B<VerifyPeer> B<true>|B<false>
=item B<VerifyHost> B<true>|B<false>
=item B<ValuesAbsolute> B<true>|B<false>
-Enables or disables reporting of free, used and used disk space in 1K-blocks.
-Defaults to true.
+Enables or disables reporting of free and used disk space in 1K-blocks.
+Defaults to B<true>.
-=item B<ValuesPercentage> B<true>|B<false>
+=item B<ValuesPercentage> B<false>|B<true>
-Enables or disables reporting of free, used and used disk space in percentage.
-Defaults to false.
+Enables or disables reporting of free and used disk space in percentage.
+Defaults to B<false>.
-This is useful for deploying collectd on the cloud, where machines with
-different disk size may exist. Then it is more practical to configure thresholds
-based on relative disk size.
+This is useful for deploying I<collectd> on the cloud, where machines with
+different disk size may exist. Then it is more practical to configure
+thresholds based on relative disk size.
=back
=back
++=head2 Plugin C<load>
+
+The I<Load plugin> collects the system load. These numbers give a rough overview
+over the utilization of a machine. The system load is defined as the number of
+runnable tasks in the run-queue and is provided by many operating systems as a
+one, five or fifteen minute average.
+
+The following configuration options are available:
+
+=over 4
+
+=item B<ReportRelative> B<false>|B<true>
+
+When enabled, system load divided by number of available CPU cores is reported
+for intervals 1 min, 5 min and 15 min. Defaults to false.
+
+=back
+
+
=head2 Plugin C<logfile>
=over 4
ShowCPU true
ShowCPUCores true
ShowMemory true
-
+
ShowTemperatures true
Temperature vddg
Temperature vddq
ShowPower true
Power total0
Power total1
- IgnoreSelectedPower true
+ IgnoreSelectedPower true
</Plugin>
The following options are valid inside the B<PluginE<nbsp>mic> block:
=item fout
-Fan Out
+Fan Out
=item vccp
=item total0
-Total power utilization averaged over Time Window 0 (uWatts).
+Total power utilization averaged over Time Window 0 (uWatts).
=item total1
-Total power utilization averaged over Time Window 0 (uWatts).
+Total power utilization averaged over Time Window 0 (uWatts).
=item inst
=item imax
-Max instantaneous power (uWatts).
+Max instantaneous power (uWatts).
=item pcie
-PCI-E connector power (uWatts).
+PCI-E connector power (uWatts).
=item c2x3
-2x3 connector power (uWatts).
+2x3 connector power (uWatts).
=item c2x4
-2x4 connector power (uWatts).
+2x4 connector power (uWatts).
=item vccp
-Core rail (uVolts).
+Core rail (uVolts).
=item vddg
-Uncore rail (uVolts).
+Uncore rail (uVolts).
=item vddq
-Memory subsystem rail (uVolts).
+Memory subsystem rail (uVolts).
+
+=back
=back
+=head2 Plugin C<memory>
+
+The I<memory plugin> provides the following configuration options:
+
+=over 4
+
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of physical memory usage in absolute numbers,
+i.e. bytes. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of physical memory usage in percentages, e.g.
+percent of physical memory used. Defaults to B<false>.
+
+This is useful for deploying I<collectd> in a heterogeneous environment in
+which the sizes of physical memory vary.
+
=back
=head2 Plugin C<modbus>
Type voltage
Instance "input-1"
</Data>
-
+
<Data "voltage-input-2">
RegisterBase 2
RegisterType float
Type voltage
Instance "input-2"
</Data>
-
+
<Host "modbus.example.com">
Address "192.168.0.42"
Port "502"
Interval 60
-
+
<Slave 1>
Instance "power-supply"
Collect "voltage-input-1"
User "username"
Password "aef4Aebe"
Interval 30
-
+
<WAFL>
Interval 30
GetNameCache true
GetBufferCache true
GetInodeCache true
</WAFL>
-
+
<Disks>
Interval 30
GetBusy true
</Disks>
-
+
<VolumePerf>
Interval 30
GetIO "volume0"
GetLatency "volume0"
IgnoreSelectedLatency false
</VolumePerf>
-
+
<VolumeUsage>
Interval 30
GetCapacity "vol0"
GetSnapshot "vol3"
IgnoreSelectedSnapshot false
</VolumeUsage>
-
+
<Quota>
Interval 60
</Quota>
-
+
<Snapvault>
Interval 30
</Snapvault>
-
+
<System>
Interval 30
GetCPULoad true
# Export to an internal server
# (demonstrates usage without additional options)
Server "collectd.internal.tld"
-
+
# Export to an external server
# (demonstrates usage with signature options)
<Server "collectd.external.tld">
When enabled, the I<swap I/O> is reported in bytes. When disabled, the default,
I<swap I/O> is reported in pages. This option is available under Linux only.
+=item B<ValuesAbsolute> B<true>|B<false>
+
+Enables or disables reporting of absolute swap metrics, i.e. number of I<bytes>
+available and used. Defaults to B<true>.
+
+=item B<ValuesPercentage> B<false>|B<true>
+
+Enables or disables reporting of relative swap metrics, i.e. I<percent>
+available and free. Defaults to B<false>.
+
+This is useful for deploying I<collectd> in a heterogeneous environment, where
+swap sizes differ and you want to specify generic thresholds or similar.
+
=back
=head2 Plugin C<syslog>
<Plugin "tail">
<File "/var/log/exim4/mainlog">
Instance "exim"
+ Interval 60
<Match>
Regex "S=([1-9][0-9]*)"
DSType "CounterAdd"
next B<Instance> option. This way you can extract several plugin instances from
one logfile, handy when parsing syslog and the like.
+The B<Interval> option allows you to define the length of time between reads. If
+this is not set, the default Interval will be used.
+
Each B<Match> block has the following options to describe how the match should
be performed:
TTLFactor 2.0
</Node>
Tag "foobar"
+ Attribute "foo" "bar"
</Plugin>
The following options are understood by the I<write_riemann plugin>:
Add the given string as an additional tag to the metric being sent to
I<Riemann>.
+=item B<Attribute> I<String> I<String>
+
+Consider the two given strings to be the key and value of an additional
+attribute for each metric being sent out to I<Riemann>.
+
=back
=head1 THRESHOLD CONFIGURATION
Max 100
Satisfy "All"
</Match>
-
+
# Match if the value of any data source is outside the range of 0 - 100.
<Match "value">
Min 0
<Target "replace">
# Replace "example.net" with "example.com"
Host "\\<example.net\\>" "example.com"
-
+
# Strip "www." from hostnames
Host "\\<www\\." ""
</Target>
# define COLLECTD_DEFAULT_INTERVAL 10.0
#endif
+ #ifndef COLLECTD_USERAGENT
+ # define COLLECTD_USERAGENT PACKAGE_NAME"/"PACKAGE_VERSION
+ #endif
+
/* Remove GNU specific __attribute__ settings when using another compiler */
#if !__GNUC__
# define __attribute__(x) /**/
/**
* collectd - src/common.c
- * Copyright (C) 2005-2010 Florian octo Forster
+ * Copyright (C) 2005-2014 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
return (buffer_len);
} /* size_t strstripnewline */
-int escape_slashes (char *buf, int buf_len)
+int escape_slashes (char *buffer, size_t buffer_size)
{
int i;
+ size_t buffer_len;
- if (strcmp (buf, "/") == 0)
- {
- if (buf_len < 5)
- return (-1);
+ buffer_len = strlen (buffer);
- strncpy (buf, "root", buf_len);
+ if (buffer_len <= 1)
+ {
+ if (strcmp ("/", buffer) == 0)
+ {
+ if (buffer_size < 5)
+ return (-1);
+ sstrncpy (buffer, "root", buffer_size);
+ }
return (0);
}
- if (buf_len <= 1)
- return (0);
-
/* Move one to the left */
- if (buf[0] == '/')
- memmove (buf, buf + 1, buf_len - 1);
+ if (buffer[0] == '/')
+ {
+ memmove (buffer, buffer + 1, buffer_len);
+ buffer_len--;
+ }
- for (i = 0; i < buf_len - 1; i++)
+ for (i = 0; i < buffer_len - 1; i++)
{
- if (buf[i] == '\0')
- break;
- else if (buf[i] == '/')
- buf[i] = '_';
+ if (buffer[i] == '/')
+ buffer[i] = '_';
}
- buf[i] = '\0';
return (0);
} /* int escape_slashes */
char ident[128];
*ksp_ptr = NULL;
-
+
if (kc == NULL)
return (-1);
while ((ent = readdir (dh)) != NULL)
{
int status;
-
+
if (include_hidden)
{
if ((strcmp (".", ent->d_name) == 0)
return (0);
} /* }}} value_t rate_to_value */
+int value_to_rate (value_t *ret_rate, derive_t value, /* {{{ */
+ value_to_rate_state_t *state,
+ int ds_type, cdtime_t t)
+{
+ double interval;
+
+ /* Another invalid state: The time is not increasing. */
+ if (t <= state->last_time)
+ {
+ memset (state, 0, sizeof (*state));
+ return (EINVAL);
+ }
+
+ interval = CDTIME_T_TO_DOUBLE(t - state->last_time);
+
+ /* Previous value is invalid. */
+ if (state->last_time == 0) /* {{{ */
+ {
+ if (ds_type == DS_TYPE_DERIVE)
+ {
+ state->last_value.derive = value;
+ }
+ else if (ds_type == DS_TYPE_COUNTER)
+ {
+ state->last_value.counter = (counter_t) value;
+ }
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ {
+ state->last_value.absolute = (absolute_t) value;
+ }
+ else
+ {
+ assert (23 == 42);
+ }
+
+ state->last_time = t;
+ return (EAGAIN);
+ } /* }}} */
+
+ if (ds_type == DS_TYPE_DERIVE)
+ {
+ ret_rate->gauge = (value - state->last_value.derive) / interval;
+ state->last_value.derive = value;
+ }
+ else if (ds_type == DS_TYPE_COUNTER)
+ {
+ ret_rate->gauge = (((counter_t)value) - state->last_value.counter) / interval;
+ state->last_value.counter = (counter_t) value;
+ }
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ {
+ ret_rate->gauge = (((absolute_t)value) - state->last_value.absolute) / interval;
+ state->last_value.absolute = (absolute_t) value;
+ }
+ else
+ {
+ assert (23 == 42);
+ }
+
+ state->last_time = t;
+ return (0);
+} /* }}} value_t rate_to_value */
+
int service_name_to_port_number (const char *service_name)
{
struct addrinfo *ai_list;
/**
* collectd - src/common.h
- * Copyright (C) 2005-2010 Florian octo Forster
+ * Copyright (C) 2005-2014 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
};
typedef struct rate_to_value_state_s rate_to_value_state_t;
+struct value_to_rate_state_s
+{
+ value_t last_value;
+ cdtime_t last_time;
+};
+typedef struct value_to_rate_state_s value_to_rate_state_t;
+
char *sstrncpy (char *dest, const char *src, size_t n);
__attribute__ ((format(printf,3,4)))
* escape_slashes
*
* DESCRIPTION
- * Removes slashes from the string `buf' and substitutes them with something
- * appropriate. This function should be used whenever a path is to be used as
- * (part of) an instance.
+ * Removes slashes ("/") from "buffer". If buffer contains a single slash,
+ * the result will be "root". Leading slashes are removed. All other slashes
+ * are replaced with underscores ("_").
+ * This function is used by plugin_dispatch_values() to escape all parts of
+ * the identifier.
*
* PARAMETERS
- * `buf' String to be escaped.
- * `buf_len' Length of the buffer. No more then this many bytes will be
- * written to `buf', including the trailing null-byte.
+ * `buffer' String to be escaped.
+ * `buffer_size' Size of the buffer. No more then this many bytes will be
+ * written to `buffer', including the trailing null-byte.
*
* RETURN VALUE
* Returns zero upon success and a value smaller than zero upon failure.
*/
-int escape_slashes (char *buf, int buf_len);
+int escape_slashes (char *buffer, size_t buffer_size);
/*
* NAME
int rate_to_value (value_t *ret_value, gauge_t rate,
rate_to_value_state_t *state, int ds_type, cdtime_t t);
+int value_to_rate (value_t *ret_rate, derive_t value,
+ value_to_rate_state_t *state, int ds_type, cdtime_t t);
+
/* Converts a service name (a string) to a port number
* (in the range [1-65535]). Returns less than zero on error. */
int service_name_to_port_number (const char *service_name);
*
* 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
+ * 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
#endif
#define CONNTRACK_FILE "/proc/sys/net/netfilter/nf_conntrack_count"
+#define CONNTRACK_MAX_FILE "/proc/sys/net/netfilter/nf_conntrack_max"
-static void conntrack_submit (value_t conntrack)
+static void conntrack_submit (const char *type, const char *type_instance,
+ value_t conntrack)
{
value_list_t vl = VALUE_LIST_INIT;
vl.values_len = 1;
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "conntrack", sizeof (vl.plugin));
- sstrncpy (vl.type, "conntrack", sizeof (vl.type));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ if (type_instance != NULL)
+ sstrncpy (vl.type_instance, type_instance,
+ sizeof (vl.type_instance));
plugin_dispatch_values (&vl);
} /* static void conntrack_submit */
static int conntrack_read (void)
{
- value_t conntrack;
+ value_t conntrack, conntrack_max, conntrack_pct;
FILE *fh;
char buffer[64];
size_t buffer_len;
if (parse_value (buffer, &conntrack, DS_TYPE_GAUGE) != 0)
return (-1);
- conntrack_submit (conntrack);
+ conntrack_submit ("conntrack", NULL, conntrack);
+
+ fh = fopen (CONNTRACK_MAX_FILE, "r");
+ if (fh == NULL)
+ return (-1);
+
+ memset (buffer, 0, sizeof (buffer));
+ if (fgets (buffer, sizeof (buffer), fh) == NULL)
+ {
+ fclose (fh);
+ return (-1);
+ }
+ fclose (fh);
+
+ /* strip trailing newline. */
+ buffer_len = strlen (buffer);
+ while ((buffer_len > 0) && isspace ((int) buffer[buffer_len - 1]))
+ {
+ buffer[buffer_len - 1] = 0;
+ buffer_len--;
+ }
+
+ if (parse_value (buffer, &conntrack_max, DS_TYPE_GAUGE) != 0)
+ return (-1);
+
+ conntrack_submit ("conntrack", "max", conntrack_max);
+ conntrack_pct.gauge = (conntrack.gauge / conntrack_max.gauge) * 100;
+ conntrack_submit ("percent", "used", conntrack_pct);
+
return (0);
} /* static int conntrack_read */
/**
* collectd - src/cpu.c
* Copyright (C) 2005-2010 Florian octo Forster
- * Copyright (C) 2008 Oleg King
- * Copyright (C) 2009 Simon Kuhnle
- * Copyright (C) 2009 Manuel Sanmartin
+ * Copyright (C) 2008 Oleg King
+ * Copyright (C) 2009 Simon Kuhnle
+ * Copyright (C) 2009 Manuel Sanmartin
*
* 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
*
* 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
+ * 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
# define CAN_USE_SYSCTL 0
#endif
+#define CPU_SUBMIT_USER 0
+#define CPU_SUBMIT_SYSTEM 1
+#define CPU_SUBMIT_WAIT 2
+#define CPU_SUBMIT_NICE 3
+#define CPU_SUBMIT_SWAP 4
+#define CPU_SUBMIT_INTERRUPT 5
+#define CPU_SUBMIT_SOFTIRQ 6
+#define CPU_SUBMIT_STEAL 7
+#define CPU_SUBMIT_IDLE 8
+#define CPU_SUBMIT_ACTIVE 9
+#define CPU_SUBMIT_MAX 10
+
#if HAVE_STATGRAB_H
# include <statgrab.h>
#endif
# error "No applicable input method."
#endif
+static const char *cpu_state_names[] = {
+ "user",
+ "system",
+ "wait",
+ "nice",
+ "swap",
+ "interrupt",
+ "softirq",
+ "steal",
+ "idle",
+ "active"
+};
+
#ifdef PROCESSOR_CPU_LOAD_INFO
static mach_port_t port_host;
static processor_port_array_t cpu_list;
#if PROCESSOR_TEMPERATURE
static int cpu_temp_retry_counter = 0;
-static int cpu_temp_retry_step = 1;
-static int cpu_temp_retry_max = 1;
+static int cpu_temp_retry_step = 1;
+static int cpu_temp_retry_max = 1;
#endif /* PROCESSOR_TEMPERATURE */
/* #endif PROCESSOR_CPU_LOAD_INFO */
static int pnumcpu;
#endif /* HAVE_PERFSTAT */
+static value_to_rate_state_t *percents = NULL;
+static gauge_t agg_percents[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+
+};
+static int percents_cells = 0;
+static int cpu_count = 0;
+
+
+static _Bool report_by_cpu = 1;
+static _Bool report_percent = 0;
+static _Bool report_active = 0;
+
+static const char *config_keys[] =
+{
+ "ReportByCpu",
+ "ReportActive",
+ "ValuesPercentage"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+
+static int cpu_config (const char *key, const char *value)
+{
+ if (strcasecmp (key, "ReportByCpu") == 0) {
+ report_by_cpu = IS_TRUE (value) ? 1 : 0;
+ if (!report_by_cpu)
+ report_percent = 1;
+ }
+ if (strcasecmp (key, "ValuesPercentage") == 0) {
+ report_percent = IS_TRUE (value) ? 1 : 0;
+ if (!report_percent)
+ report_by_cpu = 1;
+ }
+ if (strcasecmp (key, "ReportActive") == 0)
+ report_active = IS_TRUE (value) ? 1 : 0;
+ return (-1);
+}
+
+static int cpu_states_grow (void)
+{
+ void *tmp;
+ int size;
+ int i;
+
+ size = cpu_count * CPU_SUBMIT_MAX; /* always alloc for all states */
+
+ if (size <= 0)
+ return 0;
+
+ if (percents_cells >= size)
+ return 0;
+
+ if (percents == NULL) {
+ percents = malloc(size * sizeof(*percents));
+ if (percents == NULL)
+ return -1;
+ for (i = 0; i < size; i++)
+ memset(&percents[i], 0, sizeof(*percents));
+ percents_cells = size;
+ return 0;
+ }
+
+ tmp = realloc(percents, size * sizeof(*percents));
+
+ if (tmp == NULL) {
+ ERROR ("cpu plugin: could not reserve enough space to hold states");
+ percents = NULL;
+ return -1;
+ }
+
+ percents = tmp;
+
+ for (i = percents_cells ; i < size; i++)
+ memset(&percents[i], 0, sizeof(*percents));
+
+ percents_cells = size;
+ return 0;
+} /* cpu_states_grow */
+
+
static int init (void)
{
#if PROCESSOR_CPU_LOAD_INFO || PROCESSOR_TEMPERATURE
return (0);
} /* int init */
-static void submit (int cpu_num, const char *type_instance, derive_t value)
+static void submit_value (int cpu_num, int cpu_state, const char *type, value_t value)
{
value_t values[1];
value_list_t vl = VALUE_LIST_INIT;
- values[0].derive = value;
+ memcpy(&values[0], &value, sizeof(value));
vl.values = values;
vl.values_len = 1;
+
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "cpu", sizeof (vl.plugin));
- ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
- "%i", cpu_num);
- sstrncpy (vl.type, "cpu", sizeof (vl.type));
- sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
+ sstrncpy (vl.type, type, sizeof (vl.type));
+ sstrncpy (vl.type_instance, cpu_state_names[cpu_state],
+ sizeof (vl.type_instance));
+ if (cpu_num >= 0) {
+ ssnprintf (vl.plugin_instance, sizeof (vl.plugin_instance),
+ "%i", cpu_num);
+ }
plugin_dispatch_values (&vl);
}
+static void submit_percent(int cpu_num, int cpu_state, gauge_t percent)
+{
+ value_t value;
+
+ value.gauge = percent;
+ submit_value (cpu_num, cpu_state, "percent", value);
+}
+
+static void submit_derive(int cpu_num, int cpu_state, derive_t derive)
+{
+ value_t value;
+
+ value.derive = derive;
+ submit_value (cpu_num, cpu_state, "cpu", value);
+}
+
+static void submit_flush (void)
+{
+ int i = 0;
+
+ if (report_by_cpu) {
+ cpu_count = 0;
+ return;
+ }
+
+ for (i = 0; i < CPU_SUBMIT_MAX; i++) {
+ if (agg_percents[i] == -1)
+ continue;
+
+ submit_percent(-1, i, agg_percents[i] / cpu_count);
+ agg_percents[i] = -1;
+ }
+ cpu_count = 0;
+}
+
+static void submit (int cpu_num, derive_t *derives)
+{
+
+ int i = 0;
+
+ if (!report_percent && report_by_cpu) {
+ derive_t cpu_active = 0;
+ for (i = 0; i < CPU_SUBMIT_ACTIVE; i++)
+ {
+ if (derives[i] == -1)
+ continue;
+
+ if (i != CPU_SUBMIT_IDLE)
+ cpu_active += derives[i];
+
+ submit_derive(cpu_num, i, derives[i]);
+ }
+ if (report_active)
+ submit_derive(cpu_num, CPU_SUBMIT_ACTIVE, cpu_active);
+ }
+ else /* we are reporting percents */
+ {
+ cdtime_t cdt;
+ gauge_t percent;
+ gauge_t cpu_total = 0;
+ gauge_t cpu_active = 0;
+ gauge_t local_rates[CPU_SUBMIT_MAX];
+
+ cpu_count++;
+ if (cpu_states_grow())
+ return;
+
+ memset(local_rates, 0, sizeof(local_rates));
+
+ cdt = cdtime();
+ for (i = 0; i < CPU_SUBMIT_ACTIVE; i++) {
+ value_t rate;
+ int index;
+
+ if (derives[i] == -1)
+ continue;
+
+ index = (cpu_num * CPU_SUBMIT_MAX) + i;
+ if (value_to_rate(&rate, derives[i], &percents[index],
+ DS_TYPE_DERIVE, cdt) != 0) {
+ local_rates[i] = -1;
+ continue;
+ }
+
+ local_rates[i] = rate.gauge;
+ cpu_total += rate.gauge;
+ if (i != CPU_SUBMIT_IDLE)
+ cpu_active += rate.gauge;
+ }
+ if (cpu_total == 0.0)
+ return;
+
+ if (report_active)
+ local_rates[CPU_SUBMIT_ACTIVE] = cpu_active;
+
+ for (i = 0; i < CPU_SUBMIT_MAX; i++) {
+ if (local_rates[i] == -1)
+ continue;
+
+ percent = (local_rates[i] / cpu_total) * 100;
+ if (report_by_cpu)
+ submit_percent (cpu_num, i, percent);
+ else {
+ if (agg_percents[i] == -1)
+ agg_percents[i] = percent;
+ else
+ agg_percents[i] += percent;
+ }
+
+ }
+ }
+}
+
static int cpu_read (void)
{
#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;
+ 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;
+ 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
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ memset(derives, -1, sizeof(derives));
cpu_host = 0;
cpu_info_len = PROCESSOR_BASIC_INFO_COUNT;
continue;
}
- submit (cpu, "user", (derive_t) cpu_info.cpu_ticks[CPU_STATE_USER]);
- submit (cpu, "nice", (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE]);
- submit (cpu, "system", (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM]);
- submit (cpu, "idle", (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE]);
+ derives[CPU_SUBMIT_USER] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_USER];
+ derives[CPU_SUBMIT_NICE] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_NICE];
+ derives[CPU_SUBMIT_SYSTEM] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_SYSTEM];
+ derives[CPU_SUBMIT_IDLE] = (derive_t) cpu_info.cpu_ticks[CPU_STATE_IDLE];
+ submit (cpu, derives);
+
#endif /* PROCESSOR_CPU_LOAD_INFO */
#if PROCESSOR_TEMPERATURE
/*
if (cpu_temp_len != 1)
{
DEBUG ("processor_info (PROCESSOR_TEMPERATURE) returned %i elements..?",
- (int) cpu_temp_len);
+ (int) cpu_temp_len);
continue;
}
cpu_temp_retry_step = 1;
#endif /* PROCESSOR_TEMPERATURE */
}
+ submit_flush ();
/* #endif PROCESSOR_CPU_LOAD_INFO */
#elif defined(KERNEL_LINUX)
int cpu;
- derive_t user, nice, syst, idle;
- derive_t wait, intr, sitr; /* sitr == soft interrupt */
FILE *fh;
char buf[1024];
while (fgets (buf, 1024, fh) != NULL)
{
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
if (strncmp (buf, "cpu", 3))
continue;
if ((buf[3] < '0') || (buf[3] > '9'))
continue;
cpu = atoi (fields[0] + 3);
- user = atoll (fields[1]);
- nice = atoll (fields[2]);
- syst = atoll (fields[3]);
- idle = atoll (fields[4]);
-
- submit (cpu, "user", user);
- submit (cpu, "nice", nice);
- submit (cpu, "system", syst);
- submit (cpu, "idle", idle);
+ derives[CPU_SUBMIT_USER] = atoll(fields[1]);
+ derives[CPU_SUBMIT_NICE] = atoll(fields[2]);
+ derives[CPU_SUBMIT_SYSTEM] = atoll(fields[3]);
+ derives[CPU_SUBMIT_IDLE] = atoll(fields[4]);
if (numfields >= 8)
{
- wait = atoll (fields[5]);
- intr = atoll (fields[6]);
- sitr = atoll (fields[7]);
-
- submit (cpu, "wait", wait);
- submit (cpu, "interrupt", intr);
- submit (cpu, "softirq", sitr);
+ derives[CPU_SUBMIT_WAIT] = atoll(fields[5]);
+ derives[CPU_SUBMIT_INTERRUPT] = atoll(fields[6]);
+ derives[CPU_SUBMIT_SOFTIRQ] = atoll(fields[6]);
if (numfields >= 9)
- submit (cpu, "steal", atoll (fields[8]));
+ derives[CPU_SUBMIT_STEAL] = atoll(fields[8]);
}
+ submit(cpu, derives);
}
+ submit_flush();
fclose (fh);
/* #endif defined(KERNEL_LINUX) */
#elif defined(HAVE_LIBKSTAT)
int cpu;
- derive_t user, syst, idle, wait;
static cpu_stat_t cs;
if (kc == NULL)
for (cpu = 0; cpu < numcpu; cpu++)
{
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
if (kstat_read (kc, ksp[cpu], &cs) == -1)
continue; /* error message? */
- idle = (derive_t) cs.cpu_sysinfo.cpu[CPU_IDLE];
- user = (derive_t) cs.cpu_sysinfo.cpu[CPU_USER];
- syst = (derive_t) cs.cpu_sysinfo.cpu[CPU_KERNEL];
- wait = (derive_t) cs.cpu_sysinfo.cpu[CPU_WAIT];
-
- submit (ksp[cpu]->ks_instance, "user", user);
- submit (ksp[cpu]->ks_instance, "system", syst);
- submit (ksp[cpu]->ks_instance, "idle", idle);
- submit (ksp[cpu]->ks_instance, "wait", wait);
+ memset(derives, -1, sizeof(derives));
+ derives[CPU_SUBMIT_IDLE] = cs.cpu_sysinfo.cpu[CPU_IDLE];
+ derives[CPU_SUBMIT_USER] = cs.cpu_sysinfo.cpu[CPU_USER];
+ derives[CPU_SUBMIT_SYSTEM] = cs.cpu_sysinfo.cpu[CPU_KERNEL];
+ derives[CPU_SUBMIT_WAIT] = cs.cpu_sysinfo.cpu[CPU_WAIT];
+ submit (ksp[cpu]->ks_instance, derives);
}
+ submit_flush ();
/* #endif defined(HAVE_LIBKSTAT) */
#elif CAN_USE_SYSCTL
}
for (i = 0; i < numcpu; i++) {
- submit (i, "user", cpuinfo[i][CP_USER]);
- submit (i, "nice", cpuinfo[i][CP_NICE]);
- submit (i, "system", cpuinfo[i][CP_SYS]);
- submit (i, "idle", cpuinfo[i][CP_IDLE]);
- submit (i, "interrupt", cpuinfo[i][CP_INTR]);
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
+ derives[CPU_SUBMIT_USER] = cpuinfo[i][CP_USER];
+ derives[CPU_SUBMIT_NICE] = cpuinfo[i][CP_NICE];
+ derives[CPU_SUBMIT_SYSTEM] = cpuinfo[i][CP_SYS];
+ derives[CPU_SUBMIT_IDLE] = cpuinfo[i][CP_IDLE];
+ derives[CPU_SUBMIT_INTERRUPT] = cpuinfo[i][CP_INTR];
+ submit(i, derives);
}
+ submit_flush();
/* #endif CAN_USE_SYSCTL */
#elif defined(HAVE_SYSCTLBYNAME) && defined(HAVE_SYSCTL_KERN_CP_TIMES)
long cpuinfo[maxcpu][CPUSTATES];
}
for (i = 0; i < numcpu; i++) {
- submit (i, "user", cpuinfo[i][CP_USER]);
- submit (i, "nice", cpuinfo[i][CP_NICE]);
- submit (i, "system", cpuinfo[i][CP_SYS]);
- submit (i, "idle", cpuinfo[i][CP_IDLE]);
- submit (i, "interrupt", cpuinfo[i][CP_INTR]);
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+
+ derives[CPU_SUBMIT_USER] = cpuinfo[i][CP_USER];
+ derives[CPU_SUBMIT_NICE] = cpuinfo[i][CP_NICE];
+ derives[CPU_SUBMIT_SYSTEM] = cpuinfo[i][CP_SYS];
+ derives[CPU_SUBMIT_IDLE] = cpuinfo[i][CP_IDLE];
+ derives[CPU_SUBMIT_INTERRUPT] = cpuinfo[i][CP_INTR];
+ submit(i, derives);
}
+ submit_flush();
+
/* #endif HAVE_SYSCTL_KERN_CP_TIMES */
#elif defined(HAVE_SYSCTLBYNAME)
long cpuinfo[CPUSTATES];
size_t cpuinfo_size;
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
cpuinfo_size = sizeof (cpuinfo);
return (-1);
}
- submit (0, "user", cpuinfo[CP_USER]);
- submit (0, "nice", cpuinfo[CP_NICE]);
- submit (0, "system", cpuinfo[CP_SYS]);
- submit (0, "idle", cpuinfo[CP_IDLE]);
- submit (0, "interrupt", cpuinfo[CP_INTR]);
+ derives[CPU_SUBMIT_USER] = cpuinfo[CP_USER];
+ derives[CPU_SUBMIT_SYSTEM] = cpuinfo[CP_SYS];
+ derives[CPU_SUBMIT_NICE] = cpuinfo[CP_NICE];
+ derives[CPU_SUBMIT_IDLE] = cpuinfo[CP_IDLE];
+ derives[CPU_SUBMIT_INTERRUPT] = cpuinfo[CP_INTR];
+ submit(0, derives);
+ submit_flush();
+
/* #endif HAVE_SYSCTLBYNAME */
#elif defined(HAVE_LIBSTATGRAB)
sg_cpu_stats *cs;
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
cs = sg_get_cpu_stats ();
if (cs == NULL)
return (-1);
}
- submit (0, "idle", (derive_t) cs->idle);
- submit (0, "nice", (derive_t) cs->nice);
- submit (0, "swap", (derive_t) cs->swap);
- submit (0, "system", (derive_t) cs->kernel);
- submit (0, "user", (derive_t) cs->user);
- submit (0, "wait", (derive_t) cs->iowait);
+ derives[CPU_SUBMIT_IDLE] = (derive_t) cs->idle;
+ derives[CPU_SUBMIT_NICE] = (derive_t) cs->nice;
+ derives[CPU_SUBMIT_SWAP] = (derive_t) cs->swap;
+ derives[CPU_SUBMIT_SYSTEM] = (derive_t) cs->kernel;
+ derives[CPU_SUBMIT_USER] = (derive_t) cs->user;
+ derives[CPU_SUBMIT_WAIT] = (derive_t) cs->iowait;
+ submit(0, derives);
+ submit_flush();
/* #endif HAVE_LIBSTATGRAB */
#elif defined(HAVE_PERFSTAT)
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
-
- if (pnumcpu != numcpu || perfcpu == NULL)
+
+ if (pnumcpu != numcpu || perfcpu == NULL)
{
- if (perfcpu != NULL)
+ if (perfcpu != NULL)
free(perfcpu);
perfcpu = malloc(numcpu * sizeof(perfstat_cpu_t));
}
return (-1);
}
- for (i = 0; i < cpus; i++)
+ for (i = 0; i < cpus; i++)
{
- submit (i, "idle", (derive_t) perfcpu[i].idle);
- submit (i, "system", (derive_t) perfcpu[i].sys);
- submit (i, "user", (derive_t) perfcpu[i].user);
- submit (i, "wait", (derive_t) perfcpu[i].wait);
+ derive_t derives[CPU_SUBMIT_MAX] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
+ };
+ derives[CPU_SUBMIT_IDLE] = perfcpu[i].idle;
+ derives[CPU_SUBMIT_SYSTEM] = perfcpu[i].sys;
+ derives[CPU_SUBMIT_USER] = perfcpu[i].user;
+ derives[CPU_SUBMIT_WAIT] = perfcpu[i].wait;
+ submit(i, derives);
}
+ submit_flush();
#endif /* HAVE_PERFSTAT */
return (0);
void module_register (void)
{
plugin_register_init ("cpu", init);
+ plugin_register_config ("cpu", cpu_config, config_keys, config_keys_num);
plugin_register_read ("cpu", cpu_read);
} /* void module_register */
char *user;
char *pass;
char *credentials;
+ _Bool digest;
_Bool verify_peer;
_Bool verify_host;
char *cacert;
curl_easy_setopt (wp->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (wp->curl, CURLOPT_WRITEFUNCTION, cc_curl_callback);
curl_easy_setopt (wp->curl, CURLOPT_WRITEDATA, wp);
- curl_easy_setopt (wp->curl, CURLOPT_USERAGENT,
- PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (wp->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (wp->curl, CURLOPT_ERRORBUFFER, wp->curl_errbuf);
curl_easy_setopt (wp->curl, CURLOPT_URL, wp->url);
curl_easy_setopt (wp->curl, CURLOPT_FOLLOWLOCATION, 1L);
ssnprintf (wp->credentials, credentials_size, "%s:%s",
wp->user, (wp->pass == NULL) ? "" : wp->pass);
curl_easy_setopt (wp->curl, CURLOPT_USERPWD, wp->credentials);
+
+ if (wp->digest)
+ {
+ curl_easy_setopt (wp->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ curl_easy_setopt (wp->curl, CURLOPT_USERNAME, wp->user);
+ curl_easy_setopt (wp->curl, CURLOPT_PASSWORD, wp->pass);
+ }
}
curl_easy_setopt (wp->curl, CURLOPT_SSL_VERIFYPEER, (long) wp->verify_peer);
page->url = NULL;
page->user = NULL;
page->pass = NULL;
+ page->digest = 0;
page->verify_peer = 1;
page->verify_host = 1;
page->response_time = 0;
status = cf_util_get_string (child, &page->user);
else if (strcasecmp ("Password", child->key) == 0)
status = cf_util_get_string (child, &page->pass);
+ else if (strcasecmp ("Digest", child->key) == 0)
+ status = cf_util_get_boolean (child, &page->digest);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
status = cf_util_get_boolean (child, &page->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
char *user;
char *pass;
char *credentials;
+ _Bool digest;
_Bool verify_peer;
_Bool verify_host;
char *cacert;
curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cj_curl_callback);
curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
- curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
- PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
curl_easy_setopt (db->curl, CURLOPT_URL, db->url);
ssnprintf (db->credentials, credentials_size, "%s:%s",
db->user, (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
+
+ if (db->digest)
+ {
+ curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+ curl_easy_setopt (db->curl, CURLOPT_PASSWORD, db->pass);
+ }
}
curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, (long) db->verify_peer);
status = cf_util_get_string (child, &db->user);
else if (db->url && strcasecmp ("Password", child->key) == 0)
status = cf_util_get_string (child, &db->pass);
+ else if (strcasecmp ("Digest", child->key) == 0)
+ status = cf_util_get_boolean (child, &db->digest);
else if (db->url && strcasecmp ("VerifyPeer", child->key) == 0)
status = cf_util_get_boolean (child, &db->verify_peer);
else if (db->url && strcasecmp ("VerifyHost", child->key) == 0)
char *user;
char *pass;
char *credentials;
+ _Bool digest;
_Bool verify_peer;
_Bool verify_host;
char *cacert;
curl_easy_setopt (db->curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (db->curl, CURLOPT_WRITEFUNCTION, cx_curl_callback);
curl_easy_setopt (db->curl, CURLOPT_WRITEDATA, db);
- curl_easy_setopt (db->curl, CURLOPT_USERAGENT,
- PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (db->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (db->curl, CURLOPT_ERRORBUFFER, db->curl_errbuf);
curl_easy_setopt (db->curl, CURLOPT_URL, db->url);
ssnprintf (db->credentials, credentials_size, "%s:%s",
db->user, (db->pass == NULL) ? "" : db->pass);
curl_easy_setopt (db->curl, CURLOPT_USERPWD, db->credentials);
+
+ if (db->digest)
+ {
+ curl_easy_setopt (db->curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
+ curl_easy_setopt (db->curl, CURLOPT_USERNAME, db->user);
+ curl_easy_setopt (db->curl, CURLOPT_PASSWORD, db->pass);
+ }
}
curl_easy_setopt (db->curl, CURLOPT_SSL_VERIFYPEER, db->verify_peer ? 1L : 0L);
status = cf_util_get_string (child, &db->user);
else if (strcasecmp ("Password", child->key) == 0)
status = cf_util_get_string (child, &db->pass);
+ else if (strcasecmp ("Digest", child->key) == 0)
+ status = cf_util_get_boolean (child, &db->digest);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
status = cf_util_get_boolean (child, &db->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
static cdbi_database_t **databases = NULL;
static size_t databases_num = 0;
+static int cdbi_read_database (user_data_t *ud);
+
/*
* Functions
*/
}
else
{
+ user_data_t ud;
+ char *name = NULL;
+
databases = temp;
databases[databases_num] = db;
databases_num++;
+
+ memset (&ud, 0, sizeof (ud));
+ ud.data = (void *) db;
+ ud.free_func = NULL;
+ name = ssnprintf_alloc("dbi:%s", db->name);
+
+ plugin_register_complex_read (/* group = */ NULL,
+ /* name = */ name ? name : db->name,
+ /* callback = */ cdbi_read_database,
+ /* interval = */ NULL,
+ /* user_data = */ &ud);
+ free (name);
}
}
cdbi_config_add_database (child);
else
{
- WARNING ("snmp plugin: Ignoring unknown config option `%s'.", child->key);
+ WARNING ("dbi plugin: Ignoring unknown config option `%s'.", child->key);
}
} /* for (ci->children) */
return (0);
} /* }}} int cdbi_connect_database */
-static int cdbi_read_database (cdbi_database_t *db) /* {{{ */
+static int cdbi_read_database (user_data_t *ud) /* {{{ */
{
+ cdbi_database_t *db = (cdbi_database_t *) ud->data;
size_t i;
int success;
int status;
return (0);
} /* }}} int cdbi_read_database */
-static int cdbi_read (void) /* {{{ */
-{
- size_t i;
- int success = 0;
- int status;
-
- for (i = 0; i < databases_num; i++)
- {
- status = cdbi_read_database (databases[i]);
- if (status == 0)
- success++;
- }
-
- if (success == 0)
- {
- ERROR ("dbi plugin: No database could be read. Will return an error so "
- "the plugin will be delayed.");
- return (-1);
- }
-
- return (0);
-} /* }}} int cdbi_read */
-
static int cdbi_shutdown (void) /* {{{ */
{
size_t i;
{
plugin_register_complex_config ("dbi", cdbi_config);
plugin_register_init ("dbi", cdbi_init);
- plugin_register_read ("dbi", cdbi_read);
plugin_register_shutdown ("dbi", cdbi_shutdown);
} /* }}} void module_register */
static int fc_config_add_chain (const oconfig_item_t *ci) /* {{{ */
{
- fc_chain_t *chain;
+ fc_chain_t *chain = NULL;
int status = 0;
int i;
+ int new_chain = 1;
if ((ci->values_num != 1)
|| (ci->values[0].type != OCONFIG_TYPE_STRING))
return (-1);
}
- chain = (fc_chain_t *) malloc (sizeof (*chain));
+ if (chain_list_head != NULL)
+ {
+ if ((chain = fc_chain_get_by_name (ci->values[0].value.string)) != NULL)
+ new_chain = 0;
+ }
+
if (chain == NULL)
{
- ERROR ("fc_config_add_chain: malloc failed.");
- return (-1);
+ chain = (fc_chain_t *) malloc (sizeof (*chain));
+ if (chain == NULL)
+ {
+ ERROR ("fc_config_add_chain: malloc failed.");
+ return (-1);
+ }
+ memset (chain, 0, sizeof (*chain));
+ sstrncpy (chain->name, ci->values[0].value.string, sizeof (chain->name));
+ chain->rules = NULL;
+ chain->targets = NULL;
+ chain->next = NULL;
}
- memset (chain, 0, sizeof (*chain));
- sstrncpy (chain->name, ci->values[0].value.string, sizeof (chain->name));
- chain->rules = NULL;
- chain->targets = NULL;
- chain->next = NULL;
for (i = 0; i < ci->children_num; i++)
{
if (chain_list_head != NULL)
{
+ if (!new_chain)
+ return (0);
+
fc_chain_t *ptr;
ptr = chain_list_head;
/* Configure servers */
int lcc_server_set_ttl (lcc_server_t *srv, uint8_t ttl);
+int lcc_server_set_interface (lcc_server_t *srv, char const *interface);
int lcc_server_set_security_level (lcc_server_t *srv,
lcc_security_level_t level,
const char *username, const char *password);
/**
* collectd - src/libcollectdclient/network.c
- * Copyright (C) 2005-2012 Florian octo Forster
+ * Copyright (C) 2005-2013 Florian Forster
+ * Copyright (C) 2010 Max Henkel
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* DEALINGS IN THE SOFTWARE.
*
* Authors:
- * Florian octo Forster <octo at collectd.org>
+ * Florian Forster <octo at collectd.org>
+ * Max Henkel <henkel at gmx.at>
**/
#include "collectd.h"
# include <netinet/in.h>
#endif
+#if HAVE_NET_IF_H
+# include <net/if.h>
+#endif
+
#include "collectd/network.h"
#include "collectd/network_buffer.h"
return (0);
} /* }}} int lcc_server_set_ttl */
+int lcc_server_set_interface (lcc_server_t *srv, char const *interface) /* {{{ */
+{
+ int if_index;
+ int status;
+
+ if ((srv == NULL) || (interface == NULL))
+ return (EINVAL);
+
+ if_index = if_nametoindex (interface);
+ if (if_index == 0)
+ return (ENOENT);
+
+ /* IPv4 multicast */
+ if (srv->sa->sa_family == AF_INET)
+ {
+ struct sockaddr_in *addr = (struct sockaddr_in *) srv->sa;
+
+ if (IN_MULTICAST (ntohl (addr->sin_addr.s_addr)))
+ {
+#if HAVE_STRUCT_IP_MREQN_IMR_IFINDEX
+ /* If possible, use the "ip_mreqn" structure which has
+ * an "interface index" member. Using the interface
+ * index is preferred here, because of its similarity
+ * to the way IPv6 handles this. Unfortunately, it
+ * appears not to be portable. */
+ struct ip_mreqn mreq;
+
+ memset (&mreq, 0, sizeof (mreq));
+ mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+ mreq.imr_address.s_addr = ntohl (INADDR_ANY);
+ mreq.imr_ifindex = if_index;
+#else
+ struct ip_mreq mreq;
+
+ memset (&mreq, 0, sizeof (mreq));
+ mreq.imr_multiaddr.s_addr = addr->sin_addr.s_addr;
+ mreq.imr_interface.s_addr = ntohl (INADDR_ANY);
+#endif
+
+ status = setsockopt (srv->fd, IPPROTO_IP, IP_MULTICAST_IF,
+ &mreq, sizeof (mreq));
+ if (status != 0)
+ return (status);
+
+ return (0);
+ }
+ }
+
+ /* IPv6 multicast */
+ if (srv->sa->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *addr = (struct sockaddr_in6 *) srv->sa;
+
+ if (IN6_IS_ADDR_MULTICAST (&addr->sin6_addr))
+ {
+ status = setsockopt (srv->fd, IPPROTO_IPV6, IPV6_MULTICAST_IF,
+ &if_index, sizeof (if_index));
+ if (status != 0)
+ return (status);
+
+ return (0);
+ }
+ }
+
+ /* else: Not a multicast interface. */
+#if defined(SO_BINDTODEVICE)
+ status = setsockopt (srv->fd, SOL_SOCKET, SO_BINDTODEVICE,
+ interface, strlen (interface) + 1);
+ if (status != 0)
+ return (-1);
+#endif
+
+ return (0);
+} /* }}} int lcc_server_set_interface */
+
int lcc_server_set_security_level (lcc_server_t *srv, /* {{{ */
lcc_security_level_t level,
const char *username, const char *password)
* collectd - src/load.c
* Copyright (C) 2005-2008 Florian octo Forster
* Copyright (C) 2009 Manuel Sanmartin
+ * Copyright (C) 2013 Vedran Bartonicek
*
* 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
* Authors:
* Florian octo Forster <octo at verplant.org>
* Manuel Sanmartin
+ * Vedran Bartonicek <vbartoni at gmail.com>
**/
#define _BSD_SOURCE
#include "common.h"
#include "plugin.h"
+#include <unistd.h>
+
#ifdef HAVE_SYS_LOADAVG_H
#include <sys/loadavg.h>
#endif
# include <libperfstat.h>
#endif /* HAVE_PERFSTAT */
+static _Bool report_relative_load = 0;
+
+static const char *config_keys[] =
+{
+ "ReportRelative"
+};
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+
+static int load_config (const char *key, const char *value)
+{
+ if (strcasecmp (key, "ReportRelative") == 0)
+#ifdef _SC_NPROCESSORS_ONLN
+ report_relative_load = IS_TRUE (value) ? 1 : 0;
+#else
+ WARNING ("load plugin: The \"ReportRelative\" configuration "
+ "is not available, because I can't determine the "
+ "number of CPUS on this system. Sorry.");
+#endif
+ return (-1);
+
+}
static void load_submit (gauge_t snum, gauge_t mnum, gauge_t lnum)
{
value_t values[3];
value_list_t vl = VALUE_LIST_INIT;
+ int cores = 0;
+ char errbuf[1024];
+
+#ifdef _SC_NPROCESSORS_ONLN
+ if (report_relative_load) {
+ if ((cores = sysconf(_SC_NPROCESSORS_ONLN)) < 1) {
+ WARNING ("load: sysconf failed : %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
+ }
+ }
+#endif
+ if (cores > 0) {
+ snum /= cores;
+ mnum /= cores;
+ lnum /= cores;
+ }
values[0].gauge = snum;
values[1].gauge = mnum;
vl.values = values;
vl.values_len = STATIC_ARRAY_SIZE (values);
+
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "load", sizeof (vl.plugin));
sstrncpy (vl.type, "load", sizeof (vl.type));
+ if (cores > 0) {
+ sstrncpy(vl.type_instance, "relative",
+ sizeof (vl.type_instance));
+ }
+
plugin_dispatch_values (&vl);
}
double load[3];
if (getloadavg (load, 3) == 3)
- load_submit (load[LOADAVG_1MIN], load[LOADAVG_5MIN], load[LOADAVG_15MIN]);
- else
- {
- char errbuf[1024];
- WARNING ("load: getloadavg failed: %s",
- sstrerror (errno, errbuf, sizeof (errbuf)));
+ load_submit (load[LOADAVG_1MIN], load[LOADAVG_5MIN], load[LOADAVG_15MIN]);
+ else
+ {
+ char errbuf[1024];
+ WARNING ("load: getloadavg failed: %s",
+ sstrerror (errno, errbuf, sizeof (errbuf)));
}
/* #endif HAVE_GETLOADAVG */
#elif defined(KERNEL_LINUX)
- gauge_t snum, mnum, lnum;
+ gauge_t snum, mnum, lnum;
FILE *loadavg;
char buffer[16];
mnum = atof (fields[1]);
lnum = atof (fields[2]);
- load_submit (snum, mnum, lnum);
+ load_submit(snum, mnum, lnum);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBSTATGRAB
- gauge_t snum, mnum, lnum;
+ gauge_t snum, mnum, lnum;
sg_load_stats *ls;
if ((ls = sg_get_load_stats ()) == NULL)
snum = ls->min1;
mnum = ls->min5;
lnum = ls->min15;
-
- load_submit (snum, mnum, lnum);
+ load_submit(snum, mnum, lnum);
/* #endif HAVE_LIBSTATGRAB */
#elif HAVE_PERFSTAT
- gauge_t snum, mnum, lnum;
+ gauge_t snum, mnum, lnum;
perfstat_cpu_total_t cputotal;
if (perfstat_cpu_total(NULL, &cputotal, sizeof(perfstat_cpu_total_t), 1) < 0)
snum = (float)cputotal.loadavg[0]/(float)(1<<SBITS);
mnum = (float)cputotal.loadavg[1]/(float)(1<<SBITS);
lnum = (float)cputotal.loadavg[2]/(float)(1<<SBITS);
-
- load_submit (snum, mnum, lnum);
+ load_submit(snum, mnum, lnum);
/* #endif HAVE_PERFSTAT */
#else
void module_register (void)
{
+ plugin_register_config ("load", load_config, config_keys, config_keys_num);
plugin_register_read ("load", load_read);
} /* void module_register */
/*
* For an explanation on these fields please refer to
- * <http://code.sixapart.com/svn/memcached/trunk/server/doc/protocol.txt>
+ * <https://github.com/memcached/memcached/blob/master/doc/protocol.txt>
*/
/*
{
submit_gauge ("memcached_connections", "current", atof (fields[2]), st);
}
+ else if (FIELD_IS ("listen_disabled_num"))
+ {
+ submit_derive ("memcached_connections", "listen_disabled", atof (fields[2]), st);
+ }
/*
* Commands
/**
* collectd - src/memory.c
- * Copyright (C) 2005-2008 Florian octo Forster
+ * Copyright (C) 2005-2014 Florian octo Forster
* Copyright (C) 2009 Simon Kuhnle
* Copyright (C) 2009 Manuel Sanmartin
*
/* endif HAVE_LIBSTATGRAB */
#elif HAVE_PERFSTAT
static int pagesize;
-static perfstat_memory_total_t pmemory;
/* endif HAVE_PERFSTAT */
#else
# error "No applicable input method."
#endif
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
+
+static int memory_config (oconfig_item_t *ci) /* {{{ */
+{
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
+ {
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("ValuesAbsolute", child->key) == 0)
+ cf_util_get_boolean (child, &values_absolute);
+ else if (strcasecmp ("ValuesPercentage", child->key) == 0)
+ cf_util_get_boolean (child, &values_percentage);
+ else
+ ERROR ("memory plugin: Invalid configuration option: "
+ "\"%s\".", child->key);
+ }
+
+ return (0);
+} /* }}} int memory_config */
+
static int memory_init (void)
{
#if HAVE_HOST_STATISTICS
return (0);
} /* int memory_init */
-static void memory_submit (const char *type_instance, gauge_t value)
-{
- value_t values[1];
- value_list_t vl = VALUE_LIST_INIT;
-
- values[0].gauge = value;
-
- vl.values = values;
- vl.values_len = 1;
- sstrncpy (vl.host, hostname_g, sizeof (vl.host));
- sstrncpy (vl.plugin, "memory", sizeof (vl.plugin));
- sstrncpy (vl.type, "memory", sizeof (vl.type));
- sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-
- plugin_dispatch_values (&vl);
-}
+#define MEMORY_SUBMIT(...) do { \
+ if (values_absolute) \
+ plugin_dispatch_multivalue (vl, 0, __VA_ARGS__, NULL); \
+ if (values_percentage) \
+ plugin_dispatch_multivalue (vl, 1, __VA_ARGS__, NULL); \
+} while (0)
-static int memory_read (void)
+static int memory_read_internal (value_list_t *vl)
{
#if HAVE_HOST_STATISTICS
kern_return_t status;
inactive = (gauge_t) (((uint64_t) vm_data.inactive_count) * ((uint64_t) pagesize));
free = (gauge_t) (((uint64_t) vm_data.free_count) * ((uint64_t) pagesize));
- memory_submit ("wired", wired);
- memory_submit ("active", active);
- memory_submit ("inactive", inactive);
- memory_submit ("free", free);
+ MEMORY_SUBMIT ("wired", wired,
+ "active", active,
+ "inactive", inactive,
+ "free", free);
/* #endif HAVE_HOST_STATISTICS */
#elif HAVE_SYSCTLBYNAME
if (!isnan (sysctl_vals[i]))
sysctl_vals[i] *= sysctl_vals[0];
- memory_submit ("free", sysctl_vals[2]);
- memory_submit ("wired", sysctl_vals[3]);
- memory_submit ("active", sysctl_vals[4]);
- memory_submit ("inactive", sysctl_vals[5]);
- memory_submit ("cache", sysctl_vals[6]);
+ MEMORY_SUBMIT ("free", (gauge_t) sysctl_vals[2],
+ "wired", (gauge_t) sysctl_vals[3],
+ "active", (gauge_t) sysctl_vals[4],
+ "inactive", (gauge_t) sysctl_vals[5],
+ "cache", (gauge_t) sysctl_vals[6]);
/* #endif HAVE_SYSCTLBYNAME */
#elif KERNEL_LINUX
char *fields[8];
int numfields;
- long long mem_used = 0;
- long long mem_buffered = 0;
- long long mem_cached = 0;
- long long mem_free = 0;
+ gauge_t mem_total = 0;
+ gauge_t mem_used = 0;
+ gauge_t mem_buffered = 0;
+ gauge_t mem_cached = 0;
+ gauge_t mem_free = 0;
if ((fh = fopen ("/proc/meminfo", "r")) == NULL)
{
return (-1);
}
- while (fgets (buffer, 1024, fh) != NULL)
+ while (fgets (buffer, sizeof (buffer), fh) != NULL)
{
- long long *val = NULL;
+ gauge_t *val = NULL;
if (strncasecmp (buffer, "MemTotal:", 9) == 0)
- val = &mem_used;
+ val = &mem_total;
else if (strncasecmp (buffer, "MemFree:", 8) == 0)
val = &mem_free;
else if (strncasecmp (buffer, "Buffers:", 8) == 0)
else
continue;
- numfields = strsplit (buffer, fields, 8);
-
+ numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
if (numfields < 2)
continue;
- *val = atoll (fields[1]) * 1024LL;
+ *val = 1024.0 * atof (fields[1]);
}
if (fclose (fh))
sstrerror (errno, errbuf, sizeof (errbuf)));
}
- if (mem_used >= (mem_free + mem_buffered + mem_cached))
- {
- mem_used -= mem_free + mem_buffered + mem_cached;
- memory_submit ("used", mem_used);
- memory_submit ("buffered", mem_buffered);
- memory_submit ("cached", mem_cached);
- memory_submit ("free", mem_free);
- }
+ if (mem_total < (mem_free + mem_buffered + mem_cached))
+ return (-1);
+
+ mem_used = mem_total - (mem_free + mem_buffered + mem_cached);
+ MEMORY_SUBMIT ("used", mem_used,
+ "buffered", mem_buffered,
+ "cached", mem_cached,
+ "free", mem_free);
/* #endif KERNEL_LINUX */
#elif HAVE_LIBKSTAT
- /* Most of the additions here were taken as-is from the k9toolkit from
- * Brendan Gregg and are subject to change I guess */
+ /* Most of the additions here were taken as-is from the k9toolkit from
+ * Brendan Gregg and are subject to change I guess */
long long mem_used;
long long mem_free;
long long mem_lock;
}
/* mem_kern is accounted for in mem_lock */
- if ( pp_kernel < mem_lock )
+ if (pp_kernel < mem_lock)
{
mem_kern = pp_kernel;
mem_lock -= pp_kernel;
mem_kern *= pagesize; /* it's 2011 RAM is cheap */
mem_unus *= pagesize;
- memory_submit ("used", mem_used);
- memory_submit ("free", mem_free);
- memory_submit ("locked", mem_lock);
- memory_submit ("kernel", mem_kern);
- memory_submit ("unusable", mem_unus);
+ MEMORY_SUBMIT ("used", (gauge_t) mem_used,
+ "free", (gauge_t) mem_free,
+ "locked", (gauge_t) mem_lock,
+ "kernel", (gauge_t) mem_kern,
+ "unusable", (gauge_t) mem_unus);
/* #endif HAVE_LIBKSTAT */
#elif HAVE_SYSCTL
int mib[] = {CTL_VM, VM_METER};
struct vmtotal vmtotal;
+ gauge_t mem_active;
+ gauge_t mem_inactive;
+ gauge_t mem_free;
size_t size;
memset (&vmtotal, 0, sizeof (vmtotal));
}
assert (pagesize > 0);
- memory_submit ("active", vmtotal.t_arm * pagesize);
- memory_submit ("inactive", (vmtotal.t_rm - vmtotal.t_arm) * pagesize);
- memory_submit ("free", vmtotal.t_free * pagesize);
+ mem_active = (gauge_t) (vmtotal.t_arm * pagesize);
+ mem_inactive = (gauge_t) ((vmtotal.t_rm - vmtotal.t_arm) * pagesize);
+ mem_free = (gauge_t) (vmtotal.t_free * pagesize);
+
+ MEMORY_SUBMIT ("active", mem_active,
+ "inactive", mem_inactive,
+ "free", mem_free);
/* #endif HAVE_SYSCTL */
#elif HAVE_LIBSTATGRAB
sg_mem_stats *ios;
- if ((ios = sg_get_mem_stats ()) != NULL)
- {
- memory_submit ("used", ios->used);
- memory_submit ("cached", ios->cache);
- memory_submit ("free", ios->free);
- }
+ ios = sg_get_mem_stats ();
+ if (ios == NULL)
+ return (-1);
+
+ MEMORY_SUBMIT ("used", (gauge_t) ios->used,
+ "cached", (gauge_t) ios->cache,
+ "free", (gauge_t) ios->free);
/* #endif HAVE_LIBSTATGRAB */
#elif HAVE_PERFSTAT
- if (perfstat_memory_total(NULL, &pmemory, sizeof(perfstat_memory_total_t), 1) < 0)
+ perfstat_memory_total_t pmemory;
+
+ memset (&pmemory, 0, sizeof (pmemory));
+ if (perfstat_memory_total(NULL, &pmemory, sizeof(pmemory), 1) < 0)
{
char errbuf[1024];
WARNING ("memory plugin: perfstat_memory_total failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
- memory_submit ("used", pmemory.real_inuse * pagesize);
- memory_submit ("free", pmemory.real_free * pagesize);
- memory_submit ("cached", pmemory.numperm * pagesize);
- memory_submit ("system", pmemory.real_system * pagesize);
- memory_submit ("user", pmemory.real_process * pagesize);
+
+ /* Unfortunately, the AIX documentation is not very clear on how these
+ * numbers relate to one another. The only thing is states explcitly
+ * is:
+ * real_total = real_process + real_free + numperm + real_system
+ *
+ * Another segmentation, which would be closer to the numbers reported
+ * by the "svmon" utility, would be:
+ * real_total = real_free + real_inuse
+ * real_inuse = "active" + real_pinned + numperm
+ */
+ MEMORY_SUBMIT ("free", (gauge_t) (pmemory.real_free * pagesize),
+ "cached", (gauge_t) (pmemory.numperm * pagesize),
+ "system", (gauge_t) (pmemory.real_system * pagesize),
+ "user", (gauge_t) (pmemory.real_process * pagesize));
#endif /* HAVE_PERFSTAT */
return (0);
-}
+} /* }}} int memory_read_internal */
+
+static int memory_read (void) /* {{{ */
+{
+ value_t v[1];
+ value_list_t vl = VALUE_LIST_INIT;
+
+ vl.values = v;
+ vl.values_len = STATIC_ARRAY_SIZE (v);
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "memory", sizeof (vl.plugin));
+ sstrncpy (vl.type, "memory", sizeof (vl.type));
+ vl.time = cdtime ();
+
+ return (memory_read_internal (&vl));
+} /* }}} int memory_read */
void module_register (void)
{
+ plugin_register_complex_config ("memory", memory_config);
plugin_register_init ("memory", memory_init);
plugin_register_read ("memory", memory_read);
} /* void module_register */
{
if ((db->host == NULL)
|| (strcmp ("", db->host) == 0)
+ || (strcmp ("127.0.0.1", db->host) == 0)
|| (strcmp ("localhost", db->host) == 0))
sstrncpy (buf, hostname_g, buflen);
else
#include <libmnl/libmnl.h>
+struct ir_link_stats_storage_s {
+
+ uint64_t rx_packets;
+ uint64_t tx_packets;
+ uint64_t rx_bytes;
+ uint64_t tx_bytes;
+ uint64_t rx_errors;
+ uint64_t tx_errors;
+
+ uint64_t rx_dropped;
+ uint64_t tx_dropped;
+ uint64_t multicast;
+ uint64_t collisions;
+
+ uint64_t rx_length_errors;
+ uint64_t rx_over_errors;
+ uint64_t rx_crc_errors;
+ uint64_t rx_frame_errors;
+ uint64_t rx_fifo_errors;
+ uint64_t rx_missed_errors;
+
+ uint64_t tx_aborted_errors;
+ uint64_t tx_carrier_errors;
+ uint64_t tx_fifo_errors;
+ uint64_t tx_heartbeat_errors;
+ uint64_t tx_window_errors;
+};
+
+union ir_link_stats_u {
+ struct rtnl_link_stats *stats32;
+#ifdef HAVE_RTNL_LINK_STATS64
+ struct rtnl_link_stats64 *stats64;
+#endif
+};
+
typedef struct ir_ignorelist_s
{
char *device;
} /* int update_iflist */
static void check_ignorelist_and_submit (const char *dev,
- struct rtnl_link_stats *stats)
+ struct ir_link_stats_storage_s *stats)
{
if (check_ignorelist (dev, "interface", NULL) == 0)
} /* void check_ignorelist_and_submit */
+#define COPY_RTNL_LINK_VALUE(dst_stats, src_stats, value_name) \
+ (dst_stats)->value_name = (src_stats)->value_name
+
+#define COPY_RTNL_LINK_STATS(dst_stats, src_stats) \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_packets); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_packets); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_bytes); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_bytes); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_dropped); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_dropped); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, multicast); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, collisions); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_length_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_over_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_crc_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_frame_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_fifo_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, rx_missed_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_aborted_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_carrier_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_fifo_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_heartbeat_errors); \
+ COPY_RTNL_LINK_VALUE (dst_stats, src_stats, tx_window_errors)
+
+#ifdef HAVE_RTNL_LINK_STATS64
+static void check_ignorelist_and_submit64 (const char *dev,
+ struct rtnl_link_stats64 *stats)
+{
+ struct ir_link_stats_storage_s s;
+
+ COPY_RTNL_LINK_STATS (&s, stats);
+
+ check_ignorelist_and_submit (dev, &s);
+}
+#endif
+
+static void check_ignorelist_and_submit32 (const char *dev,
+ struct rtnl_link_stats *stats)
+{
+ struct ir_link_stats_storage_s s;
+
+ COPY_RTNL_LINK_STATS(&s, stats);
+
+ check_ignorelist_and_submit (dev, &s);
+}
+
static int link_filter_cb (const struct nlmsghdr *nlh,
void *args __attribute__((unused)))
{
struct ifinfomsg *ifm = mnl_nlmsg_get_payload (nlh);
struct nlattr *attr;
- struct rtnl_link_stats *stats = NULL;
const char *dev = NULL;
+ union ir_link_stats_u stats;
if (nlh->nlmsg_type != RTM_NEWLINK)
{
ERROR ("netlink plugin: link_filter_cb: dev == NULL");
return MNL_CB_ERROR;
}
+#ifdef HAVE_RTNL_LINK_STATS64
+ mnl_attr_for_each (attr, nlh, sizeof (*ifm))
+ {
+ if (mnl_attr_get_type (attr) != IFLA_STATS64)
+ continue;
+
+ if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats.stats64)) < 0)
+ {
+ ERROR ("netlink plugin: link_filter_cb: IFLA_STATS64 mnl_attr_validate2 failed.");
+ return MNL_CB_ERROR;
+ }
+ stats.stats64 = mnl_attr_get_payload (attr);
+
+ check_ignorelist_and_submit64 (dev, stats.stats64);
+ return MNL_CB_OK;
+ }
+#endif
mnl_attr_for_each (attr, nlh, sizeof (*ifm))
{
if (mnl_attr_get_type (attr) != IFLA_STATS)
continue;
- if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats)) < 0)
+ if (mnl_attr_validate2 (attr, MNL_TYPE_UNSPEC, sizeof (*stats.stats32)) < 0)
{
ERROR ("netlink plugin: link_filter_cb: IFLA_STATS mnl_attr_validate2 failed.");
return MNL_CB_ERROR;
}
- stats = mnl_attr_get_payload (attr);
+ stats.stats32 = mnl_attr_get_payload (attr);
- check_ignorelist_and_submit (dev, stats);
- break;
- }
+ check_ignorelist_and_submit32 (dev, stats.stats32);
- if (stats == NULL)
- {
- DEBUG ("netlink plugin: link_filter: No statistics for interface %s.", dev);
return MNL_CB_OK;
}
+ DEBUG ("netlink plugin: link_filter: No statistics for interface %s.", dev);
return MNL_CB_OK;
+
} /* int link_filter_cb */
#if HAVE_TCA_STATS2
curl_easy_setopt (curl, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, nginx_curl_callback);
- curl_easy_setopt (curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, nginx_curl_error);
if (user != NULL)
#include "pinba.pb-c.h"
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+# define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
/*
* Defines
*/
/**
* collectd - src/plugin.c
- * Copyright (C) 2005-2013 Florian octo Forster
+ * Copyright (C) 2005-2014 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
return (0);
}
+__attribute__((sentinel))
+int plugin_dispatch_multivalue (value_list_t const *template, /* {{{ */
+ _Bool store_percentage, ...)
+{
+ value_list_t *vl;
+ int failed = 0;
+ gauge_t sum = 0.0;
+ va_list ap;
+
+ assert (template->values_len == 1);
+
+ va_start (ap, store_percentage);
+ while (42)
+ {
+ char const *name;
+ gauge_t value;
+
+ name = va_arg (ap, char const *);
+ if (name == NULL)
+ break;
+
+ value = va_arg (ap, gauge_t);
+ if (!isnan (value))
+ sum += value;
+ }
+ va_end (ap);
+
+ vl = plugin_value_list_clone (template);
+ /* plugin_value_list_clone makes sure vl->time is set to non-zero. */
+ if (store_percentage)
+ sstrncpy (vl->type, "percent", sizeof (vl->type));
+
+ va_start (ap, store_percentage);
+ while (42)
+ {
+ char const *name;
+ int status;
+
+ /* Set the type instance. */
+ name = va_arg (ap, char const *);
+ if (name == NULL)
+ break;
+ sstrncpy (vl->type_instance, name, sizeof (vl->type_instance));
+
+ /* Set the value. */
+ vl->values[0].gauge = va_arg (ap, gauge_t);
+ if (store_percentage)
+ vl->values[0].gauge *= 100.0 / sum;
+
+ status = plugin_write_enqueue (vl);
+ if (status != 0)
+ failed++;
+ }
+ va_end (ap);
+
+ plugin_value_list_free (vl);
+ return (failed);
+} /* }}} int plugin_dispatch_multivalue */
+
int plugin_dispatch_notification (const notification_t *notif)
{
llentry_t *le;
#define PLUGIN_H
/**
* collectd - src/plugin.h
- * Copyright (C) 2005-2011 Florian octo Forster
+ * Copyright (C) 2005-2014 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
* function.
*/
int plugin_dispatch_values (value_list_t const *vl);
+
+/*
+ * NAME
+ * plugin_dispatch_multivalue
+ *
+ * SYNOPSIS
+ * plugin_dispatch_multivalue (vl, 1,
+ * "free", 42.0,
+ * "used", 58.0,
+ * NULL);
+ *
+ * DESCRIPTION
+ * Takes a list of type instances and values and dispatches that in a batch,
+ * making sure that all values have the same time stamp. If "store_percentage"
+ * is set to true, the "type" is set to "percent" and a percentage is
+ * calculated and dispatched, rather than the absolute values. Values that are
+ * NaN are dispatched as NaN and will not influence the total.
+ *
+ * The variadic arguments is a list of type_instance / gauge pairs, that are
+ * interpreted as type "char const *" and "gauge_t". The last argument must be
+ * a NULL pointer to signal end-of-list.
+ *
+ * RETURNS
+ * The number of values it failed to dispatch (zero on success).
+ */
+__attribute__((sentinel))
+int plugin_dispatch_multivalue (value_list_t const *vl,
+ _Bool store_percentage, ...);
+
int plugin_dispatch_missing (const value_list_t *vl);
int plugin_dispatch_notification (const notification_t *notif);
}
if (C_PSQL_IS_UNIX_DOMAIN_SOCKET (db->host)
+ || (0 == strcmp (db->host, "127.0.0.1"))
|| (0 == strcmp (db->host, "localhost")))
host = hostname_g;
else
#define REDIS_DEF_PORT 6379
#define REDIS_DEF_TIMEOUT 2000
#define MAX_REDIS_NODE_NAME 64
+#define MAX_REDIS_PASSWD_LENGTH 512
/* Redis plugin configuration example:
*
{
char name[MAX_REDIS_NODE_NAME];
char host[HOST_NAME_MAX];
- char passwd[HOST_NAME_MAX];
+ char passwd[MAX_REDIS_PASSWD_LENGTH];
int port;
int timeout;
#include <net-snmp/net-snmp-config.h>
#include <net-snmp/net-snmp-includes.h>
+#include <fnmatch.h>
+
/*
* Private data structes
*/
{
char *name; /* used to reference this from the `Collect' option */
char *type; /* used to find the data_set */
- int is_table;
+ _Bool is_table;
instance_t instance;
char *instance_prefix;
oid_t *values;
double scale;
double shift;
struct data_definition_s *next;
+ char **ignores;
+ size_t ignores_len;
+ int invert_match;
};
typedef struct data_definition_s data_definition_t;
{
char *name;
char *address;
- char *community;
int version;
+
+ /* snmpv1/2 options */
+ char *community;
+
+ /* snmpv3 security options */
+ char *username;
+ oid *auth_protocol;
+ size_t auth_protocol_len;
+ char *auth_passphrase;
+ oid *priv_protocol;
+ size_t priv_protocol_len;
+ char *priv_passphrase;
+ int security_level;
+ char *context;
+
void *sess_handle;
c_complain_t complaint;
cdtime_t interval;
sfree (hd->name);
sfree (hd->address);
sfree (hd->community);
+ sfree (hd->username);
+ sfree (hd->auth_passphrase);
+ sfree (hd->priv_passphrase);
+ sfree (hd->context);
sfree (hd->data_list);
sfree (hd);
* csnmp_config
* +-> call_snmp_init_once
* +-> csnmp_config_add_data
- * ! +-> csnmp_config_add_data_type
- * ! +-> csnmp_config_add_data_table
* ! +-> csnmp_config_add_data_instance
* ! +-> csnmp_config_add_data_instance_prefix
* ! +-> csnmp_config_add_data_values
* +-> csnmp_config_add_host
- * +-> csnmp_config_add_host_address
- * +-> csnmp_config_add_host_community
* +-> csnmp_config_add_host_version
* +-> csnmp_config_add_host_collect
+ * +-> csnmp_config_add_host_auth_protocol
+ * +-> csnmp_config_add_host_priv_protocol
+ * +-> csnmp_config_add_host_security_level
*/
static void call_snmp_init_once (void)
{
have_init = 1;
} /* void call_snmp_init_once */
-static int csnmp_config_add_data_type (data_definition_t *dd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `Type' needs exactly one string argument.");
- return (-1);
- }
-
- sfree (dd->type);
- dd->type = strdup (ci->values[0].value.string);
- if (dd->type == NULL)
- return (-1);
-
- return (0);
-} /* int csnmp_config_add_data_type */
-
-static int csnmp_config_add_data_table (data_definition_t *dd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("snmp plugin: `Table' needs exactly one boolean argument.");
- return (-1);
- }
-
- dd->is_table = ci->values[0].value.boolean ? 1 : 0;
-
- return (0);
-} /* int csnmp_config_add_data_table */
-
static int csnmp_config_add_data_instance (data_definition_t *dd, oconfig_item_t *ci)
{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `Instance' needs exactly one string argument.");
- return (-1);
- }
+ char buffer[DATA_MAX_NAME_LEN];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
if (dd->is_table)
{
/* Instance is an OID */
dd->instance.oid.oid_len = MAX_OID_LEN;
- if (!read_objid (ci->values[0].value.string,
+ if (!read_objid (buffer,
dd->instance.oid.oid, &dd->instance.oid.oid_len))
{
- ERROR ("snmp plugin: read_objid (%s) failed.",
- ci->values[0].value.string);
+ ERROR ("snmp plugin: read_objid (%s) failed.", buffer);
return (-1);
}
}
else
{
/* Instance is a simple string */
- sstrncpy (dd->instance.string, ci->values[0].value.string,
+ sstrncpy (dd->instance.string, buffer,
sizeof (dd->instance.string));
}
static int csnmp_config_add_data_instance_prefix (data_definition_t *dd,
oconfig_item_t *ci)
{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `InstancePrefix' needs exactly one string argument.");
- return (-1);
- }
+ int status;
if (!dd->is_table)
{
return (-1);
}
- sfree (dd->instance_prefix);
- dd->instance_prefix = strdup (ci->values[0].value.string);
- if (dd->instance_prefix == NULL)
- return (-1);
-
- return (0);
+ status = cf_util_get_string(ci, &dd->instance_prefix);
+ return status;
} /* int csnmp_config_add_data_instance_prefix */
static int csnmp_config_add_data_values (data_definition_t *dd, oconfig_item_t *ci)
return (0);
} /* int csnmp_config_add_data_instance */
-static int csnmp_config_add_data_shift (data_definition_t *dd, oconfig_item_t *ci)
+static int csnmp_config_add_data_blacklist(data_definition_t *dd, oconfig_item_t *ci)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ int i;
+
+ if (ci->values_num < 1)
+ return (0);
+
+ for (i = 0; i < ci->values_num; i++)
{
- WARNING ("snmp plugin: The `Shift' config option needs exactly one number argument.");
- return (-1);
+ if (ci->values[i].type != OCONFIG_TYPE_STRING)
+ {
+ WARNING ("snmp plugin: `Ignore' needs only string argument.");
+ return (-1);
+ }
}
- dd->shift = ci->values[0].value.number;
+ dd->ignores_len = 0;
+ dd->ignores = NULL;
- return (0);
-} /* int csnmp_config_add_data_shift */
+ for (i = 0; i < ci->values_num; ++i)
+ {
+ if (strarray_add(&(dd->ignores), &(dd->ignores_len), ci->values[i].value.string) != 0)
+ {
+ ERROR("snmp plugin: Can't allocate memory");
+ strarray_free(dd->ignores, dd->ignores_len);
+ return (ENOMEM);
+ }
+ }
+ return 0;
+} /* int csnmp_config_add_data_blacklist */
-static int csnmp_config_add_data_scale (data_definition_t *dd, oconfig_item_t *ci)
+static int csnmp_config_add_data_blacklist_match_inverted(data_definition_t *dd, oconfig_item_t *ci)
{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_NUMBER))
+ if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
{
- WARNING ("snmp plugin: The `Scale' config option needs exactly one number argument.");
+ WARNING ("snmp plugin: `InvertMatch' needs exactly one boolean argument.");
return (-1);
}
- dd->scale = ci->values[0].value.number;
+ dd->invert_match = ci->values[0].value.boolean ? 1 : 0;
return (0);
-} /* int csnmp_config_add_data_scale */
+} /* int csnmp_config_add_data_blacklist_match_inverted */
static int csnmp_config_add_data (oconfig_item_t *ci)
{
int status = 0;
int i;
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: The `Data' config option needs exactly one string argument.");
- return (-1);
- }
-
dd = (data_definition_t *) malloc (sizeof (data_definition_t));
if (dd == NULL)
return (-1);
memset (dd, '\0', sizeof (data_definition_t));
- dd->name = strdup (ci->values[0].value.string);
- if (dd->name == NULL)
+ status = cf_util_get_string(ci, &dd->name);
+ if (status != 0)
{
free (dd);
return (-1);
}
+
dd->scale = 1.0;
dd->shift = 0.0;
status = 0;
if (strcasecmp ("Type", option->key) == 0)
- status = csnmp_config_add_data_type (dd, option);
+ status = cf_util_get_string(option, &dd->type);
else if (strcasecmp ("Table", option->key) == 0)
- status = csnmp_config_add_data_table (dd, option);
+ status = cf_util_get_boolean(option, &dd->is_table);
else if (strcasecmp ("Instance", option->key) == 0)
status = csnmp_config_add_data_instance (dd, option);
else if (strcasecmp ("InstancePrefix", option->key) == 0)
else if (strcasecmp ("Values", option->key) == 0)
status = csnmp_config_add_data_values (dd, option);
else if (strcasecmp ("Shift", option->key) == 0)
- status = csnmp_config_add_data_shift (dd, option);
+ status = cf_util_get_double(option, &dd->shift);
else if (strcasecmp ("Scale", option->key) == 0)
- status = csnmp_config_add_data_scale (dd, option);
+ status = cf_util_get_double(option, &dd->scale);
+ else if (strcasecmp ("Ignore", option->key) == 0)
+ status = csnmp_config_add_data_blacklist(dd, option);
+ else if (strcasecmp ("InvertMatch", option->key) == 0)
+ status = csnmp_config_add_data_blacklist_match_inverted(dd, option);
else
{
WARNING ("snmp plugin: Option `%s' not allowed here.", option->key);
sfree (dd->name);
sfree (dd->instance_prefix);
sfree (dd->values);
+ sfree (dd->ignores);
sfree (dd);
return (-1);
}
return (0);
} /* int csnmp_config_add_data */
-static int csnmp_config_add_host_address (host_definition_t *hd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: The `Address' config option needs exactly one string argument.");
- return (-1);
- }
-
- if (hd->address == NULL)
- free (hd->address);
-
- hd->address = strdup (ci->values[0].value.string);
- if (hd->address == NULL)
- return (-1);
-
- DEBUG ("snmp plugin: host = %s; host->address = %s;",
- hd->name, hd->address);
-
- return (0);
-} /* int csnmp_config_add_host_address */
-
-static int csnmp_config_add_host_community (host_definition_t *hd, oconfig_item_t *ci)
-{
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: The `Community' config option needs exactly one string argument.");
- return (-1);
- }
-
- if (hd->community == NULL)
- free (hd->community);
-
- hd->community = strdup (ci->values[0].value.string);
- if (hd->community == NULL)
- return (-1);
-
- DEBUG ("snmp plugin: host = %s; host->community = %s;",
- hd->name, hd->community);
-
- return (0);
-} /* int csnmp_config_add_host_community */
-
static int csnmp_config_add_host_version (host_definition_t *hd, oconfig_item_t *ci)
{
int version;
}
version = (int) ci->values[0].value.number;
- if ((version != 1) && (version != 2))
+ if ((version < 1) || (version > 3))
{
- WARNING ("snmp plugin: `Version' must either be `1' or `2'.");
+ WARNING ("snmp plugin: `Version' must either be `1', `2', or `3'.");
return (-1);
}
return (0);
} /* int csnmp_config_add_host_collect */
+static int csnmp_config_add_host_auth_protocol (host_definition_t *hd, oconfig_item_t *ci)
+{
+ char buffer[4];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ if (strcasecmp("MD5", buffer) == 0) {
+ hd->auth_protocol = usmHMACMD5AuthProtocol;
+ hd->auth_protocol_len = sizeof(usmHMACMD5AuthProtocol)/sizeof(oid);
+ }
+ else if (strcasecmp("SHA", buffer) == 0) {
+ hd->auth_protocol = usmHMACSHA1AuthProtocol;
+ hd->auth_protocol_len = sizeof(usmHMACSHA1AuthProtocol)/sizeof(oid);
+ }
+ else
+ {
+ WARNING ("snmp plugin: The `AuthProtocol' config option must be `MD5' or `SHA'.");
+ return (-1);
+ }
+
+ DEBUG ("snmp plugin: host = %s; host->auth_protocol = %s;",
+ hd->name, hd->auth_protocol == usmHMACMD5AuthProtocol ? "MD5" : "SHA");
+
+ return (0);
+} /* int csnmp_config_add_host_auth_protocol */
+
+static int csnmp_config_add_host_priv_protocol (host_definition_t *hd, oconfig_item_t *ci)
+{
+ char buffer[4];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ if (strcasecmp("AES", buffer) == 0)
+ {
+ hd->priv_protocol = usmAESPrivProtocol;
+ hd->priv_protocol_len = sizeof(usmAESPrivProtocol)/sizeof(oid);
+ }
+ else if (strcasecmp("DES", buffer) == 0) {
+ hd->priv_protocol = usmDESPrivProtocol;
+ hd->priv_protocol_len = sizeof(usmDESPrivProtocol)/sizeof(oid);
+ }
+ else
+ {
+ WARNING ("snmp plugin: The `PrivProtocol' config option must be `AES' or `DES'.");
+ return (-1);
+ }
+
+ DEBUG ("snmp plugin: host = %s; host->priv_protocol = %s;",
+ hd->name, hd->priv_protocol == usmAESPrivProtocol ? "AES" : "DES");
+
+ return (0);
+} /* int csnmp_config_add_host_priv_protocol */
+
+static int csnmp_config_add_host_security_level (host_definition_t *hd, oconfig_item_t *ci)
+{
+ char buffer[16];
+ int status;
+
+ status = cf_util_get_string_buffer(ci, buffer, sizeof(buffer));
+ if (status != 0)
+ return status;
+
+ if (strcasecmp("noAuthNoPriv", buffer) == 0)
+ hd->security_level = SNMP_SEC_LEVEL_NOAUTH;
+ else if (strcasecmp("authNoPriv", buffer) == 0)
+ hd->security_level = SNMP_SEC_LEVEL_AUTHNOPRIV;
+ else if (strcasecmp("authPriv", buffer) == 0)
+ hd->security_level = SNMP_SEC_LEVEL_AUTHPRIV;
+ else
+ {
+ WARNING ("snmp plugin: The `SecurityLevel' config option must be `noAuthNoPriv', `authNoPriv', or `authPriv'.");
+ return (-1);
+ }
+
+ DEBUG ("snmp plugin: host = %s; host->security_level = %d;",
+ hd->name, hd->security_level);
+
+ return (0);
+} /* int csnmp_config_add_host_security_level */
+
static int csnmp_config_add_host (oconfig_item_t *ci)
{
host_definition_t *hd;
user_data_t cb_data;
struct timespec cb_interval;
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("snmp plugin: `Host' needs exactly one string argument.");
- return (-1);
- }
-
hd = (host_definition_t *) malloc (sizeof (host_definition_t));
if (hd == NULL)
return (-1);
hd->version = 2;
C_COMPLAIN_INIT (&hd->complaint);
- hd->name = strdup (ci->values[0].value.string);
- if (hd->name == NULL)
- {
- free (hd);
- return (-1);
- }
+ status = cf_util_get_string(ci, &hd->name);
+ if (status != 0)
+ return status;
hd->sess_handle = NULL;
hd->interval = 0;
status = 0;
if (strcasecmp ("Address", option->key) == 0)
- status = csnmp_config_add_host_address (hd, option);
+ status = cf_util_get_string(option, &hd->address);
else if (strcasecmp ("Community", option->key) == 0)
- status = csnmp_config_add_host_community (hd, option);
+ status = cf_util_get_string(option, &hd->community);
else if (strcasecmp ("Version", option->key) == 0)
status = csnmp_config_add_host_version (hd, option);
else if (strcasecmp ("Collect", option->key) == 0)
csnmp_config_add_host_collect (hd, option);
else if (strcasecmp ("Interval", option->key) == 0)
cf_util_get_cdtime (option, &hd->interval);
+ else if (strcasecmp ("Username", option->key) == 0)
+ status = cf_util_get_string(option, &hd->username);
+ else if (strcasecmp ("AuthProtocol", option->key) == 0)
+ status = csnmp_config_add_host_auth_protocol (hd, option);
+ else if (strcasecmp ("PrivacyProtocol", option->key) == 0)
+ status = csnmp_config_add_host_priv_protocol (hd, option);
+ else if (strcasecmp ("AuthPassphrase", option->key) == 0)
+ status = cf_util_get_string(option, &hd->auth_passphrase);
+ else if (strcasecmp ("PrivacyPassphrase", option->key) == 0)
+ status = cf_util_get_string(option, &hd->priv_passphrase);
+ else if (strcasecmp ("SecurityLevel", option->key) == 0)
+ status = csnmp_config_add_host_security_level (hd, option);
+ else if (strcasecmp ("Context", option->key) == 0)
+ status = cf_util_get_string(option, &hd->context);
else
{
WARNING ("snmp plugin: csnmp_config_add_host: Option `%s' not allowed here.", option->key);
status = -1;
break;
}
- if (hd->community == NULL)
+ if (hd->community == NULL && hd->version < 3)
{
WARNING ("snmp plugin: `Community' not given for host `%s'", hd->name);
status = -1;
break;
}
+ if (hd->version == 3)
+ {
+ if (hd->username == NULL)
+ {
+ WARNING ("snmp plugin: `Username' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->security_level == 0)
+ {
+ WARNING ("snmp plugin: `SecurityLevel' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->security_level == SNMP_SEC_LEVEL_AUTHNOPRIV || hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ if (hd->auth_protocol == NULL)
+ {
+ WARNING ("snmp plugin: `AuthProtocol' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->auth_passphrase == NULL)
+ {
+ WARNING ("snmp plugin: `AuthPassphrase' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ }
+ if (hd->security_level == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ if (hd->priv_protocol == NULL)
+ {
+ WARNING ("snmp plugin: `PrivacyProtocol' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ if (hd->priv_passphrase == NULL)
+ {
+ WARNING ("snmp plugin: `PrivacyPassphrase' not given for host `%s'", hd->name);
+ status = -1;
+ break;
+ }
+ }
+ }
break;
} /* while (status == 0) */
static void csnmp_host_open_session (host_definition_t *host)
{
struct snmp_session sess;
+ int error;
if (host->sess_handle != NULL)
csnmp_host_close_session (host);
snmp_sess_init (&sess);
sess.peername = host->address;
- sess.community = (u_char *) host->community;
- sess.community_len = strlen (host->community);
- sess.version = (host->version == 1) ? SNMP_VERSION_1 : SNMP_VERSION_2c;
+ switch (host->version)
+ {
+ case 1:
+ sess.version = SNMP_VERSION_1;
+ break;
+ case 3:
+ sess.version = SNMP_VERSION_3;
+ break;
+ default:
+ sess.version = SNMP_VERSION_2c;
+ break;
+ }
+
+ if (host->version == 3)
+ {
+ sess.securityName = host->username;
+ sess.securityNameLen = strlen (host->username);
+ sess.securityLevel = host->security_level;
+
+ if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHNOPRIV || sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ sess.securityAuthProto = host->auth_protocol;
+ sess.securityAuthProtoLen = host->auth_protocol_len;
+ sess.securityAuthKeyLen = USM_AUTH_KU_LEN;
+ error = generate_Ku (sess.securityAuthProto,
+ sess.securityAuthProtoLen,
+ (u_char *) host->auth_passphrase,
+ strlen(host->auth_passphrase),
+ sess.securityAuthKey,
+ &sess.securityAuthKeyLen);
+ if (error != SNMPERR_SUCCESS) {
+ ERROR ("snmp plugin: host %s: Error generating Ku from auth_passphrase. (Error %d)", host->name, error);
+ }
+ }
+
+ if (sess.securityLevel == SNMP_SEC_LEVEL_AUTHPRIV)
+ {
+ sess.securityPrivProto = host->priv_protocol;
+ sess.securityPrivProtoLen = host->priv_protocol_len;
+ sess.securityPrivKeyLen = USM_PRIV_KU_LEN;
+ error = generate_Ku (sess.securityAuthProto,
+ sess.securityAuthProtoLen,
+ (u_char *) host->priv_passphrase,
+ strlen(host->priv_passphrase),
+ sess.securityPrivKey,
+ &sess.securityPrivKeyLen);
+ if (error != SNMPERR_SUCCESS) {
+ ERROR ("snmp plugin: host %s: Error generating Ku from priv_passphrase. (Error %d)", host->name, error);
+ }
+ }
+
+ if (host->context != NULL)
+ {
+ sess.contextName = host->context;
+ sess.contextNameLen = strlen (host->context);
+ }
+ }
+ else /* SNMPv1/2 "authenticates" with community string */
+ {
+ sess.community = (u_char *) host->community;
+ sess.community_len = strlen (host->community);
+ }
/* snmp_sess_open will copy the `struct snmp_session *'. */
host->sess_handle = snmp_sess_open (&sess);
struct variable_list *vb;
oid_t vb_name;
int status;
+ uint32_t i;
+ uint32_t is_matched;
/* Set vb on the last variable */
for (vb = res->variables;
char *ptr;
csnmp_strvbcopy (il->instance, vb, sizeof (il->instance));
-
+ is_matched = 0;
+ for (i = 0; i < dd->ignores_len; i++)
+ {
+ status = fnmatch(dd->ignores[i], il->instance, 0);
+ if (status == 0)
+ {
+ if (dd->invert_match == 0)
+ {
+ sfree(il);
+ return 0;
+ }
+ else
+ {
+ is_matched = 1;
+ break;
+ }
+ }
+ }
+ if (dd->invert_match != 0 && is_matched == 0)
+ {
+ sfree(il);
+ return 0;
+ }
for (ptr = il->instance; *ptr != '\0'; ptr++)
{
if ((*ptr > 0) && (*ptr < 32))
sfree (data_this->name);
sfree (data_this->type);
sfree (data_this->values);
+ sfree (data_this->ignores);
sfree (data_this);
data_this = data_next;
#include <netdb.h>
#include <poll.h>
+/* AIX doesn't have MSG_DONTWAIT */
+#ifndef MSG_DONTWAIT
+# define MSG_DONTWAIT MSG_NONBLOCK
+#endif
+
#ifndef STATSD_DEFAULT_NODE
# define STATSD_DEFAULT_NODE NULL
#endif
/**
* collectd - src/swap.c
- * Copyright (C) 2005-2012 Florian octo Forster
+ * Copyright (C) 2005-2014 Florian octo Forster
* Copyright (C) 2009 Stefan Völkel
* Copyright (C) 2009 Manuel Sanmartin
* Copyright (C) 2010 Aurélien Reynaud
#elif HAVE_PERFSTAT
static int pagesize;
-static perfstat_memory_total_t pmemory;
/*# endif HAVE_PERFSTAT */
#else
# error "No applicable input method."
#endif /* HAVE_LIBSTATGRAB */
-static const char *config_keys[] =
-{
- "ReportBytes",
- "ReportByDevice"
-};
-static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+static _Bool values_absolute = 1;
+static _Bool values_percentage = 0;
-static int swap_config (const char *key, const char *value) /* {{{ */
+static int swap_config (oconfig_item_t *ci) /* {{{ */
{
- if (strcasecmp ("ReportBytes", key) == 0)
+ int i;
+
+ for (i = 0; i < ci->children_num; i++)
{
+ oconfig_item_t *child = ci->children + i;
+ if (strcasecmp ("ReportBytes", child->key) == 0)
#if KERNEL_LINUX
- report_bytes = IS_TRUE (value) ? 1 : 0;
+ cf_util_get_boolean (child, &report_bytes);
#else
- WARNING ("swap plugin: The \"ReportBytes\" option is only "
- "valid under Linux. "
- "The option is going to be ignored.");
+ WARNING ("swap plugin: The \"ReportBytes\" option "
+ "is only valid under Linux. "
+ "The option is going to be ignored.");
#endif
- }
- else if (strcasecmp ("ReportByDevice", key) == 0)
- {
+ else if (strcasecmp ("ReportByDevice", child->key) == 0)
#if SWAP_HAVE_REPORT_BY_DEVICE
- if (IS_TRUE (value))
- report_by_device = 1;
- else
- report_by_device = 0;
+ cf_util_get_boolean (child, &report_by_device);
#else
- WARNING ("swap plugin: The \"ReportByDevice\" option is not "
- "supported on this platform. "
- "The option is going to be ignored.");
+ WARNING ("swap plugin: The \"ReportByDevice\" option "
+ "is not supported on this platform. "
+ "The option is going to be ignored.");
#endif /* SWAP_HAVE_REPORT_BY_DEVICE */
- }
- else
- {
- return (-1);
+ else if (strcasecmp ("ValuesAbsolute", child->key) == 0)
+ cf_util_get_boolean (child, &values_absolute);
+ else if (strcasecmp ("ValuesPercentage", child->key) == 0)
+ cf_util_get_boolean (child, &values_percentage);
+ else
+ WARNING ("swap plugin: Unknown config option: \"%s\"",
+ child->key);
}
return (0);
return (0);
} /* }}} int swap_init */
-static void swap_submit (const char *plugin_instance, /* {{{ */
- const char *type, const char *type_instance,
- value_t value)
+static void swap_submit_usage (char const *plugin_instance, /* {{{ */
+ gauge_t used, gauge_t free,
+ char const *other_name, gauge_t other_value)
{
+ value_t v[1];
value_list_t vl = VALUE_LIST_INIT;
- assert (type != NULL);
-
- vl.values = &value;
- vl.values_len = 1;
+ vl.values = v;
+ vl.values_len = STATIC_ARRAY_SIZE (v);
sstrncpy (vl.host, hostname_g, sizeof (vl.host));
sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
if (plugin_instance != NULL)
- sstrncpy (vl.plugin_instance, plugin_instance, sizeof (vl.plugin_instance));
- sstrncpy (vl.type, type, sizeof (vl.type));
- if (type_instance != NULL)
- sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
-
- plugin_dispatch_values (&vl);
-} /* }}} void swap_submit_inst */
+ sstrncpy (vl.plugin_instance, plugin_instance,
+ sizeof (vl.plugin_instance));
+ sstrncpy (vl.type, "swap", sizeof (vl.type));
+
+ if (values_absolute)
+ plugin_dispatch_multivalue (&vl, 0,
+ "used", used, "free", free,
+ other_name, other_value, NULL);
+ if (values_percentage)
+ plugin_dispatch_multivalue (&vl, 1,
+ "used", used, "free", free,
+ other_name, other_value, NULL);
+} /* }}} void swap_submit_usage */
-static void swap_submit_gauge (const char *plugin_instance, /* {{{ */
- const char *type_instance, gauge_t value)
+#if KERNEL_LINUX || HAVE_PERFSTAT
+__attribute__((nonnull(1)))
+static void swap_submit_derive (char const *type_instance, /* {{{ */
+ derive_t value)
{
- value_t v;
+ value_list_t vl = VALUE_LIST_INIT;
+ value_t v[1];
- v.gauge = value;
- swap_submit (plugin_instance, "swap", type_instance, v);
-} /* }}} void swap_submit_gauge */
+ v[0].derive = value;
-#if KERNEL_LINUX || HAVE_PERFSTAT
-static void swap_submit_derive (const char *plugin_instance, /* {{{ */
- const char *type_instance, derive_t value)
-{
- value_t v;
+ vl.values = v;
+ vl.values_len = STATIC_ARRAY_SIZE (v);
+ sstrncpy (vl.host, hostname_g, sizeof (vl.host));
+ sstrncpy (vl.plugin, "swap", sizeof (vl.plugin));
+ sstrncpy (vl.type, "swap_io", sizeof (vl.type));
+ sstrncpy (vl.type_instance, type_instance, sizeof (vl.type_instance));
- v.derive = value;
- swap_submit (plugin_instance, "swap_io", type_instance, v);
+ plugin_dispatch_values (&vl);
} /* }}} void swap_submit_derive */
#endif
char *endptr;
char path[PATH_MAX];
- gauge_t size;
+ gauge_t total;
gauge_t used;
- gauge_t free;
numfields = strsplit (buffer, fields, STATIC_ARRAY_SIZE (fields));
if (numfields != 5)
errno = 0;
endptr = NULL;
- size = strtod (fields[2], &endptr);
+ total = strtod (fields[2], &endptr);
if ((endptr == fields[2]) || (errno != 0))
continue;
if ((endptr == fields[3]) || (errno != 0))
continue;
- if (size < used)
+ if (total < used)
continue;
- free = size - used;
-
- swap_submit_gauge (path, "used", used);
- swap_submit_gauge (path, "free", free);
+ swap_submit_usage (path, used, total - used, NULL, NAN);
}
fclose (fh);
swap_used = swap_total - (swap_free + swap_cached);
- swap_submit_gauge (NULL, "used", 1024.0 * swap_used);
- swap_submit_gauge (NULL, "free", 1024.0 * swap_free);
- swap_submit_gauge (NULL, "cached", 1024.0 * swap_cached);
-
+ swap_submit_usage (NULL, swap_used, swap_free, "cached", swap_cached);
return (0);
} /* }}} int swap_read_combined */
swap_out = swap_out * pagesize;
}
- swap_submit_derive (NULL, "in", swap_in);
- swap_submit_derive (NULL, "out", swap_out);
+ swap_submit_derive ("in", swap_in);
+ swap_submit_derive ("out", swap_out);
return (0);
} /* }}} int swap_read_io */
/* kstat-based read function */
static int swap_read_kstat (void) /* {{{ */
{
- derive_t swap_alloc;
- derive_t swap_resv;
- derive_t swap_avail;
+ gauge_t swap_alloc;
+ gauge_t swap_resv;
+ gauge_t swap_avail;
struct anoninfo ai;
* swap_alloc = pagesize * ( ai.ani_max - ai.ani_free );
* can suffer from a 32bit overflow.
*/
- swap_alloc = (derive_t) ((ai.ani_max - ai.ani_free) * pagesize);
- swap_resv = (derive_t) ((ai.ani_resv + ai.ani_free - ai.ani_max)
- * pagesize);
- swap_avail = (derive_t) ((ai.ani_max - ai.ani_resv) * pagesize);
-
- swap_submit_gauge (NULL, "used", swap_alloc);
- swap_submit_gauge (NULL, "free", swap_avail);
- swap_submit_gauge (NULL, "reserved", swap_resv);
+ swap_alloc = (gauge_t) ((ai.ani_max - ai.ani_free) * pagesize);
+ swap_resv = (gauge_t) ((ai.ani_resv + ai.ani_free - ai.ani_max) * pagesize);
+ swap_avail = (gauge_t) ((ai.ani_max - ai.ani_resv) * pagesize);
+ swap_submit_usage (NULL, swap_alloc, swap_avail, "reserved", swap_resv);
return (0);
} /* }}} int swap_read_kstat */
/* #endif 0 && HAVE_LIBKSTAT */
int status;
int i;
- derive_t avail = 0;
- derive_t total = 0;
+ gauge_t avail = 0;
+ gauge_t total = 0;
swap_num = swapctl (SC_GETNSWP, NULL);
if (swap_num < 0)
for (i = 0; i < swap_num; i++)
{
char path[PATH_MAX];
- derive_t this_total;
- derive_t this_avail;
+ gauge_t this_total;
+ gauge_t this_avail;
if ((s->swt_ent[i].ste_flags & ST_INDEL) != 0)
continue;
- this_total = ((derive_t) s->swt_ent[i].ste_pages) * pagesize;
- this_avail = ((derive_t) s->swt_ent[i].ste_free) * pagesize;
+ this_total = (gauge_t) (s->swt_ent[i].ste_pages * pagesize);
+ this_avail = (gauge_t) (s->swt_ent[i].ste_free * pagesize);
/* Shortcut for the "combined" setting (default) */
if (!report_by_device)
sstrncpy (path, s->swt_ent[i].ste_path, sizeof (path));
escape_slashes (path, sizeof (path));
- swap_submit_gauge (path, "used", (gauge_t) (this_total - this_avail));
- swap_submit_gauge (path, "free", (gauge_t) this_avail);
+ swap_submit_usage (path, this_total - this_avail, this_avail,
+ NULL, NAN);
} /* for (swap_num) */
if (total < avail)
{
- ERROR ("swap plugin: Total swap space (%"PRIi64") "
- "is less than free swap space (%"PRIi64").",
+ ERROR ("swap plugin: Total swap space (%g) is less than free swap space (%g).",
total, avail);
sfree (s_paths);
sfree (s);
return (-1);
}
- /* If the "separate" option was specified (report_by_device == 2), all
+ /* If the "separate" option was specified (report_by_device == 1), all
* values have already been dispatched from within the loop. */
if (!report_by_device)
- {
- swap_submit_gauge (NULL, "used", (gauge_t) (total - avail));
- swap_submit_gauge (NULL, "free", (gauge_t) avail);
- }
+ swap_submit_usage (NULL, total - avail, avail, NULL, NAN);
sfree (s_paths);
sfree (s);
int status;
int i;
- derive_t used = 0;
- derive_t total = 0;
+ gauge_t used = 0;
+ gauge_t total = 0;
swap_num = swapctl (SWAP_NSWAP, NULL, 0);
if (swap_num < 0)
}
#if defined(DEV_BSIZE) && (DEV_BSIZE > 0)
-# define C_SWAP_BLOCK_SIZE ((derive_t) DEV_BSIZE)
+# define C_SWAP_BLOCK_SIZE ((gauge_t) DEV_BSIZE)
#else
-# define C_SWAP_BLOCK_SIZE ((derive_t) 512)
+# define C_SWAP_BLOCK_SIZE 512.0
#endif
+ /* TODO: Report per-device stats. The path name is available from
+ * swap_entries[i].se_path */
for (i = 0; i < swap_num; i++)
{
if ((swap_entries[i].se_flags & SWF_ENABLE) == 0)
continue;
- used += ((derive_t) swap_entries[i].se_inuse)
- * C_SWAP_BLOCK_SIZE;
- total += ((derive_t) swap_entries[i].se_nblks)
- * C_SWAP_BLOCK_SIZE;
+ used += ((gauge_t) swap_entries[i].se_inuse) * C_SWAP_BLOCK_SIZE;
+ total += ((gauge_t) swap_entries[i].se_nblks) * C_SWAP_BLOCK_SIZE;
}
if (total < used)
{
- ERROR ("swap plugin: Total swap space (%"PRIu64") "
- "is less than used swap space (%"PRIu64").",
+ ERROR ("swap plugin: Total swap space (%g) is less than used swap space (%g).",
total, used);
return (-1);
}
- swap_submit_gauge (NULL, "used", (gauge_t) used);
- swap_submit_gauge (NULL, "free", (gauge_t) (total - used));
+ swap_submit_usage (NULL, used, total - used, NULL, NAN);
sfree (swap_entries);
-
return (0);
} /* }}} int swap_read */
/* #endif HAVE_SWAPCTL && HAVE_SWAPCTL_THREE_ARGS */
return (-1);
/* The returned values are bytes. */
- swap_submit_gauge (NULL, "used", (gauge_t) sw_usage.xsu_used);
- swap_submit_gauge (NULL, "free", (gauge_t) sw_usage.xsu_avail);
+ swap_submit_usage (NULL,
+ (gauge_t) sw_usage.xsu_used, (gauge_t) sw_usage.xsu_avail,
+ NULL, NAN);
return (0);
} /* }}} int swap_read */
struct kvm_swap data_s;
int status;
- derive_t used;
- derive_t free;
- derive_t total;
+ gauge_t used;
+ gauge_t total;
if (kvm_obj == NULL)
return (-1);
if (status == -1)
return (-1);
- total = (derive_t) data_s.ksw_total;
- used = (derive_t) data_s.ksw_used;
+ total = (gauge_t) data_s.ksw_total;
+ used = (gauge_t) data_s.ksw_used;
- total *= (derive_t) kvm_pagesize;
- used *= (derive_t) kvm_pagesize;
+ total *= (gauge_t) kvm_pagesize;
+ used *= (gauge_t) kvm_pagesize;
- free = total - used;
-
- swap_submit_gauge (NULL, "used", (gauge_t) used);
- swap_submit_gauge (NULL, "free", (gauge_t) free);
+ swap_submit_usage (NULL, used, total - used, NULL, NAN);
return (0);
} /* }}} int swap_read */
sg_swap_stats *swap;
swap = sg_get_swap_stats ();
-
if (swap == NULL)
return (-1);
- swap_submit_gauge (NULL, "used", (gauge_t) swap->used);
- swap_submit_gauge (NULL, "free", (gauge_t) swap->free);
+ swap_submit_usage (NULL, (gauge_t) swap->used, (gauge_t) swap->free,
+ NULL, NAN);
return (0);
} /* }}} int swap_read */
#elif HAVE_PERFSTAT
static int swap_read (void) /* {{{ */
{
- if(perfstat_memory_total(NULL, &pmemory, sizeof(perfstat_memory_total_t), 1) < 0)
+ perfstat_memory_total_t pmemory;
+ int status;
+
+ gauge_t total;
+ gauge_t free;
+ gauge_t reserved;
+
+ memset (&pmemory, 0, sizeof (pmemory));
+ status = perfstat_memory_total (NULL, &pmemory, sizeof(perfstat_memory_total_t), 1);
+ if (status < 0)
{
char errbuf[1024];
- WARNING ("memory plugin: perfstat_memory_total failed: %s",
+ WARNING ("swap plugin: perfstat_memory_total failed: %s",
sstrerror (errno, errbuf, sizeof (errbuf)));
return (-1);
}
- swap_submit_gauge (NULL, "used", (gauge_t) (pmemory.pgsp_total - pmemory.pgsp_free) * pagesize);
- swap_submit_gauge (NULL, "free", (gauge_t) pmemory.pgsp_free * pagesize );
- swap_submit_gauge (NULL, "reserved", (gauge_t) pmemory.pgsp_rsvd * pagesize);
- swap_submit_derive (NULL, "in", (derive_t) pmemory.pgspins * pagesize);
- swap_submit_derive (NULL, "out", (derive_t) pmemory.pgspouts * pagesize);
+ total = (gauge_t) (pmemory.pgsp_total * pagesize);
+ free = (gauge_t) (pmemory.pgsp_free * pagesize);
+ reserved = (gauge_t) (pmemory.pgsp_rsvd * pagesize);
+
+ swap_submit_usage (NULL, total - free, free, "reserved", reserved);
+ swap_submit_derive ("in", (derive_t) pmemory.pgspins * pagesize);
+ swap_submit_derive ("out", (derive_t) pmemory.pgspouts * pagesize);
return (0);
} /* }}} int swap_read */
void module_register (void)
{
- plugin_register_config ("swap", swap_config,
- config_keys, config_keys_num);
+ plugin_register_complex_config ("swap", swap_config);
plugin_register_init ("swap", swap_init);
plugin_register_read ("swap", swap_read);
} /* void module_register */
{
log_level = parse_log_severity (value);
if (log_level < 0)
+ {
+ log_level = LOG_INFO;
+ ERROR ("syslog: invalid loglevel [%s] defauling to 'info'", value);
return (1);
+ }
}
else if (strcasecmp (key, "NotifyLevel") == 0)
{
* <Plugin tail>
* <File "/var/log/exim4/mainlog">
* Instance "exim"
+ * Interval 60
* <Match>
* Regex "S=([1-9][0-9]*)"
* ExcludeRegex "U=root.*S="
int flags;
char *type;
char *type_instance;
+ cdtime_t interval;
};
typedef struct ctail_config_match_s ctail_config_match_t;
cu_tail_match_t **tail_match_list = NULL;
size_t tail_match_list_num = 0;
+cdtime_t tail_match_list_intervals[255];
static int ctail_config_add_match_dstype (ctail_config_match_t *cm,
oconfig_item_t *ci)
} /* int ctail_config_add_match_dstype */
static int ctail_config_add_match (cu_tail_match_t *tm,
- const char *plugin_instance, oconfig_item_t *ci)
+ const char *plugin_instance, oconfig_item_t *ci, cdtime_t interval)
{
ctail_config_match_t cm;
int status;
if (status == 0)
{
status = tail_match_add_match_simple (tm, cm.regex, cm.excluderegex,
- cm.flags, "tail", plugin_instance, cm.type, cm.type_instance);
+ cm.flags, "tail", plugin_instance, cm.type, cm.type_instance, interval);
if (status != 0)
{
static int ctail_config_add_file (oconfig_item_t *ci)
{
cu_tail_match_t *tm;
+ cdtime_t interval = 0;
char *plugin_instance = NULL;
int num_matches = 0;
int status;
{
oconfig_item_t *option = ci->children + i;
- if (strcasecmp ("Match", option->key) == 0)
+ if (strcasecmp ("Instance", option->key) == 0)
+ status = cf_util_get_string (option, &plugin_instance);
+ else if (strcasecmp ("Interval", option->key) == 0)
+ cf_util_get_cdtime (option, &interval);
+ else if (strcasecmp ("Match", option->key) == 0)
{
- status = ctail_config_add_match (tm, plugin_instance, option);
+ status = ctail_config_add_match (tm, plugin_instance, option, interval);
if (status == 0)
num_matches++;
/* Be mild with failed matches.. */
status = 0;
}
- else if (strcasecmp ("Instance", option->key) == 0)
- status = cf_util_get_string (option, &plugin_instance);
else
{
- WARNING ("tail plugin: Option `%s' not allowed here.", option->key);
status = -1;
}
tail_match_list = temp;
tail_match_list[tail_match_list_num] = tm;
+ tail_match_list_intervals[tail_match_list_num] = interval;
tail_match_list_num++;
}
return (0);
} /* int ctail_config */
-static int ctail_init (void)
+static int ctail_read (user_data_t *ud)
{
- if (tail_match_list_num == 0)
+ int status;
+
+ status = tail_match_read ((cu_tail_match_t *)ud->data);
+ if (status != 0)
{
- WARNING ("tail plugin: File list is empty. Returning an error.");
+ ERROR ("tail plugin: tail_match_read failed.");
return (-1);
}
return (0);
-} /* int ctail_init */
+} /* int ctail_read */
-static int ctail_read (void)
+static int ctail_init (void)
{
- int success = 0;
+ struct timespec cb_interval;
+ char str[255];
+ user_data_t ud;
size_t i;
- for (i = 0; i < tail_match_list_num; i++)
+ if (tail_match_list_num == 0)
{
- int status;
+ WARNING ("tail plugin: File list is empty. Returning an error.");
+ return (-1);
+ }
- status = tail_match_read (tail_match_list[i]);
- if (status != 0)
- {
- ERROR ("tail plugin: tail_match_read[%zu] failed.", i);
- }
- else
- {
- success++;
- }
+ for (i = 0; i < tail_match_list_num; i++)
+ {
+ ud.data = (void *)tail_match_list[i];
+ ssnprintf(str, sizeof(str), "tail-%zu", i);
+ CDTIME_T_TO_TIMESPEC (tail_match_list_intervals[i], &cb_interval);
+ plugin_register_complex_read (NULL, str, ctail_read, &cb_interval, &ud);
}
- if (success == 0)
- return (-1);
return (0);
-} /* int ctail_read */
+} /* int ctail_init */
static int ctail_shutdown (void)
{
{
plugin_register_complex_config ("tail", ctail_config);
plugin_register_init ("tail", ctail_init);
- plugin_register_read ("tail", ctail_read);
plugin_register_shutdown ("tail", ctail_shutdown);
} /* void module_register */
"CLOSED",
"LISTEN",
"SYN_SENT",
- "SYN_RCVD",
+ "SYN_RECV",
"ESTABLISHED",
"CLOSE_WAIT",
- "FIN_WAIT_1",
+ "FIN_WAIT1",
"CLOSING",
"LAST_ACK",
- "FIN_WAIT_2",
+ "FIN_WAIT2",
"TIME_WAIT"
};
static int cache_compare (const cache_entry_t *a, const cache_entry_t *b)
{
+#if COLLECT_DEBUG
assert ((a != NULL) && (b != NULL));
+#endif
return (strcmp (a->name, b->name));
} /* int cache_compare */
#include "utils_cache.h"
#include "utils_parse_option.h"
+#define GRAPHITE_FORBIDDEN " \t\"\\:!/()\n\r"
+
/* Utils functions to format data sets in graphite format.
* Largely taken from write_graphite.c as it remains the same formatting */
return (0);
}
+static void escape_graphite_string (char *buffer, char escape_char)
+{
+ char *head;
+
+ assert (strchr(GRAPHITE_FORBIDDEN, escape_char) == NULL);
+
+ for (head = buffer + strcspn(buffer, GRAPHITE_FORBIDDEN);
+ *head != '\0';
+ head += strcspn(head, GRAPHITE_FORBIDDEN))
+ *head = escape_char;
+}
+
int format_graphite (char *buffer, size_t buffer_size,
data_set_t const *ds, value_list_t const *vl,
char const *prefix, char const *postfix, char const escape_char,
return (status);
}
- escape_string (key, sizeof (key));
+ escape_graphite_string (key, escape_char);
/* Convert the values to an ASCII representation and put that into
* `values'. */
status = gr_format_values (values, sizeof (values), i, ds, vl, rates);
char plugin_instance[DATA_MAX_NAME_LEN];
char type[DATA_MAX_NAME_LEN];
char type_instance[DATA_MAX_NAME_LEN];
+ cdtime_t interval;
};
typedef struct cu_tail_match_simple_s cu_tail_match_simple_t;
int flags;
cu_tail_t *tail;
+ cdtime_t interval;
cu_tail_match_match_t *matches;
size_t matches_num;
};
sstrncpy (vl.type_instance, data->type_instance,
sizeof (vl.type_instance));
+ vl.interval = data->interval;
plugin_dispatch_values (&vl);
if (match_value->ds_type & UTILS_MATCH_DS_TYPE_GAUGE)
obj->matches = temp;
obj->matches_num++;
+ DEBUG ("tail_match_add_match interval %lf", CDTIME_T_TO_DOUBLE(((cu_tail_match_simple_t *)user_data)->interval));
temp = obj->matches + (obj->matches_num - 1);
temp->match = match;
int tail_match_add_match_simple (cu_tail_match_t *obj,
const char *regex, const char *excluderegex, int ds_type,
const char *plugin, const char *plugin_instance,
- const char *type, const char *type_instance)
+ const char *type, const char *type_instance, const cdtime_t interval)
{
cu_match_t *match;
cu_tail_match_simple_t *user_data;
sstrncpy (user_data->type_instance, type_instance,
sizeof (user_data->type_instance));
+ user_data->interval = interval;
+
status = tail_match_add_match (obj, match, simple_submit_match,
user_data, free);
int tail_match_add_match_simple (cu_tail_match_t *obj,
const char *regex, const char *excluderegex, int ds_type,
const char *plugin, const char *plugin_instance,
- const char *type, const char *type_instance);
+ const char *type, const char *type_instance, const cdtime_t interval);
/*
* NAME
char *user;
char *pass;
char *credentials;
- int verify_peer;
- int verify_host;
+ _Bool verify_peer;
+ _Bool verify_host;
char *cacert;
- int store_rates;
+ char *capath;
+ char *clientkey;
+ char *clientcert;
+ char *clientkeypass;
+ long sslversion;
+ _Bool store_rates;
#define WH_FORMAT_COMMAND 0
#define WH_FORMAT_JSON 1
}
curl_easy_setopt (cb->curl, CURLOPT_NOSIGNAL, 1L);
- curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, PACKAGE_NAME"/"PACKAGE_VERSION);
+ curl_easy_setopt (cb->curl, CURLOPT_USERAGENT, COLLECTD_USERAGENT);
headers = NULL;
headers = curl_slist_append (headers, "Accept: */*");
curl_easy_setopt (cb->curl, CURLOPT_SSL_VERIFYPEER, (long) cb->verify_peer);
curl_easy_setopt (cb->curl, CURLOPT_SSL_VERIFYHOST,
cb->verify_host ? 2L : 0L);
+ curl_easy_setopt (cb->curl, CURLOPT_SSLVERSION, cb->sslversion);
if (cb->cacert != NULL)
curl_easy_setopt (cb->curl, CURLOPT_CAINFO, cb->cacert);
+ if (cb->capath != NULL)
+ curl_easy_setopt (cb->curl, CURLOPT_CAPATH, cb->capath);
+
+ if (cb->clientkey != NULL && cb->clientcert != NULL)
+ {
+ curl_easy_setopt (cb->curl, CURLOPT_SSLKEY, cb->clientkey);
+ curl_easy_setopt (cb->curl, CURLOPT_SSLCERT, cb->clientcert);
+
+ if (cb->clientkeypass != NULL)
+ curl_easy_setopt (cb->curl, CURLOPT_SSLKEYPASSWD, cb->clientkeypass);
+ }
wh_reset_buffer (cb);
sfree (cb->pass);
sfree (cb->credentials);
sfree (cb->cacert);
+ sfree (cb->capath);
+ sfree (cb->clientkey);
+ sfree (cb->clientcert);
+ sfree (cb->clientkeypass);
sfree (cb);
} /* }}} void wh_callback_free */
return (status);
} /* }}} int wh_write */
-static int config_set_string (char **ret_string, /* {{{ */
- oconfig_item_t *ci)
-{
- char *string;
-
- if ((ci->values_num != 1)
- || (ci->values[0].type != OCONFIG_TYPE_STRING))
- {
- WARNING ("write_http plugin: The `%s' config option "
- "needs exactly one string argument.", ci->key);
- return (-1);
- }
-
- string = strdup (ci->values[0].value.string);
- if (string == NULL)
- {
- ERROR ("write_http plugin: strdup failed.");
- return (-1);
- }
-
- if (*ret_string != NULL)
- free (*ret_string);
- *ret_string = string;
-
- return (0);
-} /* }}} int config_set_string */
-
-static int config_set_boolean (int *dest, oconfig_item_t *ci) /* {{{ */
-{
- if ((ci->values_num != 1) || (ci->values[0].type != OCONFIG_TYPE_BOOLEAN))
- {
- WARNING ("write_http plugin: The `%s' config option "
- "needs exactly one boolean argument.", ci->key);
- return (-1);
- }
-
- *dest = ci->values[0].value.boolean ? 1 : 0;
-
- return (0);
-} /* }}} int config_set_boolean */
-
static int config_set_format (wh_callback_t *cb, /* {{{ */
oconfig_item_t *ci)
{
}
return (0);
-} /* }}} int config_set_string */
+} /* }}} int config_set_format */
static int wh_config_url (oconfig_item_t *ci) /* {{{ */
{
return (-1);
}
memset (cb, 0, sizeof (*cb));
- cb->location = NULL;
- cb->user = NULL;
- cb->pass = NULL;
- cb->credentials = NULL;
cb->verify_peer = 1;
cb->verify_host = 1;
- cb->cacert = NULL;
cb->format = WH_FORMAT_COMMAND;
- cb->curl = NULL;
+ cb->sslversion = CURL_SSLVERSION_DEFAULT;
pthread_mutex_init (&cb->send_lock, /* attr = */ NULL);
- config_set_string (&cb->location, ci);
+ cf_util_get_string (ci, &cb->location);
if (cb->location == NULL)
return (-1);
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("User", child->key) == 0)
- config_set_string (&cb->user, child);
+ cf_util_get_string (child, &cb->user);
else if (strcasecmp ("Password", child->key) == 0)
- config_set_string (&cb->pass, child);
+ cf_util_get_string (child, &cb->pass);
else if (strcasecmp ("VerifyPeer", child->key) == 0)
- config_set_boolean (&cb->verify_peer, child);
+ cf_util_get_boolean (child, &cb->verify_peer);
else if (strcasecmp ("VerifyHost", child->key) == 0)
- config_set_boolean (&cb->verify_host, child);
+ cf_util_get_boolean (child, &cb->verify_host);
else if (strcasecmp ("CACert", child->key) == 0)
- config_set_string (&cb->cacert, child);
+ cf_util_get_string (child, &cb->cacert);
+ else if (strcasecmp ("CAPath", child->key) == 0)
+ cf_util_get_string (child, &cb->capath);
+ else if (strcasecmp ("ClientKey", child->key) == 0)
+ cf_util_get_string (child, &cb->clientkey);
+ else if (strcasecmp ("ClientCert", child->key) == 0)
+ cf_util_get_string (child, &cb->clientcert);
+ else if (strcasecmp ("ClientKeyPass", child->key) == 0)
+ cf_util_get_string (child, &cb->clientkeypass);
+ else if (strcasecmp ("SSLVersion", child->key) == 0)
+ {
+ char *value = NULL;
+
+ cf_util_get_string (child, &value);
+
+ if (value == NULL || strcasecmp ("default", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_DEFAULT;
+ else if (strcasecmp ("SSLv2", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_SSLv2;
+ else if (strcasecmp ("SSLv3", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_SSLv3;
+ else if (strcasecmp ("TLSv1", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1;
+#if (LIBCURL_VERSION_MAJOR > 7) || (LIBCURL_VERSION_MAJOR == 7 && LIBCURL_VERSION_MINOR >= 34)
+ else if (strcasecmp ("TLSv1_0", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1_0;
+ else if (strcasecmp ("TLSv1_1", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1_1;
+ else if (strcasecmp ("TLSv1_2", value) == 0)
+ cb->sslversion = CURL_SSLVERSION_TLSv1_2;
+#endif
+ else
+ ERROR ("write_http plugin: Invalid SSLVersion "
+ "option: %s.", value);
+
+ sfree(value);
+ }
else if (strcasecmp ("Format", child->key) == 0)
config_set_format (cb, child);
else if (strcasecmp ("StoreRates", child->key) == 0)
- config_set_boolean (&cb->store_rates, child);
+ cf_util_get_boolean (child, &cb->store_rates);
else
{
ERROR ("write_http plugin: Invalid configuration "
static char **riemann_tags;
static size_t riemann_tags_num;
+static char **riemann_attrs;
+static size_t riemann_attrs_num;
static void riemann_event_protobuf_free (Event *event) /* {{{ */
{
} /* }}} void riemann_msg_protobuf_free */
/* host->lock must be held when calling this function. */
-static int
-riemann_connect(struct riemann_host *host)
+static int riemann_connect(struct riemann_host *host) /* {{{ */
{
int e;
struct addrinfo *ai, *res, hints;
return -1;
}
return 0;
-}
+} /* }}} int riemann_connect */
/* host->lock must be held when calling this function. */
-static int
-riemann_disconnect (struct riemann_host *host)
+static int riemann_disconnect (struct riemann_host *host) /* {{{ */
{
if ((host->flags & F_CONNECT) == 0)
return (0);
host->flags &= ~F_CONNECT;
return (0);
-}
+} /* }}} int riemann_disconnect */
-static int
-riemann_send(struct riemann_host *host, Msg const *msg)
+static int riemann_send_msg (struct riemann_host *host, const Msg *msg) /* {{{ */
{
- u_char *buffer;
+ int status = 0;
+ u_char *buffer = NULL;
size_t buffer_len;
- int status;
-
- pthread_mutex_lock (&host->lock);
status = riemann_connect (host);
if (status != 0)
- {
- pthread_mutex_unlock (&host->lock);
return status;
- }
buffer_len = msg__get_packed_size(msg);
+
if (host->use_tcp)
buffer_len += 4;
buffer = malloc (buffer_len);
if (buffer == NULL) {
- pthread_mutex_unlock (&host->lock);
ERROR ("write_riemann plugin: malloc failed.");
return ENOMEM;
}
if (status != 0)
{
char errbuf[1024];
-
- riemann_disconnect (host);
- pthread_mutex_unlock (&host->lock);
-
ERROR ("write_riemann plugin: Sending to Riemann at %s:%s failed: %s",
(host->node != NULL) ? host->node : RIEMANN_HOST,
(host->service != NULL) ? host->service : RIEMANN_PORT,
return -1;
}
- pthread_mutex_unlock (&host->lock);
sfree (buffer);
return 0;
-}
+} /* }}} int riemann_send_msg */
+
+static int riemann_recv_ack(struct riemann_host *host) /* {{{ */
+{
+ int status = 0;
+ Msg *msg = NULL;
+ uint32_t header;
+
+ status = (int) sread (host->s, &header, 4);
+
+ if (status != 0)
+ return -1;
+
+ size_t size = ntohl(header);
+
+ // Buffer on the stack since acknowledges are typically small.
+ u_char buffer[size];
+ memset (buffer, 0, size);
+
+ status = (int) sread (host->s, buffer, size);
+
+ if (status != 0)
+ return status;
+
+ msg = msg__unpack (NULL, size, buffer);
+
+ if (msg == NULL)
+ return -1;
+
+ if (!msg->ok)
+ {
+ ERROR ("write_riemann plugin: Sending to Riemann at %s:%s acknowledgement message reported error: %s",
+ (host->node != NULL) ? host->node : RIEMANN_HOST,
+ (host->service != NULL) ? host->service : RIEMANN_PORT,
+ msg->error);
+
+ msg__free_unpacked(msg, NULL);
+ return -1;
+ }
+
+ msg__free_unpacked (msg, NULL);
+ return 0;
+} /* }}} int riemann_recv_ack */
+
+/**
+ * Function to send messages (Msg) to riemann.
+ *
+ * Acquires the host lock, disconnects on errors.
+ */
+static int riemann_send(struct riemann_host *host, Msg const *msg) /* {{{ */
+{
+ int status = 0;
+ pthread_mutex_lock (&host->lock);
+
+ status = riemann_send_msg(host, msg);
+ if (status != 0) {
+ riemann_disconnect (host);
+ pthread_mutex_unlock (&host->lock);
+ return status;
+ }
+
+ /*
+ * For TCP we need to receive message acknowledgemenent.
+ */
+ if (host->use_tcp)
+ {
+ status = riemann_recv_ack(host);
+
+ if (status != 0)
+ {
+ riemann_disconnect (host);
+ pthread_mutex_unlock (&host->lock);
+ return status;
+ }
+ }
+
+ pthread_mutex_unlock (&host->lock);
+ return 0;
+} /* }}} int riemann_send */
static int riemann_event_add_tag (Event *event, char const *tag) /* {{{ */
{
riemann_event_add_attribute (event, "type_instance",
n->type_instance);
+ for (i = 0; i < riemann_attrs_num; i += 2)
+ riemann_event_add_attribute(event,
+ riemann_attrs[i],
+ riemann_attrs[i +1]);
+
for (i = 0; i < riemann_tags_num; i++)
riemann_event_add_tag (event, riemann_tags[i]);
n->type, n->type_instance);
event->service = strdup (&service_buffer[1]);
- /* Pull in values from threshold */
+ if (n->message[0] != 0)
+ riemann_event_add_attribute (event, "description", n->message);
+
+ /* Pull in values from threshold and add extra attributes */
for (meta = n->meta; meta != NULL; meta = meta->next)
{
- if (strcasecmp ("CurrentValue", meta->name) != 0)
+ if (strcasecmp ("CurrentValue", meta->name) == 0 && meta->type == NM_TYPE_DOUBLE)
+ {
+ event->metric_d = meta->nm_value.nm_double;
+ event->has_metric_d = 1;
continue;
+ }
- event->metric_d = meta->nm_value.nm_double;
- event->has_metric_d = 1;
- break;
+ if (meta->type == NM_TYPE_STRING) {
+ riemann_event_add_attribute (event, meta->name, meta->nm_value.nm_string);
+ continue;
+ }
}
DEBUG ("write_riemann plugin: Successfully created protobuf for notification: "
riemann_event_add_attribute (event, "ds_index", ds_index);
}
+ for (i = 0; i < riemann_attrs_num; i += 2)
+ riemann_event_add_attribute(event,
+ riemann_attrs[i],
+ riemann_attrs[i +1]);
+
for (i = 0; i < riemann_tags_num; i++)
riemann_event_add_tag (event, riemann_tags[i]);
return (msg);
} /* }}} Msg *riemann_value_list_to_protobuf */
-static int
-riemann_notification(const notification_t *n, user_data_t *ud)
+static int riemann_notification(const notification_t *n, user_data_t *ud) /* {{{ */
{
int status;
struct riemann_host *host = ud->data;
return (status);
} /* }}} int riemann_notification */
-static int
-riemann_write(const data_set_t *ds,
+static int riemann_write(const data_set_t *ds, /* {{{ */
const value_list_t *vl,
user_data_t *ud)
{
riemann_msg_protobuf_free (msg);
return status;
-}
+} /* }}} int riemann_write */
-static void
-riemann_free(void *p)
+static void riemann_free(void *p) /* {{{ */
{
struct riemann_host *host = p;
sfree(host->service);
pthread_mutex_destroy (&host->lock);
sfree(host);
-}
+} /* }}} void riemann_free */
-static int
-riemann_config_node(oconfig_item_t *ci)
+static int riemann_config_node(oconfig_item_t *ci) /* {{{ */
{
struct riemann_host *host = NULL;
int status = 0;
pthread_mutex_unlock (&host->lock);
return status;
-}
+} /* }}} int riemann_config_node */
-static int
-riemann_config(oconfig_item_t *ci)
+static int riemann_config(oconfig_item_t *ci) /* {{{ */
{
int i;
oconfig_item_t *child;
if (strcasecmp("Node", child->key) == 0) {
riemann_config_node (child);
+ } else if (strcasecmp(child->key, "attribute") == 0) {
+ char *key = NULL;
+ char *val = NULL;
+
+ if (child->values_num != 2) {
+ WARNING("riemann attributes need both a key and a value.");
+ return (-1);
+ }
+ if (child->values[0].type != OCONFIG_TYPE_STRING ||
+ child->values[1].type != OCONFIG_TYPE_STRING) {
+ WARNING("riemann attribute needs string arguments.");
+ return (-1);
+ }
+ if ((key = strdup(child->values[0].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute key.");
+ return (-1);
+ }
+ if ((val = strdup(child->values[1].value.string)) == NULL) {
+ WARNING("cannot allocate memory for attribute value.");
+ return (-1);
+ }
+ strarray_add(&riemann_attrs, &riemann_attrs_num, key);
+ strarray_add(&riemann_attrs, &riemann_attrs_num, val);
+ DEBUG("write_riemann: got attr: %s => %s", key, val);
+ sfree(key);
+ sfree(val);
} else if (strcasecmp(child->key, "tag") == 0) {
char *tmp = NULL;
status = cf_util_get_string(child, &tmp);
}
}
return (0);
-}
+} /* }}} int riemann_config */
-void
-module_register(void)
+void module_register(void)
{
plugin_register_complex_config ("write_riemann", riemann_config);
}