From 89f3604407aff8f4cb2ed958252c61e23c767e24 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 9 Jun 2022 06:52:39 +0200 Subject: Adding upstream version 1.35.0. Signed-off-by: Daniel Baumann --- web/api/formatters/json/json.c | 102 ++++++++++++++++++++++++++--------------- 1 file changed, 65 insertions(+), 37 deletions(-) (limited to 'web/api/formatters/json') diff --git a/web/api/formatters/json/json.c b/web/api/formatters/json/json.c index bf311e22c..af1156d27 100644 --- a/web/api/formatters/json/json.c +++ b/web/api/formatters/json/json.c @@ -16,7 +16,7 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct //info("RRD2JSON(): %s: BEGIN", r->st->id); int row_annotations = 0, dates, dates_with_new = 0; - char kq[2] = "", // key quote + char kq[2] = "", // key quote sq[2] = "", // string quote pre_label[101] = "", // before each label post_label[101] = "", // after each label @@ -28,7 +28,8 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct normal_annotation[201] = "", // default row annotation overflow_annotation[201] = "", // overflow row annotation data_begin[101] = "", // between labels and values - finish[101] = ""; // at the end of everything + finish[101] = "", // at the end of everything + object_rows_time[101] = ""; if(datatable) { dates = JSON_DATES_JS; @@ -49,7 +50,7 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct strcpy(post_value, "}"); strcpy(post_line, "]}"); snprintfz(data_begin, 100, "\n ],\n %srows%s:\n [\n", kq, kq); - strcpy(finish, "\n ]\n}"); + strcpy(finish, "\n]\n}"); 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); snprintfz(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq); @@ -76,23 +77,38 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct dates_with_new = 0; } if( options & RRDR_OPTION_OBJECTSROWS ) - strcpy(pre_date, " { "); + strcpy(pre_date, " { "); else - strcpy(pre_date, " [ "); - strcpy(pre_label, ", \""); + strcpy(pre_date, " [ "); + strcpy(pre_label, ",\""); strcpy(post_label, "\""); - strcpy(pre_value, ", "); + strcpy(pre_value, ","); if( options & RRDR_OPTION_OBJECTSROWS ) strcpy(post_line, "}"); else strcpy(post_line, "]"); snprintfz(data_begin, 100, "],\n %sdata%s:\n [\n", kq, kq); - strcpy(finish, "\n ]\n}"); + strcpy(finish, "\n]\n}"); buffer_sprintf(wb, "{\n %slabels%s: [", kq, kq); buffer_sprintf(wb, "%stime%s", sq, sq); + + if( options & RRDR_OPTION_OBJECTSROWS ) + snprintfz(object_rows_time, 100, "%stime%s: ", kq, kq); + } + size_t pre_value_len = strlen(pre_value); + size_t post_value_len = strlen(post_value); + size_t pre_label_len = strlen(pre_label); + size_t post_label_len = strlen(post_label); + size_t pre_date_len = strlen(pre_date); + size_t post_date_len = strlen(post_date); + size_t post_line_len = strlen(post_line); + size_t normal_annotation_len = strlen(normal_annotation); + size_t overflow_annotation_len = strlen(overflow_annotation); + size_t object_rows_time_len = strlen(object_rows_time); + // ------------------------------------------------------------------------- // print the JSON header @@ -104,18 +120,19 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct if(unlikely(r->od[c] & RRDR_DIMENSION_HIDDEN)) continue; if(unlikely((options & RRDR_OPTION_NONZERO) && !(r->od[c] & RRDR_DIMENSION_NONZERO))) continue; - buffer_strcat(wb, pre_label); + buffer_fast_strcat(wb, pre_label, pre_label_len); buffer_strcat(wb, rd->name); // buffer_strcat(wb, "."); // buffer_strcat(wb, rd->rrdset->name); - buffer_strcat(wb, post_label); + buffer_fast_strcat(wb, post_label, post_label_len); i++; } if(!i) { - buffer_strcat(wb, pre_label); - buffer_strcat(wb, "no data"); - buffer_strcat(wb, post_label); + buffer_fast_strcat(wb, pre_label, pre_label_len); + buffer_fast_strcat(wb, "no data", 7); + buffer_fast_strcat(wb, post_label, post_label_len); } + size_t total_number_of_dimensions = i; // print the begin of row data buffer_strcat(wb, data_begin); @@ -133,6 +150,13 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct step = -1; } + // pre-allocate a large enough buffer for us + // this does not need to be accurate - it is just a hint to avoid multiple realloc(). + buffer_need_bytes(wb, + ( 20 * rrdr_rows(r)) // timestamp + json overhead + + ( (pre_value_len + post_value_len + 4) * total_number_of_dimensions * rrdr_rows(r) ) // number + ); + // for each line in the array calculated_number total = 1; for(i = start; i != end ;i += step) { @@ -146,48 +170,52 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct struct tm tmbuf, *tm = localtime_r(&now, &tmbuf); if(!tm) { error("localtime_r() failed."); continue; } - if(likely(i != start)) buffer_strcat(wb, ",\n"); - buffer_strcat(wb, pre_date); + if(likely(i != start)) buffer_fast_strcat(wb, ",\n", 2); + buffer_fast_strcat(wb, pre_date, pre_date_len); if( options & RRDR_OPTION_OBJECTSROWS ) - buffer_sprintf(wb, "%stime%s: ", kq, kq); + buffer_fast_strcat(wb, object_rows_time, object_rows_time_len); - if(dates_with_new) - buffer_strcat(wb, "new "); + if(unlikely(dates_with_new)) + buffer_fast_strcat(wb, "new ", 4); buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec); - buffer_strcat(wb, post_date); + buffer_fast_strcat(wb, post_date, post_date_len); - if(row_annotations) { + if(unlikely(row_annotations)) { // google supports one annotation per row int annotation_found = 0; for(c = 0, rd = temp_rd?temp_rd:r->st->dimensions; rd ;c++, rd = rd->next) { if(unlikely(!(r->od[c] & RRDR_DIMENSION_SELECTED))) continue; - if(co[c] & RRDR_VALUE_RESET) { - buffer_strcat(wb, overflow_annotation); + if(unlikely(co[c] & RRDR_VALUE_RESET)) { + buffer_fast_strcat(wb, overflow_annotation, overflow_annotation_len); annotation_found = 1; break; } } - if(!annotation_found) - buffer_strcat(wb, normal_annotation); + if(likely(!annotation_found)) + buffer_fast_strcat(wb, normal_annotation, normal_annotation_len); } } else { // print the timestamp of the line - if(likely(i != start)) buffer_strcat(wb, ",\n"); - buffer_strcat(wb, pre_date); + if(likely(i != start)) + buffer_fast_strcat(wb, ",\n", 2); - if( options & RRDR_OPTION_OBJECTSROWS ) - buffer_sprintf(wb, "%stime%s: ", kq, kq); + buffer_fast_strcat(wb, pre_date, pre_date_len); + + if(unlikely( options & RRDR_OPTION_OBJECTSROWS )) + buffer_fast_strcat(wb, object_rows_time, object_rows_time_len); buffer_rrd_value(wb, (calculated_number)r->t[i]); + // in ms - if(options & RRDR_OPTION_MILLISECONDS) buffer_strcat(wb, "000"); + if(unlikely(options & RRDR_OPTION_MILLISECONDS)) + buffer_fast_strcat(wb, "000", 3); - buffer_strcat(wb, post_date); + buffer_fast_strcat(wb, post_date, post_date_len); } int set_min_max = 0; @@ -213,16 +241,16 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct calculated_number n = cn[c]; - buffer_strcat(wb, pre_value); + buffer_fast_strcat(wb, pre_value, pre_value_len); - if( options & RRDR_OPTION_OBJECTSROWS ) + if(unlikely( options & RRDR_OPTION_OBJECTSROWS )) buffer_sprintf(wb, "%s%s%s: ", kq, rd->name, kq); if(co[c] & RRDR_VALUE_EMPTY) { - if(options & RRDR_OPTION_NULL2ZERO) - buffer_strcat(wb, "0"); + if(unlikely(options & RRDR_OPTION_NULL2ZERO)) + buffer_fast_strcat(wb, "0", 1); else - buffer_strcat(wb, "null"); + buffer_fast_strcat(wb, "null", 4); } else { if(unlikely((options & RRDR_OPTION_ABSOLUTE) && n < 0)) @@ -243,10 +271,10 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable, struct buffer_rrd_value(wb, n); } - buffer_strcat(wb, post_value); + buffer_fast_strcat(wb, post_value, post_value_len); } - buffer_strcat(wb, post_line); + buffer_fast_strcat(wb, post_line, post_line_len); } buffer_strcat(wb, finish); -- cgit v1.2.3