diff options
Diffstat (limited to 'web/api/formatters/json_wrapper.c')
-rw-r--r-- | web/api/formatters/json_wrapper.c | 208 |
1 files changed, 134 insertions, 74 deletions
diff --git a/web/api/formatters/json_wrapper.c b/web/api/formatters/json_wrapper.c index b8f47ea57d..b19ce2590a 100644 --- a/web/api/formatters/json_wrapper.c +++ b/web/api/formatters/json_wrapper.c @@ -368,17 +368,60 @@ static void query_target_summary_instances_v2(BUFFER *wb, QUERY_TARGET *qt, cons buffer_json_array_close(wb); } +struct dimensions_sorted_walkthrough_data { + BUFFER *wb; + struct summary_total_counts *totals; + QUERY_TARGET *qt; +}; + +struct dimensions_sorted_entry { + const char *id; + const char *name; + STORAGE_POINT query_points; + QUERY_METRICS_COUNTS metrics; + uint32_t priority; +}; + +static int dimensions_sorted_walktrhough_cb(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data) { + struct dimensions_sorted_walkthrough_data *sdwd = data; + BUFFER *wb = sdwd->wb; + struct summary_total_counts *totals = sdwd->totals; + QUERY_TARGET *qt = sdwd->qt; + struct dimensions_sorted_entry *z = value; + + buffer_json_add_array_item_object(wb); + buffer_json_member_add_string(wb, "id", z->id); + if (z->id != z->name && z->name) + buffer_json_member_add_string(wb, "nm", z->name); + + query_target_metric_counts(wb, &z->metrics); + query_target_points_statistics(wb, qt, &z->query_points); + buffer_json_member_add_uint64(wb, "pri", z->priority); + buffer_json_object_close(wb); + + aggregate_into_summary_totals(totals, &z->metrics); + + return 1; +} + +int dimensions_sorted_compar(const DICTIONARY_ITEM **item1, const DICTIONARY_ITEM **item2) { + struct dimensions_sorted_entry *z1 = dictionary_acquired_item_value(*item1); + struct dimensions_sorted_entry *z2 = dictionary_acquired_item_value(*item2); + + if(z1->priority == z2->priority) + return strcmp(dictionary_acquired_item_name(*item1), dictionary_acquired_item_name(*item2)); + else if(z1->priority < z2->priority) + return -1; + else + return 1; +} + static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, const char *key, bool v2, struct summary_total_counts *totals) { - char name[RRD_ID_LENGTH_MAX * 2 + 2]; + char buf[RRD_ID_LENGTH_MAX * 2 + 2]; buffer_json_member_add_array(wb, key); DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE); - struct { - const char *id; - const char *name; - STORAGE_POINT query_points; - QUERY_METRICS_COUNTS metrics; - } *z; + struct dimensions_sorted_entry *z; size_t q = 0; for (long c = 0; c < (long) qt->dimensions.used; c++) { QUERY_DIMENSION * qd = query_dimension(qt, c); @@ -392,23 +435,31 @@ static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, co qm = tqm; } + const char *key, *id, *name; + if(v2) { - z = dictionary_set(dict, rrdmetric_acquired_name(rma), NULL, sizeof(*z)); - if(!z->id) - z->id = rrdmetric_acquired_name(rma); - if(!z->name) - z->name = rrdmetric_acquired_name(rma); + key = rrdmetric_acquired_name(rma); + id = key; + name = key; } else { - snprintfz(name, RRD_ID_LENGTH_MAX * 2 + 1, "%s:%s", + snprintfz(buf, RRD_ID_LENGTH_MAX * 2 + 1, "%s:%s", rrdmetric_acquired_id(rma), rrdmetric_acquired_name(rma)); + key = buf; + id = rrdmetric_acquired_id(rma); + name = rrdmetric_acquired_name(rma); + } - z = dictionary_set(dict, name, NULL, sizeof(*z)); - if (!z->id) - z->id = rrdmetric_acquired_id(rma); - if (!z->name) - z->name = rrdmetric_acquired_name(rma); + z = dictionary_set(dict, key, NULL, sizeof(*z)); + if(!z->id) { + z->id = id; + z->name = name; + z->priority = qd->priority; + } + else { + if(qd->priority < z->priority) + z->priority = qd->priority; } if(qm) { @@ -423,27 +474,26 @@ static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, co else z->metrics.excluded++; } - dfe_start_read(dict, z) { - if(v2) { - buffer_json_add_array_item_object(wb); - buffer_json_member_add_string(wb, "id", z->id); - if(z->id != z->name) - buffer_json_member_add_string(wb, "nm", z->name); - - query_target_metric_counts(wb, &z->metrics); - query_target_points_statistics(wb, qt, &z->query_points); - buffer_json_object_close(wb); - aggregate_into_summary_totals(totals, &z->metrics); - } - else { - buffer_json_add_array_item_array(wb); - buffer_json_add_array_item_string(wb, z->id); - buffer_json_add_array_item_string(wb, z->name); - buffer_json_array_close(wb); - } - } - dfe_done(z); + if(v2) { + struct dimensions_sorted_walkthrough_data t = { + .wb = wb, + .totals = totals, + .qt = qt, + }; + dictionary_sorted_walkthrough_rw(dict, DICTIONARY_LOCK_READ, dimensions_sorted_walktrhough_cb, + &t, dimensions_sorted_compar); + } + else { + // v1 + dfe_start_read(dict, z) { + buffer_json_add_array_item_array(wb); + buffer_json_add_array_item_string(wb, z->id); + buffer_json_add_array_item_string(wb, z->name); + buffer_json_array_close(wb); + } + dfe_done(z); + } dictionary_destroy(dict); buffer_json_array_close(wb); } @@ -805,18 +855,6 @@ static inline void rrdr_dimension_query_points_statistics(BUFFER *wb, const char buffer_json_object_close(wb); } -static void rrdr_timings_v12(BUFFER *wb, const char *key, RRDR *r) { - QUERY_TARGET *qt = r->internal.qt; - - qt->timings.finished_ut = now_monotonic_usec(); - buffer_json_member_add_object(wb, key); - buffer_json_member_add_double(wb, "prep_ms", (NETDATA_DOUBLE)(qt->timings.preprocessed_ut - qt->timings.received_ut) / USEC_PER_MS); - buffer_json_member_add_double(wb, "query_ms", (NETDATA_DOUBLE)(qt->timings.executed_ut - qt->timings.preprocessed_ut) / USEC_PER_MS); - buffer_json_member_add_double(wb, "output_ms", (NETDATA_DOUBLE)(qt->timings.finished_ut - qt->timings.executed_ut) / USEC_PER_MS); - buffer_json_member_add_double(wb, "total_ms", (NETDATA_DOUBLE)(qt->timings.finished_ut - qt->timings.received_ut) / USEC_PER_MS); - buffer_json_object_close(wb); -} - void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb) { QUERY_TARGET *qt = r->internal.qt; DATASOURCE_FORMAT format = qt->request.format; @@ -948,35 +986,50 @@ static void rrdr_grouped_by_array_v2(BUFFER *wb, const char *key, RRDR *r, RRDR_ buffer_json_member_add_array(wb, key); - if(qt->request.group_by & RRDR_GROUP_BY_SELECTED) + // find the deeper group-by + ssize_t g = 0; + for(g = 0; g < MAX_QUERY_GROUP_BY_PASSES ;g++) { + if(qt->request.group_by[g].group_by == RRDR_GROUP_BY_NONE) + break; + } + + if(g > 0) + g--; + + RRDR_GROUP_BY group_by = qt->request.group_by[g].group_by; + + if(group_by & RRDR_GROUP_BY_SELECTED) buffer_json_add_array_item_string(wb, "selected"); + else if(group_by & RRDR_GROUP_BY_PERCENTAGE_OF_INSTANCE) + buffer_json_add_array_item_string(wb, "percentage-of-instance"); + else { - if(qt->request.group_by & RRDR_GROUP_BY_DIMENSION) + if(group_by & RRDR_GROUP_BY_DIMENSION) buffer_json_add_array_item_string(wb, "dimension"); - if(qt->request.group_by & RRDR_GROUP_BY_INSTANCE) + if(group_by & RRDR_GROUP_BY_INSTANCE) buffer_json_add_array_item_string(wb, "instance"); - if(qt->request.group_by & RRDR_GROUP_BY_LABEL) { + if(group_by & RRDR_GROUP_BY_LABEL) { BUFFER *b = buffer_create(0, NULL); - for (size_t l = 0; l < qt->group_by.used; l++) { + for (size_t l = 0; l < qt->group_by[g].used; l++) { buffer_flush(b); buffer_fast_strcat(b, "label:", 6); - buffer_strcat(b, qt->group_by.label_keys[l]); + buffer_strcat(b, qt->group_by[g].label_keys[l]); buffer_json_add_array_item_string(wb, buffer_tostring(b)); } buffer_free(b); } - if(qt->request.group_by & RRDR_GROUP_BY_NODE) + if(group_by & RRDR_GROUP_BY_NODE) buffer_json_add_array_item_string(wb, "node"); - if(qt->request.group_by & RRDR_GROUP_BY_CONTEXT) + if(group_by & RRDR_GROUP_BY_CONTEXT) buffer_json_add_array_item_string(wb, "context"); - if(qt->request.group_by & RRDR_GROUP_BY_UNITS) + if(group_by & RRDR_GROUP_BY_UNITS) buffer_json_add_array_item_string(wb, "units"); } @@ -1237,7 +1290,6 @@ void rrdr_json_wrapper_begin2(RRDR *r, BUFFER *wb) { buffer_json_initialize(wb, kq, sq, 0, true, options & RRDR_OPTION_MINIFY); buffer_json_member_add_uint64(wb, "api", 2); - buffer_json_agents_array_v2(wb, 0); if(options & RRDR_OPTION_DEBUG) { buffer_json_member_add_string(wb, "id", qt->id); @@ -1284,21 +1336,28 @@ void rrdr_json_wrapper_begin2(RRDR *r, BUFFER *wb) { buffer_json_member_add_string(wb, "time_resampling", NULL); buffer_json_object_close(wb); // time - buffer_json_member_add_object(wb, "metrics"); + buffer_json_member_add_array(wb, "metrics"); + for(size_t g = 0; g < MAX_QUERY_GROUP_BY_PASSES ;g++) { + if(qt->request.group_by[g].group_by == RRDR_GROUP_BY_NONE) + break; - buffer_json_member_add_array(wb, "group_by"); - buffer_json_group_by_to_array(wb, qt->request.group_by); - buffer_json_array_close(wb); + buffer_json_add_array_item_object(wb); + { + buffer_json_member_add_array(wb, "group_by"); + buffer_json_group_by_to_array(wb, qt->request.group_by[g].group_by); + buffer_json_array_close(wb); - buffer_json_member_add_array(wb, "group_by_label"); - for(size_t l = 0; l < qt->group_by.used ;l++) - buffer_json_add_array_item_string(wb, qt->group_by.label_keys[l]); - buffer_json_array_close(wb); + buffer_json_member_add_array(wb, "group_by_label"); + for (size_t l = 0; l < qt->group_by[g].used; l++) + buffer_json_add_array_item_string(wb, qt->group_by[g].label_keys[l]); + buffer_json_array_close(wb); - buffer_json_member_add_string(wb, "aggregation", - group_by_aggregate_function_to_string( - qt->request.group_by_aggregate_function)); - buffer_json_object_close(wb); // dimensions + buffer_json_member_add_string( + wb, "aggregation",group_by_aggregate_function_to_string(qt->request.group_by[g].aggregation)); + } + buffer_json_object_close(wb); + } + buffer_json_array_close(wb); // group_by } buffer_json_object_close(wb); // aggregations @@ -1444,7 +1503,7 @@ void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb) { buffer_json_member_add_double(wb, "min", r->view.min); buffer_json_member_add_double(wb, "max", r->view.max); - rrdr_timings_v12(wb, "timings", r); + buffer_json_query_timings(wb, "timings", &r->internal.qt->timings); buffer_json_finalize(wb); } @@ -1497,6 +1556,7 @@ void rrdr_json_wrapper_end2(RRDR *r, BUFFER *wb) { } buffer_json_object_close(wb); // view - rrdr_timings_v12(wb, "timings", r); + buffer_json_agents_array_v2(wb, &r->internal.qt->timings, 0); + buffer_json_cloud_timings(wb, "timings", &r->internal.qt->timings); buffer_json_finalize(wb); } |