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/charts2json.c | 32 +++++----- web/api/formatters/json/json.c | 102 ++++++++++++++++++----------- web/api/formatters/json_wrapper.c | 76 +++++++++++++++++++++- web/api/formatters/json_wrapper.h | 3 +- web/api/formatters/rrd2json.c | 131 +++++++++++++++++++++----------------- web/api/formatters/rrd2json.h | 28 +++++--- web/api/formatters/rrdset2json.c | 2 - 7 files changed, 249 insertions(+), 125 deletions(-) (limited to 'web/api/formatters') diff --git a/web/api/formatters/charts2json.c b/web/api/formatters/charts2json.c index 856ffb5eb..4325b6530 100644 --- a/web/api/formatters/charts2json.c +++ b/web/api/formatters/charts2json.c @@ -8,30 +8,30 @@ const char* get_release_channel() { static int use_stable = -1; if (use_stable == -1) { - char filename[FILENAME_MAX + 1]; + char filename[FILENAME_MAX + 1]; snprintfz(filename, FILENAME_MAX, "%s/.environment", netdata_configured_user_config_dir); procfile *ff = procfile_open(filename, "=", PROCFILE_FLAG_DEFAULT); - if(!ff) { - use_stable=1; - } else { + if (ff) { procfile_set_quotes(ff, "'\""); ff = procfile_readall(ff); - if(!ff) { - use_stable=1; - } else { + if (ff) { unsigned int i; - for(i = 0; i < procfile_lines(ff); i++) { - if (!procfile_linewords(ff, i)) continue; - - if (!strcmp(procfile_lineword(ff, i, 0), "RELEASE_CHANNEL") && !strcmp(procfile_lineword(ff, i, 1), "stable")) { - use_stable = 1; + for (i = 0; i < procfile_lines(ff); i++) { + if (!procfile_linewords(ff, i)) + continue; + if (!strcmp(procfile_lineword(ff, i, 0), "RELEASE_CHANNEL")) { + if (!strcmp(procfile_lineword(ff, i, 1), "stable")) + use_stable = 1; + else if (!strcmp(procfile_lineword(ff, i, 1), "nightly")) + use_stable = 0; break; } } procfile_close(ff); - if (use_stable == -1) use_stable = 0; } } + if (use_stable == -1) + use_stable = strchr(program_version, '-') ? 0 : 1; } return (use_stable)?"stable":"nightly"; } @@ -150,7 +150,9 @@ struct array_printer { BUFFER *wb; }; -int print_collector(void *entry, void *data) { +static int print_collector_callback(const char *name, void *entry, void *data) { + (void)name; + struct array_printer *ap = (struct array_printer *)data; BUFFER *wb = ap->wb; struct collector *col=(struct collector *) entry; @@ -187,6 +189,6 @@ void chartcollectors2json(RRDHOST *host, BUFFER *wb) { .c = 0, .wb = wb }; - dictionary_get_all(dict, print_collector, &ap); + dictionary_walkthrough_read(dict, print_collector_callback, &ap); dictionary_destroy(dict); } 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); diff --git a/web/api/formatters/json_wrapper.c b/web/api/formatters/json_wrapper.c index 264377e20..7097a5b77 100644 --- a/web/api/formatters/json_wrapper.c +++ b/web/api/formatters/json_wrapper.c @@ -2,9 +2,28 @@ #include "json_wrapper.h" +struct value_output { + int c; + BUFFER *wb; +}; + +static int value_list_output(const char *name, void *entry, void *data) { + (void)name; + + struct value_output *ap = (struct value_output *)data; + BUFFER *wb = ap->wb; + char *output = (char *) entry; + if(ap->c) buffer_strcat(wb, ","); + buffer_strcat(wb, output); + (ap->c)++; + return 0; +} + void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, int string_value, - struct context_param *context_param_list, char *chart_label_key) + QUERY_PARAMS *rrdset_query_data) { + struct context_param *context_param_list = rrdset_query_data->context_param_list; + char *chart_label_key = rrdset_query_data->chart_label_key; RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; int should_lock = (!context_param_list || !(context_param_list->flags & CONTEXT_FLAGS_ARCHIVE)); @@ -98,6 +117,61 @@ void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS } buffer_strcat(wb, "],\n"); + if (rrdset_query_data->show_dimensions) { + buffer_sprintf(wb, " %sfull_dimension_list%s: [", kq, kq); + + char name[RRD_ID_LENGTH_MAX * 2 + 2]; + char output[RRD_ID_LENGTH_MAX * 2 + 8]; + char value[RRD_ID_LENGTH_MAX * 2 + 1]; + + struct value_output co = {.c = 0, .wb = wb}; + + DICTIONARY *dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + for (i = 0, rd = temp_rd ? temp_rd : r->st->dimensions; rd; rd = rd->next) { + snprintfz(name, RRD_ID_LENGTH_MAX * 2, "%s:%s", rd->id, rd->name); + int len = snprintfz(output, RRD_ID_LENGTH_MAX * 2 + 7, "[\"%s\",\"%s\"]", rd->id, rd->name); + dictionary_set(dict, name, output, len+1); + } + dictionary_walkthrough_read(dict, value_list_output, &co); + dictionary_destroy(dict); + + co.c = 0; + buffer_sprintf(wb, "],\n %sfull_chart_list%s: [", kq, kq); + dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + for (i = 0, rd = temp_rd ? temp_rd : r->st->dimensions; rd; rd = rd->next) { + int len = snprintfz(output, RRD_ID_LENGTH_MAX * 2 + 7, "[\"%s\",\"%s\"]", rd->rrdset->id, rd->rrdset->name); + snprintfz(name, RRD_ID_LENGTH_MAX * 2, "%s:%s", rd->rrdset->id, rd->rrdset->name); + dictionary_set(dict, name, output, len + 1); + } + + dictionary_walkthrough_read(dict, value_list_output, &co); + dictionary_destroy(dict); + + RRDSET *st; + co.c = 0; + buffer_sprintf(wb, "],\n %sfull_chart_labels%s: [", kq, kq); + dict = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED); + for (i = 0, rd = temp_rd ? temp_rd : r->st->dimensions; rd; rd = rd->next) { + st = rd->rrdset; + if (likely(st->state)) { + struct label_index *labels = &st->state->labels; + if (labels->head) { + netdata_rwlock_rdlock(&labels->labels_rwlock); + for (struct label *label = labels->head; label; label = label->next) { + sanitize_json_string(value, label->value, RRD_ID_LENGTH_MAX * 2); + int len = snprintfz(output, RRD_ID_LENGTH_MAX * 2 + 7, "[\"%s\", \"%s\"]", label->key, value); + snprintfz(name, RRD_ID_LENGTH_MAX * 2, "%s:%s", label->key, value); + dictionary_set(dict, name, output, len + 1); + } + netdata_rwlock_unlock(&labels->labels_rwlock); + } + } + } + dictionary_walkthrough_read(dict, value_list_output, &co); + dictionary_destroy(dict); + buffer_strcat(wb, "],\n"); + } + // Composite charts if (context_mode && temp_rd) { buffer_sprintf( diff --git a/web/api/formatters/json_wrapper.h b/web/api/formatters/json_wrapper.h index 14662db74..65dbd5b65 100644 --- a/web/api/formatters/json_wrapper.h +++ b/web/api/formatters/json_wrapper.h @@ -5,7 +5,8 @@ #include "rrd2json.h" -extern void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, int string_value, struct context_param *context_param_list, char *chart_key); +extern void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb, uint32_t format, RRDR_OPTIONS options, int string_value, + QUERY_PARAMS *query_params); extern void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb, uint32_t format, uint32_t options, int string_value); #endif //NETDATA_API_FORMATTER_JSON_WRAPPER_H diff --git a/web/api/formatters/rrd2json.c b/web/api/formatters/rrd2json.c index 1a8b07c7c..1de6be4e3 100644 --- a/web/api/formatters/rrd2json.c +++ b/web/api/formatters/rrd2json.c @@ -2,27 +2,27 @@ #include "web/api/web_api_v1.h" -static inline void free_single_rrdrim(RRDDIM *temp_rd, int archive_mode) +static inline void free_single_rrdrim(ONEWAYALLOC *owa, RRDDIM *temp_rd, int archive_mode) { if (unlikely(!temp_rd)) return; - freez((char *)temp_rd->id); - freez((char *)temp_rd->name); + onewayalloc_freez(owa, (char *)temp_rd->id); if (unlikely(archive_mode)) { temp_rd->rrdset->counter--; if (!temp_rd->rrdset->counter) { - freez((char *)temp_rd->rrdset->name); - freez(temp_rd->rrdset->context); - freez(temp_rd->rrdset); + onewayalloc_freez(owa, (char *)temp_rd->rrdset->name); + onewayalloc_freez(owa, temp_rd->rrdset->context); + onewayalloc_freez(owa, temp_rd->rrdset); } } - freez(temp_rd->state); - freez(temp_rd); + + onewayalloc_freez(owa, temp_rd->state); + onewayalloc_freez(owa, temp_rd); } -static inline void free_rrddim_list(RRDDIM *temp_rd, int archive_mode) +static inline void free_rrddim_list(ONEWAYALLOC *owa, RRDDIM *temp_rd, int archive_mode) { if (unlikely(!temp_rd)) return; @@ -30,22 +30,22 @@ static inline void free_rrddim_list(RRDDIM *temp_rd, int archive_mode) RRDDIM *t; while (temp_rd) { t = temp_rd->next; - free_single_rrdrim(temp_rd, archive_mode); + free_single_rrdrim(owa, temp_rd, archive_mode); temp_rd = t; } } -void free_context_param_list(struct context_param **param_list) +void free_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list) { if (unlikely(!param_list || !*param_list)) return; - free_rrddim_list(((*param_list)->rd), (*param_list)->flags & CONTEXT_FLAGS_ARCHIVE); - freez((*param_list)); + free_rrddim_list(owa, ((*param_list)->rd), (*param_list)->flags & CONTEXT_FLAGS_ARCHIVE); + onewayalloc_freez(owa, (*param_list)); *param_list = NULL; } -void rebuild_context_param_list(struct context_param *context_param_list, time_t after_requested) +void rebuild_context_param_list(ONEWAYALLOC *owa, struct context_param *context_param_list, time_t after_requested) { RRDDIM *temp_rd = context_param_list->rd; RRDDIM *new_rd_list = NULL, *t; @@ -59,19 +59,19 @@ void rebuild_context_param_list(struct context_param *context_param_list, time_t temp_rd->next = new_rd_list; new_rd_list = temp_rd; } else - free_single_rrdrim(temp_rd, is_archived); + free_single_rrdrim(owa, temp_rd, is_archived); temp_rd = t; } context_param_list->rd = new_rd_list; }; -void build_context_param_list(struct context_param **param_list, RRDSET *st) +void build_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list, RRDSET *st) { if (unlikely(!param_list || !st)) return; if (unlikely(!(*param_list))) { - *param_list = mallocz(sizeof(struct context_param)); + *param_list = onewayalloc_mallocz(owa, sizeof(struct context_param)); (*param_list)->first_entry_t = LONG_MAX; (*param_list)->last_entry_t = 0; (*param_list)->flags = CONTEXT_FLAGS_CONTEXT; @@ -86,14 +86,10 @@ void build_context_param_list(struct context_param **param_list, RRDSET *st) (*param_list)->last_entry_t = MAX((*param_list)->last_entry_t, rrdset_last_entry_t_nolock(st)); rrddim_foreach_read(rd1, st) { - RRDDIM *rd = mallocz(rd1->memsize); - memcpy(rd, rd1, rd1->memsize); - rd->id = strdupz(rd1->id); - rd->name = strdupz(rd1->name); - rd->state = mallocz(sizeof(*rd->state)); - memcpy(rd->state, rd1->state, sizeof(*rd->state)); - memcpy(&rd->state->collect_ops, &rd1->state->collect_ops, sizeof(struct rrddim_collect_ops)); - memcpy(&rd->state->query_ops, &rd1->state->query_ops, sizeof(struct rrddim_query_ops)); + RRDDIM *rd = onewayalloc_memdupz(owa, rd1, rd1->memsize); + rd->id = onewayalloc_strdupz(owa, rd1->id); + rd->name = onewayalloc_strdupz(owa, rd1->name); + rd->state = onewayalloc_memdupz(owa, rd1->state, sizeof(*rd->state)); rd->next = (*param_list)->rd; (*param_list)->rd = rd; } @@ -169,22 +165,27 @@ int rrdset2value_api_v1( , int *value_is_null , int timeout ) { + int ret = HTTP_RESP_INTERNAL_SERVER_ERROR; + + ONEWAYALLOC *owa = onewayalloc_create(0); - RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions, NULL, timeout); + RRDR *r = rrd2rrdr(owa, st, points, after, before, group_method, group_time, options, dimensions, NULL, timeout); if(!r) { if(value_is_null) *value_is_null = 1; - return HTTP_RESP_INTERNAL_SERVER_ERROR; + ret = HTTP_RESP_INTERNAL_SERVER_ERROR; + goto cleanup; } if(rrdr_rows(r) == 0) { - rrdr_free(r); + rrdr_free(owa, r); if(db_after) *db_after = 0; if(db_before) *db_before = 0; if(value_is_null) *value_is_null = 1; - return HTTP_RESP_BAD_REQUEST; + ret = HTTP_RESP_BAD_REQUEST; + goto cleanup; } if(wb) { @@ -199,14 +200,18 @@ int rrdset2value_api_v1( long i = (!(options & RRDR_OPTION_REVERSED))?rrdr_rows(r) - 1:0; *n = rrdr2value(r, i, options, value_is_null, NULL); + ret = HTTP_RESP_OK; - rrdr_free(r); - return HTTP_RESP_OK; +cleanup: + if(r) rrdr_free(owa, r); + onewayalloc_destroy(owa); + return ret; } int rrdset2anything_api_v1( - RRDSET *st - , BUFFER *wb + ONEWAYALLOC *owa + , RRDSET *st + , QUERY_PARAMS *query_params , BUFFER *dimensions , uint32_t format , long points @@ -216,30 +221,38 @@ int rrdset2anything_api_v1( , long group_time , uint32_t options , time_t *latest_timestamp - , struct context_param *context_param_list - , char *chart_label_key - , int max_anomaly_rates - , int timeout ) { - if (context_param_list && !(context_param_list->flags & CONTEXT_FLAGS_ARCHIVE)) + BUFFER *wb = query_params->wb; + if (query_params->context_param_list && !(query_params->context_param_list->flags & CONTEXT_FLAGS_ARCHIVE)) st->last_accessed_time = now_realtime_sec(); - RRDR *r = rrd2rrdr(st, points, after, before, group_method, group_time, options, dimensions?buffer_tostring(dimensions):NULL, context_param_list, timeout); + RRDR *r = rrd2rrdr( + owa, + st, + points, + after, + before, + group_method, + group_time, + options, + dimensions ? buffer_tostring(dimensions) : NULL, + query_params->context_param_list, + query_params->timeout); if(!r) { buffer_strcat(wb, "Cannot generate output with these parameters on this chart."); return HTTP_RESP_INTERNAL_SERVER_ERROR; } if (r->result_options & RRDR_RESULT_OPTION_CANCEL) { - rrdr_free(r); + rrdr_free(owa, r); return HTTP_RESP_BACKEND_FETCH_FAILED; } if (st && st->state && st->state->is_ar_chart) - ml_process_rrdr(r, max_anomaly_rates); + ml_process_rrdr(r, query_params->max_anomaly_rates); - RRDDIM *temp_rd = context_param_list ? context_param_list->rd : NULL; + RRDDIM *temp_rd = query_params->context_param_list ? query_params->context_param_list->rd : NULL; if(r->result_options & RRDR_RESULT_OPTION_RELATIVE) buffer_no_cacheable(wb); @@ -253,7 +266,7 @@ int rrdset2anything_api_v1( case DATASOURCE_SSV: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 1, query_params); rrdr2ssv(r, wb, options, "", " ", "", temp_rd); rrdr_json_wrapper_end(r, wb, format, options, 1); } @@ -266,7 +279,7 @@ int rrdset2anything_api_v1( case DATASOURCE_SSV_COMMA: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 1, query_params); rrdr2ssv(r, wb, options, "", ",", "", temp_rd); rrdr_json_wrapper_end(r, wb, format, options, 1); } @@ -279,7 +292,7 @@ int rrdset2anything_api_v1( case DATASOURCE_JS_ARRAY: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 0, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 0, query_params); rrdr2ssv(r, wb, options, "[", ",", "]", temp_rd); rrdr_json_wrapper_end(r, wb, format, options, 0); } @@ -292,7 +305,7 @@ int rrdset2anything_api_v1( case DATASOURCE_CSV: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 1, query_params); rrdr2csv(r, wb, format, options, "", ",", "\\n", "", temp_rd); rrdr_json_wrapper_end(r, wb, format, options, 1); } @@ -305,7 +318,7 @@ int rrdset2anything_api_v1( case DATASOURCE_CSV_MARKDOWN: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 1, query_params); rrdr2csv(r, wb, format, options, "", "|", "\\n", "", temp_rd); rrdr_json_wrapper_end(r, wb, format, options, 1); } @@ -318,7 +331,7 @@ int rrdset2anything_api_v1( case DATASOURCE_CSV_JSON_ARRAY: wb->contenttype = CT_APPLICATION_JSON; if(options & RRDR_OPTION_JSON_WRAP) { - rrdr_json_wrapper_begin(r, wb, format, options, 0, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 0, query_params); buffer_strcat(wb, "[\n"); rrdr2csv(r, wb, format, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n", temp_rd); buffer_strcat(wb, "\n]"); @@ -335,7 +348,7 @@ int rrdset2anything_api_v1( case DATASOURCE_TSV: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 1, query_params); rrdr2csv(r, wb, format, options, "", "\t", "\\n", "", temp_rd); rrdr_json_wrapper_end(r, wb, format, options, 1); } @@ -348,7 +361,7 @@ int rrdset2anything_api_v1( case DATASOURCE_HTML: if(options & RRDR_OPTION_JSON_WRAP) { wb->contenttype = CT_APPLICATION_JSON; - rrdr_json_wrapper_begin(r, wb, format, options, 1, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 1, query_params); buffer_strcat(wb, "\\n
\\n\\n"); rrdr2csv(r, wb, format, options, "\\n", "", temp_rd); buffer_strcat(wb, "
", "", "
\\n
\\n\\n"); @@ -366,9 +379,9 @@ int rrdset2anything_api_v1( wb->contenttype = CT_APPLICATION_X_JAVASCRIPT; if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 0, query_params); - rrdr2json(r, wb, options, 1, context_param_list); + rrdr2json(r, wb, options, 1, query_params->context_param_list); if(options & RRDR_OPTION_JSON_WRAP) rrdr_json_wrapper_end(r, wb, format, options, 0); @@ -378,9 +391,9 @@ int rrdset2anything_api_v1( wb->contenttype = CT_APPLICATION_JSON; if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 0, query_params); - rrdr2json(r, wb, options, 1, context_param_list); + rrdr2json(r, wb, options, 1, query_params->context_param_list); if(options & RRDR_OPTION_JSON_WRAP) rrdr_json_wrapper_end(r, wb, format, options, 0); @@ -389,9 +402,9 @@ int rrdset2anything_api_v1( case DATASOURCE_JSONP: wb->contenttype = CT_APPLICATION_X_JAVASCRIPT; if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 0, query_params); - rrdr2json(r, wb, options, 0, context_param_list); + rrdr2json(r, wb, options, 0, query_params->context_param_list); if(options & RRDR_OPTION_JSON_WRAP) rrdr_json_wrapper_end(r, wb, format, options, 0); @@ -402,15 +415,15 @@ int rrdset2anything_api_v1( wb->contenttype = CT_APPLICATION_JSON; if(options & RRDR_OPTION_JSON_WRAP) - rrdr_json_wrapper_begin(r, wb, format, options, 0, context_param_list, chart_label_key); + rrdr_json_wrapper_begin(r, wb, format, options, 0, query_params); - rrdr2json(r, wb, options, 0, context_param_list); + rrdr2json(r, wb, options, 0, query_params->context_param_list); if(options & RRDR_OPTION_JSON_WRAP) rrdr_json_wrapper_end(r, wb, format, options, 0); break; } - rrdr_free(r); + rrdr_free(owa, r); return HTTP_RESP_OK; } diff --git a/web/api/formatters/rrd2json.h b/web/api/formatters/rrd2json.h index af809c54f..60bed5b90 100644 --- a/web/api/formatters/rrd2json.h +++ b/web/api/formatters/rrd2json.h @@ -4,6 +4,17 @@ #define NETDATA_RRD2JSON_H 1 #include "web/api/web_api_v1.h" + +typedef struct query_params { + struct context_param *context_param_list; + BUFFER *wb; + char *chart_label_key; + int max_anomaly_rates; + int timeout; + int show_dimensions; +} QUERY_PARAMS; + + #include "web/api/exporters/allmetrics.h" #include "web/api/queries/rrdr.h" @@ -54,9 +65,10 @@ extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb); extern void rrdr_buffer_print_format(BUFFER *wb, uint32_t format); extern int rrdset2anything_api_v1( - RRDSET *st - , BUFFER *wb - , BUFFER *dimensions + ONEWAYALLOC *owa + , RRDSET *st + , + QUERY_PARAMS *query_params, BUFFER *dimensions , uint32_t format , long points , long long after @@ -65,10 +77,6 @@ extern int rrdset2anything_api_v1( , long group_time , uint32_t options , time_t *latest_timestamp - , struct context_param *context_param_list - , char *chart_label_key - , int max_anomaly_rates - , int timeout ); extern int rrdset2value_api_v1( @@ -88,8 +96,8 @@ extern int rrdset2value_api_v1( , int timeout ); -extern void build_context_param_list(struct context_param **param_list, RRDSET *st); -extern void rebuild_context_param_list(struct context_param *context_param_list, time_t after_requested); -extern void free_context_param_list(struct context_param **param_list); +extern void build_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list, RRDSET *st); +extern void rebuild_context_param_list(ONEWAYALLOC *owa, struct context_param *context_param_list, time_t after_requested); +extern void free_context_param_list(ONEWAYALLOC *owa, struct context_param **param_list); #endif /* NETDATA_RRD2JSON_H */ diff --git a/web/api/formatters/rrdset2json.c b/web/api/formatters/rrdset2json.c index ce237ab23..c83b22e63 100644 --- a/web/api/formatters/rrdset2json.c +++ b/web/api/formatters/rrdset2json.c @@ -52,7 +52,6 @@ void rrdset2json(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memor "\t\t\t\"priority\": %ld,\n" "\t\t\t\"plugin\": \"%s\",\n" "\t\t\t\"module\": \"%s\",\n" - "\t\t\t\"enabled\": %s,\n" "\t\t\t\"units\": \"%s\",\n" "\t\t\t\"data_url\": \"/api/v1/data?chart=%s\",\n" "\t\t\t\"chart_type\": \"%s\",\n", @@ -66,7 +65,6 @@ void rrdset2json(RRDSET *st, BUFFER *wb, size_t *dimensions_count, size_t *memor st->priority, st->plugin_name ? st->plugin_name : "", st->module_name ? st->module_name : "", - rrdset_flag_check(st, RRDSET_FLAG_ENABLED) ? "true" : "false", st->units, st->name, rrdset_type_name(st->chart_type)); -- cgit v1.2.3