adapted prometheus formatting based on #2436
Costa Tsaousis (ktsaou) committed
Jul 13, 2017 at 22:19 UTC
fdd6bb81af362b2bcf563f61e62124f8dfc8e843
4 files changed
+188
-33
src/backend_prometheus.c
+150
-32
@@ -67,6 +67,38 @@ static inline size_t prometheus_label_copy(char *d, const char *s, size_t usable
67
return n;
68
}
69
70
+static inline char *prometheus_units_copy(char *d, const char *s, size_t usable) {
71
+ const char *sorig = s;
72
+ char *ret = d;
73
+ size_t n;
74
+
75
+ *d++ = '_';
76
+ for(n = 1; *s && n < usable ; d++, s++, n++) {
77
+ register char c = *s;
78
+
79
+ if(!isalnum(c)) *d = '_';
80
+ else *d = c;
81
+ }
82
+
83
+ if(n == 2 && sorig[0] == '%') {
84
+ n = 0;
85
+ d = ret;
86
+ s = "_percent";
87
+ for( ; *s && n < usable ; n++) *d++ = *s++;
88
+ }
89
+ else if(n > 3 && sorig[n-3] == '/' && sorig[n-2] == 's') {
90
+ n = n - 2;
91
+ d -= 2;
92
+ s = "_persec";
93
+ for( ; *s && n < usable ; n++) *d++ = *s++;
94
+ }
95
+
96
+ *d = '\0';
97
+
98
+ return ret;
99
+}
100
+
101
+
102
#define PROMETHEUS_ELEMENT_MAX 256
103
#define PROMETHEUS_LABELS_MAX 1024
104
@@ -94,6 +126,7 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
126
char chart[PROMETHEUS_ELEMENT_MAX + 1];
127
char context[PROMETHEUS_ELEMENT_MAX + 1];
128
char family[PROMETHEUS_ELEMENT_MAX + 1];
129
+ char units[PROMETHEUS_ELEMENT_MAX + 1] = "";
130
131
prometheus_label_copy(chart, (names && st->name)?st->name:st->id, PROMETHEUS_ELEMENT_MAX);
132
prometheus_label_copy(family, st->family, PROMETHEUS_ELEMENT_MAX);
@@ -102,8 +135,23 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
135
if(likely(backends_can_send_rrdset(options, st))) {
136
rrdset_rdlock(st);
137
138
+ int as_collected = ((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED);
139
+ int homogeneus = 1;
140
+ if(as_collected) {
141
+ if(rrdset_flag_check(st, RRDSET_FLAG_HOMEGENEOUS_CHECK))
142
+ rrdset_update_heterogeneous_flag(st);
143
+
144
+ if(rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS))
145
+ homogeneus = 0;
146
+ }
147
+ else {
148
+ if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
149
+ prometheus_units_copy(units, st->units, PROMETHEUS_ELEMENT_MAX);
150
+ }
151
+
152
if(unlikely(help))
106
- buffer_sprintf(wb, "\n# COMMENT chart \"%s\", context \"%s\", family \"%s\", units \"%s\"\n"
153
+ buffer_sprintf(wb, "\n# COMMENT %s chart \"%s\", context \"%s\", family \"%s\", units \"%s\"\n"
154
+ , (homogeneus)?"homogeneus":"heterogeneous"
155
, (names && st->name) ? st->name : st->id
156
, st->context
157
, st->family
@@ -115,54 +163,109 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
163
rrddim_foreach_read(rd, st) {
164
if(rd->collections_counter) {
165
char dimension[PROMETHEUS_ELEMENT_MAX + 1];
166
+ char *suffix = "";
167
119
- if ((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AS_COLLECTED) {
168
+ if (as_collected) {
169
// we need as-collected / raw data
170
122
- prometheus_name_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
123
-
171
const char *t = "gauge", *h = "gives";
172
if(rd->algorithm == RRD_ALGORITHM_INCREMENTAL ||
173
rd->algorithm == RRD_ALGORITHM_PCENT_OVER_DIFF_TOTAL) {
174
t = "counter";
175
h = "delta gives";
176
+ suffix = "_total";
177
}
178
131
- if(unlikely(help))
179
+ if(homogeneus) {
180
+ // all the dimensions of the chart, has the same algorithm, multiplier and divisor
181
+ // we add all dimensions as labels
182
+
183
+ prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
184
+
185
+ if(unlikely(help))
186
+ buffer_sprintf(wb
187
+ , "# COMMENT %s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
188
+ , prefix
189
+ , context
190
+ , suffix
191
+ , (names && st->name) ? st->name : st->id
192
+ , st->context
193
+ , st->family
194
+ , (names && rd->name) ? rd->name : rd->id
195
+ , rd->multiplier
196
+ , rd->divisor
197
+ , h
198
+ , st->units
199
+ , t
200
+ );
201
+
202
+ if(unlikely(types))
203
+ buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s %s\n"
204
+ , prefix
205
+ , context
206
+ , suffix
207
+ , t
208
+ );
209
+
210
buffer_sprintf(wb
133
- , "# COMMENT %s_%s_%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
211
+ , "%s_%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
212
, prefix
213
, context
214
+ , suffix
215
+ , chart
216
+ , family
217
, dimension
137
- , (names && st->name) ? st->name : st->id
138
- , st->context
139
- , st->family
140
- , (names && rd->name) ? rd->name : rd->id
141
- , rd->multiplier
142
- , rd->divisor
143
- , h
144
- , st->units
145
- , t
218
+ , labels
219
+ , rd->last_collected_value
220
+ , timeval_msec(&rd->last_collected_time)
221
);
222
+ }
223
+ else {
224
+ // the dimensions of the chart, do not have the same algorithm, multiplier or divisor
225
+ // we create a metric per dimension
226
+
227
+ prometheus_name_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
228
+
229
+ if(unlikely(help))
230
+ buffer_sprintf(wb
231
+ , "# COMMENT %s_%s_%s%s: chart \"%s\", context \"%s\", family \"%s\", dimension \"%s\", value * " COLLECTED_NUMBER_FORMAT " / " COLLECTED_NUMBER_FORMAT " %s %s (%s)\n"
232
+ , prefix
233
+ , context
234
+ , dimension
235
+ , suffix
236
+ , (names && st->name) ? st->name : st->id
237
+ , st->context
238
+ , st->family
239
+ , (names && rd->name) ? rd->name : rd->id
240
+ , rd->multiplier
241
+ , rd->divisor
242
+ , h
243
+ , st->units
244
+ , t
245
+ );
246
148
- if(unlikely(types))
149
- buffer_sprintf(wb, "# COMMENT TYPE %s_%s_%s %s\n"
247
+ if(unlikely(types))
248
+ buffer_sprintf(wb, "# COMMENT TYPE %s_%s_%s%s %s\n"
249
+ , prefix
250
+ , context
251
+ , dimension
252
+ , suffix
253
+ , t
254
+ );
255
+
256
+ buffer_sprintf(wb
257
+ , "%s_%s_%s%s{chart=\"%s\",family=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
258
, prefix
259
, context
260
, dimension
153
- , t
261
+ , suffix
262
+ , chart
263
+ , family
264
+ , labels
265
+ , rd->last_collected_value
266
+ , timeval_msec(&rd->last_collected_time)
267
);
155
-
156
- buffer_sprintf(wb, "%s_%s_%s{chart=\"%s\",family=\"%s\"%s} " COLLECTED_NUMBER_FORMAT " %llu\n"
157
- , prefix
158
- , context
159
- , dimension
160
- , chart
161
- , family
162
- , labels
163
- , rd->last_collected_value
164
- , timeval_msec(&rd->last_collected_time)
165
- );
268
+ }
269
}
270
else {
271
// we need average or sum of the data
@@ -171,12 +274,20 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
274
calculated_number value = backend_calculate_value_from_stored_data(st, rd, after, before, options, &first_t, &last_t);
275
276
if(!isnan(value) && !isinf(value)) {
277
+
278
+ if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_AVERAGE)
279
+ suffix = "_average";
280
+ else if((options & BACKEND_SOURCE_BITS) == BACKEND_SOURCE_DATA_SUM)
281
+ suffix = "_sum";
282
+
283
prometheus_label_copy(dimension, (names && rd->name) ? rd->name : rd->id, PROMETHEUS_ELEMENT_MAX);
284
285
if (unlikely(help))
177
- buffer_sprintf(wb, "# COMMENT %s_%s: dimension \"%s\", value is %s, gauge, dt %llu to %llu inclusive\n"
286
+ buffer_sprintf(wb, "# COMMENT %s_%s%s%s: dimension \"%s\", value is %s, gauge, dt %llu to %llu inclusive\n"
287
, prefix
288
, context
289
+ , units
290
+ , suffix
291
, (names && rd->name) ? rd->name : rd->id
292
, st->units
293
, (unsigned long long)first_t
@@ -184,11 +295,18 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus(RRDHOST *host, BUFFER
295
);
296
297
if (unlikely(types))
187
- buffer_sprintf(wb, "# COMMENT TYPE %s_%s gauge\n", prefix, context);
298
+ buffer_sprintf(wb, "# COMMENT TYPE %s_%s%s%s gauge\n"
299
+ , prefix
300
+ , context
301
+ , units
302
+ , suffix
303
+ );
304
189
- buffer_sprintf(wb, "%s_%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " CALCULATED_NUMBER_FORMAT " %llu\n"
305
+ buffer_sprintf(wb, "%s_%s%s%s{chart=\"%s\",family=\"%s\",dimension=\"%s\"%s} " CALCULATED_NUMBER_FORMAT " %llu\n"
306
, prefix
307
, context
308
+ , units
309
+ , suffix
310
, chart
311
, family
312
, dimension
src/rrd.h
+4
-1
@@ -227,7 +227,8 @@ typedef enum rrdset_flags {
227
RRDSET_FLAG_BACKEND_IGNORE = 1 << 5, // if set, this chart should not be sent to backends
228
RRDSET_FLAG_EXPOSED_UPSTREAM = 1 << 6, // if set, we have sent this chart to netdata master (streaming)
229
RRDSET_FLAG_STORE_FIRST = 1 << 7, // if set, do not eliminate the first collection during interpolation
230
- RRDSET_FLAG_HETEROGENEOUS = 1 << 8 // if set, the chart is not homogeneus (dimensions in it have multiple algorithms, multipliers or dividers)
230
+ RRDSET_FLAG_HETEROGENEOUS = 1 << 8, // if set, the chart is not homogeneous (dimensions in it have multiple algorithms, multipliers or dividers)
231
+ RRDSET_FLAG_HOMEGENEOUS_CHECK= 1 << 9 // if set, the chart should be checked to determine if the dimensions as homogeneous
232
} RRDSET_FLAGS;
233
234
#ifdef HAVE_C___ATOMIC
@@ -596,6 +597,8 @@ extern void rrdhost_free(RRDHOST *host);
597
extern void rrdhost_save(RRDHOST *host);
598
extern void rrdhost_delete(RRDHOST *host);
599
600
+extern void rrdset_update_heterogeneous_flag(RRDSET *st);
601
+
602
extern RRDSET *rrdset_find(RRDHOST *host, const char *id);
603
#define rrdset_find_localhost(id) rrdset_find(localhost, id)
604
src/rrddim.c
+3
@@ -57,6 +57,7 @@ inline int rrddim_set_algorithm(RRDSET *st, RRDDIM *rd, RRD_ALGORITHM algorithm)
57
debug(D_RRD_CALLS, "Updating algorithm of dimension '%s/%s' from %s to %s", st->id, rd->name, rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm));
58
rd->algorithm = algorithm;
59
rd->exposed = 0;
60
+ rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
61
return 1;
62
}
63
@@ -67,6 +68,7 @@ inline int rrddim_set_multiplier(RRDSET *st, RRDDIM *rd, collected_number multip
68
debug(D_RRD_CALLS, "Updating multiplier of dimension '%s/%s' from " COLLECTED_NUMBER_FORMAT " to " COLLECTED_NUMBER_FORMAT, st->id, rd->name, rd->multiplier, multiplier);
69
rd->multiplier = multiplier;
70
rd->exposed = 0;
71
+ rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
72
return 1;
73
}
74
@@ -77,6 +79,7 @@ inline int rrddim_set_divisor(RRDSET *st, RRDDIM *rd, collected_number divisor)
79
debug(D_RRD_CALLS, "Updating divisor of dimension '%s/%s' from " COLLECTED_NUMBER_FORMAT " to " COLLECTED_NUMBER_FORMAT, st->id, rd->name, rd->divisor, divisor);
80
rd->divisor = divisor;
81
rd->exposed = 0;
82
+ rrdset_flag_set(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
83
return 1;
84
}
85
src/rrdset.c
+31
@@ -190,6 +190,37 @@ inline void rrdset_isnot_obsolete(RRDSET *st) {
190
}
191
}
192
193
+inline void rrdset_update_heterogeneous_flag(RRDSET *st) {
194
+ RRDDIM *rd;
195
+
196
+ rrdset_flag_clear(st, RRDSET_FLAG_HOMEGENEOUS_CHECK);
197
+
198
+ RRD_ALGORITHM algorithm = st->dimensions->algorithm;
199
+ collected_number multiplier = abs(st->dimensions->multiplier);
200
+ collected_number divisor = abs(st->dimensions->divisor);
201
+
202
+ rrddim_foreach_read(rd, st) {
203
+ if(algorithm != rd->algorithm || multiplier != abs(rd->multiplier) || divisor != abs(rd->divisor)) {
204
+ if(!rrdset_flag_check(st, RRDSET_FLAG_HETEROGENEOUS)) {
205
+ #ifdef NETDATA_INTERNAL_CHECKS
206
+ info("Dimension '%s' added on chart '%s' of host '%s' is not homogeneous to other dimensions already present (algorithm is '%s' vs '%s', multiplier is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ", divisor is " COLLECTED_NUMBER_FORMAT " vs " COLLECTED_NUMBER_FORMAT ").",
207
+ rd->name,
208
+ st->name,
209
+ st->rrdhost->hostname,
210
+ rrd_algorithm_name(rd->algorithm), rrd_algorithm_name(algorithm),
211
+ rd->multiplier, multiplier,
212
+ rd->divisor, divisor
213
+ );
214
+ #endif
215
+ rrdset_flag_set(st, RRDSET_FLAG_HETEROGENEOUS);
216
+ }
217
+ return;
218
+ }
219
+ }
220
+
221
+ rrdset_flag_clear(st, RRDSET_FLAG_HETEROGENEOUS);
222
+}
223
+
224
// ----------------------------------------------------------------------------
225
// RRDSET - reset a chart
226