collectd_CPPFLAGS = $(AM_CPPFLAGS) $(LTDLINCL)
collectd_CFLAGS = $(AM_CFLAGS)
collectd_LDFLAGS = -export-dynamic
- collectd_LDADD =
+ collectd_LDADD = -lm
collectd_DEPENDENCIES =
# Link to these libraries..
endif
if BUILD_AIX
collectd_LDFLAGS += -Wl,-bexpall,-brtllib
- collectd_LDADD += -lm
endif
# The daemon needs to call sg_init, so we need to link it against libstatgrab,
pkglib_LTLIBRARIES += amqp.la
amqp_la_SOURCES = amqp.c \
utils_cmd_putval.c utils_cmd_putval.h \
+ utils_format_graphite.c utils_format_graphite.h \
utils_format_json.c utils_format_json.h
amqp_la_LDFLAGS = -module -avoid-version $(BUILD_WITH_LIBRABBITMQ_LDFLAGS)
amqp_la_CPPFLAGS = $(AM_CPPFLAGS) $(BUILD_WITH_LIBRABBITMQ_CPPFLAGS)
if BUILD_PLUGIN_WRITE_GRAPHITE
pkglib_LTLIBRARIES += write_graphite.la
write_graphite_la_SOURCES = write_graphite.c \
- utils_format_json.c utils_format_json.h
+ utils_format_graphite.c utils_format_graphite.h \
+ utils_format_json.c utils_format_json.h
write_graphite_la_LDFLAGS = -module -avoid-version
collectd_LDADD += "-dlopen" write_graphite.la
collectd_DEPENDENCIES += write_graphite.la
fi
pinba.pb-c.c pinba.pb-c.h: pinba.proto
- protoc-c --c_out $(builddir) pinba.proto
+ protoc-c --c_out . pinba.proto
install-exec-hook:
$(mkinstalldirs) $(DESTDIR)$(sysconfdir)
#include "plugin.h"
#include "utils_cmd_putval.h"
#include "utils_format_json.h"
+#include "utils_format_graphite.h"
#include <pthread.h>
#define CAMQP_DM_VOLATILE 1
#define CAMQP_DM_PERSISTENT 2
-#define CAMQP_FORMAT_COMMAND 1
-#define CAMQP_FORMAT_JSON 2
+#define CAMQP_FORMAT_COMMAND 1
+#define CAMQP_FORMAT_JSON 2
+#define CAMQP_FORMAT_GRAPHITE 3
#define CAMQP_CHANNEL 1
uint8_t delivery_mode;
_Bool store_rates;
int format;
+ /* publish & graphite format only */
+ char *prefix;
+ char *postfix;
+ char escape_char;
/* subscribe only */
char *exchange_type;
sfree (conf->exchange_type);
sfree (conf->queue);
sfree (conf->routing_key);
+ sfree (conf->prefix);
+ sfree (conf->postfix);
+
sfree (conf);
} /* }}} void camqp_config_free */
camqp_config_free (conf);
pthread_exit (NULL);
+ return (NULL);
} /* }}} void *camqp_subscribe_thread */
static int camqp_subscribe_init (camqp_config_t *conf) /* {{{ */
props.content_type = amqp_cstring_bytes("text/collectd");
else if (conf->format == CAMQP_FORMAT_JSON)
props.content_type = amqp_cstring_bytes("application/json");
+ else if (conf->format == CAMQP_FORMAT_GRAPHITE)
+ props.content_type = amqp_cstring_bytes("text/graphite");
else
assert (23 == 42);
props.delivery_mode = conf->delivery_mode;
format_json_value_list (buffer, &bfill, &bfree, ds, vl, conf->store_rates);
format_json_finalize (buffer, &bfill, &bfree);
}
+ else if (conf->format == CAMQP_FORMAT_GRAPHITE)
+ {
+ status = format_graphite (buffer, sizeof (buffer), ds, vl,
+ conf->prefix, conf->postfix, conf->escape_char);
+ if (status != 0)
+ {
+ ERROR ("amqp plugin: format_graphite failed with status %i.",
+ status);
+ return (status);
+ }
+ }
else
{
ERROR ("amqp plugin: Invalid format (%i).", conf->format);
conf->format = CAMQP_FORMAT_COMMAND;
else if (strcasecmp ("JSON", string) == 0)
conf->format = CAMQP_FORMAT_JSON;
+ else if (strcasecmp ("Graphite", string) == 0)
+ conf->format = CAMQP_FORMAT_GRAPHITE;
else
{
WARNING ("amqp plugin: Invalid format string: %s",
/* publish only */
conf->delivery_mode = CAMQP_DM_VOLATILE;
conf->store_rates = 0;
+ /* publish & graphite only */
+ conf->prefix = NULL;
+ conf->postfix = NULL;
+ conf->escape_char = '_';
/* subscribe only */
conf->exchange_type = NULL;
conf->queue = NULL;
status = cf_util_get_boolean (child, &conf->store_rates);
else if ((strcasecmp ("Format", child->key) == 0) && publish)
status = camqp_config_set_format (child, conf);
+ else if ((strcasecmp ("GraphitePrefix", child->key) == 0) && publish)
+ status = cf_util_get_string (child, &conf->prefix);
+ else if ((strcasecmp ("GraphitePostfix", child->key) == 0) && publish)
+ status = cf_util_get_string (child, &conf->postfix);
+ else if ((strcasecmp ("GraphiteEscapeChar", child->key) == 0) && publish)
+ {
+ char *tmp_buff = NULL;
+ status = cf_util_get_string (child, &tmp_buff);
+ if (strlen (tmp_buff) > 1)
+ WARNING ("amqp plugin: The option \"GraphiteEscapeChar\" handles "
+ "only one character. Others will be ignored.");
+ conf->escape_char = tmp_buff[0];
+ sfree (tmp_buff);
+ }
else
WARNING ("amqp plugin: Ignoring unknown "
"configuration option \"%s\".", child->key);
behavior.
The syntax of this config file is similar to the config file of the famous
- B<Apache Webserver>. Each line contains either a key-value-pair or a
- section-start or -end. Empty lines and everything after the hash-symbol `#' is
- ignored. Values are either string, enclosed in double-quotes,
- (floating-point-)numbers or a boolean expression, i.E<nbsp>e. either B<true> or
- B<false>. String containing of only alphanumeric characters and underscores do
- not need to be quoted. Lines may be wrapped by using `\' as the last character
- before the newline. This allows long lines to be split into multiple lines.
- Quoted strings may be wrapped as well. However, those are treated special in
- that whitespace at the beginning of the following lines will be ignored, which
- allows for nicely indenting the wrapped lines.
-
- The configuration is read and processed in order, i.E<nbsp>e. from top to
- bottom. So the plugins are loaded in the order listed in this config file. It
- is a good idea to load any logging plugins first in order to catch messages
- from plugins during configuration. Also, the C<LoadPlugin> option B<must> occur
- B<before> the C<E<lt>Plugin ...E<gt>> block.
+ I<Apache> webserver. Each line contains either an option (a key and a list of
+ one or more values) or a section-start or -end. Empty lines and everything
+ after a non-quoted hash-symbol (C<#>) is ignored. I<Keys> are unquoted
+ strings, consisting only of alphanumeric characters and the underscore (C<_>)
+ character. Keys are handled case insensitive by I<collectd> itself and all
+ plugins included with it. I<Values> can either be an I<unquoted string>, a
+ I<quoted string> (enclosed in double-quotes) a I<number> or a I<boolean>
+ expression. I<Unquoted strings> consist of only alphanumeric characters and
+ underscores (C<_>) and do not need to be quoted. I<Quoted strings> are
+ enclosed in double quotes (C<">). You can use the backslash character (C<\>)
+ to include double quotes as part of the string. I<Numbers> can be specified in
+ decimal and floating point format (using a dot C<.> as decimal separator),
+ hexadecimal when using the C<0x> prefix and octal with a leading zero (C<0>).
+ I<Boolean> values are either B<true> or B<false>.
+
+ Lines may be wrapped by using C<\> as the last character before the newline.
+ This allows long lines to be split into multiple lines. Quoted strings may be
+ wrapped as well. However, those are treated special in that whitespace at the
+ beginning of the following lines will be ignored, which allows for nicely
+ indenting the wrapped lines.
+
+ The configuration is read and processed in order, i.e. from top to bottom. So
+ the plugins are loaded in the order listed in this config file. It is a good
+ idea to load any logging plugins first in order to catch messages from plugins
+ during configuration. Also, the C<LoadPlugin> option B<must> occur B<before>
+ the appropriate C<E<lt>Plugin ...E<gt>> block.
=head1 GLOBAL OPTIONS
# Persistent false
# Format "command"
# StoreRates false
+ # GraphitePrefix "collectd."
+ # GraphiteEscapeChar "_"
</Publish>
# Receive values from an AMQP broker
an easy and straight forward exchange format. The C<Content-Type> header field
will be set to C<application/json>.
+If set to B<Graphite>, values are encoded in the I<Graphite> format, which is
+"<metric> <value> <timestamp>\n". The C<Content-Type> header field will be set to
+C<text/graphite>.
+
A subscribing client I<should> use the C<Content-Type> header field to
determine how to decode the values. Currently, the I<AMQP plugin> itself can
only decode the B<Command> format.
Please note that currently this option is only used if the B<Format> option has
been set to B<JSON>.
+=item B<GraphitePrefix> (Publish and B<Format>=I<Graphite> only)
+
+A prefix can be added in the metric name when outputting in the I<Graphite> format.
+It's added before the I<Host> name.
+Metric name will be "<prefix><host><postfix><plugin><type><name>"
+
+=item B<GraphitePostfix> (Publish and B<Format>=I<Graphite> only)
+
+A postfix can be added in the metric name when outputting in the I<Graphite> format.
+It's added after the I<Host> name.
+Metric name will be "<prefix><host><postfix><plugin><type><name>"
+
+=item B<GraphiteEscapeChar> (Publish and B<Format>=I<Graphite> only)
+
+Specify a character to replace dots (.) in the host part of the metric name.
+In I<Graphite> metric name, dots are used as separators between different
+metric parts (host, plugin, type).
+Default is "_" (I<Underscore>).
+
=back
=head2 Plugin C<apache>
about cache utilization, memory and bandwidth used.
L<http://www.danga.com/memcached/>
+ <Plugin "memcached">
+ <Instance "name">
+ Host "memcache.example.com"
+ Port 11211
+ </Instance>
+ </Plugin>
+
+The plugin configuration consists of one or more B<Instance> blocks which
+specify one I<memcached> connection each. Within the B<Instance> blocks, the
+following options are allowed:
+
=over 4
=item B<Host> I<Hostname>
TCP-Port to connect to. Defaults to B<11211>.
+=item B<Socket> I<Path>
+
+Connect to I<memcached> using the UNIX domain socket at I<Path>. If this
+setting is given, the B<Host> and B<Port> settings are ignored.
+
=back
=head2 Plugin C<modbus>
Defines the "database alias" or "service name" to connect to. Usually, these
names are defined in the file named C<$ORACLE_HOME/network/admin/tnsnames.ora>.
+=item B<Host> I<Host>
+
+Hostname to use when dispatching values for this database. Defaults to using
+the global hostname of the I<collectd> instance.
+
=item B<Username> I<Username>
Username used for authentication.
connections. Either a service name of a port number may be given. Please note
that numerical port numbers must be given as a string, too.
+=item B<Password> I<Password>
+
+Use I<Password> to authenticate when connecting to I<Redis>.
+
=item B<Timeout> I<Timeout in miliseconds>
The B<Timeout> option set the socket timeout for node response. Since the Redis
If set to B<true>, the plugin instance and type instance will be in their own
path component, for example C<host.cpu.0.cpu.idle>. If set to B<false> (the
default), the plugin and plugin instance (and likewise the type and type
- instance) are put into once component, for example C<host.cpu-0.cpu-idle>.
+ instance) are put into one component, for example C<host.cpu-0.cpu-idle>.
=item B<AlwaysAppendDS> B<false>|B<true>
struct o_database_s
{
char *name;
+ char *host;
char *connect_id;
char *username;
char *password;
* Functions
*/
static void o_report_error (const char *where, /* {{{ */
+ const char *db_name, const char *query_name,
const char *what, OCIError *eh)
{
char buffer[2048];
int status;
unsigned int record_number;
+ if (db_name == NULL)
+ db_name = "(none)";
+ if (query_name == NULL)
+ query_name = "(none)";
+
/* An operation may cause / return multiple errors. Loop until we have
* handled all errors available (with a fail-save limit of 16). */
for (record_number = 1; record_number <= 16; record_number++)
buffer[buffer_length] = 0;
}
- ERROR ("oracle plugin: %s: %s failed: %s", where, what, buffer);
+ ERROR ("oracle plugin: %s (db = %s, query = %s): %s failed: %s",
+ where, db_name, query_name, what, buffer);
}
else
{
- ERROR ("oracle plugin: %s: %s failed. Additionally, OCIErrorGet failed with status %i.",
- where, what, status);
+ ERROR ("oracle plugin: %s (db = %s, query = %s): %s failed. "
+ "Additionally, OCIErrorGet failed with status %i.",
+ where, db_name, query_name, what, status);
return;
}
}
* </Plugin>
*/
-static int o_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 ("oracle 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 ("oracle plugin: strdup failed.");
- return (-1);
- }
-
- if (*ret_string != NULL)
- free (*ret_string);
- *ret_string = string;
-
- return (0);
-} /* }}} int o_config_set_string */
-
static int o_config_add_database (oconfig_item_t *ci) /* {{{ */
{
o_database_t *db;
return (-1);
}
memset (db, 0, sizeof (*db));
+ db->name = NULL;
+ db->host = NULL;
+ db->connect_id = NULL;
+ db->username = NULL;
+ db->password = NULL;
- status = o_config_set_string (&db->name, ci);
+ status = cf_util_get_string (ci, &db->name);
if (status != 0)
{
sfree (db);
oconfig_item_t *child = ci->children + i;
if (strcasecmp ("ConnectID", child->key) == 0)
- status = o_config_set_string (&db->connect_id, child);
+ status = cf_util_get_string (child, &db->connect_id);
+ else if (strcasecmp ("Host", child->key) == 0)
+ status = cf_util_get_string (child, &db->host);
else if (strcasecmp ("Username", child->key) == 0)
- status = o_config_set_string (&db->username, child);
+ status = cf_util_get_string (child, &db->username);
else if (strcasecmp ("Password", child->key) == 0)
- status = o_config_set_string (&db->password, child);
+ status = cf_util_get_string (child, &db->password);
else if (strcasecmp ("Query", child->key) == 0)
status = udb_query_pick_from_list (child, queries, queries_num,
&db->queries, &db->queries_num);
OCI_HTYPE_STMT, /* user_data_size = */ 0, /* user_data = */ NULL);
if (status != OCI_SUCCESS)
{
- o_report_error ("o_read_database_query", "OCIHandleAlloc", oci_error);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIHandleAlloc", oci_error);
oci_statement = NULL;
return (-1);
}
/* mode = */ OCI_DEFAULT);
if (status != OCI_SUCCESS)
{
- o_report_error ("o_read_database_query", "OCIStmtPrepare", oci_error);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIStmtPrepare", oci_error);
OCIHandleFree (oci_statement, OCI_HTYPE_STMT);
oci_statement = NULL;
return (-1);
/* mode = */ OCI_DEFAULT);
if (status != OCI_SUCCESS)
{
- DEBUG ("oracle plugin: o_read_database_query: status = %i (%#x)", status, status);
- o_report_error ("o_read_database_query", "OCIStmtExecute", oci_error);
- ERROR ("oracle plugin: o_read_database_query: "
- "Failing statement was: %s", udb_query_get_statement (q));
+ o_report_error ("o_read_database_query", db->name, udb_query_get_name (q),
+ "OCIStmtExecute", oci_error);
return (-1);
} /* }}} */
OCI_ATTR_PARAM_COUNT, oci_error);
if (status != OCI_SUCCESS)
{
- o_report_error ("o_read_database_query", "OCIAttrGet", oci_error);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIAttrGet", oci_error);
return (-1);
} /* }}} */
if (status != OCI_SUCCESS)
{
/* This is probably alright */
- DEBUG ("oracle plugin: o_read_database_query: status = %#x (= %i);", status, status);
- o_report_error ("o_read_database_query", "OCIParamGet", oci_error);
+ DEBUG ("oracle plugin: o_read_database_query: status = %#x (= %i);",
+ status, status);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIParamGet", oci_error);
status = OCI_SUCCESS;
break;
}
if (status != OCI_SUCCESS)
{
OCIDescriptorFree (oci_param, OCI_DTYPE_PARAM);
- o_report_error ("o_read_database_query", "OCIAttrGet (OCI_ATTR_NAME)",
- oci_error);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIAttrGet (OCI_ATTR_NAME)", oci_error);
continue;
}
NULL, NULL, NULL, OCI_DEFAULT);
if (status != OCI_SUCCESS)
{
- o_report_error ("o_read_database_query", "OCIDefineByPos", oci_error);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIDefineByPos", oci_error);
continue;
}
} /* for (j = 1; j <= param_counter; j++) */
/* }}} End of the ``define'' stuff. */
- status = udb_query_prepare_result (q, prep_area, hostname_g,
+ status = udb_query_prepare_result (q, prep_area,
+ (db->host != NULL) ? db->host : hostname_g,
/* plugin = */ "oracle", db->name, column_names, column_num,
/* interval = */ 0);
if (status != 0)
}
else if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
{
- o_report_error ("o_read_database_query", "OCIStmtFetch2", oci_error);
+ o_report_error ("o_read_database_query", db->name,
+ udb_query_get_name (q), "OCIStmtFetch2", oci_error);
break;
}
OCI_ATTR_SERVER, oci_error);
if (status != OCI_SUCCESS)
{
- o_report_error ("o_read_database", "OCIAttrGet", oci_error);
+ o_report_error ("o_read_database", db->name, NULL, "OCIAttrGet",
+ oci_error);
return (-1);
}
OCI_ATTR_SERVER_STATUS, oci_error);
if (status != OCI_SUCCESS)
{
- o_report_error ("o_read_database", "OCIAttrGet", oci_error);
+ o_report_error ("o_read_database", db->name, NULL, "OCIAttrGet",
+ oci_error);
return (-1);
}
}
(OraText *) db->connect_id, (ub4) strlen (db->connect_id));
if ((status != OCI_SUCCESS) && (status != OCI_SUCCESS_WITH_INFO))
{
- o_report_error ("o_read_database", "OCILogon", oci_error);
+ char errfunc[256];
+
+ ssnprintf (errfunc, sizeof (errfunc), "OCILogon(\"%s\")", db->connect_id);
+
+ o_report_error ("o_read_database", db->name, NULL, errfunc, oci_error);
DEBUG ("oracle plugin: OCILogon (%s): db->oci_service_context = %p;",
db->connect_id, db->oci_service_context);
db->oci_service_context = NULL;
#include <pthread.h>
#include <credis.h>
+ #ifndef HOST_NAME_MAX
+ # define HOST_NAME_MAX _POSIX_HOST_NAME_MAX
+ #endif
+
#define REDIS_DEF_HOST "localhost"
#define REDIS_DEF_PORT 6379
#define REDIS_DEF_TIMEOUT 2000
{
char name[MAX_REDIS_NODE_NAME];
char host[HOST_NAME_MAX];
+ char passwd[HOST_NAME_MAX];
int port;
int timeout;
}
else if (strcasecmp ("Timeout", option->key) == 0)
status = cf_util_get_int (option, &rn.timeout);
+ else if (strcasecmp ("Password", option->key) == 0)
+ status = cf_util_get_string_buffer (option, rn.passwd, sizeof (rn.passwd));
else
WARNING ("redis plugin: Option `%s' not allowed inside a `Node' "
"block. I'll ignore this option.", option->key);
continue;
}
+ if (strlen (rn->passwd) > 0)
+ {
+ DEBUG ("redis plugin: authenticanting node `%s' passwd(%s).", rn->name, rn->passwd);
+ status = credis_auth(rh, rn->passwd);
+ if (status != 0)
+ {
+ WARNING ("redis plugin: unable to authenticate on node `%s'.", rn->name);
+ credis_close (rh);
+ continue;
+ }
+ }
+
memset (&info, 0, sizeof (info));
status = credis_info (rh, &info);
if (status != 0)