summaryrefslogtreecommitdiffstats
path: root/exporting/opentsdb
diff options
context:
space:
mode:
authorVladimir Kobal <vlad@prokk.net>2020-01-09 12:51:41 +0200
committerGitHub <noreply@github.com>2020-01-09 12:51:41 +0200
commit0fba85e2c20add69546cefbf37bb2033d2d1e052 (patch)
treedd124104fb54f99ef2ddca7e92e946d2d7f7aa31 /exporting/opentsdb
parent37edc6898b453b80806f07264cc94acf04bdd39e (diff)
Send host labels via exporting connectors (#7554)
* Add labels to the JSON exporting connector * Add labels to the Graphite exporting connector * Add labels to the OpenTSDB telnet exporting connector * Add labels to the OpenTSDB HTTP exporting connector * Replace control characters in JSON strings * Add unit tests
Diffstat (limited to 'exporting/opentsdb')
-rw-r--r--exporting/opentsdb/opentsdb.c116
-rw-r--r--exporting/opentsdb/opentsdb.h4
2 files changed, 108 insertions, 12 deletions
diff --git a/exporting/opentsdb/opentsdb.c b/exporting/opentsdb/opentsdb.c
index b216c76b44..a1e810de93 100644
--- a/exporting/opentsdb/opentsdb.c
+++ b/exporting/opentsdb/opentsdb.c
@@ -28,7 +28,7 @@ int init_opentsdb_connector(struct connector *connector)
int init_opentsdb_telnet_instance(struct instance *instance)
{
instance->start_batch_formatting = NULL;
- instance->start_host_formatting = NULL;
+ instance->start_host_formatting = format_host_labels_opentsdb_telnet;
instance->start_chart_formatting = NULL;
if (EXPORTING_OPTIONS_DATA_SOURCE(instance->config.options) == EXPORTING_SOURCE_DATA_AS_COLLECTED)
@@ -37,7 +37,7 @@ int init_opentsdb_telnet_instance(struct instance *instance)
instance->metric_formatting = format_dimension_stored_opentsdb_telnet;
instance->end_chart_formatting = NULL;
- instance->end_host_formatting = NULL;
+ instance->end_host_formatting = flush_host_labels;
instance->end_batch_formatting = NULL;
instance->buffer = (void *)buffer_create(0);
@@ -60,7 +60,7 @@ int init_opentsdb_telnet_instance(struct instance *instance)
int init_opentsdb_http_instance(struct instance *instance)
{
instance->start_batch_formatting = NULL;
- instance->start_host_formatting = NULL;
+ instance->start_host_formatting = format_host_labels_opentsdb_http;
instance->start_chart_formatting = NULL;
if (EXPORTING_OPTIONS_DATA_SOURCE(instance->config.options) == EXPORTING_SOURCE_DATA_AS_COLLECTED)
@@ -69,7 +69,7 @@ int init_opentsdb_http_instance(struct instance *instance)
instance->metric_formatting = format_dimension_stored_opentsdb_http;
instance->end_chart_formatting = NULL;
- instance->end_host_formatting = NULL;
+ instance->end_host_formatting = flush_host_labels;
instance->end_batch_formatting = NULL;
instance->buffer = (void *)buffer_create(0);
@@ -84,6 +84,58 @@ int init_opentsdb_http_instance(struct instance *instance)
}
/**
+ * Copy a label value and substitute underscores in place of charachters which can't be used in OpenTSDB output
+ *
+ * @param dst a destination string.
+ * @param src a source string.
+ * @param len the maximum number of characters copied.
+ */
+
+void sanitize_opentsdb_label_value(char *dst, char *src, size_t len)
+{
+ while (*src != '\0' && len) {
+ if (isalpha(*src) || isdigit(*src) || *src == '-' || *src == '_' || *src == '.' || *src == '/' || IS_UTF8_BYTE(*src))
+ *dst++ = *src;
+ else
+ *dst++ = '_';
+ src++;
+ len--;
+ }
+ *dst = '\0';
+}
+
+/**
+ * Format host labels for JSON connector
+ *
+ * @param instance an instance data structure.
+ * @param host a data collecting host.
+ * @return Always returns 0.
+ */
+int format_host_labels_opentsdb_telnet(struct instance *instance, RRDHOST *host)
+{
+ if (!instance->labels)
+ instance->labels = buffer_create(1024);
+
+ if (unlikely(!sending_labels_configured(instance)))
+ return 0;
+
+ netdata_rwlock_rdlock(&host->labels_rwlock);
+ for (struct label *label = host->labels; label; label = label->next) {
+ if (!should_send_label(instance, label))
+ continue;
+
+ char value[CONFIG_MAX_VALUE + 1];
+ sanitize_opentsdb_label_value(value, label->value, CONFIG_MAX_VALUE);
+
+ if (*value)
+ buffer_sprintf(instance->labels, " %s=%s", label->key, value);
+ }
+ netdata_rwlock_unlock(&host->labels_rwlock);
+
+ return 0;
+}
+
+/**
* Format dimension using collected data for OpenTSDB telnet connector
*
* @param instance an instance data structure.
@@ -110,7 +162,7 @@ int format_dimension_collected_opentsdb_telnet(struct instance *instance, RRDDIM
buffer_sprintf(
instance->buffer,
- "put %s.%s.%s %llu " COLLECTED_NUMBER_FORMAT " host=%s%s%s\n",
+ "put %s.%s.%s %llu " COLLECTED_NUMBER_FORMAT " host=%s%s%s%s\n",
engine->config.prefix,
chart_name,
dimension_name,
@@ -118,7 +170,8 @@ int format_dimension_collected_opentsdb_telnet(struct instance *instance, RRDDIM
rd->last_collected_value,
engine->config.hostname,
(host->tags) ? " " : "",
- (host->tags) ? host->tags : "");
+ (host->tags) ? host->tags : "",
+ (instance->labels) ? buffer_tostring(instance->labels) : "");
return 0;
}
@@ -156,7 +209,7 @@ int format_dimension_stored_opentsdb_telnet(struct instance *instance, RRDDIM *r
buffer_sprintf(
instance->buffer,
- "put %s.%s.%s %llu " CALCULATED_NUMBER_FORMAT " host=%s%s%s\n",
+ "put %s.%s.%s %llu " CALCULATED_NUMBER_FORMAT " host=%s%s%s%s\n",
engine->config.prefix,
chart_name,
dimension_name,
@@ -164,7 +217,8 @@ int format_dimension_stored_opentsdb_telnet(struct instance *instance, RRDDIM *r
value,
engine->config.hostname,
(host->tags) ? " " : "",
- (host->tags) ? host->tags : "");
+ (host->tags) ? host->tags : "",
+ (instance->labels) ? buffer_tostring(instance->labels) : "");
return 0;
}
@@ -193,6 +247,42 @@ static inline void opentsdb_build_message(BUFFER *buffer, char *message, const c
}
/**
+ * Format host labels for OpenTSDB HTTP connector
+ *
+ * @param instance an instance data structure.
+ * @param host a data collecting host.
+ * @return Always returns 0.
+ */
+int format_host_labels_opentsdb_http(struct instance *instance, RRDHOST *host)
+{
+ if (!instance->labels)
+ instance->labels = buffer_create(1024);
+
+ if (unlikely(!sending_labels_configured(instance)))
+ return 0;
+
+ netdata_rwlock_rdlock(&host->labels_rwlock);
+ for (struct label *label = host->labels; label; label = label->next) {
+ if (!should_send_label(instance, label))
+ continue;
+
+ char escaped_value[CONFIG_MAX_VALUE * 2 + 1];
+ sanitize_json_string(escaped_value, label->value, CONFIG_MAX_VALUE);
+
+ char value[CONFIG_MAX_VALUE + 1];
+ sanitize_opentsdb_label_value(value, escaped_value, CONFIG_MAX_VALUE);
+
+ if (*value) {
+ buffer_strcat(instance->labels, ",");
+ buffer_sprintf(instance->labels, "\"%s\":\"%s\"", label->key, value);
+ }
+ }
+ netdata_rwlock_unlock(&host->labels_rwlock);
+
+ return 0;
+}
+
+/**
* Format dimension using collected data for OpenTSDB HTTP connector
*
* @param instance an instance data structure.
@@ -226,7 +316,7 @@ int format_dimension_collected_opentsdb_http(struct instance *instance, RRDDIM *
" \"timestamp\": %llu,"
" \"value\": " COLLECTED_NUMBER_FORMAT ","
" \"tags\": {"
- " \"host\": \"%s%s%s\""
+ " \"host\": \"%s%s%s\"%s"
" }"
"}",
engine->config.prefix,
@@ -236,7 +326,8 @@ int format_dimension_collected_opentsdb_http(struct instance *instance, RRDDIM *
rd->last_collected_value,
engine->config.hostname,
(host->tags) ? " " : "",
- (host->tags) ? host->tags : "");
+ (host->tags) ? host->tags : "",
+ instance->labels ? buffer_tostring(instance->labels) : "");
if (length > 0) {
opentsdb_build_message(instance->buffer, message, engine->config.hostname, length);
@@ -285,7 +376,7 @@ int format_dimension_stored_opentsdb_http(struct instance *instance, RRDDIM *rd)
" \"timestamp\": %llu,"
" \"value\": " CALCULATED_NUMBER_FORMAT ","
" \"tags\": {"
- " \"host\": \"%s%s%s\""
+ " \"host\": \"%s%s%s\"%s"
" }"
"}",
engine->config.prefix,
@@ -295,7 +386,8 @@ int format_dimension_stored_opentsdb_http(struct instance *instance, RRDDIM *rd)
value,
engine->config.hostname,
(host->tags) ? " " : "",
- (host->tags) ? host->tags : "");
+ (host->tags) ? host->tags : "",
+ instance->labels ? buffer_tostring(instance->labels) : "");
if (length > 0) {
opentsdb_build_message(instance->buffer, message, engine->config.hostname, length);
diff --git a/exporting/opentsdb/opentsdb.h b/exporting/opentsdb/opentsdb.h
index 929f49b1bb..df99356e92 100644
--- a/exporting/opentsdb/opentsdb.h
+++ b/exporting/opentsdb/opentsdb.h
@@ -9,6 +9,10 @@ int init_opentsdb_connector(struct connector *connector);
int init_opentsdb_telnet_instance(struct instance *instance);
int init_opentsdb_http_instance(struct instance *instance);
+void sanitize_opentsdb_label_value(char *dst, char *src, size_t len);
+int format_host_labels_opentsdb_telnet(struct instance *instance, RRDHOST *host);
+int format_host_labels_opentsdb_http(struct instance *instance, RRDHOST *host);
+
int format_dimension_collected_opentsdb_telnet(struct instance *instance, RRDDIM *rd);
int format_dimension_stored_opentsdb_telnet(struct instance *instance, RRDDIM *rd);