summaryrefslogtreecommitdiffstats
path: root/web/api/formatters/json_wrapper.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/api/formatters/json_wrapper.c')
-rw-r--r--web/api/formatters/json_wrapper.c208
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);
}