if test "x$TMPDIR" != "x"
then
AC_MSG_RESULT([found in $TMPDIR])
- JAVA_LDFLAGS="$JAVA_LDFLAGS -L$TMPDIR"
+ JAVA_LDFLAGS="$JAVA_LDFLAGS -L$TMPDIR -Wl,-rpath -Wl,$TMPDIR"
else
AC_MSG_RESULT([not found])
fi
AM_CONDITIONAL(BUILD_WITH_LIBXMMS, test "x$with_libxmms" = "xyes")
# }}}
+# --with-libyajl {{{
+with_libyajl_cppflags=""
+with_libyajl_ldflags=""
+AC_ARG_WITH(libyajl, [AS_HELP_STRING([--with-libyajl@<:@=PREFIX@:>@], [Path to libyajl.])],
+[
+ if test "x$withval" != "xno" && test "x$withval" != "xyes"
+ then
+ with_libyajl_cppflags="-I$withval/include"
+ with_libyajl_ldflags="-L$withval/lib"
+ with_libyajl="yes"
+ else
+ with_libyajl="$withval"
+ fi
+],
+[
+ with_libyajl="yes"
+])
+if test "x$with_libyajl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+
+ AC_CHECK_HEADERS(yajl/yajl_parse.h, [with_libyajl="yes"], [with_libyajl="no (yajl/yajl_parse.h not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+ SAVE_CPPFLAGS="$CPPFLAGS"
+ SAVE_LDFLAGS="$LDFLAGS"
+ CPPFLAGS="$CPPFLAGS $with_libyajl_cppflags"
+ LDFLAGS="$LDFLAGS $with_libyajl_ldflags"
+
+ AC_CHECK_LIB(yajl, yajl_alloc, [with_libyajl="yes"], [with_libyajl="no (Symbol 'yajl_alloc' not found)"])
+
+ CPPFLAGS="$SAVE_CPPFLAGS"
+ LDFLAGS="$SAVE_LDFLAGS"
+fi
+if test "x$with_libyajl" = "xyes"
+then
+ BUILD_WITH_LIBYAJL_CPPFLAGS="$with_libyajl_cppflags"
+ BUILD_WITH_LIBYAJL_LDFLAGS="$with_libyajl_ldflags"
+ BUILD_WITH_LIBYAJL_LIBS="-lyajl"
+ AC_SUBST(BUILD_WITH_LIBYAJL_CPPFLAGS)
+ AC_SUBST(BUILD_WITH_LIBYAJL_LDFLAGS)
+ AC_SUBST(BUILD_WITH_LIBYAJL_LIBS)
+ AC_DEFINE(HAVE_LIBYAJL, 1, [Define if libyajl is present and usable.])
+fi
+AM_CONDITIONAL(BUILD_WITH_LIBYAJL, test "x$with_libyajl" = "xyes")
+# }}}
+
# pkg-config --exists 'libxml-2.0'; pkg-config --exists libvirt {{{
with_libxml2="no (pkg-config isn't available)"
with_libxml2_cflags=""
plugin_battery="no"
plugin_bind="no"
plugin_conntrack="no"
+plugin_couchdb="no"
plugin_cpu="no"
plugin_cpufreq="no"
plugin_df="no"
plugin_ipmi="yes"
fi
+if test "x$with_libcurl" = "xyes" && test "x$with_libyajl" = "xyes"
+then
+ plugin_couchdb="yes"
+fi
+
if test "x$have_processor_info" = "xyes"
then
plugin_cpu="yes"
AC_PLUGIN([battery], [$plugin_battery], [Battery statistics])
AC_PLUGIN([bind], [$plugin_bind], [ISC Bind nameserver statistics])
AC_PLUGIN([conntrack], [$plugin_conntrack], [nf_conntrack statistics])
+AC_PLUGIN([couchdb], [$plugin_couchdb], [CouchDB statistics])
AC_PLUGIN([cpufreq], [$plugin_cpufreq], [CPU frequency statistics])
AC_PLUGIN([cpu], [$plugin_cpu], [CPU usage statistics])
AC_PLUGIN([csv], [yes], [CSV output plugin])
AC_PLUGIN([notify_email], [$with_libesmtp], [Email notifier])
AC_PLUGIN([ntpd], [yes], [NTPd statistics])
AC_PLUGIN([nut], [$with_libupsclient], [Network UPS tools statistics])
+AC_PLUGIN([olsrd], [yes], [olsrd statistics])
AC_PLUGIN([onewire], [$with_libowcapi], [OneWire sensor statistics])
AC_PLUGIN([openvpn], [yes], [OpenVPN client statistics])
AC_PLUGIN([oracle], [$with_oracle], [Oracle plugin])
libcurl . . . . . . . $with_libcurl
libdbi . . . . . . . $with_libdbi
libesmtp . . . . . . $with_libesmtp
+ libganglia . . . . . $with_libganglia
libgcrypt . . . . . . $with_libgcrypt
libiokit . . . . . . $with_libiokit
libiptc . . . . . . . $with_libiptc
libvirt . . . . . . . $with_libvirt
libxml2 . . . . . . . $with_libxml2
libxmms . . . . . . . $with_libxmms
+ libyajl . . . . . . . $with_libyajl
oracle . . . . . . . $with_oracle
Features:
battery . . . . . . . $enable_battery
bind . . . . . . . . $enable_bind
conntrack . . . . . . $enable_conntrack
+ couchdb . . . . . . . $enable_couchdb
cpu . . . . . . . . . $enable_cpu
cpufreq . . . . . . . $enable_cpufreq
csv . . . . . . . . . $enable_csv
notify_email . . . . $enable_notify_email
ntpd . . . . . . . . $enable_ntpd
nut . . . . . . . . . $enable_nut
+ olsrd . . . . . . . . $enable_olsrd
onewire . . . . . . . $enable_onewire
openvpn . . . . . . . $enable_openvpn
oracle . . . . . . . $enable_oracle
collectd_DEPENDENCIES += conntrack.la
endif
+if BUILD_PLUGIN_COUCHDB
+pkglib_LTLIBRARIES += couchdb.la
+couchdb_la_SOURCES = couchdb.c
+couchdb_la_CFLAGS = $(AM_CFLAGS)
+couchdb_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBYAJL_LDFLAGS)
+couchdb_la_CPPFLAGS = $(BUILD_WITH_LIBYAJL_CPPFLAGS)
+couchdb_la_LIBADD = $(BUILD_WITH_LIBYAJL_LIBS)
+if BUILD_WITH_LIBCURL
+couchdb_la_CFLAGS += $(BUILD_WITH_LIBCURL_CFLAGS)
+couchdb_la_LIBADD += $(BUILD_WITH_LIBCURL_LIBS)
+endif
+collectd_LDADD += "-dlopen" couchdb.la
+collectd_DEPENDENCIES += couchdb.la
+endif
+
if BUILD_PLUGIN_CPU
pkglib_LTLIBRARIES += cpu.la
cpu_la_SOURCES = cpu.c
collectd_DEPENDENCIES += nut.la
endif
+if BUILD_PLUGIN_OLSRD
+pkglib_LTLIBRARIES += olsrd.la
+olsrd_la_SOURCES = olsrd.c
+olsrd_la_LDFLAGS = -module -avoid-version
+olsrd_la_LIBADD =
+if BUILD_WITH_LIBSOCKET
+olsrd_la_LIBADD += -lsocket
+endif
+collectd_LDADD += "-dlopen" olsrd.la
+collectd_DEPENDENCIES += olsrd.la
+endif
+
if BUILD_PLUGIN_ONEWIRE
pkglib_LTLIBRARIES += onewire.la
onewire_la_SOURCES = onewire.c
ping_la_SOURCES = ping.c
ping_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBOPING_CPPFLAGS)
ping_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBOPING_LDFLAGS)
- ping_la_LIBADD = -loping
+ ping_la_LIBADD = -loping -lm
collectd_LDADD += "-dlopen" ping.la
collectd_DEPENDENCIES += ping.la
endif
pkglib_LTLIBRARIES += sensors.la
sensors_la_SOURCES = sensors.c
sensors_la_CFLAGS = $(AM_CFLAGS) $(BUILD_WITH_LIBSENSORS_CFLAGS)
- sensors_la_LDFLAGS = -module -avoid-version
- sensors_la_LIBADD = $(BUILD_WITH_LIBSENSORS_LDFLAGS)
+ sensors_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBSENSORS_LDFLAGS)
+ sensors_la_LIBADD = -lsensors
collectd_LDADD += "-dlopen" sensors.la
collectd_DEPENDENCIES += sensors.la
endif
#@BUILD_PLUGIN_BATTERY_TRUE@LoadPlugin battery
#@BUILD_PLUGIN_BIND_TRUE@LoadPlugin bind
#@BUILD_PLUGIN_CONNTRACK_TRUE@LoadPlugin conntrack
+#@BUILD_PLUGIN_COUCHDB_TRUE@LoadPlugin couchdb
@BUILD_PLUGIN_CPU_TRUE@@BUILD_PLUGIN_CPU_TRUE@LoadPlugin cpu
#@BUILD_PLUGIN_CPUFREQ_TRUE@LoadPlugin cpufreq
@LOAD_PLUGIN_CSV@LoadPlugin csv
#@BUILD_PLUGIN_NOTIFY_EMAIL_TRUE@LoadPlugin notify_email
#@BUILD_PLUGIN_NTPD_TRUE@LoadPlugin ntpd
#@BUILD_PLUGIN_NUT_TRUE@LoadPlugin nut
+#@BUILD_PLUGIN_OLSRD_TRUE@LoadPlugin olsrd
#@BUILD_PLUGIN_ONEWIRE_TRUE@LoadPlugin onewire
#@BUILD_PLUGIN_OPENVPN_TRUE@LoadPlugin openvpn
#@BUILD_PLUGIN_ORACLE_TRUE@LoadPlugin oracle
# </View>
#</Plugin>
+#<Plugin couchdb>
+## See: http://wiki.apache.org/couchdb/Runtime_Statistics
+# <URL "http://localhost:5984/_stats">
+# Instance "httpd"
+# <Key "httpd/requests/count">
+# Type "http_requests"
+# </Key>
+#
+# <Key "httpd_request_methods/*/count">
+# Type "http_request_methods"
+# </Key>
+#
+# <Key "httpd_status_codes/*/count">
+# Type "http_response_codes"
+# </Key>
+# </URL>
+## Database status metrics:
+# <URL "http://localhost:5984/_all_dbs">
+# Instance "dbs"
+# <Key "*/doc_count">
+# Type "gauge"
+# </Key>
+# <Key "*/doc_del_count">
+# Type "counter"
+# </Key>
+# <Key "*/disk_size">
+# Type "bytes"
+# </Key>
+# </URL>
+#</Plugin>
+
#<Plugin csv>
# DataDir "@prefix@/var/lib/@PACKAGE_NAME@/csv"
# StoreRates false
# IgnoreSelected false
#</Plugin>
+ #<Plugin ipmi>
+ # Sensor "some_sensor"
+ # Sensor "another_one"
+ # IgnoreSelected false
+ # NotifySensorAdd false
+ # NotifySensorRemove true
+ # NotifySensorNotPresent false
+ #</Plugin>
+
#<Plugin iptables>
# Chain table chain
#</Plugin>
# UPS "upsname@hostname:port"
#</Plugin>
+#<Plugin olsrd>
+# Host "127.0.0.1"
+# Port "2006"
+# CollectLinks "Summary"
+# CollectRoutes "Summary"
+# CollectTopology "Summary"
+#</Plugin>
+
#<Plugin onewire>
# Device "-s localhost:4304"
# Sensor "F10FCA000800"
=back
+=head2 Plugin C<couchdb>
+
+The couchdb plugin uses B<libcurl> (L<http://curl.haxx.se/>) and B<libyajl>
+(L<http://www.lloydforge.org/projects/yajl/>) to collect values from CouchDB
+documents (stored JSON notation).
+
+The following example will collect several values from the built-in `_stats'
+runtime statistics module (L<http://wiki.apache.org/couchdb/Runtime_Statistics>).
+
+ <Plugin couchdb>
+ <URL "http://localhost:5984/_stats">
+ Instance "httpd"
+ <Key "httpd/requests/count">
+ Type "http_requests"
+ </Key>
+
+ <Key "httpd_request_methods/*/count">
+ Type "http_request_methods"
+ </Key>
+
+ <Key "httpd_status_codes/*/count">
+ Type "http_response_codes"
+ </Key>
+ </URL>
+ </Plugin>
+
+The following example will collect the status values from each database:
+
+ <URL "http://localhost:5984/_all_dbs">
+ Instance "dbs"
+ <Key "*/doc_count">
+ Type "gauge"
+ </Key>
+ <Key "*/doc_del_count">
+ Type "counter"
+ </Key>
+ <Key "*/disk_size">
+ Type "bytes"
+ </Key>
+ </URL>
+
+In the B<Plugin> block, there may be one or more B<URL> blocks, each defining
+a URL to be fetched via HTTP (libcurl) and one or more B<Key> blocks.
+The B<Key> string argument must be in a path format, of which is used to collect
+a value from a JSON map object. If a B<Key> path element is that of a I<*> wildcard,
+the values for all keys will be collectd.
+
+The following options are valid within B<URL> blocks:
+
+=over 4
+
+=item B<Instance> I<Instance>
+
+Sets the plugin instance to I<Instance>.
+
+=item B<User> I<Name>
+
+Username to use if authorization is required to read the page.
+
+=item B<Password> I<Password>
+
+Password to use if authorization is required to read the page.
+
+=item B<VerifyPeer> B<true>|B<false>
+
+Enable or disable peer SSL certificate verification. See
+L<http://curl.haxx.se/docs/sslcerts.html> for details. Enabled by default.
+
+=item B<VerifyHost> B<true>|B<false>
+
+Enable or disable peer host name verification. If enabled, the plugin checks if
+the C<Common Name> or a C<Subject Alternate Name> field of the SSL certificate
+matches the host name provided by the B<URL> option. If this identity check
+fails, the connection is aborted. Obviously, only works when connecting to a
+SSL enabled server. Enabled by default.
+
+=item B<CACert> I<file>
+
+File that holds one or more SSL certificates. If you want to use HTTPS you will
+possibly need this option. What CA certificates come bundled with C<libcurl>
+and are checked by default depends on the distribution you use.
+
+=back
+
+The following options are valid within B<Key> blocks:
+
+=over 4
+
+=item B<Type> I<Type>
+
+Sets the type used to dispatch the values to the daemon. Detailed information
+about types and their configuration can be found in L<types.db(5)>. This
+option is mandatory.
+
+=item B<Instance> I<Instance>
+
+Type-instance to use. Defaults to the current map key or current string array element value.
+
+=back
+
=head2 Plugin C<cpufreq>
This plugin doesn't have any options. It reads
Ignore packets that originate from this address.
+=item B<SelectNumericQueryTypes> B<true>|B<false>
+
+Enabled by default, collects unknown (and thus presented as numeric only) query types.
+
=back
=head2 Plugin C<email>
=back
+=head2 Plugin C<olsrd>
+
+The I<olsrd> plugin connects to the TCP port opened by the I<txtinfo> plugin of
+the Optimized Link State Routing daemon and reads information about the current
+state of the meshed network.
+
+The following configuration options are understood:
+
+=over 4
+
+=item B<Host> I<Host>
+
+Connect to I<Host>. Defaults to B<"localhost">.
+
+=item B<Port> I<Port>
+
+Specifies the port to connect to. This must be a string, even if you give the
+port as a number rather than a service name. Defaults to B<"2006">.
+
+=item B<CollectLinks> B<No>|B<Summary>|B<Detail>
+
+Specifies what information to collect about links, i.E<nbsp>e. direct
+connections of the daemon queried. If set to B<No>, no information is
+collected. If set to B<Summary>, the number of links and the average of all
+I<link quality> (LQ) and I<neighbor link quality> (NLQ) values is calculated.
+If set to B<Detail> LQ and NLQ are collected per link.
+
+Defaults to B<Detail>.
+
+=item B<CollectRoutes> B<No>|B<Summary>|B<Detail>
+
+Specifies what information to collect about routes of the daemon queried. If
+set to B<No>, no information is collected. If set to B<Summary>, the number of
+routes and the average I<metric> and I<ETX> is calculated. If set to B<Detail>
+metric and ETX are collected per route.
+
+Defaults to B<Summary>.
+
+=item B<CollectTopology> B<No>|B<Summary>|B<Detail>
+
+Specifies what information to collect about the global topology. If set to
+B<No>, no information is collected. If set to B<Summary>, the number of links
+in the entire topology and the average I<link quality> (LQ) is calculated.
+If set to B<Detail> LQ and NLQ are collected for each link in the entire topology.
+
+Defaults to B<Summary>.
+
+=back
+
=head2 Plugin C<onewire>
B<EXPERIMENTAL!> See notes below.
The B<Query> block defines one database query which may later be used by a
database definition. It accepts a single mandatory argument which specifies
the name of the query. The names of all queries have to be unique (see the
- B<MinPGVersion> and B<MaxPGVersion> options below for an exception to this
+ B<MinVersion> and B<MaxVersion> options below for an exception to this
rule). The following configuration options are available to define the query:
In each B<Query> block, there is one or more B<Result> blocks. B<Result>
should be used. The first option specifies the data found in the first column,
the second option that of the second column, and so on.
- =item B<MinPGVersion> I<version>
+ =item B<MinVersion> I<version>
- =item B<MaxPGVersion> I<version>
+ =item B<MaxVersion> I<version>
Specify the minimum or maximum version of PostgreSQL that this query should be
used with. Some statistics might only be available with certain versions of
and patch-level versions, each represented as two-decimal-digit numbers. For
example, version 8.2.3 will become 80203.
+ =item B<MinPGVersion> I<version>
+
+ =item B<MaxPGVersion> I<version>
+
+ These are deprecated synonyms for B<MinVersion> and B<MaxVersion>
+ respectively. They will be removed in version 5 of collectd.
+
=back
The following predefined queries are available (the definitions can be found
return (0);
} /* int parse_identifier */
-int parse_value (const char *value, value_t *ret_value, const data_source_t ds)
+int parse_value (const char *value, value_t *ret_value, int ds_type)
{
- char *endptr = NULL;
-
- if (DS_TYPE_COUNTER == ds.type)
- ret_value->counter = (counter_t)strtoll (value, &endptr, 0);
- else if (DS_TYPE_GAUGE == ds.type)
- ret_value->gauge = (gauge_t)strtod (value, &endptr);
- else {
- ERROR ("parse_value: Invalid data source \"%s\" "
- "(type = %i).", ds.name, ds.type);
- return -1;
- }
-
- if (value == endptr) {
- ERROR ("parse_value: Failed to parse string as number: %s.", value);
- return -1;
- }
- else if ((NULL != endptr) && ('\0' != *endptr))
- WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
- endptr);
- return 0;
+ char *endptr = NULL;
+
+ switch (ds_type)
+ {
+ case DS_TYPE_COUNTER:
+ ret_value->counter = (counter_t) strtoull (value, &endptr, 0);
+ break;
+
+ case DS_TYPE_GAUGE:
+ ret_value->gauge = (gauge_t) strtod (value, &endptr);
+ break;
+
+ case DS_TYPE_DERIVE:
+ ret_value->counter = (derive_t) strtoll (value, &endptr, 0);
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ ret_value->counter = (absolute_t) strtoull (value, &endptr, 0);
+ break;
+
+ default:
+ ERROR ("parse_value: Invalid data source type: %i.", ds_type);
+ return -1;
+ }
+
+ if (value == endptr) {
+ ERROR ("parse_value: Failed to parse string as number: %s.", value);
+ return -1;
+ }
+ else if ((NULL != endptr) && ('\0' != *endptr))
+ WARNING ("parse_value: Ignoring trailing garbage after number: %s.",
+ endptr);
+ return 0;
} /* int parse_value */
int parse_values (char *buffer, value_list_t *vl, const data_set_t *ds)
dummy = NULL;
if (i >= vl->values_len)
+ {
+ /* Make sure i is invalid. */
+ i = vl->values_len + 1;
break;
+ }
if (i == -1)
{
{
if ((strcmp ("U", ptr) == 0) && (ds->ds[i].type == DS_TYPE_GAUGE))
vl->values[i].gauge = NAN;
- else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i]))
+ else if (0 != parse_value (ptr, &vl->values[i], ds->ds[i].type))
return -1;
}
{
"Interface",
"IgnoreSource",
- NULL
+ "SelectNumericQueryTypes"
};
-static int config_keys_num = 2;
+static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
+static int select_numeric_qtype = 1;
#define PCAP_SNAPLEN 1460
static char *pcap_device = NULL;
if (value != NULL)
ignore_list_add_name (value);
}
+ else if (strcasecmp (key, "SelectNumericQueryTypes") == 0)
+ {
+ if ((value != NULL) && IS_FALSE (value))
+ select_numeric_qtype = 0;
+ else
+ select_numeric_qtype = 1;
+ }
else
{
return (-1);
if (dns->qr == 0)
{
/* This is a query */
+ int skip = 0;
+ if (!select_numeric_qtype)
+ {
+ const char *str = qtype_str(dns->qtype);
+ if ((str == NULL) || (str[0] == '#'))
+ skip = 1;
+ }
+
pthread_mutex_lock (&traffic_mutex);
tr_queries += dns->length;
pthread_mutex_unlock (&traffic_mutex);
- pthread_mutex_lock (&qtype_mutex);
- counter_list_add (&qtype_list, dns->qtype, 1);
- pthread_mutex_unlock (&qtype_mutex);
+ if (skip == 0)
+ {
+ pthread_mutex_lock (&qtype_mutex);
+ counter_list_add (&qtype_list, dns->qtype, 1);
+ pthread_mutex_unlock (&qtype_mutex);
+ }
}
else
{
}
/* Passing `pcap_device == NULL' is okay and the same as passign "any" */
- DEBUG ("Creating PCAP object..");
+ DEBUG ("dns plugin: Creating PCAP object..");
pcap_obj = pcap_open_live ((pcap_device != NULL) ? pcap_device : "any",
PCAP_SNAPLEN,
0 /* Not promiscuous */,
se->vl.values[ds_index].counter += value.counter;
else if (ds_type == DS_TYPE_GAUGE)
se->vl.values[ds_index].gauge = value.gauge;
+ else if (ds_type == DS_TYPE_DERIVE)
+ se->vl.values[ds_index].DERIVE += value.derive;
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ se->vl.values[ds_index].ABSOLUTE = value.absolute;
+
se->flags |= (0x01 << ds_index);
/* Check if all values have been set and submit if so. */
value_t value_counter;
value_t value_gauge;
+ value_t value_derive;
/* Fill in `host', `name', `value_counter', and `value_gauge' according to
* the value type, or return with an error. */
name = msg_uint.metric_id.name;
value_counter.counter = (counter_t) msg_uint.ui;
value_gauge.gauge = (gauge_t) msg_uint.ui;
+ value_derive.derive = (derive_t) msg_uint.ui;
break;
}
endptr = NULL;
errno = 0;
- value_counter.counter = (counter_t) strtoll (msg_string.str,
+ value_counter.counter = (counter_t) strtoull (msg_string.str,
&endptr, /* base = */ 0);
if ((endptr == msg_string.str) || (errno != 0))
value_counter.counter = -1;
if ((endptr == msg_string.str) || (errno != 0))
value_gauge.gauge = NAN;
+ endptr = NULL;
+ errno = 0;
+ value_derive.derive = (derive_t) strtoll (msg_string.str,
+ &endptr, /* base = */ 0);
+ if ((endptr == msg_string.str) || (errno != 0))
+ value_derive.derive = 0;
+
break;
}
name = msg_float.metric_id.name;
value_counter.counter = (counter_t) msg_float.f;
value_gauge.gauge = (gauge_t) msg_float.f;
+ value_derive.derive = (derive_t) msg_float.f;
break;
}
name = msg_double.metric_id.name;
value_counter.counter = (counter_t) msg_double.d;
value_gauge.gauge = (gauge_t) msg_double.d;
+ value_derive.derive = (derive_t) msg_double.d;
break;
}
default:
map = metric_lookup (name);
if (map != NULL)
+ {
+ value_t val_copy;
+
+ val_copy = value_counter;
+ if (map->ds_type == DS_TYPE_GAUGE)
+ val_copy = value_gauge;
+ else if (map->ds_type == DS_TYPE_DERIVE)
+ val_copy = value_derive;
+
return (staging_entry_update (host, name,
map->type, map->type_instance,
map->ds_index, map->ds_type,
- (map->ds_type == DS_TYPE_COUNTER) ? value_counter : value_gauge));
+ val_copy));
+ }
DEBUG ("gmond plugin: Cannot find a translation for %s.", name);
return (-1);
jmethodID m_long_constructor;
/* Look up the java.lang.Long class */
- c_long = (*jvm_env)->FindClass (jvm_env, "java.lang.Long");
+ c_long = (*jvm_env)->FindClass (jvm_env, "java/lang/Long");
if (c_long == NULL)
{
ERROR ("java plugin: ctoj_jlong_to_number: Looking up the "
jmethodID m_double_constructor;
/* Look up the java.lang.Long class */
- c_double = (*jvm_env)->FindClass (jvm_env, "java.lang.Double");
+ c_double = (*jvm_env)->FindClass (jvm_env, "java/lang/Double");
if (c_double == NULL)
{
ERROR ("java plugin: ctoj_jdouble_to_number: Looking up the "
return (ctoj_jlong_to_number (jvm_env, (jlong) value.counter));
else if (ds_type == DS_TYPE_GAUGE)
return (ctoj_jdouble_to_number (jvm_env, (jdouble) value.gauge));
+ if (ds_type == DS_TYPE_DERIVE)
+ return (ctoj_jlong_to_number (jvm_env, (jlong) value.derive));
+ if (ds_type == DS_TYPE_ABSOLUTE)
+ return (ctoj_jlong_to_number (jvm_env, (jlong) value.absolute));
else
return (NULL);
} /* }}} jobject ctoj_value_to_number */
/* Search for the `DataSet (String type)' constructor. */
m_constructor = (*jvm_env)->GetMethodID (jvm_env,
- c_dataset, "<init>", "(Ljava.lang.String;)V");
+ c_dataset, "<init>", "(Ljava/lang/String;)V");
if (m_constructor == NULL)
{
ERROR ("java plugin: ctoj_data_set: Looking up the "
class_ptr = (*jvm_env)->GetObjectClass (jvm_env, object_ptr);
- if (ds_type == DS_TYPE_COUNTER)
+ if (ds_type == DS_TYPE_GAUGE)
{
- jlong tmp_long;
+ jdouble tmp_double;
- status = jtoc_long (jvm_env, &tmp_long,
- class_ptr, object_ptr, "longValue");
+ status = jtoc_double (jvm_env, &tmp_double,
+ class_ptr, object_ptr, "doubleValue");
if (status != 0)
{
ERROR ("java plugin: jtoc_value: "
- "jtoc_long failed.");
+ "jtoc_double failed.");
return (-1);
}
- (*ret_value).counter = (counter_t) tmp_long;
+ (*ret_value).gauge = (gauge_t) tmp_double;
}
else
{
- jdouble tmp_double;
+ jlong tmp_long;
- status = jtoc_double (jvm_env, &tmp_double,
- class_ptr, object_ptr, "doubleValue");
+ status = jtoc_long (jvm_env, &tmp_long,
+ class_ptr, object_ptr, "longValue");
if (status != 0)
{
ERROR ("java plugin: jtoc_value: "
- "jtoc_double failed.");
+ "jtoc_long failed.");
return (-1);
}
- (*ret_value).gauge = (gauge_t) tmp_double;
+
+ if (ds_type == DS_TYPE_DERIVE)
+ (*ret_value).derive = (derive_t) tmp_long;
+ else if (ds_type == DS_TYPE_ABSOLUTE)
+ (*ret_value).absolute = (absolute_t) tmp_long;
+ else
+ (*ret_value).counter = (counter_t) tmp_long;
}
return (0);
class->class = NULL;
class->object = NULL;
+ { /* Replace all dots ('.') with slashes ('/'). Dots are usually used
+ thorough the Java community, but (Sun's) `FindClass' and friends need
+ slashes. */
+ size_t i;
+ for (i = 0; class->name[i] != 0; i++)
+ if (class->name[i] == '.')
+ class->name[i] = '/';
+ }
+
DEBUG ("java plugin: Loading class %s", class->name);
class->class = (*jvm_env)->FindClass (jvm_env, class->name);
/* Even though Posix requires "strerror_r" to return an "int",
* some systems (e.g. the GNU libc) return a "char *" _and_
* ignore the second argument ... -tokkee */
- char *sstrerror (int errnum, char *buf, size_t buflen)
+ static char *sstrerror (int errnum, char *buf, size_t buflen)
{
buf[0] = 0;
else
SSTRCATF (command, ":%g", vl->values[i].gauge);
}
+ else if (vl->values_types[i] == LCC_TYPE_DERIVE)
+ SSTRCATF (command, ":%"PRIu64, vl->values[i].derive);
+ else if (vl->values_types[i] == LCC_TYPE_ABSOLUTE)
+ SSTRCATF (command, ":%"PRIu64, vl->values[i].absolute);
+
} /* for (i = 0; i < vl->values_len; i++) */
status = lcc_sendreceive (c, command, &res);
char name[6 * DATA_MAX_NAME_LEN];
int values_num;
gauge_t *values_gauge;
- counter_t *values_counter;
+ value_t *values_raw;
/* Time contained in the package
* (for calculating rates) */
time_t last_time;
memset (ce, '\0', sizeof (cache_entry_t));
ce->values_num = values_num;
- ce->values_gauge = (gauge_t *) calloc (values_num, sizeof (gauge_t));
- ce->values_counter = (counter_t *) calloc (values_num, sizeof (counter_t));
- if ((ce->values_gauge == NULL) || (ce->values_counter == NULL))
+ ce->values_gauge = calloc (values_num, sizeof (*ce->values_gauge));
+ ce->values_raw = calloc (values_num, sizeof (*ce->values_raw));
+ if ((ce->values_gauge == NULL) || (ce->values_raw == NULL))
{
sfree (ce->values_gauge);
- sfree (ce->values_counter);
+ sfree (ce->values_raw);
sfree (ce);
ERROR ("utils_cache: cache_alloc: calloc failed.");
return (NULL);
return;
sfree (ce->values_gauge);
- sfree (ce->values_counter);
+ sfree (ce->values_raw);
sfree (ce);
} /* void cache_free */
return (0);
} /* int uc_send_notification */
+static void uc_check_range (const data_set_t *ds, cache_entry_t *ce)
+{
+ int i;
+
+ for (i = 0; i < ds->ds_num; i++)
+ {
+ if (isnan (ce->values_gauge[i]))
+ continue;
+ else if (ce->values_gauge[i] < ds->ds[i].min)
+ ce->values_gauge[i] = NAN;
+ else if (ce->values_gauge[i] > ds->ds[i].max)
+ ce->values_gauge[i] = NAN;
+ }
+} /* void uc_check_range */
+
static int uc_insert (const data_set_t *ds, const value_list_t *vl,
const char *key)
{
for (i = 0; i < ds->ds_num; i++)
{
- if (ds->ds[i].type == DS_TYPE_COUNTER)
+ switch (ds->ds[i].type)
{
- ce->values_gauge[i] = NAN;
- ce->values_counter[i] = vl->values[i].counter;
- }
- else /* if (ds->ds[i].type == DS_TYPE_GAUGE) */
- {
- ce->values_gauge[i] = vl->values[i].gauge;
- }
+ case DS_TYPE_COUNTER:
+ ce->values_gauge[i] = NAN;
+ ce->values_raw[i].counter = vl->values[i].counter;
+ break;
+
+ case DS_TYPE_GAUGE:
+ ce->values_gauge[i] = vl->values[i].gauge;
+ ce->values_raw[i].gauge = vl->values[i].gauge;
+ break;
+
+ case DS_TYPE_DERIVE:
+ ce->values_gauge[i] = NAN;
+ ce->values_raw[i].derive = vl->values[i].derive;
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ ce->values_gauge[i] = NAN;
+ if (vl->interval > 0)
+ ce->values_gauge[i] = ((double) vl->values[i].absolute)
+ / ((double) vl->interval);
+ ce->values_raw[i].absolute = vl->values[i].absolute;
+ break;
+
+ default:
+ /* This shouldn't happen. */
+ ERROR ("uc_insert: Don't know how to handle data source type %i.",
+ ds->ds[i].type);
+ return (-1);
+ } /* switch (ds->ds[i].type) */
} /* for (i) */
+ /* Prune invalid gauge data */
+ uc_check_range (ds, ce);
+
ce->last_time = vl->time;
ce->last_update = time (NULL);
ce->interval = vl->interval;
(keys_len + 1) * sizeof (char *));
if (tmp == NULL)
{
- ERROR ("uc_purge: realloc failed.");
+ ERROR ("uc_check_timeout: realloc failed.");
c_avl_iterator_destroy (iter);
+ sfree (keys);
pthread_mutex_unlock (&cache_lock);
return (-1);
}
}
} /* while (c_avl_iterator_next) */
+ ce = NULL;
+
for (i = 0; i < keys_len; i++)
{
int status;
{
ERROR ("uc_check_timeout: ut_check_interesting failed.");
sfree (keys[i]);
+ continue;
}
else if (status == 0) /* ``service'' is uninteresting */
{
- ce = NULL;
DEBUG ("uc_check_timeout: %s is missing but ``uninteresting''",
keys[i]);
status = c_avl_remove (cache_tree, keys[i],
sfree (key);
cache_free (ce);
}
- else if (status == 2) /* persist */
+
+ /* If we get here, the value is ``interesting''. Query the record from the
+ * cache and update the state field. */
+ if (c_avl_get (cache_tree, keys[i], (void *) &ce) != 0)
+ {
+ ERROR ("uc_check_timeout: cannot get data for %s from cache", keys[i]);
+ /* Do not free `keys[i]' so a notification is sent further down. */
+ continue;
+ }
+ assert (ce != NULL);
+
+ if (status == 2) /* persist */
{
DEBUG ("uc_check_timeout: %s is missing, sending notification.",
keys[i]);
ce->state = STATE_MISSING;
+ /* Do not free `keys[i]' so a notification is sent further down. */
}
else if (status == 1) /* do not persist */
{
DEBUG ("uc_check_timeout: %s is missing but "
"notification has already been sent.",
keys[i]);
+ /* Set `keys[i]' to NULL to no notification is sent. */
sfree (keys[i]);
}
else /* (ce->state != STATE_MISSING) */
DEBUG ("uc_check_timeout: %s is missing, sending one notification.",
keys[i]);
ce->state = STATE_MISSING;
+ /* Do not free `keys[i]' so a notification is sent further down. */
}
}
else
WARNING ("uc_check_timeout: ut_check_interesting (%s) returned "
"invalid status %i.",
keys[i], status);
+ sfree (keys[i]);
}
} /* for (keys[i]) */
for (i = 0; i < ds->ds_num; i++)
{
- if (ds->ds[i].type == DS_TYPE_COUNTER)
+ switch (ds->ds[i].type)
{
- counter_t diff;
-
- /* check if the counter has wrapped around */
- if (vl->values[i].counter < ce->values_counter[i])
- {
- if (ce->values_counter[i] <= 4294967295U)
- diff = (4294967295U - ce->values_counter[i])
- + vl->values[i].counter;
- else
- diff = (18446744073709551615ULL - ce->values_counter[i])
- + vl->values[i].counter;
- }
- else /* counter has NOT wrapped around */
- {
- diff = vl->values[i].counter - ce->values_counter[i];
- }
+ case DS_TYPE_COUNTER:
+ {
+ counter_t diff;
+
+ /* check if the counter has wrapped around */
+ if (vl->values[i].counter < ce->values_raw[i].counter)
+ {
+ if (ce->values_raw[i].counter <= 4294967295U)
+ diff = (4294967295U - ce->values_raw[i].counter)
+ + vl->values[i].counter;
+ else
+ diff = (18446744073709551615ULL - ce->values_raw[i].counter)
+ + vl->values[i].counter;
+ }
+ else /* counter has NOT wrapped around */
+ {
+ diff = vl->values[i].counter - ce->values_raw[i].counter;
+ }
+
+ ce->values_gauge[i] = ((double) diff)
+ / ((double) (vl->time - ce->last_time));
+ ce->values_raw[i].counter = vl->values[i].counter;
+ }
+ break;
+
+ case DS_TYPE_GAUGE:
+ ce->values_raw[i].gauge = vl->values[i].gauge;
+ ce->values_gauge[i] = vl->values[i].gauge;
+ break;
+
+ case DS_TYPE_DERIVE:
+ {
+ derive_t diff;
+
+ diff = vl->values[i].derive - ce->values_raw[i].derive;
+
+ ce->values_gauge[i] = ((double) diff)
+ / ((double) (vl->time - ce->last_time));
+ ce->values_raw[i].derive = vl->values[i].derive;
+ }
+ break;
+
+ case DS_TYPE_ABSOLUTE:
+ ce->values_gauge[i] = ((double) vl->values[i].absolute)
+ / ((double) (vl->time - ce->last_time));
+ ce->values_raw[i].absolute = vl->values[i].absolute;
+ break;
+
+ default:
+ /* This shouldn't happen. */
+ pthread_mutex_unlock (&cache_lock);
+ ERROR ("uc_update: Don't know how to handle data source type %i.",
+ ds->ds[i].type);
+ return (-1);
+ } /* switch (ds->ds[i].type) */
- ce->values_gauge[i] = ((double) diff)
- / ((double) (vl->time - ce->last_time));
- ce->values_counter[i] = vl->values[i].counter;
- }
- else /* if (ds->ds[i].type == DS_TYPE_GAUGE) */
- {
- ce->values_gauge[i] = vl->values[i].gauge;
- }
DEBUG ("uc_update: %s: ds[%i] = %lf", name, i, ce->values_gauge[i]);
} /* for (i) */
+ /* Prune invalid gauge data */
+ uc_check_range (ds, ce);
+
ce->last_time = vl->time;
ce->last_update = time (NULL);
ce->interval = vl->interval;