if (publish)
{
char cbname[128];
- user_data_t ud = { conf, camqp_config_free };
-
ssnprintf (cbname, sizeof (cbname), "amqp/%s", conf->name);
- status = plugin_register_write (cbname, camqp_write, &ud);
+ status = plugin_register_write (cbname, camqp_write,
+ &(user_data_t) {
+ .data = conf,
+ .free_func = camqp_config_free,
+ });
if (status != 0)
{
camqp_config_free (conf);
if (status == 0)
{
- user_data_t ud = {
- .data = st,
- .free_func = apache_free
- };
-
char callback_name[3*DATA_MAX_NAME_LEN];
ssnprintf (callback_name, sizeof (callback_name),
/* name = */ callback_name,
/* callback = */ apache_read_host,
/* interval = */ 0,
- /* user_data = */ &ud);
+ &(user_data_t) {
+ .data = st,
+ .free_func = apache_free,
+ });
+
}
if (status != 0)
# StoreRates true
# AlwaysAppendDS false
# EscapeCharacter "_"
+# DropDuplicateFields false
# </Node>
#</Plugin>
identifier. If set to B<false> (the default), this is only done when there is
more than one DS.
+=item B<DropDuplicateFields> B<false>|B<true>
+
+If set to B<true>, detect and remove duplicate components in Graphite metric
+names. For example, the metric name C<host.load.load.shortterm> will
+be shortened to C<host.load.shortterm>.
+
=back
=head2 Plugin C<write_log>
=item B<MetaData> I<String> I<String>
-Set the appropriate field to the given string. The strings for plugin instance
-and type instance may be empty, the strings for host and plugin may not be
-empty. It's currently not possible to set the type of a value this way.
+Set the appropriate field to the given string. The strings for plugin instance,
+type instance, and meta data may be empty, the strings for host and plugin may
+not be empty. It's currently not possible to set the type of a value this way.
+
+The following placeholders will be replaced by an appropriate value:
+
+=over 4
+
+=item B<%{host}>
+
+=item B<%{plugin}>
+
+=item B<%{plugin_instance}>
+
+=item B<%{type}>
+
+=item B<%{type_instance}>
+
+These placeholders are replaced by the identifier field of the same name.
+
+=item B<%{meta:>I<name>B<}>
+
+These placeholders are replaced by the meta data value with the given name.
+
+=back
+
+Please note that these placeholders are B<case sensitive>!
+
+=item B<DeleteMetaData> I<String>
+
+Delete the named meta data field.
=back
cb_name = ssnprintf_alloc ("curl_json-%s-%s",
db->instance, db->url ? db->url : db->sock);
- user_data_t ud = {
- .data = db,
- .free_func = cj_free
- };
-
plugin_register_complex_read (/* group = */ NULL, cb_name, cj_read,
/* interval = */ db->interval,
- &ud);
+ &(user_data_t) {
+ .data = db,
+ .free_func = cj_free,
+ });
sfree (cb_name);
}
else
cb_name = ssnprintf_alloc ("curl_xml-%s-%s", db->instance, db->url);
- user_data_t ud = {
- .data = db,
- .free_func = cx_free
- };
-
plugin_register_complex_read (/* group = */ "curl_xml", cb_name, cx_read,
- /* interval = */ 0, &ud);
+ /* interval = */ 0,
+ &(user_data_t) {
+ .data = db,
+ .free_func = cx_free,
+ });
sfree (cb_name);
}
else
#include "collectd.h"
+#include "common.h"
#include "plugin.h"
#include "meta_data.h"
+#define MD_MAX_NONSTRING_CHARS 128
+
/*
* Data types
*/
return (0);
} /* }}} int meta_data_get_boolean */
+int meta_data_as_string (meta_data_t *md, /* {{{ */
+ const char *key, char **value)
+{
+ meta_entry_t *e;
+ char *actual;
+ char buffer[MD_MAX_NONSTRING_CHARS]; /* For non-string types. */
+ char *temp;
+ int type;
+
+ if ((md == NULL) || (key == NULL) || (value == NULL))
+ return (-EINVAL);
+
+ pthread_mutex_lock (&md->lock);
+
+ e = md_entry_lookup (md, key);
+ if (e == NULL)
+ {
+ pthread_mutex_unlock (&md->lock);
+ return (-ENOENT);
+ }
+
+ type = e->type;
+
+ switch (type)
+ {
+ case MD_TYPE_STRING:
+ actual = e->value.mv_string;
+ break;
+ case MD_TYPE_SIGNED_INT:
+ ssnprintf (buffer, sizeof (buffer), "%"PRIi64, e->value.mv_signed_int);
+ actual = buffer;
+ break;
+ case MD_TYPE_UNSIGNED_INT:
+ ssnprintf (buffer, sizeof (buffer), "%"PRIu64, e->value.mv_unsigned_int);
+ actual = buffer;
+ break;
+ case MD_TYPE_DOUBLE:
+ ssnprintf (buffer, sizeof (buffer), GAUGE_FORMAT, e->value.mv_double);
+ actual = buffer;
+ break;
+ case MD_TYPE_BOOLEAN:
+ actual = e->value.mv_boolean ? "true" : "false";
+ break;
+ default:
+ pthread_mutex_unlock (&md->lock);
+ ERROR ("meta_data_as_string: unknown type %d for key `%s'", type, key);
+ return (-ENOENT);
+ }
+
+ pthread_mutex_unlock (&md->lock);
+
+ temp = md_strdup (actual);
+ if (temp == NULL)
+ {
+ pthread_mutex_unlock (&md->lock);
+ ERROR ("meta_data_as_string: md_strdup failed for key `%s'.", key);
+ return (-ENOMEM);
+ }
+
+ *value = temp;
+
+ return (0);
+} /* }}} int meta_data_as_string */
+
/* vim: set sw=2 sts=2 et fdm=marker : */
const char *key,
_Bool *value);
+/* Returns the value as a string, regardless of the type. */
+int meta_data_as_string (meta_data_t *md,
+ const char *key,
+ char **value);
+
#endif /* META_DATA_H */
/* vim: set sw=2 sts=2 et : */
}
else
{
- char *name = NULL;
-
databases = temp;
databases[databases_num] = db;
databases_num++;
- name = ssnprintf_alloc("dbi:%s", db->name);
-
- user_data_t ud = {
- .data = db
- };
-
+ char *name = ssnprintf_alloc("dbi:%s", db->name);
plugin_register_complex_read (/* group = */ NULL,
/* name = */ name ? name : db->name,
/* callback = */ cdbi_read_database,
/* interval = */ (db->interval > 0) ? db->interval : 0,
- /* user_data = */ &ud);
- free (name);
+ &(user_data_t) {
+ .data = db,
+ });
+ sfree (name);
}
}
DEBUG ("java plugin: Registering new read callback: %s", cbi->name);
- user_data_t ud = {
- .data = cbi,
- .free_func = cjni_callback_info_destroy
- };
-
plugin_register_complex_read (/* group = */ NULL, cbi->name, cjni_read,
- /* interval = */ 0, &ud);
+ /* interval = */ 0, &(user_data_t) {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy,
+ });
(*jvm_env)->DeleteLocalRef (jvm_env, o_read);
DEBUG ("java plugin: Registering new write callback: %s", cbi->name);
- user_data_t ud = {
- .data = cbi,
- .free_func = cjni_callback_info_destroy
- };
-
- plugin_register_write (cbi->name, cjni_write, &ud);
+ plugin_register_write (cbi->name, cjni_write, &(user_data_t) {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy,
+ });
(*jvm_env)->DeleteLocalRef (jvm_env, o_write);
DEBUG ("java plugin: Registering new flush callback: %s", cbi->name);
- user_data_t ud = {
- .data = cbi,
- .free_func = cjni_callback_info_destroy
- };
-
- plugin_register_flush (cbi->name, cjni_flush, &ud);
+ plugin_register_flush (cbi->name, cjni_flush, &(user_data_t) {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy,
+ });
(*jvm_env)->DeleteLocalRef (jvm_env, o_flush);
DEBUG ("java plugin: Registering new log callback: %s", cbi->name);
- user_data_t ud = {
- .data = cbi,
- .free_func = cjni_callback_info_destroy
- };
-
- plugin_register_log (cbi->name, cjni_log, &ud);
+ plugin_register_log (cbi->name, cjni_log, &(user_data_t) {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy,
+ });
(*jvm_env)->DeleteLocalRef (jvm_env, o_log);
DEBUG ("java plugin: Registering new notification callback: %s", cbi->name);
- user_data_t ud = {
- .data = cbi,
- .free_func = cjni_callback_info_destroy
- };
-
- plugin_register_notification (cbi->name, cjni_notification, &ud);
+ plugin_register_notification (cbi->name, cjni_notification, &(user_data_t) {
+ .data = cbi,
+ .free_func = cjni_callback_info_destroy,
+ });
(*jvm_env)->DeleteLocalRef (jvm_env, o_notification);
cb->lua_function_name = strdup(function_name);
pthread_mutex_init(&cb->lock, NULL);
- user_data_t ud = {
- .data = cb
- };
-
int status = plugin_register_complex_read(/* group = */ "lua",
/* name = */ function_name,
/* callback = */ clua_read,
/* interval = */ 0,
- /* user_data = */ &ud);
+ &(user_data_t) {
+ .data = cb,
+ });
if (status != 0)
return luaL_error(L, "%s", "plugin_register_complex_read failed");
cb->lua_function_name = strdup(function_name);
pthread_mutex_init(&cb->lock, NULL);
- user_data_t ud = {
- .data = cb
- };
-
int status = plugin_register_write(/* name = */ function_name,
/* callback = */ clua_write,
- /* user_data = */ &ud);
+ &(user_data_t) {
+ .data = cb,
+ });
if (status != 0)
return luaL_error(L, "%s", "plugin_register_write failed");
assert (st->name != NULL);
ssnprintf (callback_name, sizeof (callback_name), "memcached/%s", st->name);
- user_data_t ud = {
- .data = st,
- .free_func = memcached_free
- };
-
status = plugin_register_complex_read (/* group = */ "memcached",
/* name = */ callback_name,
/* callback = */ memcached_read,
/* interval = */ 0,
- /* user_data = */ &ud);
+ &(user_data_t) {
+ .data = st,
+ .free_func = memcached_free,
+ });
+
return (status);
} /* int memcached_add_read_callback */
if (status == 0)
{
- user_data_t ud;
char name[1024];
- ud.data = host;
- ud.free_func = host_free;
-
ssnprintf (name, sizeof (name), "modbus-%s", host->host);
plugin_register_complex_read (/* group = */ NULL, name,
/* callback = */ mb_read,
/* interval = */ host->interval,
- &ud);
+ &(user_data_t) {
+ .data = host,
+ .free_func = host_free,
+ });
}
else
{
}
ssnprintf (cb_name, sizeof (cb_name), "mqtt/%s", conf->name);
- user_data_t user_data = {
- .data = conf
- };
-
- plugin_register_write (cb_name, mqtt_write, &user_data);
+ plugin_register_write (cb_name, mqtt_write, &(user_data_t) {
+ .data = conf,
+ });
return (0);
} /* mqtt_config_publisher */
else
sstrncpy (cb_name, "mysql", sizeof (cb_name));
- user_data_t ud = {
- .data = db,
- .free_func = mysql_database_free
- };
-
plugin_register_complex_read (/* group = */ NULL, cb_name,
- mysql_read,
- /* interval = */ 0, &ud);
+ mysql_read, /* interval = */ 0, &(user_data_t) {
+ .data = db,
+ .free_func = mysql_database_free,
+ });
}
else
{
else
ssnprintf (cb_name, sizeof (cb_name), "netapp-%s", host->name);
- user_data_t ud = {
- .data = host,
- .free_func = (void (*) (void *)) free_host_config
- };
-
plugin_register_complex_read (/* group = */ NULL, cb_name,
/* callback = */ cna_read,
/* interval = */ host->interval,
- /* user data = */ &ud);
+ &(user_data_t) {
+ .data = host,
+ .free_func = (void *) free_host_config,
+ });
return (0);
} /* }}} int cna_register_host */
(st->host != NULL) ? st->host : hostname_g,
(st->name != NULL) ? st->name : "default");
- user_data_t ud = {
- .data = st
- };
-
status = plugin_register_complex_read (/* group = */ NULL,
/* name = */ callback_name,
/* callback = */ cldap_read_host,
/* interval = */ 0,
- /* user_data = */ &ud);
+ &(user_data_t) {
+ .data = st,
+ });
}
}
c->data = data;
c->next = NULL;
- user_data_t user_data = {
- .data = c,
- .free_func = cpy_destroy_user_data
- };
+ register_function(buf, handler, &(user_data_t) {
+ .data = c,
+ .free_func = cpy_destroy_user_data,
+ });
- register_function(buf, handler, &user_data);
++cpy_num_callbacks;
return cpy_string_to_unicode_or_bytes(buf);
}
c->data = data;
c->next = NULL;
- user_data_t user_data = {
- .data = c,
- .free_func = cpy_destroy_user_data
- };
-
plugin_register_complex_read(/* group = */ "python", buf,
- cpy_read_callback, DOUBLE_TO_CDTIME_T (interval), &user_data);
+ cpy_read_callback, DOUBLE_TO_CDTIME_T (interval),
+ &(user_data_t) {
+ .data = c,
+ .free_func = cpy_destroy_user_data,
+ });
++cpy_num_callbacks;
return cpy_string_to_unicode_or_bytes(buf);
}
{
cr_data_t *router_data;
char read_name[128];
- user_data_t user_data;
int status;
router_data = calloc (1, sizeof (*router_data));
}
ssnprintf (read_name, sizeof (read_name), "routeros/%s", router_data->node);
- user_data.data = router_data;
- user_data.free_func = (void *) cr_free_data;
if (status == 0)
status = plugin_register_complex_read (/* group = */ NULL, read_name,
- cr_read, /* interval = */ 0, &user_data);
+ cr_read, /* interval = */ 0, &(user_data_t) {
+ .data = router_data,
+ .free_func = (void *) cr_free_data,
+ });
if (status != 0)
cr_free_data (router_data);
ssnprintf (cb_name, sizeof (cb_name), "snmp-%s", hd->name);
- user_data_t ud = {
- .data = hd,
- .free_func = csnmp_host_definition_destroy
- };
-
status = plugin_register_complex_read (/* group = */ NULL, cb_name,
- csnmp_read_host, hd->interval, /* user_data = */ &ud);
+ csnmp_read_host, hd->interval, &(user_data_t) {
+ .data = hd,
+ .free_func = csnmp_host_definition_destroy,
+ });
if (status != 0)
{
ERROR ("snmp plugin: Registering complex read function failed.");
{
ssnprintf(str, sizeof(str), "tail-%zu", i);
- user_data_t ud = {
- .data = tail_match_list[i]
- };
-
- plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i], &ud);
+ plugin_register_complex_read (NULL, str, ctail_read, tail_match_list_intervals[i],
+ &(user_data_t) {
+ .data = tail_match_list[i],
+ });
}
return (0);
ssnprintf (cb_name, sizeof (cb_name), "tail_csv/%s", id->path);
- user_data_t ud = {
- .data = id,
- .free_func = tcsv_instance_definition_destroy
- };
-
- status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval, &ud);
-
+ status = plugin_register_complex_read(NULL, cb_name, tcsv_read, id->interval,
+ &(user_data_t) {
+ .data = id,
+ .free_func = tcsv_instance_definition_destroy,
+ });
if (status != 0){
ERROR("tail_csv plugin: Registering complex read function failed.");
tcsv_instance_definition_destroy(id);
#include "common.h"
#include "filter_chain.h"
+#include "meta_data.h"
+#include "utils_subst.h"
+
+struct ts_key_list_s
+{
+ char *key;
+ struct ts_key_list_s *next;
+};
+typedef struct ts_key_list_s ts_key_list_t;
+
+static void ts_key_list_free (ts_key_list_t *l) /* {{{ */
+{
+ if (l == NULL)
+ return;
+
+ sfree (l->key);
+
+ if (l->next != NULL)
+ ts_key_list_free (l->next);
+
+ sfree (l);
+} /* }}} void ts_name_list_free */
struct ts_data_s
{
/* char *type; */
char *type_instance;
meta_data_t *meta;
+ ts_key_list_t *meta_delete;
};
typedef struct ts_data_s ts_data_t;
|| (ci->values[1].type != OCONFIG_TYPE_STRING))
{
ERROR ("ts_util_get_key_and_string_wo_strdup: The %s option requires "
- "exactly two string argument.", ci->key);
+ "exactly two string arguments.", ci->key);
return (-1);
}
if (strlen (key) == 0)
{
- ERROR ("Target `set': The `%s' option does not accept empty string as first argument.",
- ci->key);
+ ERROR ("Target `set': The `%s' option does not accept empty string as "
+ "first argument.", ci->key);
return (-1);
}
if (!may_be_empty && (strlen (string) == 0))
{
- ERROR ("Target `set': The `%s' option does not accept empty string as second argument.",
- ci->key);
+ ERROR ("Target `set': The `%s' option does not accept empty string as "
+ "second argument.", ci->key);
return (-1);
}
if ((*dest) == NULL)
{
- // Create a new meta_data_t
+ /* Create a new meta_data_t */
if ((*dest = meta_data_create()) == NULL)
{
ERROR ("Target `set': failed to create a meta data for `%s'.", ci->key);
- return (-1);
+ return (-ENOMEM);
}
}
return (meta_data_add_string (*dest, key, string));
} /* }}} int ts_config_add_meta */
+static int ts_config_add_meta_delete (ts_key_list_t **dest, /* {{{ */
+ const oconfig_item_t *ci)
+{
+ ts_key_list_t *entry = NULL;
+
+ entry = calloc (1, sizeof (*entry));
+ if (entry == NULL)
+ {
+ ERROR ("ts_config_add_meta_delete: calloc failed.");
+ return (-ENOMEM);
+ }
+
+ if (cf_util_get_string (ci, &entry->key) != 0)
+ {
+ ts_key_list_free (entry);
+ return (-1); /* An error has already been reported. */
+ }
+
+ if (strlen (entry->key) == 0)
+ {
+ ERROR ("Target `set': The `%s' option does not accept empty string as "
+ "first argument.", ci->key);
+ ts_key_list_free (entry);
+ return (-1);
+ }
+
+ entry->next = *dest;
+ *dest = entry;
+
+ return (0);
+} /* }}} int ts_config_add_meta_delete */
+
+static void ts_subst (char *dest, size_t size, const char *string, /* {{{ */
+ const value_list_t *vl)
+{
+ char temp[DATA_MAX_NAME_LEN];
+
+ /* Initialize the field with the template. */
+ sstrncpy (dest, string, size);
+
+ if (strchr (dest, '%') == NULL)
+ return;
+
+#define REPLACE_FIELD(t, v) \
+ if (subst_string (temp, sizeof (temp), dest, t, v) != NULL) \
+ sstrncpy (dest, temp, size);
+ REPLACE_FIELD ("%{host}", vl->host);
+ REPLACE_FIELD ("%{plugin}", vl->plugin);
+ REPLACE_FIELD ("%{plugin_instance}", vl->plugin_instance);
+ REPLACE_FIELD ("%{type}", vl->type);
+ REPLACE_FIELD ("%{type_instance}", vl->type_instance);
+
+ if (vl->meta != NULL)
+ {
+ char **meta_toc;
+ int meta_entries = meta_data_toc (vl->meta, &meta_toc);
+ for (int i = 0; i < meta_entries; i++)
+ {
+ char meta_name[DATA_MAX_NAME_LEN];
+ char *value_str;
+ const char *key = meta_toc[i];
+
+ ssnprintf (meta_name, sizeof (meta_name), "%%{meta:%s}", key);
+ if (meta_data_as_string (vl->meta, key, &value_str) != 0)
+ continue;
+
+ REPLACE_FIELD (meta_name, value_str);
+ sfree (value_str);
+ }
+
+ strarray_free (meta_toc, (size_t) meta_entries);
+ }
+} /* }}} int ts_subst */
+
static int ts_destroy (void **user_data) /* {{{ */
{
ts_data_t *data;
/* free (data->type); */
free (data->type_instance);
meta_data_destroy(data->meta);
+ ts_key_list_free (data->meta_delete);
free (data);
return (0);
/* data->type = NULL; */
data->type_instance = NULL;
data->meta = NULL;
+ data->meta_delete = NULL;
status = 0;
for (int i = 0; i < ci->children_num; i++)
else if (strcasecmp ("MetaData", child->key) == 0)
status = ts_config_add_meta (&data->meta, child,
/* may be empty = */ 1);
+ else if (strcasecmp ("DeleteMetaData", child->key) == 0)
+ status = ts_config_add_meta_delete (&data->meta_delete, child);
else
{
ERROR ("Target `set': The `%s' configuration option is not understood "
&& (data->plugin_instance == NULL)
/* && (data->type == NULL) */
&& (data->type_instance == NULL)
- && (data->meta == NULL))
+ && (data->meta == NULL)
+ && (data->meta_delete == NULL))
{
ERROR ("Target `set': You need to set at least one of `Host', "
- "`Plugin', `PluginInstance', `TypeInstance', `MetaData'.");
+ "`Plugin', `PluginInstance', `TypeInstance', "
+ "`MetaData', or `DeleteMetaData'.");
status = -1;
}
+ if (data->meta != NULL)
+ {
+ /* If data->meta_delete is NULL, this loop is a no-op. */
+ for (ts_key_list_t *l=data->meta_delete; l != NULL; l = l->next)
+ {
+ if (meta_data_type (data->meta, l->key) != 0)
+ {
+ /* MetaData and DeleteMetaData for the same key. */
+ ERROR ("Target `set': Can only have one of `MetaData' or "
+ "`DeleteMetaData' for any given key.");
+ status = -1;
+ }
+ }
+ }
+
break;
}
notification_meta_t __attribute__((unused)) **meta, void **user_data)
{
ts_data_t *data;
+ value_list_t orig;
+ meta_data_t *new_meta = NULL;
if ((ds == NULL) || (vl == NULL) || (user_data == NULL))
return (-EINVAL);
return (-EINVAL);
}
+ orig = *vl;
+
if (data->meta != NULL)
{
- meta_data_clone_merge(&(vl->meta), data->meta);
+ char temp[DATA_MAX_NAME_LEN*2];
+ int meta_entries;
+ char **meta_toc;
+
+ if ((new_meta = meta_data_create()) == NULL)
+ {
+ ERROR ("Target `set': failed to create replacement metadata.");
+ return (-ENOMEM);
+ }
+
+ meta_entries = meta_data_toc (data->meta, &meta_toc);
+ for (int i = 0; i < meta_entries; i++)
+ {
+ const char *key = meta_toc[i];
+ char *string;
+ int status;
+
+ status = meta_data_get_string (data->meta, key, &string);
+ if (status)
+ {
+ ERROR ("Target `set': Unable to get replacement metadata value `%s'.",
+ key);
+ strarray_free (meta_toc, (size_t) meta_entries);
+ return (status);
+ }
+
+ ts_subst (temp, sizeof (temp), string, &orig);
+
+ DEBUG ("target_set: ts_invoke: setting metadata value for key `%s': "
+ "`%s'.", key, temp);
+
+ status = meta_data_add_string (new_meta, key, temp);
+
+ if (status)
+ {
+ ERROR ("Target `set': Unable to set metadata value `%s'.", key);
+ strarray_free (meta_toc, (size_t) meta_entries);
+ return (status);
+ }
+ }
+
+ strarray_free (meta_toc, (size_t) meta_entries);
+ }
+
+#define SUBST_FIELD(f) \
+ if (data->f != NULL) { \
+ ts_subst (vl->f, sizeof (vl->f), data->f, &orig); \
+ DEBUG ("target_set: ts_invoke: setting "#f": `%s'.", vl->f); \
+ }
+ SUBST_FIELD (host);
+ SUBST_FIELD (plugin);
+ SUBST_FIELD (plugin_instance);
+ /* SUBST_FIELD (type); */
+ SUBST_FIELD (type_instance);
+
+ /* Need to merge the metadata in now, because of the shallow copy. */
+ if (new_meta != NULL)
+ {
+ meta_data_clone_merge(&(vl->meta), new_meta);
+ meta_data_destroy(new_meta);
}
-#define SET_FIELD(f) if (data->f != NULL) { sstrncpy (vl->f, data->f, sizeof (vl->f)); }
- SET_FIELD (host);
- SET_FIELD (plugin);
- SET_FIELD (plugin_instance);
- /* SET_FIELD (type); */
- SET_FIELD (type_instance);
+ /* If data->meta_delete is NULL, this loop is a no-op. */
+ for (ts_key_list_t *l=data->meta_delete; l != NULL; l = l->next)
+ {
+ DEBUG ("target_set: ts_invoke: deleting metadata value for key `%s'.",
+ l->key);
+ meta_data_delete(vl->meta, l->key);
+ }
return (FC_TARGET_CONTINUE);
} /* }}} int ts_invoke */
sstrncpy (tmp_plugin, n_plugin, sizeof (tmp_plugin));
if (n_type_instance[0] != '\0')
- ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s",
- n_type,
- (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
- n_type_instance);
+ {
+ if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(n_plugin, n_type) == 0)
+ sstrncpy (tmp_type, n_type_instance, sizeof (tmp_type));
+ else
+ ssnprintf (tmp_type, sizeof (tmp_type), "%s%c%s",
+ n_type,
+ (flags & GRAPHITE_SEPARATE_INSTANCES) ? '.' : '-',
+ n_type_instance);
+ }
else
sstrncpy (tmp_type, n_type, sizeof (tmp_type));
/* Assert always_append_ds -> ds_name */
assert (!(flags & GRAPHITE_ALWAYS_APPEND_DS) || (ds_name != NULL));
if (ds_name != NULL)
- ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s",
- prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name);
+ {
+ if ((flags & GRAPHITE_DROP_DUPE_FIELDS) && strcmp(tmp_plugin, tmp_type) == 0)
+ ssnprintf (ret, ret_len, "%s%s%s.%s.%s",
+ prefix, n_host, postfix, tmp_plugin, ds_name);
+ else
+ ssnprintf (ret, ret_len, "%s%s%s.%s.%s.%s",
+ prefix, n_host, postfix, tmp_plugin, tmp_type, ds_name);
+ }
else
ssnprintf (ret, ret_len, "%s%s%s.%s.%s",
prefix, n_host, postfix, tmp_plugin, tmp_type);
#define GRAPHITE_STORE_RATES 0x01
#define GRAPHITE_SEPARATE_INSTANCES 0x02
#define GRAPHITE_ALWAYS_APPEND_DS 0x04
+#define GRAPHITE_DROP_DUPE_FIELDS 0x08
int format_graphite (char *buffer,
size_t buffer_size, const data_set_t *ds,
varnish_config_apply_default (conf);
- user_data_t ud = {
- .data = conf,
- .free_func = varnish_config_free
- };
-
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ "varnish/localhost",
/* callback = */ varnish_read,
/* interval = */ 0,
- /* user data = */ &ud);
+ &(user_data_t) {
+ .data = conf,
+ .free_func = varnish_config_free,
+ });
return (0);
} /* }}} int varnish_init */
static int varnish_config_instance (const oconfig_item_t *ci) /* {{{ */
{
user_config_t *conf;
- user_data_t ud;
char callback_name[DATA_MAX_NAME_LEN];
conf = calloc (1, sizeof (*conf));
ssnprintf (callback_name, sizeof (callback_name), "varnish/%s",
(conf->instance == NULL) ? "localhost" : conf->instance);
- ud.data = conf;
- ud.free_func = varnish_config_free;
-
plugin_register_complex_read (/* group = */ "varnish",
/* name = */ callback_name,
/* callback = */ varnish_read,
/* interval = */ 0,
- /* user data = */ &ud);
+ &(user_data_t) {
+ .data = conf,
+ .free_func = varnish_config_free,
+ });
have_instance = 1;
else if (strcasecmp ("AlwaysAppendDS", child->key) == 0)
cf_util_get_flag (child, &cb->format_flags,
GRAPHITE_ALWAYS_APPEND_DS);
+ else if (strcasecmp ("DropDuplicateFields", child->key) == 0)
+ cf_util_get_flag (child, &cb->format_flags,
+ GRAPHITE_DROP_DUPE_FIELDS);
else if (strcasecmp ("EscapeCharacter", child->key) == 0)
config_set_char (&cb->escape_char, child);
else
ssnprintf (callback_name, sizeof (callback_name), "write_graphite/%s",
cb->name);
- user_data_t ud = {
- .data = cb,
- .free_func = wg_callback_free
- };
-
- plugin_register_write (callback_name, wg_write, &ud);
+ plugin_register_write (callback_name, wg_write,
+ &(user_data_t) {
+ .data = cb,
+ .free_func = wg_callback_free,
+ });
- ud.free_func = NULL;
- plugin_register_flush (callback_name, wg_flush, &ud);
+ plugin_register_flush (callback_name, wg_flush, &(user_data_t) { .data = cb });
return (0);
}
ssnprintf(callback_name, sizeof(callback_name),
"write_kafka/%s", tctx->topic_name);
- user_data_t ud = {
- .data = tctx,
- .free_func = kafka_topic_context_free
- };
-
- status = plugin_register_write (callback_name, kafka_write, &ud);
+ status = plugin_register_write (callback_name, kafka_write,
+ &(user_data_t) {
+ .data = tctx,
+ .free_func = kafka_topic_context_free,
+ });
if (status != 0) {
WARNING ("write_kafka plugin: plugin_register_write (\"%s\") "
"failed with status %i.",
ssnprintf (cb_name, sizeof (cb_name), "write_mongodb/%s", node->name);
- user_data_t ud = {
- .data = node,
- .free_func = wm_config_free
- };
-
- status = plugin_register_write (cb_name, wm_write, &ud);
+ status = plugin_register_write (cb_name, wm_write,
+ &(user_data_t) {
+ .data = node,
+ .free_func = wm_config_free,
+ });
INFO ("write_mongodb plugin: registered write plugin %s %d",cb_name,status);
}
ssnprintf (cb_name, sizeof (cb_name), "write_redis/%s", node->name);
- user_data_t ud = {
- .data = node,
- .free_func = wr_config_free
- };
-
- status = plugin_register_write (cb_name, wr_write, &ud);
+ status = plugin_register_write (cb_name, wr_write,
+ &(user_data_t) {
+ .data = node,
+ .free_func = wr_config_free,
+ });
}
if (status != 0)