3 unsigned long rrdset_info2json_api_old(RRDSET *st, char *options, BUFFER *wb) {
4 time_t now = now_realtime_sec();
8 st->last_accessed_time = now;
12 "\t\t\t\"id\": \"%s\",\n"
13 "\t\t\t\"name\": \"%s\",\n"
14 "\t\t\t\"type\": \"%s\",\n"
15 "\t\t\t\"family\": \"%s\",\n"
16 "\t\t\t\"context\": \"%s\",\n"
17 "\t\t\t\"title\": \"%s\",\n"
18 "\t\t\t\"priority\": %ld,\n"
19 "\t\t\t\"enabled\": %d,\n"
20 "\t\t\t\"units\": \"%s\",\n"
21 "\t\t\t\"url\": \"/data/%s/%s\",\n"
22 "\t\t\t\"chart_type\": \"%s\",\n"
23 "\t\t\t\"counter\": %lu,\n"
24 "\t\t\t\"entries\": %ld,\n"
25 "\t\t\t\"first_entry_t\": %ld,\n"
26 "\t\t\t\"last_entry\": %lu,\n"
27 "\t\t\t\"last_entry_t\": %ld,\n"
28 "\t\t\t\"last_entry_secs_ago\": %ld,\n"
29 "\t\t\t\"update_every\": %d,\n"
30 "\t\t\t\"isdetail\": %d,\n"
31 "\t\t\t\"usec_since_last_update\": %llu,\n"
32 "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
33 "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
34 "\t\t\t\"dimensions\": [\n"
42 , rrdset_flag_check(st, RRDSET_FLAG_ENABLED)?1:0
44 , st->name, options?options:""
45 , rrdset_type_name(st->chart_type)
48 , rrdset_first_entry_t(st)
49 , rrdset_last_slot(st)
50 , rrdset_last_entry_t(st)
51 , (now < rrdset_last_entry_t(st)) ? (time_t)0 : now - rrdset_last_entry_t(st)
53 , rrdset_flag_check(st, RRDSET_FLAG_DETAIL)?1:0
54 , st->usec_since_last_update
56 , st->last_collected_total
59 unsigned long memory = st->memsize;
62 rrddim_foreach_read(rd, st) {
64 memory += rd->memsize;
68 "\t\t\t\t\t\"id\": \"%s\",\n"
69 "\t\t\t\t\t\"name\": \"%s\",\n"
70 "\t\t\t\t\t\"entries\": %ld,\n"
71 "\t\t\t\t\t\"isHidden\": %d,\n"
72 "\t\t\t\t\t\"algorithm\": \"%s\",\n"
73 "\t\t\t\t\t\"multiplier\": " COLLECTED_NUMBER_FORMAT ",\n"
74 "\t\t\t\t\t\"divisor\": " COLLECTED_NUMBER_FORMAT ",\n"
75 "\t\t\t\t\t\"last_entry_t\": %ld,\n"
76 "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
77 "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
78 "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
79 "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
80 "\t\t\t\t\t\"memory\": %lu\n"
85 , rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0
86 , rrd_algorithm_name(rd->algorithm)
89 , rd->last_collected_time.tv_sec
91 , rd->calculated_value
92 , rd->last_collected_value
93 , rd->last_calculated_value
101 "\t\t\t\"memory\" : %lu\n"
110 #define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n"
111 #define RRD_GRAPH_JSON_FOOTER "\n\t]\n}\n"
113 void rrd_graph2json_api_old(RRDSET *st, char *options, BUFFER *wb)
115 buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
116 rrdset_info2json_api_old(st, options, wb);
117 buffer_strcat(wb, RRD_GRAPH_JSON_FOOTER);
120 void rrd_all2json_api_old(RRDHOST *host, BUFFER *wb)
122 unsigned long memory = 0;
126 time_t now = now_realtime_sec();
128 buffer_strcat(wb, RRD_GRAPH_JSON_HEADER);
130 rrdhost_rdlock(host);
131 rrdset_foreach_read(st, host) {
132 if(rrdset_is_available_for_viewers(st)) {
133 if(c) buffer_strcat(wb, ",\n");
134 memory += rrdset_info2json_api_old(st, NULL, wb);
137 st->last_accessed_time = now;
140 rrdhost_unlock(host);
142 buffer_sprintf(wb, "\n\t],\n"
143 "\t\"hostname\": \"%s\",\n"
144 "\t\"update_every\": %d,\n"
145 "\t\"history\": %ld,\n"
146 "\t\"memory\": %lu\n"
149 , host->rrd_update_every
150 , host->rrd_history_entries
155 time_t rrdset2json_api_old(
169 st->last_accessed_time = now_realtime_sec();
171 // -------------------------------------------------------------------------
172 // switch from JSON to google JSON
177 case DATASOURCE_DATATABLE_JSON:
178 case DATASOURCE_DATATABLE_JSONP:
183 case DATASOURCE_JSON:
189 // -------------------------------------------------------------------------
190 // validate the parameters
192 if(points < 1) points = 1;
193 if(group < 1) group = 1;
195 if(before == 0 || before > rrdset_last_entry_t(st)) before = rrdset_last_entry_t(st);
196 if(after == 0 || after < rrdset_first_entry_t(st)) after = rrdset_first_entry_t(st);
200 // our return value (the last timestamp printed)
201 // this is required to detect re-transmit in google JSONP
202 time_t last_timestamp = 0;
205 // -------------------------------------------------------------------------
206 // find how many dimensions we have
210 rrddim_foreach_read(rd, st) dimensions++;
213 buffer_strcat(wb, "No dimensions yet.");
218 // -------------------------------------------------------------------------
219 // prepare various strings, to speed up the loop
221 char overflow_annotation[201]; snprintfz(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
222 char normal_annotation[201]; snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
223 char pre_date[51]; snprintfz(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
224 char post_date[21]; snprintfz(post_date, 20, "%s}", sq);
225 char pre_value[21]; snprintfz(pre_value, 20, ",{%sv%s:", kq, kq);
226 char post_value[21]; strcpy(post_value, "}");
229 // -------------------------------------------------------------------------
230 // checks for debugging
232 if(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)) {
233 debug(D_RRD_STATS, "%s first_entry_t = %ld, last_entry_t = %ld, duration = %ld, after = %ld, before = %ld, duration = %ld, entries_to_show = %ld, group = %ld"
235 , rrdset_first_entry_t(st)
236 , rrdset_last_entry_t(st)
237 , rrdset_last_entry_t(st) - rrdset_first_entry_t(st)
246 debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%ld) is earlier than the oldest (%ld)", st->name, before, after);
248 if((before - after) > st->entries * st->update_every)
249 debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%ld) is higher than the capacity of the database (%ld)", st->name, before - after, st->entries * st->update_every);
253 // -------------------------------------------------------------------------
254 // temp arrays for keeping values per dimension
256 calculated_number group_values[dimensions]; // keep sums when grouping
257 int print_hidden[dimensions]; // keep hidden flags
258 int found_non_zero[dimensions];
259 int found_non_existing[dimensions];
262 for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
264 print_hidden[c] = rrddim_flag_check(rd, RRDDIM_FLAG_HIDDEN)?1:0;
265 found_non_zero[c] = 0;
266 found_non_existing[c] = 0;
270 // error("OLD: points=%d after=%d before=%d group=%d, duration=%d", entries_to_show, before - (st->update_every * group * entries_to_show), before, group, before - after + 1);
271 // rrd2array(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method, only_non_zero);
272 // rrd2rrdr(st, entries_to_show, before - (st->update_every * group * entries_to_show), before, group_method);
274 // -------------------------------------------------------------------------
275 // remove dimensions that contain only zeros
278 if(only_non_zero) max_loop = 2;
280 for(; max_loop ; max_loop--) {
282 // -------------------------------------------------------------------------
283 // print the JSON header
285 buffer_sprintf(wb, "{\n %scols%s:\n [\n", kq, kq);
286 buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
287 buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
288 buffer_sprintf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
290 // print the header for each dimension
291 // and update the print_hidden array for the dimensions that should be hidden
293 for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
294 if(!print_hidden[c]) {
296 buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
300 buffer_sprintf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
303 // print the begin of row data
304 buffer_sprintf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
307 // -------------------------------------------------------------------------
310 int annotate_reset = 0;
311 int annotation_count = 0;
313 long t = rrdset_time2slot(st, before),
314 stop_at_t = rrdset_time2slot(st, after),
319 time_t now = rrdset_slot2time(st, t),
320 dt = st->update_every;
322 long count = 0, printed = 0, group_count = 0;
325 if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
326 debug(D_RRD_STATS, "%s: REQUEST after:%u before:%u, points:%ld, group:%ld, CHART cur:%ld first: %u last:%u, CALC start_t:%ld, stop_t:%ld"
333 , (uint32_t)rrdset_first_entry_t(st)
334 , (uint32_t)rrdset_last_entry_t(st)
340 for(; !stop_now ; now -= dt, t--, counter++) {
341 if(t < 0) t = st->entries - 1;
342 if(t == stop_at_t) stop_now = counter;
346 if(unlikely(rrdset_flag_check(st, RRDSET_FLAG_DEBUG)))
347 debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %ld, %s %s"
354 , (group_count + 1 == group)?"PRINT":" - "
355 , (now >= after && now <= before)?"RANGE":" - "
359 // make sure we return data in the proper time range
360 if(now > before) continue;
361 if(now < after) break;
363 //if(rrdset_slot2time(st, t) != now)
364 // error("%s: slot=%ld, now=%ld, slot2time=%ld, diff=%ld, last_entry_t=%ld, rrdset_last_slot=%ld", st->id, t, now, rrdset_slot2time(st,t), now - rrdset_slot2time(st,t), rrdset_last_entry_t(st), rrdset_last_slot(st));
369 // check if we have to print this now
370 if(group_count == group) {
371 if(printed >= points) {
372 // debug(D_RRD_STATS, "Already printed all rows. Stopping.");
376 // generate the local date time
377 struct tm tmbuf, *tm = localtime_r(&now, &tmbuf);
378 if(!tm) { error("localtime() failed."); continue; }
379 if(now > last_timestamp) last_timestamp = now;
381 if(printed) buffer_strcat(wb, "]},\n");
382 buffer_strcat(wb, pre_date);
383 buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
384 buffer_strcat(wb, post_date);
389 // do the calculations
390 for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
391 storage_number n = rd->values[t];
392 calculated_number value = unpack_storage_number(n);
394 if(!does_storage_number_exist(n)) {
396 found_non_existing[c]++;
398 if(did_storage_number_reset(n)) annotate_reset = 1;
400 switch(group_method) {
402 if(abs(value) > abs(group_values[c])) group_values[c] = value;
406 group_values[c] += value;
411 group_values[c] += value;
412 if(print_this) group_values[c] /= ( group_count - found_non_existing[c] );
420 buffer_strcat(wb, overflow_annotation);
424 buffer_strcat(wb, normal_annotation);
427 for(c = 0 ; c < dimensions ; c++) {
428 if(found_non_existing[c] == group_count) {
429 // all entries are non-existing
431 buffer_strcat(wb, pre_value);
432 buffer_strcat(wb, "null");
433 buffer_strcat(wb, post_value);
435 else if(!print_hidden[c]) {
437 buffer_strcat(wb, pre_value);
438 buffer_rrd_value(wb, group_values[c]);
439 buffer_strcat(wb, post_value);
441 if(group_values[c]) found_non_zero[c]++;
444 // reset them for the next loop
446 found_non_existing[c] = 0;
449 // if all dimensions are hidden, print a null
451 buffer_strcat(wb, pre_value);
452 buffer_strcat(wb, "null");
453 buffer_strcat(wb, post_value);
461 if(printed) buffer_strcat(wb, "]}");
462 buffer_strcat(wb, "\n ]\n}\n");
464 if(only_non_zero && max_loop > 1) {
466 for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
468 found_non_existing[c] = 0;
470 if(!print_hidden[c] && !found_non_zero[c]) {
476 if(changed) buffer_flush(wb);
483 debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %zu bytes", st->name, wb->len);
486 return last_timestamp;