summaryrefslogtreecommitdiffstats
path: root/src/backends.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backends.c')
-rw-r--r--src/backends.c311
1 files changed, 222 insertions, 89 deletions
diff --git a/src/backends.c b/src/backends.c
index 3e385cab..eed4ab40 100644
--- a/src/backends.c
+++ b/src/backends.c
@@ -22,47 +22,81 @@
// 5. repeats the above forever.
//
-#define BACKEND_SOURCE_DATA_AS_COLLECTED 0x00000001
-#define BACKEND_SOURCE_DATA_AVERAGE 0x00000002
-#define BACKEND_SOURCE_DATA_SUM 0x00000004
-
+const char *backend_prefix = "netdata";
+int backend_send_names = 1;
+int backend_update_every = 10;
+uint32_t backend_options = BACKEND_SOURCE_DATA_AVERAGE;
// ----------------------------------------------------------------------------
// helper functions for backends
+static inline size_t backend_name_copy(char *d, const char *s, size_t usable) {
+ size_t n;
+
+ for(n = 0; *s && n < usable ; d++, s++, n++) {
+ char c = *s;
+
+ if(c != '.' && !isalnum(c)) *d = '_';
+ else *d = c;
+ }
+ *d = '\0';
+
+ return n;
+}
+
// calculate the SUM or AVERAGE of a dimension, for any timeframe
// may return NAN if the database does not have any value in the give timeframe
-static inline calculated_number backend_calculate_value_from_stored_data(
+inline calculated_number backend_calculate_value_from_stored_data(
RRDSET *st // the chart
, RRDDIM *rd // the dimension
, time_t after // the start timestamp
, time_t before // the end timestamp
, uint32_t options // BACKEND_SOURCE_* bitmap
+ , time_t *first_timestamp // the first point of the database used in this response
+ , time_t *last_timestamp // the timestamp that should be reported to backend
) {
// find the edges of the rrd database for this chart
time_t first_t = rrdset_first_entry_t(st);
time_t last_t = rrdset_last_entry_t(st);
+ time_t update_every = st->update_every;
- if(unlikely(before < first_t || after > last_t))
- // the chart has not been updated in the wanted timeframe
- return NAN;
+ // step back a little, to make sure we have complete data collection
+ // for all metrics
+ after -= update_every * 2;
+ before -= update_every * 2;
// align the time-frame
- // for 'after' also skip the first value by adding st->update_every
- after = after - after % st->update_every + st->update_every;
- before = before - before % st->update_every;
+ after = after - (after % update_every);
+ before = before - (before % update_every);
- if(unlikely(after < first_t))
- after = first_t;
+ // for before, loose another iteration
+ // the latest point will be reported the next time
+ before -= update_every;
if(unlikely(after > before))
- // this can happen when st->update_every > before - after
- before = after;
+ // this can happen when update_every > before - after
+ after = before;
+
+ if(unlikely(after < first_t))
+ after = first_t;
if(unlikely(before > last_t))
before = last_t;
+ if(unlikely(before < first_t || after > last_t)) {
+ // the chart has not been updated in the wanted timeframe
+ debug(D_BACKEND, "BACKEND: %s.%s.%s: aligned timeframe %lu to %lu is outside the chart's database range %lu to %lu",
+ st->rrdhost->hostname, st->id, rd->id,
+ (unsigned long)after, (unsigned long)before,
+ (unsigned long)first_t, (unsigned long)last_t
+ );
+ return NAN;
+ }
+
+ *first_timestamp = after;
+ *last_timestamp = before;
+
size_t counter = 0;
calculated_number sum = 0;
@@ -88,10 +122,15 @@ static inline calculated_number backend_calculate_value_from_stored_data(
counter++;
}
- if(unlikely(!counter))
+ if(unlikely(!counter)) {
+ debug(D_BACKEND, "BACKEND: %s.%s.%s: no values stored in database for range %lu to %lu",
+ st->rrdhost->hostname, st->id, rd->id,
+ (unsigned long)after, (unsigned long)before
+ );
return NAN;
+ }
- if(unlikely(options & BACKEND_SOURCE_DATA_SUM))
+ if(unlikely((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM))
return sum;
return sum / (calculated_number)counter;
@@ -113,7 +152,7 @@ static inline int discard_response(BUFFER *b, const char *backend) {
}
*d = '\0';
- info("Received %zu bytes from %s backend. Ignoring them. Sample: '%s'", buffer_strlen(b), backend, sample);
+ info("BACKEND: received %zu bytes from %s backend. Ignoring them. Sample: '%s'", buffer_strlen(b), backend, sample);
buffer_flush(b);
return 0;
}
@@ -138,13 +177,18 @@ static inline int format_dimension_collected_graphite_plaintext(
(void)before;
(void)options;
+ char chart_name[RRD_ID_LENGTH_MAX + 1];
+ char dimension_name[RRD_ID_LENGTH_MAX + 1];
+ backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
+ backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
+
buffer_sprintf(
b
, "%s.%s.%s.%s " COLLECTED_NUMBER_FORMAT " %u\n"
, prefix
, hostname
- , st->id
- , rd->id
+ , chart_name
+ , dimension_name
, rd->last_collected_value
, (uint32_t)rd->last_collected_time.tv_sec
);
@@ -165,7 +209,13 @@ static inline int format_dimension_stored_graphite_plaintext(
) {
(void)host;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options);
+ char chart_name[RRD_ID_LENGTH_MAX + 1];
+ char dimension_name[RRD_ID_LENGTH_MAX + 1];
+ backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
+ backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
+
+ time_t first_t = after, last_t = before;
+ calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
if(!isnan(value)) {
@@ -174,10 +224,10 @@ static inline int format_dimension_stored_graphite_plaintext(
, "%s.%s.%s.%s " CALCULATED_NUMBER_FORMAT " %u\n"
, prefix
, hostname
- , st->id
- , rd->id
+ , chart_name
+ , dimension_name
, value
- , (uint32_t) before
+ , (uint32_t) last_t
);
return 1;
@@ -209,15 +259,22 @@ static inline int format_dimension_collected_opentsdb_telnet(
(void)before;
(void)options;
+ char chart_name[RRD_ID_LENGTH_MAX + 1];
+ char dimension_name[RRD_ID_LENGTH_MAX + 1];
+ backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
+ backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
+
buffer_sprintf(
b
- , "put %s.%s.%s %u " COLLECTED_NUMBER_FORMAT " host=%s\n"
+ , "put %s.%s.%s %u " COLLECTED_NUMBER_FORMAT " host=%s%s%s\n"
, prefix
- , st->id
- , rd->id
+ , chart_name
+ , dimension_name
, (uint32_t)rd->last_collected_time.tv_sec
, rd->last_collected_value
, hostname
+ , (host->tags)?" ":""
+ , (host->tags)?host->tags:""
);
return 1;
@@ -236,19 +293,27 @@ static inline int format_dimension_stored_opentsdb_telnet(
) {
(void)host;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options);
+ time_t first_t = after, last_t = before;
+ calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
+
+ char chart_name[RRD_ID_LENGTH_MAX + 1];
+ char dimension_name[RRD_ID_LENGTH_MAX + 1];
+ backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
+ backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
if(!isnan(value)) {
buffer_sprintf(
b
- , "put %s.%s.%s %u " CALCULATED_NUMBER_FORMAT " host=%s\n"
+ , "put %s.%s.%s %u " CALCULATED_NUMBER_FORMAT " host=%s%s%s\n"
, prefix
- , st->id
- , rd->id
- , (uint32_t) before
+ , chart_name
+ , dimension_name
+ , (uint32_t) last_t
, value
, hostname
+ , (host->tags)?" ":""
+ , (host->tags)?host->tags:""
);
return 1;
@@ -329,7 +394,8 @@ static inline int format_dimension_stored_json_plaintext(
) {
(void)host;
- calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options);
+ time_t first_t = after, last_t = before;
+ calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
if(!isnan(value)) {
buffer_sprintf(b, "{"
@@ -362,7 +428,7 @@ static inline int format_dimension_stored_json_plaintext(
rd->name,
value,
- (uint32_t)before
+ (uint32_t) last_t
);
return 1;
@@ -378,6 +444,56 @@ static inline int process_json_response(BUFFER *b) {
// ----------------------------------------------------------------------------
// the backend thread
+static SIMPLE_PATTERN *charts_pattern = NULL;
+
+inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) {
+ if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_BACKEND_IGNORE)))
+ return 0;
+
+ if(unlikely(!rrdset_flag_check(st, RRDSET_FLAG_BACKEND_SEND))) {
+ // we have not checked this chart
+ if(simple_pattern_matches(charts_pattern, st->id) || simple_pattern_matches(charts_pattern, st->name))
+ rrdset_flag_set(st, RRDSET_FLAG_BACKEND_SEND);
+ else {
+ rrdset_flag_set(st, RRDSET_FLAG_BACKEND_IGNORE);
+ debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s', because it is disabled for backends.", st->id, st->rrdhost->hostname);
+ return 0;
+ }
+ }
+
+ if(unlikely(!rrdset_is_available_for_backends(st))) {
+ debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s', because it is not available for backends.", st->id, st->rrdhost->hostname);
+ return 0;
+ }
+
+ if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE && !((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED))) {
+ debug(D_BACKEND, "BACKEND: not sending chart '%s' of host '%s' because its memory mode is '%s' and the backend requires database access.", st->id, st->rrdhost->hostname, rrd_memory_mode_name(st->rrdhost->rrd_memory_mode));
+ return 0;
+ }
+
+ return 1;
+}
+
+inline uint32_t backend_parse_data_source(const char *source, uint32_t mode) {
+ if(!strcmp(source, "raw") || !strcmp(source, "as collected") || !strcmp(source, "as-collected") || !strcmp(source, "as_collected") || !strcmp(source, "ascollected")) {
+ mode |= BACKEND_SOURCE_DATA_AS_COLLECTED;
+ mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AS_COLLECTED);
+ }
+ else if(!strcmp(source, "average")) {
+ mode |= BACKEND_SOURCE_DATA_AVERAGE;
+ mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AVERAGE);
+ }
+ else if(!strcmp(source, "sum") || !strcmp(source, "volume")) {
+ mode |= BACKEND_SOURCE_DATA_SUM;
+ mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_SUM);
+ }
+ else {
+ error("BACKEND: invalid data source method '%s'.", source);
+ }
+
+ return mode;
+}
+
void *backends_main(void *ptr) {
int default_port = 0;
int sock = -1;
@@ -387,13 +503,13 @@ void *backends_main(void *ptr) {
int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL;
int (*backend_response_checker)(BUFFER *) = NULL;
- info("BACKEND thread created with task id %d", gettid());
+ info("BACKEND: thread created with task id %d", gettid());
if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
- error("Cannot set pthread cancel type to DEFERRED.");
+ error("BACKEND: cannot set pthread cancel type to DEFERRED.");
if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
- error("Cannot set pthread cancel state to ENABLE.");
+ error("BACKEND: cannot set pthread cancel state to ENABLE.");
// ------------------------------------------------------------------------
// collect configuration options
@@ -402,45 +518,35 @@ void *backends_main(void *ptr) {
.tv_sec = 0,
.tv_usec = 0
};
- uint32_t options;
int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0);
const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average");
const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite");
const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost");
- const char *prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata");
+ backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata");
const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname);
- int frequency = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", 10);
+ backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", backend_update_every);
int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10);
- long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", frequency * 2 * 1000);
+ long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", backend_update_every * 2 * 1000);
+ backend_send_names = config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", backend_send_names);
+
+ charts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send charts matching", "*"), SIMPLE_PATTERN_EXACT);
+
// ------------------------------------------------------------------------
// validate configuration options
// and prepare for sending data to our backend
- if(!enabled || frequency < 1)
- goto cleanup;
-
- if(!strcmp(source, "as collected")) {
- options = BACKEND_SOURCE_DATA_AS_COLLECTED;
- }
- else if(!strcmp(source, "average")) {
- options = BACKEND_SOURCE_DATA_AVERAGE;
- }
- else if(!strcmp(source, "sum") || !strcmp(source, "volume")) {
- options = BACKEND_SOURCE_DATA_SUM;
- }
- else {
- error("Invalid data source method '%s' for backend given. Disabling backed.", source);
- goto cleanup;
- }
+ backend_options = backend_parse_data_source(source, backend_options);
if(timeoutms < 1) {
- error("BACKED invalid timeout %ld ms given. Assuming %d ms.", timeoutms, frequency * 2 * 1000);
- timeoutms = frequency * 2 * 1000;
+ error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, backend_update_every * 2 * 1000);
+ timeoutms = backend_update_every * 2 * 1000;
}
timeout.tv_sec = (timeoutms * 1000) / 1000000;
timeout.tv_usec = (timeoutms * 1000) % 1000000;
+ if(!enabled || backend_update_every < 1)
+ goto cleanup;
// ------------------------------------------------------------------------
// select the backend type
@@ -450,7 +556,7 @@ void *backends_main(void *ptr) {
default_port = 2003;
backend_response_checker = process_graphite_response;
- if(options == BACKEND_SOURCE_DATA_AS_COLLECTED)
+ if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
backend_request_formatter = format_dimension_collected_graphite_plaintext;
else
backend_request_formatter = format_dimension_stored_graphite_plaintext;
@@ -461,7 +567,7 @@ void *backends_main(void *ptr) {
default_port = 4242;
backend_response_checker = process_opentsdb_response;
- if(options == BACKEND_SOURCE_DATA_AS_COLLECTED)
+ if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
backend_request_formatter = format_dimension_collected_opentsdb_telnet;
else
backend_request_formatter = format_dimension_stored_opentsdb_telnet;
@@ -472,19 +578,19 @@ void *backends_main(void *ptr) {
default_port = 5448;
backend_response_checker = process_json_response;
- if (options == BACKEND_SOURCE_DATA_AS_COLLECTED)
+ if ((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
backend_request_formatter = format_dimension_collected_json_plaintext;
else
backend_request_formatter = format_dimension_stored_json_plaintext;
}
else {
- error("Unknown backend type '%s'", type);
+ error("BACKEND: Unknown backend type '%s'", type);
goto cleanup;
}
if(backend_request_formatter == NULL || backend_response_checker == NULL) {
- error("backend is misconfigured - disabling it.");
+ error("BACKEND: backend is misconfigured - disabling it.");
goto cleanup;
}
@@ -509,18 +615,18 @@ void *backends_main(void *ptr) {
chart_backend_reconnects = 0,
chart_backend_latency = 0;
- RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", 130600, frequency, RRDSET_TYPE_LINE);
+ RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", 130600, backend_update_every, RRDSET_TYPE_LINE);
rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
- RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", 130610, frequency, RRDSET_TYPE_AREA);
+ RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", 130610, backend_update_every, RRDSET_TYPE_AREA);
rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
- RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", 130630, frequency, RRDSET_TYPE_LINE);
+ RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", 130630, backend_update_every, RRDSET_TYPE_LINE);
rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
@@ -534,11 +640,11 @@ void *backends_main(void *ptr) {
*
* issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html
*
- RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", 130620, frequency, RRDSET_TYPE_AREA);
+ RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", 130620, backend_update_every, RRDSET_TYPE_AREA);
rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
*/
- RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", 130630, frequency, RRDSET_TYPE_STACKED);
+ RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", 130630, backend_update_every, RRDSET_TYPE_STACKED);
rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
@@ -546,9 +652,9 @@ void *backends_main(void *ptr) {
// ------------------------------------------------------------------------
// prepare the backend main loop
- info("BACKEND configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, frequency, hostname, prefix);
+ info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, backend_update_every, hostname, backend_prefix);
- usec_t step_ut = frequency * USEC_PER_SEC;
+ usec_t step_ut = backend_update_every * USEC_PER_SEC;
time_t after = now_realtime_sec();
int failures = 0;
heartbeat_t hb;
@@ -558,9 +664,10 @@ void *backends_main(void *ptr) {
// ------------------------------------------------------------------------
// Wait for the next iteration point.
+
heartbeat_next(&hb, step_ut);
time_t before = now_realtime_sec();
-
+ debug(D_BACKEND, "BACKEND: preparing buffer for timeframe %lu to %lu", (unsigned long)after, (unsigned long)before);
// ------------------------------------------------------------------------
// add to the buffer the data we need to send to the backend
@@ -568,33 +675,59 @@ void *backends_main(void *ptr) {
int pthreadoldcancelstate;
if(unlikely(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &pthreadoldcancelstate) != 0))
- error("Cannot set pthread cancel state to DISABLE.");
+ error("BACKEND: cannot set pthread cancel state to DISABLE.");
+
+ size_t count_hosts = 0;
+ size_t count_charts_total = 0;
+ size_t count_dims_total = 0;
rrd_rdlock();
RRDHOST *host;
rrdhost_foreach_read(host) {
- if(host->rrd_memory_mode == RRD_MEMORY_MODE_NONE)
- continue;
-
rrdhost_rdlock(host);
+ count_hosts++;
+ size_t count_charts = 0;
+ size_t count_dims = 0;
+ size_t count_dims_skipped = 0;
+
+ const char *__hostname = (host == localhost)?hostname:host->hostname;
+
RRDSET *st;
rrdset_foreach_read(st, host) {
- rrdset_rdlock(st);
+ if(likely(backends_can_send_rrdset(backend_options, st))) {
+ rrdset_rdlock(st);
+
+ count_charts++;
+
+ RRDDIM *rd;
+ rrddim_foreach_read(rd, st) {
+ if (likely(rd->last_collected_time.tv_sec >= after)) {
+ chart_buffered_metrics += backend_request_formatter(b, backend_prefix, host, __hostname, st, rd, after, before, backend_options);
+ count_dims++;
+ }
+ else {
+ debug(D_BACKEND, "BACKEND: not sending dimension '%s' of chart '%s' from host '%s', its last data collection (%lu) is not within our timeframe (%lu to %lu)", rd->id, st->id, __hostname, (unsigned long)rd->last_collected_time.tv_sec, (unsigned long)after, (unsigned long)before);
+ count_dims_skipped++;
+ }
+ }
- RRDDIM *rd;
- rrddim_foreach_read(rd, st) {
- if(rd->last_collected_time.tv_sec >= after)
- chart_buffered_metrics += backend_request_formatter(b, prefix, host, (host == localhost)?hostname:host->hostname, st, rd, after, before, options);
+ rrdset_unlock(st);
}
- rrdset_unlock(st);
}
+
+ debug(D_BACKEND, "BACKEND: sending host '%s', metrics of %zu dimensions, of %zu charts. Skipped %zu dimensions.", __hostname, count_dims, count_charts, count_dims_skipped);
+ count_charts_total += count_charts;
+ count_dims_total += count_dims;
+
rrdhost_unlock(host);
}
rrd_unlock();
+ debug(D_BACKEND, "BACKEND: buffer has %zu bytes, added metrics for %zu dimensions, of %zu charts, from %zu hosts", buffer_strlen(b), count_dims_total, count_charts_total, count_hosts);
+
if(unlikely(pthread_setcancelstate(pthreadoldcancelstate, NULL) != 0))
- error("Cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate);
+ error("BACKEND: cannot set pthread cancel state to RESTORE (%d).", pthreadoldcancelstate);
// ------------------------------------------------------------------------
@@ -639,14 +772,14 @@ void *backends_main(void *ptr) {
chart_receptions++;
}
else if(r == 0) {
- error("Backend '%s' closed the socket", destination);
+ error("BACKEND: '%s' closed the socket", destination);
close(sock);
sock = -1;
}
else {
// failed to receive data
if(errno != EAGAIN && errno != EWOULDBLOCK) {
- error("Cannot receive data from backend '%s'.", destination);
+ error("BACKEND: cannot receive data from backend '%s'.", destination);
}
}
}
@@ -698,7 +831,7 @@ void *backends_main(void *ptr) {
}
else {
// oops! we couldn't send (all or some of the) data
- error("Failed to write data to database backend '%s'. Willing to write %zu bytes, wrote %zd bytes. Will re-connect.", destination, len, written);
+ error("BACKEND: failed to write data to database backend '%s'. Willing to write %zu bytes, wrote %zd bytes. Will re-connect.", destination, len, written);
chart_transmission_failures++;
if(written != -1)
@@ -713,7 +846,7 @@ void *backends_main(void *ptr) {
}
}
else {
- error("Failed to update database backend '%s'", destination);
+ error("BACKEND: failed to update database backend '%s'", destination);
chart_transmission_failures++;
// increment the counter we check for data loss
@@ -723,7 +856,7 @@ void *backends_main(void *ptr) {
if(failures > buffer_on_failures) {
// too bad! we are going to lose data
chart_lost_bytes += buffer_strlen(b);
- error("Reached %d backend failures. Flushing buffers to protect this host - this results in data loss on back-end server '%s'", failures, destination);
+ error("BACKEND: reached %d backend failures. Flushing buffers to protect this host - this results in data loss on back-end server '%s'", failures, destination);
buffer_flush(b);
failures = 0;
chart_data_lost_events++;
@@ -781,7 +914,7 @@ cleanup:
buffer_free(b);
buffer_free(response);
- info("BACKEND thread exiting");
+ info("BACKEND: thread exiting");
static_thread->enabled = 0;
pthread_exit(NULL);