@cryptotaxi247 / netdata-1 / commits / ff232c524

send host variables to prometheus (#4200)

* send host variables to prometheus; fixes #4035 * make sure labels do not start with comma * embed the custom variables scopes into the structures; expose chart variables and the host level * check the type of variable when streaming host variables * added URL option variables=yes to enable sending host variables to prometheus; code cleanup to backends * removed _host_var from variables * added flags to tag alarm variables; set the last updated time of alarm variables

Costa Tsaousis committed Sep 17, 2018 at 04:09 UTC ff232c524a5015af629a0b66bdca5bb9949d2781
21 files changed +363 -228
conf.d/health.d/ipc.conf
+2 -2
@@ -5,7 +5,7 @@
5 on: system.ipc_semaphores
6 os: linux
7 hosts: *
8 - calc: $semaphores * 100 / $ipc.semaphores.max
8 + calc: $semaphores * 100 / $ipc_semaphores_max
9 units: %
10 every: 10s
11 warn: $this > (($status >= $WARNING) ? (70) : (80))
@@ -18,7 +18,7 @@
18 on: system.ipc_semaphore_arrays
19 os: linux
20 hosts: *
21 - calc: $arrays * 100 / $ipc.semaphores.arrays.max
21 + calc: $arrays * 100 / $ipc_semaphores_arrays_max
22 units: %
23 every: 10s
24 warn: $this > (($status >= $WARNING) ? (70) : (80))
conf.d/health.d/load.conf
+1 -1
@@ -8,7 +8,7 @@
8 on: system.load
9 os: linux
10 hosts: *
11 - calc: ($system.cpu.processors <= 2) ? ( 2 ) : ( $system.cpu.processors )
11 + calc: ($active_processors == nan or $active_processors == inf or $active_processors < 2) ? ( 2 ) : ( $active_processors )
12 units: cpus
13 every: 1m
14 info: trigger point for load average alarms
conf.d/health.d/netfilter.conf
+1 -1
@@ -19,7 +19,7 @@
19 os: linux
20 hosts: *
21 lookup: max -10s unaligned of connections
22 - calc: $this * 100 / $netfilter.conntrack.max
22 + calc: $this * 100 / $netfilter_conntrack_max
23 units: %
24 every: 10s
25 warn: $this > (($status >= $WARNING) ? (70) : (80))
src/adaptive_resortable_list.c
+9
@@ -21,6 +21,15 @@ inline void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, cons
21 // fprintf(stderr, "name '%s' with hash %u and value '%s' is %llu\n", name, hash, value, (unsigned long long)*d);
22 }
23
24 +inline void arl_callback_ssize_t(const char *name, uint32_t hash, const char *value, void *dst) {
25 + (void)name;
26 + (void)hash;
27 +
28 + register ssize_t *d = dst;
29 + *d = (ssize_t)str2ll(value, NULL);
30 + // fprintf(stderr, "name '%s' with hash %u and value '%s' is %zd\n", name, hash, value, *d);
31 +}
32 +
33 // create a new ARL
34 ARL_BASE *arl_create(const char *name, void (*processor)(const char *, uint32_t, const char *, void *), size_t rechecks) {
35 ARL_BASE *base = callocz(1, sizeof(ARL_BASE));
src/adaptive_resortable_list.h
+1
@@ -117,6 +117,7 @@ extern void arl_begin(ARL_BASE *base);
117
118 extern void arl_callback_str2ull(const char *name, uint32_t hash, const char *value, void *dst);
119 extern void arl_callback_str2kernel_uint_t(const char *name, uint32_t hash, const char *value, void *dst);
120 +extern void arl_callback_ssize_t(const char *name, uint32_t hash, const char *value, void *dst);
121
122 // check a keyword against the ARL
123 // this is to be called for each keyword read from source data
src/backend_prometheus.c
+128 -44
@@ -110,8 +110,77 @@ static inline char *prometheus_units_copy(char *d, const char *s, size_t usable)
110
111 #define PROMETHEUS_ELEMENT_MAX 256
112 #define PROMETHEUS_LABELS_MAX 1024
113 +#define PROMETHEUS_VARIABLE_MAX 256
114
114 -static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb, const char *prefix, uint32_t options, time_t after, time_t before, int allhosts, int help, int types, int names, int timestamps) {
115 +struct host_variables_callback_options {
116 + RRDHOST *host;
117 + BUFFER *wb;
118 + BACKEND_OPTIONS backend_options;
119 + PROMETHEUS_OUTPUT_OPTIONS output_options;
120 + const char *prefix;
121 + const char *labels;
122 + time_t now;
123 + int host_header_printed;
124 + char name[PROMETHEUS_VARIABLE_MAX+1];
125 +};
126 +
127 +static int print_host_variables(RRDVAR *rv, void *data) {
128 + struct host_variables_callback_options *opts = data;
129 +
130 + if(rv->options & (RRDVAR_OPTION_CUSTOM_HOST_VAR|RRDVAR_OPTION_CUSTOM_CHART_VAR)) {
131 + if(!opts->host_header_printed) {
132 + opts->host_header_printed = 1;
133 +
134 + if(opts->output_options & PROMETHEUS_OUTPUT_HELP) {
135 + buffer_sprintf(opts->wb, "\n# COMMENT global host and chart variables\n");
136 + }
137 + }
138 +
139 + calculated_number value = rrdvar2number(rv);
140 + if(isnan(value) || isinf(value)) {
141 + if(opts->output_options & PROMETHEUS_OUTPUT_HELP)
142 + buffer_sprintf(opts->wb, "# COMMENT variable \"%s\" is %s. Skipped.\n", rv->name, (isnan(value))?"NAN":"INF");
143 +
144 + return 0;
145 + }
146 +
147 + char *label_pre = "";
148 + char *label_post = "";
149 + if(opts->labels && *opts->labels) {
150 + label_pre = "{";
151 + label_post = "}";
152 + }
153 +
154 + prometheus_name_copy(opts->name, rv->name, sizeof(opts->name));
155 +
156 + if(opts->output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
157 + buffer_sprintf(opts->wb
158 + , "%s_%s%s%s%s " CALCULATED_NUMBER_FORMAT " %llu\n"
159 + , opts->prefix
160 + , opts->name
161 + , label_pre
162 + , opts->labels
163 + , label_post
164 + , value
165 + , ((rv->last_updated) ? rv->last_updated : opts->now) * 1000ULL
166 + );
167 + else
168 + buffer_sprintf(opts->wb, "%s_%s%s%s%s " CALCULATED_NUMBER_FORMAT "\n"
169 + , opts->prefix
170 + , opts->name
171 + , label_pre
172 + , opts->labels
173 + , label_post
174 + , value
175 + );
176 +
177 + return 1;
178 + }
179 +
180 + return 0;
181 +}
182 +
183 +static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER *wb, const char *prefix, BACKEND_OPTIONS backend_options, time_t after, time_t before, int allhosts, PROMETHEUS_OUTPUT_OPTIONS output_options) {
184 rrdhost_rdlock(host);
185
186 char hostname[PROMETHEUS_ELEMENT_MAX + 1];
@@ -119,13 +188,13 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
188
189 char labels[PROMETHEUS_LABELS_MAX + 1] = "";
190 if(allhosts) {
122 - if(timestamps)
191 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
192 buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1 %llu\n", hostname, host->program_name, host->program_version, now_realtime_usec() / USEC_PER_MS);
193 else
194 buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1\n", hostname, host->program_name, host->program_version);
195
196 if(host->tags && *(host->tags)) {
128 - if(timestamps) {
197 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) {
198 buffer_sprintf(wb, "netdata_host_tags_info{instance=\"%s\",%s} 1 %llu\n", hostname, host->tags, now_realtime_usec() / USEC_PER_MS);
199
200 // deprecated, exists only for compatibility with older queries
@@ -143,13 +212,13 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
212 snprintfz(labels, PROMETHEUS_LABELS_MAX, ",instance=\"%s\"", hostname);
213 }
214 else {
146 - if(timestamps)
215 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
216 buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1 %llu\n", hostname, host->program_name, host->program_version, now_realtime_usec() / USEC_PER_MS);
217 else
218 buffer_sprintf(wb, "netdata_info{instance=\"%s\",application=\"%s\",version=\"%s\"} 1\n", hostname, host->program_name, host->program_version);
219
220 if(host->tags && *(host->tags)) {
152 - if(timestamps) {
221 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) {
222 buffer_sprintf(wb, "netdata_host_tags_info{%s} 1 %llu\n", host->tags, now_realtime_usec() / USEC_PER_MS);
223
224 // deprecated, exists only for compatibility with older queries
@@ -164,6 +233,21 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
233 }
234 }
235
236 + // send custom variables set for the host
237 + if(output_options & PROMETHEUS_OUTPUT_VARIABLES){
238 + struct host_variables_callback_options opts = {
239 + .host = host,
240 + .wb = wb,
241 + .labels = (labels[0] == ',')?&labels[1]:labels,
242 + .backend_options = backend_options,
243 + .output_options = output_options,
244 + .prefix = prefix,
245 + .now = now_realtime_sec(),
246 + .host_header_printed = 0
247 + };
248 + foreach_host_variable_callback(host, print_host_variables, &opts);
249 + }
250 +
251 // for each chart
252 RRDSET *st;
253 rrdset_foreach_read(st, host) {
@@ -172,14 +256,14 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
256 char family[PROMETHEUS_ELEMENT_MAX + 1];
257 char units[PROMETHEUS_ELEMENT_MAX + 1] = "";
258
175 - prometheus_label_copy(chart, (names && st->name)?st->name:st->id, PROMETHEUS_ELEMENT_MAX);
259 + prometheus_label_copy(chart, (output_options & PROMETHEUS_OUTPUT_NAMES && st->name)?st->name:st->id, PROMETHEUS_ELEMENT_MAX);
260 prometheus_label_copy(family, st->family, PROMETHEUS_ELEMENT_MAX);
261 prometheus_name_copy(context, st->context, PROMETHEUS_ELEMENT_MAX);
262
179 - if(likely(backends_can_send_rrdset(options, st))) {
263 + if(likely(backends_can_send_rrdset(backend_options, st))) {
264 rrdset_rdlock(st);
265
182 - int as_collected = ((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED);
266 + int as_collected = (BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED);
267 int homogeneus = 1;
268 if(as_collected) {
269 if(rrdset_flag_check(st, RRDSET_FLAG_HOMEGENEOUS_CHECK))
@@ -189,14 +273,14 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
273 homogeneus = 0;
274 }
275 else {
192 - if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
276 + if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AVERAGE)
277 prometheus_units_copy(units, st->units, PROMETHEUS_ELEMENT_MAX);
278 }
279
196 - if(unlikely(help))
280 + if(unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
281 buffer_sprintf(wb, "\n# COMMENT %s chart \"%s\", context \"%s\", family \"%s\", units \"%s\"\n"
282 , (homogeneus)?"homogeneus":"heterogeneous"
199 - , (names && st->name) ? st->name : st->id
283 + , (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? st->name : st->id
284 , st->context
285 , st->family
286 , st->units
@@ -224,18 +308,18 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
308 // all the dimensions of the chart, has the same algorithm, multiplier and divisor
309 // we add all dimensions as labels
310
227 - prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
311 + prometheus_label_copy(dimension, (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
312
229 - if(unlikely(help))
313 + if(unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
314 buffer_sprintf(wb
315 , "# COMMENT %s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
316 , prefix
317 , context
318 , suffix
235 - , (names && st->name) ? st->name : st->id
319 + , (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? st->name : st->id
320 , st->context
321 , st->family
238 - , (names && rd->name) ? rd->name : rd->id
322 + , (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id
323 , rd->multiplier
324 , rd->divisor
325 , h
@@ -243,7 +327,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
327 , t
328 );
329
246 - if(unlikely(types))
330 + if(unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
331 buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s %s\n"
332 , prefix
333 , context
@@ -251,7 +335,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
335 , t
336 );
337
254 - if(timestamps)
338 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
339 buffer_sprintf(wb
340 , "%s_%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
341 , prefix
@@ -281,19 +365,19 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
365 // the dimensions of the chart, do not have the same algorithm, multiplier or divisor
366 // we create a metric per dimension
367
284 - prometheus_name_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
368 + prometheus_name_copy(dimension, (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
369
286 - if(unlikely(help))
370 + if(unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
371 buffer_sprintf(wb
372 , "# COMMENT %s_%s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
373 , prefix
374 , context
375 , dimension
376 , suffix
293 - , (names && st->name) ? st->name : st->id
377 + , (output_options & PROMETHEUS_OUTPUT_NAMES && st->name) ? st->name : st->id
378 , st->context
379 , st->family
296 - , (names && rd->name) ? rd->name : rd->id
380 + , (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id
381 , rd->multiplier
382 , rd->divisor
383 , h
@@ -301,7 +385,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
385 , t
386 );
387
304 - if(unlikely(types))
388 + if(unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
389 buffer_sprintf(wb, "# COMMENT TYPE %s_%s_%s%s %s\n"
390 , prefix
391 , context
@@ -310,7 +394,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
394 , t
395 );
396
313 - if(timestamps)
397 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
398 buffer_sprintf(wb
399 , "%s_%s_%s%s{chart=\"%s\",family=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
400 , prefix
@@ -341,30 +425,30 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
425 // we need average or sum of the data
426
427 time_t first_t = after, last_t = before;
344 - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
428 + calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, backend_options, &first_t, &last_t);
429
430 if(!isnan(value) && !isinf(value)) {
431
348 - if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
432 + if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AVERAGE)
433 suffix = "_average";
350 - else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM)
434 + else if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_SUM)
435 suffix = "_sum";
436
353 - prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
437 + prometheus_label_copy(dimension, (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
438
355 - if (unlikely(help))
439 + if (unlikely(output_options & PROMETHEUS_OUTPUT_HELP))
440 buffer_sprintf(wb, "# COMMENT %s_%s%s%s: dimension \"%s\", value is %s, gauge, dt %llu to %llu inclusive\n"
441 , prefix
442 , context
443 , units
444 , suffix
361 - , (names && rd->name) ? rd->name : rd->id
445 + , (output_options & PROMETHEUS_OUTPUT_NAMES && rd->name) ? rd->name : rd->id
446 , st->units
447 , (unsigned long long)first_t
448 , (unsigned long long)last_t
449 );
450
367 - if (unlikely(types))
451 + if (unlikely(output_options & PROMETHEUS_OUTPUT_TYPES))
452 buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s%s gauge\n"
453 , prefix
454 , context
@@ -372,7 +456,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
456 , suffix
457 );
458
375 - if(timestamps)
459 + if(output_options & PROMETHEUS_OUTPUT_TIMESTAMPS)
460 buffer_sprintf(wb, "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " CALCULATED_NUMBER_FORMAT " %llu\n"
461 , prefix
462 , context
@@ -409,32 +493,32 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
493 rrdhost_unlock(host);
494 }
495
412 -static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, uint32_t options, const char *server, time_t now, int help) {
496 +static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, BACKEND_OPTIONS backend_options, const char *server, time_t now, PROMETHEUS_OUTPUT_OPTIONS output_options) {
497 if(!server || !*server) server = "default";
498
499 time_t after = prometheus_server_last_access(server, host, now);
500
501 int first_seen = 0;
502 if(!after) {
419 - after = now - backend_update_every;
503 + after = now - global_backend_update_every;
504 first_seen = 1;
505 }
506
507 if(after > now) {
508 // oops! this should never happen
425 - after = now - backend_update_every;
509 + after = now - global_backend_update_every;
510 }
511
428 - if(help) {
512 + if(output_options & PROMETHEUS_OUTPUT_HELP) {
513 int show_range = 1;
514 char *mode;
431 - if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) {
515 + if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED) {
516 mode = "as collected";
517 show_range = 0;
518 }
435 - else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
519 + else if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AVERAGE)
520 mode = "average";
437 - else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM)
521 + else if(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_SUM)
522 mode = "sum";
523 else
524 mode = "unknown";
@@ -457,24 +541,24 @@ static inline time_t prometheus_preparation(RRDHOST *host, BUFFER *wb, uint32_t
541 return after;
542 }
543
460 -void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps) {
544 +void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, BACKEND_OPTIONS backend_options, PROMETHEUS_OUTPUT_OPTIONS output_options) {
545 time_t before = now_realtime_sec();
546
547 // we start at the point we had stopped before
464 - time_t after = prometheus_preparation(host, wb, options, server, before, help);
548 + time_t after = prometheus_preparation(host, wb, backend_options, server, before, output_options);
549
466 - rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, options, after, before, 0, help, types, names, timestamps);
550 + rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, backend_options, after, before, 0, output_options);
551 }
552
469 -void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps) {
553 +void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, BACKEND_OPTIONS backend_options, PROMETHEUS_OUTPUT_OPTIONS output_options) {
554 time_t before = now_realtime_sec();
555
556 // we start at the point we had stopped before
473 - time_t after = prometheus_preparation(host, wb, options, server, before, help);
557 + time_t after = prometheus_preparation(host, wb, backend_options, server, before, output_options);
558
559 rrd_rdlock();
560 rrdhost_foreach_read(host) {
477 - rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, options, after, before, 1, help, types, names, timestamps);
561 + rrd_stats_api_v1_charts_allmetrics_prometheus(host, wb, prefix, backend_options, after, before, 1, output_options);
562 }
563 rrd_unlock();
564 }
src/backend_prometheus.h
+11 -5
@@ -1,12 +1,18 @@
1 // SPDX-License-Identifier: GPL-3.0+
2 -//
3 -// Created by costa on 09/07/17.
4 -//
2
3 #ifndef NETDATA_BACKEND_PROMETHEUS_H
4 #define NETDATA_BACKEND_PROMETHEUS_H
5
9 -extern void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps);
10 -extern void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, uint32_t options, int help, int types, int names, int timestamps);
6 +typedef enum prometheus_output_flags {
7 + PROMETHEUS_OUTPUT_NONE = 0,
8 + PROMETHEUS_OUTPUT_HELP = (1 << 0),
9 + PROMETHEUS_OUTPUT_TYPES = (1 << 1),
10 + PROMETHEUS_OUTPUT_NAMES = (1 << 2),
11 + PROMETHEUS_OUTPUT_TIMESTAMPS = (1 << 3),
12 + PROMETHEUS_OUTPUT_VARIABLES = (1 << 4)
13 +} PROMETHEUS_OUTPUT_OPTIONS;
14 +
15 +extern void rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, BACKEND_OPTIONS backend_options, PROMETHEUS_OUTPUT_OPTIONS output_options);
16 +extern void rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(RRDHOST *host, BUFFER *wb, const char *server, const char *prefix, BACKEND_OPTIONS backend_options, PROMETHEUS_OUTPUT_OPTIONS output_options);
17
18 #endif //NETDATA_BACKEND_PROMETHEUS_H
src/backends.c
+79 -78
@@ -23,10 +23,9 @@
23 // 5. repeats the above forever.
24 //
25
26 -const char *backend_prefix = "netdata";
27 -int backend_send_names = 1;
28 -int backend_update_every = 10;
29 -uint32_t backend_options = BACKEND_SOURCE_DATA_AVERAGE;
26 +const char *global_backend_prefix = "netdata";
27 +int global_backend_update_every = 10;
28 +BACKEND_OPTIONS global_backend_options = BACKEND_SOURCE_DATA_AVERAGE | BACKEND_OPTION_SEND_NAMES;
29
30 // ----------------------------------------------------------------------------
31 // helper functions for backends
@@ -53,7 +52,7 @@ inline calculated_number backend_calculate_value_from_stored_data(
52 , RRDDIM *rd // the dimension
53 , time_t after // the start timestamp
54 , time_t before // the end timestamp
56 - , uint32_t options // BACKEND_SOURCE_* bitmap
55 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
56 , time_t *first_timestamp // the first point of the database used in this response
57 , time_t *last_timestamp // the timestamp that should be reported to backend
58 ) {
@@ -133,7 +132,7 @@ inline calculated_number backend_calculate_value_from_stored_data(
132 return NAN;
133 }
134
136 - if(unlikely((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM))
135 + if(unlikely(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_SUM))
136 return sum;
137
138 return sum / (calculated_number)counter;
@@ -173,27 +172,26 @@ static inline int format_dimension_collected_graphite_plaintext(
172 , RRDDIM *rd // the dimension
173 , time_t after // the start timestamp
174 , time_t before // the end timestamp
176 - , uint32_t options // BACKEND_SOURCE_* bitmap
175 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
176 ) {
177 (void)host;
178 (void)after;
179 (void)before;
181 - (void)options;
180
181 char chart_name[RRD_ID_LENGTH_MAX + 1];
182 char dimension_name[RRD_ID_LENGTH_MAX + 1];
185 - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
186 - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
183 + backend_name_copy(chart_name, (backend_options & BACKEND_OPTION_SEND_NAMES && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
184 + backend_name_copy(dimension_name, (backend_options & BACKEND_OPTION_SEND_NAMES && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
185
186 buffer_sprintf(
187 b
190 - , "%s.%s.%s.%s " COLLECTED_NUMBER_FORMAT " %u\n"
188 + , "%s.%s.%s.%s " COLLECTED_NUMBER_FORMAT " %llu\n"
189 , prefix
190 , hostname
191 , chart_name
192 , dimension_name
193 , rd->last_collected_value
196 - , (uint32_t)rd->last_collected_time.tv_sec
194 + , (unsigned long long)rd->last_collected_time.tv_sec
195 );
196
197 return 1;
@@ -208,29 +206,29 @@ static inline int format_dimension_stored_graphite_plaintext(
206 , RRDDIM *rd // the dimension
207 , time_t after // the start timestamp
208 , time_t before // the end timestamp
211 - , uint32_t options // BACKEND_SOURCE_* bitmap
209 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
210 ) {
211 (void)host;
212
213 char chart_name[RRD_ID_LENGTH_MAX + 1];
214 char dimension_name[RRD_ID_LENGTH_MAX + 1];
217 - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
218 - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
215 + backend_name_copy(chart_name, (backend_options & BACKEND_OPTION_SEND_NAMES && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
216 + backend_name_copy(dimension_name, (backend_options & BACKEND_OPTION_SEND_NAMES && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
217
218 time_t first_t = after, last_t = before;
221 - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
219 + calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, backend_options, &first_t, &last_t);
220
221 if(!isnan(value)) {
222
223 buffer_sprintf(
224 b
227 - , "%s.%s.%s.%s " CALCULATED_NUMBER_FORMAT " %u\n"
225 + , "%s.%s.%s.%s " CALCULATED_NUMBER_FORMAT " %llu\n"
226 , prefix
227 , hostname
228 , chart_name
229 , dimension_name
230 , value
233 - , (uint32_t) last_t
231 + , (unsigned long long) last_t
232 );
233
234 return 1;
@@ -255,25 +253,24 @@ static inline int format_dimension_collected_opentsdb_telnet(
253 , RRDDIM *rd // the dimension
254 , time_t after // the start timestamp
255 , time_t before // the end timestamp
258 - , uint32_t options // BACKEND_SOURCE_* bitmap
256 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
257 ) {
258 (void)host;
259 (void)after;
260 (void)before;
263 - (void)options;
261
262 char chart_name[RRD_ID_LENGTH_MAX + 1];
263 char dimension_name[RRD_ID_LENGTH_MAX + 1];
267 - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
268 - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
264 + backend_name_copy(chart_name, (backend_options & BACKEND_OPTION_SEND_NAMES && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
265 + backend_name_copy(dimension_name, (backend_options & BACKEND_OPTION_SEND_NAMES && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
266
267 buffer_sprintf(
268 b
272 - , "put %s.%s.%s %u " COLLECTED_NUMBER_FORMAT " host=%s%s%s\n"
269 + , "put %s.%s.%s %llu " COLLECTED_NUMBER_FORMAT " host=%s%s%s\n"
270 , prefix
271 , chart_name
272 , dimension_name
276 - , (uint32_t)rd->last_collected_time.tv_sec
273 + , (unsigned long long)rd->last_collected_time.tv_sec
274 , rd->last_collected_value
275 , hostname
276 , (host->tags)?" ":""
@@ -292,27 +289,27 @@ static inline int format_dimension_stored_opentsdb_telnet(
289 , RRDDIM *rd // the dimension
290 , time_t after // the start timestamp
291 , time_t before // the end timestamp
295 - , uint32_t options // BACKEND_SOURCE_* bitmap
292 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
293 ) {
294 (void)host;
295
296 time_t first_t = after, last_t = before;
300 - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
297 + calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, backend_options, &first_t, &last_t);
298
299 char chart_name[RRD_ID_LENGTH_MAX + 1];
300 char dimension_name[RRD_ID_LENGTH_MAX + 1];
304 - backend_name_copy(chart_name, (backend_send_names && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
305 - backend_name_copy(dimension_name, (backend_send_names && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
301 + backend_name_copy(chart_name, (backend_options & BACKEND_OPTION_SEND_NAMES && st->name)?st->name:st->id, RRD_ID_LENGTH_MAX);
302 + backend_name_copy(dimension_name, (backend_options & BACKEND_OPTION_SEND_NAMES && rd->name)?rd->name:rd->id, RRD_ID_LENGTH_MAX);
303
304 if(!isnan(value)) {
305
306 buffer_sprintf(
307 b
311 - , "put %s.%s.%s %u " CALCULATED_NUMBER_FORMAT " host=%s%s%s\n"
308 + , "put %s.%s.%s %llu " CALCULATED_NUMBER_FORMAT " host=%s%s%s\n"
309 , prefix
310 , chart_name
311 , dimension_name
315 - , (uint32_t) last_t
312 + , (unsigned long long) last_t
313 , value
314 , hostname
315 , (host->tags)?" ":""
@@ -341,12 +338,12 @@ static inline int format_dimension_collected_json_plaintext(
338 , RRDDIM *rd // the dimension
339 , time_t after // the start timestamp
340 , time_t before // the end timestamp
344 - , uint32_t options // BACKEND_SOURCE_* bitmap
341 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
342 ) {
343 (void)host;
344 (void)after;
345 (void)before;
349 - (void)options;
346 + (void)backend_options;
347
348 const char *tags_pre = "", *tags_post = "", *tags = host->tags;
349 if(!tags) tags = "";
@@ -378,7 +375,7 @@ static inline int format_dimension_collected_json_plaintext(
375 "\"name\":\"%s\","
376 "\"value\":" COLLECTED_NUMBER_FORMAT ","
377
381 - "\"timestamp\": %u}\n",
378 + "\"timestamp\": %llu}\n",
379 prefix,
380 hostname,
381 tags_pre, tags, tags_post,
@@ -394,7 +391,7 @@ static inline int format_dimension_collected_json_plaintext(
391 rd->name,
392 rd->last_collected_value,
393
397 - (uint32_t)rd->last_collected_time.tv_sec
394 + (unsigned long long) rd->last_collected_time.tv_sec
395 );
396
397 return 1;
@@ -409,12 +406,12 @@ static inline int format_dimension_stored_json_plaintext(
406 , RRDDIM *rd // the dimension
407 , time_t after // the start timestamp
408 , time_t before // the end timestamp
412 - , uint32_t options // BACKEND_SOURCE_* bitmap
409 + , BACKEND_OPTIONS backend_options // BACKEND_SOURCE_* bitmap
410 ) {
411 (void)host;
412
413 time_t first_t = after, last_t = before;
417 - calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
414 + calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, backend_options, &first_t, &last_t);
415
416 if(!isnan(value)) {
417 const char *tags_pre = "", *tags_post = "", *tags = host->tags;
@@ -447,7 +444,7 @@ static inline int format_dimension_stored_json_plaintext(
444 "\"name\":\"%s\","
445 "\"value\":" CALCULATED_NUMBER_FORMAT ","
446
450 - "\"timestamp\": %u}\n",
447 + "\"timestamp\": %llu}\n",
448 prefix,
449 hostname,
450 tags_pre, tags, tags_post,
@@ -461,9 +458,9 @@ static inline int format_dimension_stored_json_plaintext(
458
459 rd->id,
460 rd->name,
464 - value,
465 -
466 - (uint32_t) last_t
461 + value,
462 +
463 + (unsigned long long) last_t
464 );
465
466 return 1;
@@ -482,7 +479,7 @@ static inline int process_json_response(BUFFER *b) {
479 static SIMPLE_PATTERN *charts_pattern = NULL;
480 static SIMPLE_PATTERN *hosts_pattern = NULL;
481
485 -inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) {
482 +inline int backends_can_send_rrdset(BACKEND_OPTIONS backend_options, RRDSET *st) {
483 RRDHOST *host = st->rrdhost;
484
485 if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_BACKEND_IGNORE)))
@@ -504,7 +501,7 @@ inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) {
501 return 0;
502 }
503
507 - if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE && !((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED))) {
504 + if(unlikely(st->rrd_memory_mode == RRD_MEMORY_MODE_NONE && !(BACKEND_OPTIONS_DATA_SOURCE(backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED))) {
505 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, host->hostname, rrd_memory_mode_name(host->rrd_memory_mode));
506 return 0;
507 }
@@ -512,24 +509,24 @@ inline int backends_can_send_rrdset(uint32_t options, RRDSET *st) {
509 return 1;
510 }
511
515 -inline uint32_t backend_parse_data_source(const char *source, uint32_t mode) {
512 +inline BACKEND_OPTIONS backend_parse_data_source(const char *source, BACKEND_OPTIONS backend_options) {
513 if(!strcmp(source, "raw") || !strcmp(source, "as collected") || !strcmp(source, "as-collected") || !strcmp(source, "as_collected") || !strcmp(source, "ascollected")) {
517 - mode |= BACKEND_SOURCE_DATA_AS_COLLECTED;
518 - mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AS_COLLECTED);
514 + backend_options |= BACKEND_SOURCE_DATA_AS_COLLECTED;
515 + backend_options &= ~(BACKEND_OPTIONS_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AS_COLLECTED);
516 }
517 else if(!strcmp(source, "average")) {
521 - mode |= BACKEND_SOURCE_DATA_AVERAGE;
522 - mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AVERAGE);
518 + backend_options |= BACKEND_SOURCE_DATA_AVERAGE;
519 + backend_options &= ~(BACKEND_OPTIONS_SOURCE_BITS ^ BACKEND_SOURCE_DATA_AVERAGE);
520 }
521 else if(!strcmp(source, "sum") || !strcmp(source, "volume")) {
525 - mode |= BACKEND_SOURCE_DATA_SUM;
526 - mode &= ~(BACKEND_SOURCE_BITS ^ BACKEND_SOURCE_DATA_SUM);
522 + backend_options |= BACKEND_SOURCE_DATA_SUM;
523 + backend_options &= ~(BACKEND_OPTIONS_SOURCE_BITS ^ BACKEND_SOURCE_DATA_SUM);
524 }
525 else {
526 error("BACKEND: invalid data source method '%s'.", source);
527 }
528
532 - return mode;
529 + return backend_options;
530 }
531
532 static void backends_main_cleanup(void *ptr) {
@@ -547,7 +544,7 @@ void *backends_main(void *ptr) {
544 int default_port = 0;
545 int sock = -1;
546 BUFFER *b = buffer_create(1), *response = buffer_create(1);
550 - int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, uint32_t) = NULL;
547 + int (*backend_request_formatter)(BUFFER *, const char *, RRDHOST *, const char *, RRDSET *, RRDDIM *, time_t, time_t, BACKEND_OPTIONS) = NULL;
548 int (*backend_response_checker)(BUFFER *) = NULL;
549
550 // ------------------------------------------------------------------------
@@ -557,35 +554,39 @@ void *backends_main(void *ptr) {
554 .tv_sec = 0,
555 .tv_usec = 0
556 };
560 - int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0);
561 - const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average");
562 - const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite");
563 - const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost");
564 - backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata");
565 - const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname);
566 - backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", backend_update_every);
567 - int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10);
568 - long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", backend_update_every * 2 * 1000);
569 - backend_send_names = config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", backend_send_names);
557 + int enabled = config_get_boolean(CONFIG_SECTION_BACKEND, "enabled", 0);
558 + const char *source = config_get(CONFIG_SECTION_BACKEND, "data source", "average");
559 + const char *type = config_get(CONFIG_SECTION_BACKEND, "type", "graphite");
560 + const char *destination = config_get(CONFIG_SECTION_BACKEND, "destination", "localhost");
561 + global_backend_prefix = config_get(CONFIG_SECTION_BACKEND, "prefix", "netdata");
562 + const char *hostname = config_get(CONFIG_SECTION_BACKEND, "hostname", localhost->hostname);
563 + global_backend_update_every = (int)config_get_number(CONFIG_SECTION_BACKEND, "update every", global_backend_update_every);
564 + int buffer_on_failures = (int)config_get_number(CONFIG_SECTION_BACKEND, "buffer on failures", 10);
565 + long timeoutms = config_get_number(CONFIG_SECTION_BACKEND, "timeout ms", global_backend_update_every * 2 * 1000);
566 +
567 + if(config_get_boolean(CONFIG_SECTION_BACKEND, "send names instead of ids", (global_backend_options & BACKEND_OPTION_SEND_NAMES)))
568 + global_backend_options |= BACKEND_OPTION_SEND_NAMES;
569 + else
570 + global_backend_options &= ~BACKEND_OPTION_SEND_NAMES;
571
572 charts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send charts matching", "*"), NULL, SIMPLE_PATTERN_EXACT);
572 - hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
573 + hosts_pattern = simple_pattern_create(config_get(CONFIG_SECTION_BACKEND, "send hosts matching", "localhost *"), NULL, SIMPLE_PATTERN_EXACT);
574
575
576 // ------------------------------------------------------------------------
577 // validate configuration options
578 // and prepare for sending data to our backend
579
579 - backend_options = backend_parse_data_source(source, backend_options);
580 + global_backend_options = backend_parse_data_source(source, global_backend_options);
581
582 if(timeoutms < 1) {
582 - error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, backend_update_every * 2 * 1000);
583 - timeoutms = backend_update_every * 2 * 1000;
583 + error("BACKEND: invalid timeout %ld ms given. Assuming %d ms.", timeoutms, global_backend_update_every * 2 * 1000);
584 + timeoutms = global_backend_update_every * 2 * 1000;
585 }
586 timeout.tv_sec = (timeoutms * 1000) / 1000000;
587 timeout.tv_usec = (timeoutms * 1000) % 1000000;
588
588 - if(!enabled || backend_update_every < 1)
589 + if(!enabled || global_backend_update_every < 1)
590 goto cleanup;
591
592 // ------------------------------------------------------------------------
@@ -596,7 +597,7 @@ void *backends_main(void *ptr) {
597 default_port = 2003;
598 backend_response_checker = process_graphite_response;
599
599 - if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
600 + if(BACKEND_OPTIONS_DATA_SOURCE(global_backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED)
601 backend_request_formatter = format_dimension_collected_graphite_plaintext;
602 else
603 backend_request_formatter = format_dimension_stored_graphite_plaintext;
@@ -607,7 +608,7 @@ void *backends_main(void *ptr) {
608 default_port = 4242;
609 backend_response_checker = process_opentsdb_response;
610
610 - if((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
611 + if(BACKEND_OPTIONS_DATA_SOURCE(global_backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED)
612 backend_request_formatter = format_dimension_collected_opentsdb_telnet;
613 else
614 backend_request_formatter = format_dimension_stored_opentsdb_telnet;
@@ -618,7 +619,7 @@ void *backends_main(void *ptr) {
619 default_port = 5448;
620 backend_response_checker = process_json_response;
621
621 - if ((backend_options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED)
622 + if (BACKEND_OPTIONS_DATA_SOURCE(global_backend_options) == BACKEND_SOURCE_DATA_AS_COLLECTED)
623 backend_request_formatter = format_dimension_collected_json_plaintext;
624 else
625 backend_request_formatter = format_dimension_stored_json_plaintext;
@@ -655,18 +656,18 @@ void *backends_main(void *ptr) {
656 chart_backend_reconnects = 0,
657 chart_backend_latency = 0;
658
658 - RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, backend_update_every, RRDSET_TYPE_LINE);
659 + RRDSET *chart_metrics = rrdset_create_localhost("netdata", "backend_metrics", NULL, "backend", NULL, "Netdata Buffered Metrics", "metrics", "backends", NULL, 130600, global_backend_update_every, RRDSET_TYPE_LINE);
660 rrddim_add(chart_metrics, "buffered", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
661 rrddim_add(chart_metrics, "lost", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
662 rrddim_add(chart_metrics, "sent", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
663
663 - RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, backend_update_every, RRDSET_TYPE_AREA);
664 + RRDSET *chart_bytes = rrdset_create_localhost("netdata", "backend_bytes", NULL, "backend", NULL, "Netdata Backend Data Size", "KB", "backends", NULL, 130610, global_backend_update_every, RRDSET_TYPE_AREA);
665 rrddim_add(chart_bytes, "buffered", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
666 rrddim_add(chart_bytes, "lost", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
667 rrddim_add(chart_bytes, "sent", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
668 rrddim_add(chart_bytes, "received", NULL, 1, 1024, RRD_ALGORITHM_ABSOLUTE);
669
669 - RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_LINE);
670 + RRDSET *chart_ops = rrdset_create_localhost("netdata", "backend_ops", NULL, "backend", NULL, "Netdata Backend Operations", "operations", "backends", NULL, 130630, global_backend_update_every, RRDSET_TYPE_LINE);
671 rrddim_add(chart_ops, "write", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
672 rrddim_add(chart_ops, "discard", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
673 rrddim_add(chart_ops, "reconnect", NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE);
@@ -680,11 +681,11 @@ void *backends_main(void *ptr) {
681 *
682 * issue #1432 and https://www.softlab.ntua.gr/facilities/documentation/unix/unix-socket-faq/unix-socket-faq-2.html
683 *
683 - RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, backend_update_every, RRDSET_TYPE_AREA);
684 + RRDSET *chart_latency = rrdset_create_localhost("netdata", "backend_latency", NULL, "backend", NULL, "Netdata Backend Latency", "ms", "backends", NULL, 130620, global_backend_update_every, RRDSET_TYPE_AREA);
685 rrddim_add(chart_latency, "latency", NULL, 1, 1000, RRD_ALGORITHM_ABSOLUTE);
686 */
687
687 - RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, backend_update_every, RRDSET_TYPE_STACKED);
688 + RRDSET *chart_rusage = rrdset_create_localhost("netdata", "backend_thread_cpu", NULL, "backend", NULL, "NetData Backend Thread CPU usage", "milliseconds/s", "backends", NULL, 130630, global_backend_update_every, RRDSET_TYPE_STACKED);
689 rrddim_add(chart_rusage, "user", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
690 rrddim_add(chart_rusage, "system", NULL, 1, 1000, RRD_ALGORITHM_INCREMENTAL);
691
@@ -692,9 +693,9 @@ void *backends_main(void *ptr) {
693 // ------------------------------------------------------------------------
694 // prepare the backend main loop
695
695 - 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);
696 + info("BACKEND: configured ('%s' on '%s' sending '%s' data, every %d seconds, as host '%s', with prefix '%s')", type, destination, source, global_backend_update_every, hostname, global_backend_prefix);
697
697 - usec_t step_ut = backend_update_every * USEC_PER_SEC;
698 + usec_t step_ut = global_backend_update_every * USEC_PER_SEC;
699 time_t after = now_realtime_sec();
700 int failures = 0;
701 heartbeat_t hb;
@@ -747,7 +748,7 @@ void *backends_main(void *ptr) {
748
749 RRDSET *st;
750 rrdset_foreach_read(st, host) {
750 - if(likely(backends_can_send_rrdset(backend_options, st))) {
751 + if(likely(backends_can_send_rrdset(global_backend_options, st))) {
752 rrdset_rdlock(st);
753
754 count_charts++;
@@ -755,7 +756,7 @@ void *backends_main(void *ptr) {
756 RRDDIM *rd;
757 rrddim_foreach_read(rd, st) {
758 if (likely(rd->last_collected_time.tv_sec >= after)) {
758 - chart_buffered_metrics += backend_request_formatter(b, backend_prefix, host, __hostname, st, rd, after, before, backend_options);
759 + chart_buffered_metrics += backend_request_formatter(b, global_backend_prefix, host, __hostname, st, rd, after, before, global_backend_options);
760 count_dims++;
761 }
762 else {
src/backends.h
+16 -10
@@ -2,21 +2,27 @@
2 #ifndef NETDATA_BACKENDS_H
3 #define NETDATA_BACKENDS_H 1
4
5 -#define BACKEND_SOURCE_DATA_AS_COLLECTED 0x00000001
6 -#define BACKEND_SOURCE_DATA_AVERAGE 0x00000002
7 -#define BACKEND_SOURCE_DATA_SUM 0x00000004
5 +typedef enum backend_options {
6 + BACKEND_OPTION_NONE = 0,
7
9 -#define BACKEND_SOURCE_BITS (BACKEND_SOURCE_DATA_AS_COLLECTED|BACKEND_SOURCE_DATA_AVERAGE|BACKEND_SOURCE_DATA_SUM)
8 + BACKEND_SOURCE_DATA_AS_COLLECTED = (1 << 0),
9 + BACKEND_SOURCE_DATA_AVERAGE = (1 << 1),
10 + BACKEND_SOURCE_DATA_SUM = (1 << 2),
11
11 -extern int backend_send_names;
12 -extern int backend_update_every;
13 -extern uint32_t backend_options;
14 -extern const char *backend_prefix;
12 + BACKEND_OPTION_SEND_NAMES = (1 << 16)
13 +} BACKEND_OPTIONS;
14 +
15 +#define BACKEND_OPTIONS_SOURCE_BITS (BACKEND_SOURCE_DATA_AS_COLLECTED|BACKEND_SOURCE_DATA_AVERAGE|BACKEND_SOURCE_DATA_SUM)
16 +#define BACKEND_OPTIONS_DATA_SOURCE(backend_options) (backend_options & BACKEND_OPTIONS_SOURCE_BITS)
17 +
18 +extern int global_backend_update_every;
19 +extern BACKEND_OPTIONS global_backend_options;
20 +extern const char *global_backend_prefix;
21
22 extern void *backends_main(void *ptr);
23
18 -extern int backends_can_send_rrdset(uint32_t options, RRDSET *st);
19 -extern uint32_t backend_parse_data_source(const char *source, uint32_t mode);
24 +extern int backends_can_send_rrdset(BACKEND_OPTIONS options, RRDSET *st);
25 +extern BACKEND_OPTIONS backend_parse_data_source(const char *source, BACKEND_OPTIONS mode);
26
27 extern calculated_number backend_calculate_value_from_stored_data(
28 RRDSET *st // the chart
src/health.c
+5
@@ -522,6 +522,11 @@ void *health_main(void *ptr) {
522 );
523
524 rc->value = rc->calculation->result;
525 +
526 + if(rc->local) rc->local->last_updated = now;
527 + if(rc->family) rc->family->last_updated = now;
528 + if(rc->hostid) rc->hostid->last_updated = now;
529 + if(rc->hostname) rc->hostname->last_updated = now;
530 }
531 }
532 }
src/health.h
+18 -10
@@ -11,11 +11,20 @@ typedef enum rrdvar_type {
11 RRDVAR_TYPE_TIME_T = 2,
12 RRDVAR_TYPE_COLLECTED = 3,
13 RRDVAR_TYPE_TOTAL = 4,
14 - RRDVAR_TYPE_INT = 5,
15 - RRDVAR_TYPE_CALCULATED_ALLOCATED = 6 // a custom variable, allocated on purpose (ie. not inherited from charts)
16 - // used only for custom host global variables
14 + RRDVAR_TYPE_INT = 5
15 } RRDVAR_TYPE;
16
17 +typedef enum rrdvar_options {
18 + RRDVAR_OPTION_DEFAULT = 0,
19 + RRDVAR_OPTION_ALLOCATED = (1 << 0), // the value ptr is allocated (not a reference)
20 + RRDVAR_OPTION_CUSTOM_HOST_VAR = (1 << 1), // this is a custom host variable, not associated with a dimension
21 + RRDVAR_OPTION_CUSTOM_CHART_VAR = (1 << 2), // this is a custom chart variable, not associated with a dimension
22 + RRDVAR_OPTION_RRDCALC_LOCAL_VAR = (1 << 3), // this is a an alarm variable, attached to a chart
23 + RRDVAR_OPTION_RRDCALC_FAMILY_VAR = (1 << 4), // this is a an alarm variable, attached to a family
24 + RRDVAR_OPTION_RRDCALC_HOST_CHARTID_VAR = (1 << 5), // this is a an alarm variable, attached to the host, using the chart id
25 + RRDVAR_OPTION_RRDCALC_HOST_CHARTNAME_VAR = (1 << 6), // this is a an alarm variable, attached to the host, using the chart name
26 +} RRDVAR_OPTIONS;
27 +
28 // the variables as stored in the variables indexes
29 // there are 3 indexes:
30 // 1. at each chart (RRDSET.rrdvar_root_index)
@@ -28,6 +37,8 @@ typedef struct rrdvar {
37 uint32_t hash;
38
39 RRDVAR_TYPE type;
40 + RRDVAR_OPTIONS options;
41 +
42 void *value;
43
44 time_t last_updated;
@@ -39,12 +50,6 @@ typedef struct rrdvar {
50 // This means, there will be no speed penalty for using
51 // these variables
52
42 -typedef enum rrdvar_options {
43 - RRDVAR_OPTION_DEFAULT = (0 << 0),
44 - RRDVAR_OPTION_ALLOCATED = (1 << 0) // the value ptr is allocated (not a reference)
45 - // future use
46 -} RRDVAR_OPTIONS;
47 -
53 typedef struct rrdsetvar {
54 char *variable; // variable name
55 uint32_t hash; // variable name hash
@@ -343,6 +348,8 @@ typedef struct alarm_log {
348
349 #include "rrd.h"
350
351 +extern calculated_number rrdvar2number(RRDVAR *rv);
352 +
353 extern void rrdsetvar_rename_all(RRDSET *st);
354 extern RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options);
355 extern void rrdsetvar_free(RRDSETVAR *rs);
@@ -369,6 +376,7 @@ void health_api_v1_chart_variables2json(RRDSET *st, BUFFER *buf);
376
377 extern RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name);
378 extern void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value);
379 +extern int foreach_host_variable_callback(RRDHOST *host, int (*callback)(RRDVAR *rv, void *data), void *data);
380
381 extern RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name);
382 extern void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rv, calculated_number value);
@@ -429,7 +437,7 @@ extern int rrdvar_fix_name(char *variable);
437 extern RRDCALC *rrdcalc_create(RRDHOST *host, RRDCALCTEMPLATE *rt, const char *chart);
438 extern void rrdcalc_create_part2(RRDHOST *host, RRDCALC *rc);
439
432 -extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value);
440 +extern RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, RRDVAR_OPTIONS options, void *value);
441 extern void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv);
442
443 extern void health_alarm_log_free_one_nochecks_nounlink(ALARM_ENTRY *ae);
src/ipc.c
+5 -5
@@ -167,7 +167,7 @@ int do_ipc(int update_every, usec_t dt) {
167 static int initialized = 0, read_limits_next = -1;
168 static struct ipc_limits limits;
169 static struct ipc_status status;
170 - static RRDSETVAR *arrays_max = NULL, *semaphores_max = NULL;
170 + static RRDVAR *arrays_max = NULL, *semaphores_max = NULL;
171 static RRDSET *st_semaphores = NULL, *st_arrays = NULL;
172 static RRDDIM *rd_semaphores = NULL, *rd_arrays = NULL;
173
@@ -224,8 +224,8 @@ int do_ipc(int update_every, usec_t dt) {
224 }
225
226 // variables
227 - semaphores_max = rrdsetvar_custom_chart_variable_create(st_semaphores, "ipc.semaphores.max");
228 - arrays_max = rrdsetvar_custom_chart_variable_create(st_arrays, "ipc.semaphores.arrays.max");
227 + semaphores_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_max");
228 + arrays_max = rrdvar_custom_host_variable_create(localhost, "ipc_semaphores_arrays_max");
229 }
230
231 if(unlikely(read_limits_next < 0)) {
@@ -233,8 +233,8 @@ int do_ipc(int update_every, usec_t dt) {
233 error("Unable to fetch semaphore limits.");
234 }
235 else {
236 - if(semaphores_max) rrdsetvar_custom_chart_variable_set(semaphores_max, limits.semmns);
237 - if(arrays_max) rrdsetvar_custom_chart_variable_set(arrays_max, limits.semmni);
236 + if(semaphores_max) rrdvar_custom_host_variable_set(localhost, semaphores_max, limits.semmns);
237 + if(arrays_max) rrdvar_custom_host_variable_set(localhost, arrays_max, limits.semmni);
238
239 st_arrays->red = limits.semmni;
240 st_semaphores->red = limits.semmns;
src/proc_net_snmp.c
+3 -6
@@ -103,7 +103,6 @@ int do_proc_net_snmp(int update_every, usec_t dt) {
103 *arl_udplite = NULL;
104
105 static RRDVAR *tcp_max_connections_var = NULL;
106 - static ssize_t last_max_connections = 0;
106
107 if(unlikely(!arl_ip)) {
108 do_ip_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/snmp", "ipv4 packets", CONFIG_BOOLEAN_AUTO);
@@ -182,7 +181,7 @@ int do_proc_net_snmp(int update_every, usec_t dt) {
181 // arl_expect(arl_tcp, "RtoAlgorithm", &snmp_root.tcp_RtoAlgorithm);
182 // arl_expect(arl_tcp, "RtoMin", &snmp_root.tcp_RtoMin);
183 // arl_expect(arl_tcp, "RtoMax", &snmp_root.tcp_RtoMax);
185 - arl_expect(arl_tcp, "MaxConn", &snmp_root.tcp_MaxConn);
184 + arl_expect_custom(arl_tcp, "MaxConn", arl_callback_ssize_t, &snmp_root.tcp_MaxConn);
185 arl_expect(arl_tcp, "ActiveOpens", &snmp_root.tcp_ActiveOpens);
186 arl_expect(arl_tcp, "PassiveOpens", &snmp_root.tcp_PassiveOpens);
187 arl_expect(arl_tcp, "AttemptFails", &snmp_root.tcp_AttemptFails);
@@ -670,10 +669,8 @@ int do_proc_net_snmp(int update_every, usec_t dt) {
669
670 // --------------------------------------------------------------------
671
673 - if(snmp_root.tcp_MaxConn != last_max_connections) {
674 - last_max_connections = snmp_root.tcp_MaxConn;
675 - rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, last_max_connections);
676 - }
672 + // this is smart enough to update it, only when it is changed
673 + rrdvar_custom_host_variable_set(localhost, tcp_max_connections_var, snmp_root.tcp_MaxConn);
674
675 // --------------------------------------------------------------------
676
src/proc_stat.c
+3 -3
@@ -122,7 +122,7 @@ int do_proc_stat(int update_every, usec_t dt) {
122 static int do_cpu = -1, do_cpu_cores = -1, do_interrupts = -1, do_context = -1, do_forks = -1, do_processes = -1, do_core_throttle_count = -1, do_package_throttle_count = -1, do_scaling_cur_freq = -1;
123 static uint32_t hash_intr, hash_ctxt, hash_processes, hash_procs_running, hash_procs_blocked;
124 static char *core_throttle_count_filename = NULL, *package_throttle_count_filename = NULL, *scaling_cur_freq_filename = NULL;
125 - static RRDSETVAR *cpus_var = NULL;
125 + static RRDVAR *cpus_var = NULL;
126 size_t cores_found = (size_t)processors;
127
128 if(unlikely(do_cpu == -1)) {
@@ -314,7 +314,7 @@ int do_proc_stat(int update_every, usec_t dt) {
314 rrddim_hide(cpu_chart->st, "idle");
315
316 if(unlikely(core == 0 && cpus_var == NULL))
317 - cpus_var = rrdsetvar_custom_chart_variable_create(cpu_chart->st, "processors");
317 + cpus_var = rrdvar_custom_host_variable_create(localhost, "active_processors");
318 }
319 else rrdset_next(cpu_chart->st);
320
@@ -561,7 +561,7 @@ int do_proc_stat(int update_every, usec_t dt) {
561 }
562
563 if(cpus_var)
564 - rrdsetvar_custom_chart_variable_set(cpus_var, cores_found);
564 + rrdvar_custom_host_variable_set(localhost, cpus_var, cores_found);
565
566 return 0;
567 }
src/rrd.h
+2 -2
@@ -104,8 +104,8 @@ typedef struct rrdfamily RRDFAMILY;
104
105 typedef enum rrddim_flags {
106 RRDDIM_FLAG_NONE = 0,
107 - RRDDIM_FLAG_HIDDEN = 1 << 0, // this dimension will not be offered to callers
108 - RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = 1 << 1 // do not offer RESET or OVERFLOW info to callers
107 + RRDDIM_FLAG_HIDDEN = (1 << 0), // this dimension will not be offered to callers
108 + RRDDIM_FLAG_DONT_DETECT_RESETS_OR_OVERFLOWS = (1 << 1) // do not offer RESET or OVERFLOW info to callers
109 } RRDDIM_FLAGS;
110
111 #ifdef HAVE_C___ATOMIC
src/rrdcalc.c
+7 -4
@@ -65,15 +65,18 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
65 st->red = rc->red;
66 }
67
68 - rc->local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
69 - rc->family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, &rc->value);
68 + rc->local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_LOCAL_VAR, &rc->value);
69 + rc->family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rc->name, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_FAMILY_VAR, &rc->value);
70
71 char fullname[RRDVAR_MAX_LENGTH + 1];
72 snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->id, rc->name);
73 - rc->hostid = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value);
73 + rc->hostid = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_HOST_CHARTID_VAR, &rc->value);
74
75 snprintfz(fullname, RRDVAR_MAX_LENGTH, "%s.%s", st->name, rc->name);
76 - rc->hostname = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, &rc->value);
76 + rc->hostname = rrdvar_create_and_index("host", &host->rrdvar_root_index, fullname, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_RRDCALC_HOST_CHARTNAME_VAR, &rc->value);
77 +
78 + if(rc->hostid && !rc->hostname)
79 + rc->hostid->options |= RRDVAR_OPTION_RRDCALC_HOST_CHARTNAME_VAR;
80
81 if(!rc->units) rc->units = strdupz(st->units);
82
src/rrddimvar.c
+10 -10
@@ -118,8 +118,8 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) {
118 // - $id
119 // - $name
120
121 - rs->var_local_id = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_id, rs->type, rs->value);
122 - rs->var_local_name = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_name, rs->type, rs->value);
121 + rs->var_local_id = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_id, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
122 + rs->var_local_name = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->key_name, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
123
124 // FAMILY VARIABLES FOR THIS DIMENSION
125 // -----------------------------------
@@ -130,10 +130,10 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) {
130 // - $chart-context.id
131 // - $chart-context.name
132
133 - rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_id, rs->type, rs->value);
134 - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_name, rs->type, rs->value);
135 - rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextid, rs->type, rs->value);
136 - rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextname, rs->type, rs->value);
133 + rs->var_family_id = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_id, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
134 + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_name, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
135 + rs->var_family_contextid = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextid, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
136 + rs->var_family_contextname = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_contextname, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
137
138 // HOST VARIABLES FOR THIS DIMENSION
139 // -----------------------------------
@@ -144,10 +144,10 @@ static inline void rrddimvar_create_variables(RRDDIMVAR *rs) {
144 // - $chart-name.id
145 // - $chart-name.name
146
147 - rs->var_host_chartidid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidid, rs->type, rs->value);
148 - rs->var_host_chartidname = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidname, rs->type, rs->value);
149 - rs->var_host_chartnameid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnameid, rs->type, rs->value);
150 - rs->var_host_chartnamename = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnamename, rs->type, rs->value);
147 + rs->var_host_chartidid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidid, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
148 + rs->var_host_chartidname = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullidname, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
149 + rs->var_host_chartnameid = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnameid, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
150 + rs->var_host_chartnamename = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullnamename, rs->type, RRDVAR_OPTION_DEFAULT, rs->value);
151 }
152
153 RRDDIMVAR *rrddimvar_create(RRDDIM *rd, RRDVAR_TYPE type, const char *prefix, const char *suffix, void *value, RRDVAR_OPTIONS options) {
src/rrdpush.c
+2 -2
@@ -135,7 +135,7 @@ static inline void rrdpush_send_chart_definition_nolock(RRDSET *st) {
135 // send the chart local custom variables
136 RRDSETVAR *rs;
137 for(rs = st->variables; rs ;rs = rs->next) {
138 - if(unlikely(rs->options && RRDVAR_OPTION_ALLOCATED)) {
138 + if(unlikely(rs->type == RRDVAR_TYPE_CALCULATED && rs->options & RRDVAR_OPTION_CUSTOM_CHART_VAR)) {
139 calculated_number *value = (calculated_number *) rs->value;
140
141 buffer_sprintf(
@@ -245,7 +245,7 @@ static int rrdpush_sender_thread_custom_host_variables_callback(void *rrdvar_ptr
245 RRDVAR *rv = (RRDVAR *)rrdvar_ptr;
246 RRDHOST *host = (RRDHOST *)host_ptr;
247
248 - if(unlikely(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)) {
248 + if(unlikely(rv->options & RRDVAR_OPTION_CUSTOM_HOST_VAR && rv->type == RRDVAR_TYPE_CALCULATED)) {
249 rrdpush_sender_add_host_variable_to_buffer_nolock(host, rv);
250
251 // return 1, so that the traversal will return the number of variables sent
src/rrdsetvar.c
+13 -9
@@ -44,6 +44,10 @@ static inline void rrdsetvar_create_variables(RRDSETVAR *rs) {
44 RRDSET *st = rs->rrdset;
45 RRDHOST *host = st->rrdhost;
46
47 + RRDVAR_OPTIONS options = rs->options;
48 + if(rs->options & RRDVAR_OPTION_ALLOCATED)
49 + options &= ~ RRDVAR_OPTION_ALLOCATED;
50 +
51 // ------------------------------------------------------------------------
52 // free the old ones (if any)
53
@@ -61,17 +65,17 @@ static inline void rrdsetvar_create_variables(RRDSETVAR *rs) {
65
66 // ------------------------------------------------------------------------
67 // CHART
64 - rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, rs->value);
68 + rs->var_local = rrdvar_create_and_index("local", &st->rrdvar_root_index, rs->variable, rs->type, options, rs->value);
69
70 // ------------------------------------------------------------------------
71 // FAMILY
68 - rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
69 - rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
72 + rs->var_family = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullid, rs->type, options, rs->value);
73 + rs->var_family_name = rrdvar_create_and_index("family", &st->rrdfamily->rrdvar_root_index, rs->key_fullname, rs->type, options, rs->value);
74
75 // ------------------------------------------------------------------------
76 // HOST
73 - rs->var_host = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullid, rs->type, rs->value);
74 - rs->var_host_name = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullname, rs->type, rs->value);
77 + rs->var_host = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullid, rs->type, options, rs->value);
78 + rs->var_host_name = rrdvar_create_and_index("host", &host->rrdvar_root_index, rs->key_fullname, rs->type, options, rs->value);
79 }
80
81 RRDSETVAR *rrdsetvar_create(RRDSET *st, const char *variable, RRDVAR_TYPE type, void *value, RRDVAR_OPTIONS options) {
@@ -144,7 +148,7 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name)
148 for(rs = st->variables; rs ; rs = rs->next) {
149 if(hash == rs->hash && strcmp(n, rs->variable) == 0) {
150 rrdset_unlock(st);
147 - if(rs->options & RRDVAR_OPTION_ALLOCATED) {
151 + if(rs->options & RRDVAR_OPTION_CUSTOM_CHART_VAR) {
152 free(n);
153 return rs;
154 }
@@ -161,7 +165,7 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name)
165 calculated_number *v = mallocz(sizeof(calculated_number));
166 *v = NAN;
167
164 - rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED);
168 + rs = rrdsetvar_create(st, n, RRDVAR_TYPE_CALCULATED, v, RRDVAR_OPTION_ALLOCATED|RRDVAR_OPTION_CUSTOM_CHART_VAR);
169 rrdset_unlock(st);
170
171 free(n);
@@ -169,8 +173,8 @@ RRDSETVAR *rrdsetvar_custom_chart_variable_create(RRDSET *st, const char *name)
173 }
174
175 void rrdsetvar_custom_chart_variable_set(RRDSETVAR *rs, calculated_number value) {
172 - if(unlikely(!(rs->options & RRDVAR_OPTION_ALLOCATED))) {
173 - error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value);
176 + if(rs->type != RRDVAR_TYPE_CALCULATED || !(rs->options & RRDVAR_OPTION_CUSTOM_CHART_VAR) || !(rs->options & RRDVAR_OPTION_ALLOCATED)) {
177 + error("RRDSETVAR: requested to set variable '%s' of chart '%s' on host '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom chart one.", rs->variable, rs->rrdset->id, rs->rrdset->rrdhost->hostname, value);
178 }
179 else {
180 calculated_number *v = rs->value;
src/rrdvar.c
+14 -6
@@ -60,14 +60,14 @@ inline void rrdvar_free(RRDHOST *host, avl_tree_lock *tree, RRDVAR *rv) {
60 error("RRDVAR: Attempted to delete variable '%s' from host '%s', but it is not found.", rv->name, host->hostname);
61 }
62
63 - if(rv->type == RRDVAR_TYPE_CALCULATED_ALLOCATED)
63 + if(rv->options & RRDVAR_OPTION_ALLOCATED)
64 freez(rv->value);
65
66 freez(rv->name);
67 freez(rv);
68 }
69
70 -inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, void *value) {
70 +inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, const char *name, RRDVAR_TYPE type, RRDVAR_OPTIONS options, void *value) {
71 char *variable = strdupz(name);
72 rrdvar_fix_name(variable);
73 uint32_t hash = simple_hash(variable);
@@ -80,7 +80,9 @@ inline RRDVAR *rrdvar_create_and_index(const char *scope, avl_tree_lock *tree, c
80 rv->name = variable;
81 rv->hash = hash;
82 rv->type = type;
83 + rv->options = options;
84 rv->value = value;
85 + rv->last_updated = now_realtime_sec();
86
87 RRDVAR *ret = rrdvar_index_add(tree, rv);
88 if(unlikely(ret != rv)) {
@@ -132,7 +134,7 @@ static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *t
134 calculated_number *v = callocz(1, sizeof(calculated_number));
135 *v = NAN;
136
135 - RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED_ALLOCATED, v);
137 + RRDVAR *rv = rrdvar_create_and_index(scope, tree_lock, name, RRDVAR_TYPE_CALCULATED, RRDVAR_OPTION_CUSTOM_HOST_VAR|RRDVAR_OPTION_ALLOCATED, v);
138 if(unlikely(!rv)) {
139 free(v);
140 debug(D_VARIABLES, "Requested variable '%s' already exists - possibly 2 plugins are updating it at the same time.", name);
@@ -141,6 +143,7 @@ static RRDVAR *rrdvar_custom_variable_create(const char *scope, avl_tree_lock *t
143 rrdvar_fix_name(variable);
144 uint32_t hash = simple_hash(variable);
145
146 + // find the existing one to return it
147 rv = rrdvar_index_find(tree_lock, variable, hash);
148
149 freez(variable);
@@ -154,25 +157,30 @@ RRDVAR *rrdvar_custom_host_variable_create(RRDHOST *host, const char *name) {
157 }
158
159 void rrdvar_custom_host_variable_set(RRDHOST *host, RRDVAR *rv, calculated_number value) {
157 - if(rv->type != RRDVAR_TYPE_CALCULATED_ALLOCATED)
160 + if(rv->type != RRDVAR_TYPE_CALCULATED || !(rv->options & RRDVAR_OPTION_CUSTOM_HOST_VAR) || !(rv->options & RRDVAR_OPTION_ALLOCATED))
161 error("requested to set variable '%s' to value " CALCULATED_NUMBER_FORMAT " but the variable is not a custom one.", rv->name, value);
162 else {
163 calculated_number *v = rv->value;
164 if(*v != value) {
165 *v = value;
166
167 + rv->last_updated = now_realtime_sec();
168 +
169 // if the host is streaming, send this variable upstream immediately
170 rrdpush_sender_send_this_host_variable_now(host, rv);
171 }
172 }
173 }
174
175 +int foreach_host_variable_callback(RRDHOST *host, int (*callback)(RRDVAR *rv, void *data), void *data) {
176 + return avl_traverse_lock(&host->rrdvar_root_index, (int (*)(void *, void *))callback, data);
177 +}
178 +
179 // ----------------------------------------------------------------------------
180 // RRDVAR lookup
181
173 -static calculated_number rrdvar2number(RRDVAR *rv) {
182 +calculated_number rrdvar2number(RRDVAR *rv) {
183 switch(rv->type) {
175 - case RRDVAR_TYPE_CALCULATED_ALLOCATED:
184 case RRDVAR_TYPE_CALCULATED: {
185 calculated_number *n = (calculated_number *)rv->value;
186 return *n;
src/web_api_v1.c
+33 -30
@@ -253,12 +253,26 @@ inline int web_client_api_request_v1_charts(RRDHOST *host, struct web_client *w,
253 return 200;
254 }
255
256 +struct prometheus_output_options {
257 + char *name;
258 + PROMETHEUS_OUTPUT_OPTIONS flag;
259 +} prometheus_output_flags_root[] = {
260 + { "help", PROMETHEUS_OUTPUT_HELP },
261 + { "types", PROMETHEUS_OUTPUT_TYPES },
262 + { "names", PROMETHEUS_OUTPUT_NAMES },
263 + { "timestamps", PROMETHEUS_OUTPUT_TIMESTAMPS },
264 + { "variables", PROMETHEUS_OUTPUT_VARIABLES },
265 +
266 + // terminator
267 + { NULL, PROMETHEUS_OUTPUT_NONE },
268 +};
269 +
270 inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client *w, char *url) {
271 int format = ALLMETRICS_SHELL;
258 - int help = 0, types = 0, timestamps = 1, names = backend_send_names; // prometheus options
272 const char *prometheus_server = w->client_ip;
260 - uint32_t prometheus_options = backend_options;
261 - const char *prometheus_prefix = backend_prefix;
273 + uint32_t prometheus_backend_options = global_backend_options;
274 + PROMETHEUS_OUTPUT_OPTIONS prometheus_output_options = PROMETHEUS_OUTPUT_TIMESTAMPS | ((global_backend_options & BACKEND_OPTION_SEND_NAMES)?PROMETHEUS_OUTPUT_NAMES:0);
275 + const char *prometheus_prefix = global_backend_prefix;
276
277 while(url) {
278 char *value = mystrsep(&url, "?&");
@@ -280,30 +294,6 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
294 else
295 format = 0;
296 }
283 - else if(!strcmp(name, "help")) {
284 - if(!strcmp(value, "yes"))
285 - help = 1;
286 - else
287 - help = 0;
288 - }
289 - else if(!strcmp(name, "types")) {
290 - if(!strcmp(value, "yes"))
291 - types = 1;
292 - else
293 - types = 0;
294 - }
295 - else if(!strcmp(name, "names")) {
296 - if(!strcmp(value, "yes"))
297 - names = 1;
298 - else
299 - names = 0;
300 - }
301 - else if(!strcmp(name, "timestamps")) {
302 - if(!strcmp(value, "yes"))
303 - timestamps = 1;
304 - else
305 - timestamps = 0;
306 - }
297 else if(!strcmp(name, "server")) {
298 prometheus_server = value;
299 }
@@ -311,7 +301,20 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
301 prometheus_prefix = value;
302 }
303 else if(!strcmp(name, "data") || !strcmp(name, "source") || !strcmp(name, "data source") || !strcmp(name, "data-source") || !strcmp(name, "data_source") || !strcmp(name, "datasource")) {
314 - prometheus_options = backend_parse_data_source(value, prometheus_options);
304 + prometheus_backend_options = backend_parse_data_source(value, prometheus_backend_options);
305 + }
306 + else {
307 + int i;
308 + for(i = 0; prometheus_output_flags_root[i].name ; i++) {
309 + if(!strcmp(name, prometheus_output_flags_root[i].name)) {
310 + if(!strcmp(value, "yes") || !strcmp(value, "1") || !strcmp(value, "true"))
311 + prometheus_output_options |= prometheus_output_flags_root[i].flag;
312 + else
313 + prometheus_output_options &= ~prometheus_output_flags_root[i].flag;
314 +
315 + break;
316 + }
317 + }
318 }
319 }
320
@@ -331,12 +334,12 @@ inline int web_client_api_request_v1_allmetrics(RRDHOST *host, struct web_client
334
335 case ALLMETRICS_PROMETHEUS:
336 w->response.data->contenttype = CT_PROMETHEUS;
334 - rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_options, help, types, names, timestamps);
337 + rrd_stats_api_v1_charts_allmetrics_prometheus_single_host(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_backend_options, prometheus_output_options);
338 return 200;
339
340 case ALLMETRICS_PROMETHEUS_ALL_HOSTS:
341 w->response.data->contenttype = CT_PROMETHEUS;
339 - rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_options, help, types, names, timestamps);
342 + rrd_stats_api_v1_charts_allmetrics_prometheus_all_hosts(host, w->response.data, prometheus_server, prometheus_prefix, prometheus_backend_options, prometheus_backend_options);
343 return 200;
344
345 default: