LogSendErrors true
Prefix "collectd"
UseTags false
+ ReverseHost false
</Node>
</Plugin>
Default value: B<false>.
+=item B<ReverseHost> B<false>|B<true>
+
+If set to B<true>, the (dot separated) parts of the B<host> field of the
+I<value list> will be rewritten in reverse order. The rewrite happens I<before>
+special characters are replaced with the B<EscapeCharacter>.
+
+This option might be convenient if the metrics are presented with Graphite in a
+DNS like tree structure (probably without replacing dots in hostnames).
+
+Example:
+ Hostname "node3.cluster1.example.com"
+ LoadPlugin "cpu"
+ LoadPlugin "write_graphite"
+ <Plugin "write_graphite">
+ <Node "graphite.example.com">
+ EscapeCharacter "."
+ ReverseHost true
+ </Node>
+ </Plugin>
+
+ result on the wire: com.example.cluster1.node3.cpu-0.cpu-idle 99.900993 1543010932
+
+Default value: B<false>.
+
=back
=head2 Plugin C<write_log>
/* Utils functions to format data sets in graphite format.
* Largely taken from write_graphite.c as it remains the same formatting */
+/* helper function for reverse_hostname */
+void reverse_string(char *r_host, int len) {
+ char t;
+ for (int i = 0; i < len / 2; i++) {
+ int j = len - i - 1;
+ t = r_host[i];
+ r_host[i] = r_host[j];
+ r_host[j] = t;
+ }
+}
+
+void reverse_hostname(char *r_host, char const *orig_host) {
+ int len_host = strlen(orig_host);
+
+ /* put reversed hostname into working copy */
+ for (int i = 0; i < len_host; i++)
+ r_host[i] = orig_host[len_host - 1 - i];
+ r_host[len_host] = '\0';
+
+ /* reverse labels (except last) */
+ int p = 0;
+ for (int i = 0; i < len_host; i++)
+ if (r_host[i] == '.') {
+ reverse_string(&r_host[p], i - p);
+ p = i + 1;
+ }
+
+ /* reverse last label */
+ reverse_string(&r_host[p], len_host - p);
+}
+
static int gr_format_values(char *ret, size_t ret_len, int ds_num,
const data_set_t *ds, const value_list_t *vl,
gauge_t const *rates) {
if (postfix == NULL)
postfix = "";
- gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char, 1);
+ if (flags & GRAPHITE_REVERSE_HOST) {
+ int len_host = strlen(vl->host);
+ char r_host[len_host + 1];
+ reverse_hostname(r_host, vl->host);
+ gr_copy_escape_part(n_host, r_host, sizeof(n_host), escape_char, 1);
+ } else {
+ gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char, 1);
+ }
gr_copy_escape_part(n_plugin, vl->plugin, sizeof(n_plugin), escape_char, 1);
gr_copy_escape_part(n_plugin_instance, vl->plugin_instance,
sizeof(n_plugin_instance), escape_char, 1);
bool preserve_separator = (flags & GRAPHITE_PRESERVE_SEPARATOR);
- gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char,
- preserve_separator);
+ if (flags & GRAPHITE_REVERSE_HOST) {
+ int len_host = strlen(vl->host);
+ char r_host[len_host + 1];
+ reverse_hostname(r_host, vl->host);
+ gr_copy_escape_part(n_host, r_host, sizeof(n_host), escape_char,
+ preserve_separator);
+ } else {
+ gr_copy_escape_part(n_host, vl->host, sizeof(n_host), escape_char,
+ preserve_separator);
+ }
gr_copy_escape_part(n_plugin, vl->plugin, sizeof(n_plugin), escape_char,
preserve_separator);
gr_copy_escape_part(n_plugin_instance, vl->plugin_instance,
* Based on the write_http plugin.
**/
-/* write_graphite plugin configuation example
+/* write_graphite plugin configuration example
*
* <Plugin write_graphite>
* <Carbon>
* LogSendErrors true
* Prefix "collectd"
* UseTags true
+ * ReverseHost false
* </Carbon>
* </Plugin>
*/
cf_util_get_flag(child, &cb->format_flags, GRAPHITE_DROP_DUPE_FIELDS);
else if (strcasecmp("UseTags", child->key) == 0)
cf_util_get_flag(child, &cb->format_flags, GRAPHITE_USE_TAGS);
+ else if (strcasecmp("ReverseHost", child->key) == 0)
+ cf_util_get_flag(child, &cb->format_flags, GRAPHITE_REVERSE_HOST);
else if (strcasecmp("EscapeCharacter", child->key) == 0)
config_set_char(&cb->escape_char, child);
else {