summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--database/contexts/api_v2.c46
-rw-r--r--database/contexts/query_target.c3
-rw-r--r--database/contexts/rrdcontext.h88
-rw-r--r--libnetdata/libnetdata.h7
-rw-r--r--web/api/formatters/json/json.c4
-rw-r--r--web/api/formatters/json_wrapper.c271
-rw-r--r--web/api/formatters/rrd2json.c9
-rw-r--r--web/api/formatters/rrd2json.h2
-rw-r--r--web/api/formatters/value/value.c14
-rw-r--r--web/api/formatters/value/value.h1
-rw-r--r--web/api/netdata-swagger.json3790
-rw-r--r--web/api/netdata-swagger.yaml3288
-rw-r--r--web/api/queries/query.c254
-rw-r--r--web/api/queries/query.h3
-rw-r--r--web/api/queries/rrdr.c7
-rw-r--r--web/api/queries/rrdr.h9
-rw-r--r--web/api/queries/weights.c265
-rw-r--r--web/api/web_api_v1.c1
18 files changed, 4067 insertions, 3995 deletions
diff --git a/database/contexts/api_v2.c b/database/contexts/api_v2.c
index c34eacbd32..5808018df4 100644
--- a/database/contexts/api_v2.c
+++ b/database/contexts/api_v2.c
@@ -97,6 +97,7 @@ struct rrdcontext_to_json_v2_data {
struct {
SIMPLE_PATTERN *scope_pattern;
SIMPLE_PATTERN *pattern;
+ size_t ni;
} nodes;
struct {
@@ -222,6 +223,21 @@ static ssize_t rrdcontext_to_json_v2_add_context(void *data, RRDCONTEXT_ACQUIRED
return 1;
}
+void buffer_json_node_add_v2(BUFFER *wb, RRDHOST *host, size_t ni, usec_t duration_ut) {
+ buffer_json_member_add_string(wb, "mg", host->machine_guid);
+ if(host->node_id)
+ buffer_json_member_add_uuid(wb, "nd", host->node_id);
+ buffer_json_member_add_string(wb, "nm", rrdhost_hostname(host));
+ buffer_json_member_add_uint64(wb, "ni", ni);
+ buffer_json_member_add_object(wb, "st");
+ buffer_json_member_add_uint64(wb, "ai", 0);
+ buffer_json_member_add_uint64(wb, "code", 200);
+ buffer_json_member_add_string(wb, "msg", "");
+ if(duration_ut)
+ buffer_json_member_add_double(wb, "ms", (NETDATA_DOUBLE)duration_ut / 1000.0);
+ buffer_json_object_close(wb);
+}
+
static ssize_t rrdcontext_to_json_v2_add_host(void *data, RRDHOST *host, bool queryable_host) {
if(!queryable_host || !host->rrdctx.contexts)
// the host matches the 'scope_host' but does not match the 'host' patterns
@@ -279,9 +295,7 @@ static ssize_t rrdcontext_to_json_v2_add_host(void *data, RRDHOST *host, bool qu
if(host_matched && (ctl->options & (CONTEXTS_V2_NODES | CONTEXTS_V2_NODES_DETAILED | CONTEXTS_V2_DEBUG))) {
buffer_json_add_array_item_object(wb);
- buffer_json_member_add_string(wb, "mg", host->machine_guid);
- buffer_json_member_add_uuid(wb, "nd", host->node_id);
- buffer_json_member_add_string(wb, "nm", rrdhost_hostname(host));
+ buffer_json_node_add_v2(wb, host, ctl->nodes.ni++, 0);
if(ctl->options & CONTEXTS_V2_NODES_DETAILED) {
buffer_json_member_add_string(wb, "version", rrdhost_program_version(host));
@@ -372,6 +386,21 @@ static void buffer_json_contexts_v2_options_to_array(BUFFER *wb, CONTEXTS_V2_OPT
buffer_json_add_array_item_string(wb, "search");
}
+void buffer_json_agents_array_v2(BUFFER *wb, time_t now_s) {
+ if(!now_s)
+ now_s = now_realtime_sec();
+
+ buffer_json_member_add_array(wb, "agents");
+ buffer_json_add_array_item_object(wb);
+ buffer_json_member_add_string(wb, "mg", localhost->machine_guid);
+ buffer_json_member_add_uuid(wb, "nd", localhost->node_id);
+ buffer_json_member_add_string(wb, "nm", rrdhost_hostname(localhost));
+ buffer_json_member_add_time_t(wb, "now", now_s);
+ buffer_json_member_add_uint64(wb, "ai", 0);
+ buffer_json_object_close(wb);
+ buffer_json_array_close(wb);
+}
+
int rrdcontext_to_json_v2(BUFFER *wb, struct api_v2_contexts_request *req, CONTEXTS_V2_OPTIONS options) {
int resp = HTTP_RESP_OK;
@@ -398,17 +427,10 @@ int rrdcontext_to_json_v2(BUFFER *wb, struct api_v2_contexts_request *req, CONTE
time_t now_s = now_realtime_sec();
buffer_json_initialize(wb, "\"", "\"", 0, true, false);
+ buffer_json_member_add_uint64(wb, "api", 2);
+ buffer_json_agents_array_v2(wb, now_s);
if(options & CONTEXTS_V2_DEBUG) {
- buffer_json_member_add_object(wb, "agent");
- buffer_json_member_add_string(wb, "mg", localhost->machine_guid);
- buffer_json_member_add_uuid(wb, "nd", localhost->node_id);
- buffer_json_member_add_string(wb, "nm", rrdhost_hostname(localhost));
- if (req->q)
- buffer_json_member_add_string(wb, "q", req->q);
- buffer_json_member_add_time_t(wb, "now", now_s);
- buffer_json_object_close(wb);
-
buffer_json_member_add_object(wb, "request");
buffer_json_member_add_object(wb, "scope");
diff --git a/database/contexts/query_target.c b/database/contexts/query_target.c
index 9fb027831a..0378f52017 100644
--- a/database/contexts/query_target.c
+++ b/database/contexts/query_target.c
@@ -977,7 +977,7 @@ QUERY_TARGET *query_target_create(QUERY_TARGET_REQUEST *qtr) {
qtr->scope_contexts = qtr->contexts;
memset(&qt->db, 0, sizeof(qt->db));
- memset(&qt->query_stats, 0, sizeof(qt->query_stats));
+ qt->query_points = STORAGE_POINT_UNSET;
// copy the request into query_thread_target
qt->request = *qtr;
@@ -985,6 +985,7 @@ QUERY_TARGET *query_target_create(QUERY_TARGET_REQUEST *qtr) {
query_target_generate_name(qt);
qt->window.after = qt->request.after;
qt->window.before = qt->request.before;
+ qt->window.options = qt->request.options;
rrdr_relative_window_to_absolute(&qt->window.after, &qt->window.before, &qt->window.now);
// prepare our local variables - we need these across all these functions
diff --git a/database/contexts/rrdcontext.h b/database/contexts/rrdcontext.h
index 45ab8f7f26..f42c43135b 100644
--- a/database/contexts/rrdcontext.h
+++ b/database/contexts/rrdcontext.h
@@ -144,55 +144,47 @@ typedef struct query_plan_entry {
#define QUERY_PLANS_MAX (RRD_STORAGE_TIERS)
-struct query_metrics_counts {
- size_t selected;
- size_t excluded;
- size_t queried;
- size_t failed;
-};
-
-struct query_instances_counts {
- size_t selected;
- size_t excluded;
- size_t queried;
- size_t failed;
-};
-
-struct query_alerts_counts {
- size_t clear;
- size_t warning;
- size_t critical;
- size_t other;
-};
-
-struct query_data_statistics { // time-aggregated (group points) statistics
- size_t group_points; // the number of group points the query generated
- NETDATA_DOUBLE min; // the min value of the group points
- NETDATA_DOUBLE max; // the max value of the group points
- NETDATA_DOUBLE sum; // the sum of the group points
- NETDATA_DOUBLE volume; // the volume of the group points
- NETDATA_DOUBLE anomaly_sum; // the anomaly sum of the group points
-};
+typedef struct query_metrics_counts { // counts the number of metrics related to an object
+ size_t selected; // selected to be queried
+ size_t excluded; // not selected to be queried
+ size_t queried; // successfully queried
+ size_t failed; // failed to be queried
+} QUERY_METRICS_COUNTS;
+
+typedef struct query_instances_counts { // counts the number of instances related to an object
+ size_t selected; // selected to be queried
+ size_t excluded; // not selected to be queried
+ size_t queried; // successfully queried
+ size_t failed; // failed to be queried
+} QUERY_INSTANCES_COUNTS;
+
+typedef struct query_alerts_counts { // counts the number of alerts related to an object
+ size_t clear; // number of alerts in clear state
+ size_t warning; // number of alerts in warning state
+ size_t critical; // number of alerts in critical state
+ size_t other; // number of alerts in any other state
+} QUERY_ALERTS_COUNTS;
typedef struct query_node {
uint32_t slot;
RRDHOST *rrdhost;
char node_id[UUID_STR_LEN];
+ usec_t duration_ut;
- struct query_data_statistics query_stats;
- struct query_instances_counts instances;
- struct query_metrics_counts metrics;
- struct query_alerts_counts alerts;
+ STORAGE_POINT query_points;
+ QUERY_INSTANCES_COUNTS instances;
+ QUERY_METRICS_COUNTS metrics;
+ QUERY_ALERTS_COUNTS alerts;
} QUERY_NODE;
typedef struct query_context {
uint32_t slot;
RRDCONTEXT_ACQUIRED *rca;
- struct query_data_statistics query_stats;
- struct query_instances_counts instances;
- struct query_metrics_counts metrics;
- struct query_alerts_counts alerts;
+ STORAGE_POINT query_points;
+ QUERY_INSTANCES_COUNTS instances;
+ QUERY_METRICS_COUNTS metrics;
+ QUERY_ALERTS_COUNTS alerts;
} QUERY_CONTEXT;
typedef struct query_instance {
@@ -202,9 +194,9 @@ typedef struct query_instance {
STRING *id_fqdn; // never access this directly - it is created on demand via query_instance_id_fqdn()
STRING *name_fqdn; // never access this directly - it is created on demand via query_instance_name_fqdn()
- struct query_data_statistics query_stats;
- struct query_metrics_counts metrics;
- struct query_alerts_counts alerts;
+ STORAGE_POINT query_points;
+ QUERY_METRICS_COUNTS metrics;
+ QUERY_ALERTS_COUNTS alerts;
} QUERY_INSTANCE;
typedef struct query_dimension {
@@ -236,7 +228,7 @@ typedef struct query_metric {
uint32_t query_dimension_id;
} link;
- struct query_data_statistics query_stats;
+ STORAGE_POINT query_points;
struct {
size_t slot;
@@ -245,6 +237,7 @@ typedef struct query_metric {
STRING *units;
} grouped_as;
+ usec_t duration_ut;
} QUERY_METRIC;
#define MAX_QUERY_TARGET_ID_LENGTH 255
@@ -320,6 +313,8 @@ struct query_versions {
uint64_t alerts_soft_hash;
};
+#define query_view_update_every(qt) ((qt)->window.group * (qt)->window.query_granularity)
+
typedef struct query_target {
char id[MAX_QUERY_TARGET_ID_LENGTH + 1]; // query identifier (for logging)
QUERY_TARGET_REQUEST request;
@@ -334,10 +329,10 @@ typedef struct query_target {
time_t after; // the absolute timestamp this query is about
time_t before; // the absolute timestamp this query is about
time_t query_granularity;
- size_t points; // the number of points the query will return (maybe different from the request)
+ size_t points; // the number of points the query will return (maybe different from the request)
size_t group;
- RRDR_TIME_GROUPING group_method;
- const char *group_options;
+ RRDR_TIME_GROUPING time_group_method;
+ const char *time_group_options;
size_t resampling_group;
NETDATA_DOUBLE resampling_divisor;
RRDR_OPTIONS options;
@@ -396,7 +391,7 @@ typedef struct query_target {
char *label_keys[GROUP_BY_MAX_LABEL_KEYS];
} group_by;
- struct query_data_statistics query_stats;
+ STORAGE_POINT query_points;
struct query_versions versions;
@@ -404,7 +399,6 @@ typedef struct query_target {
usec_t received_ut;
usec_t preprocessed_ut;
usec_t executed_ut;
- usec_t group_by_ut;
usec_t finished_ut;
} timings;
} QUERY_TARGET;
@@ -485,6 +479,8 @@ typedef enum __attribute__ ((__packed__)) {
int rrdcontext_to_json_v2(BUFFER *wb, struct api_v2_contexts_request *req, CONTEXTS_V2_OPTIONS options);
RRDCONTEXT_TO_JSON_OPTIONS rrdcontext_to_json_parse_options(char *o);
+void buffer_json_agents_array_v2(BUFFER *wb, time_t now_s);
+void buffer_json_node_add_v2(BUFFER *wb, RRDHOST *host, size_t ni, usec_t duration_ut);
// ----------------------------------------------------------------------------
// scope
diff --git a/libnetdata/libnetdata.h b/libnetdata/libnetdata.h
index 31902b3966..1a2d7c5b96 100644
--- a/libnetdata/libnetdata.h
+++ b/libnetdata/libnetdata.h
@@ -377,8 +377,8 @@ typedef struct storage_point {
time_t start_time_s; // the time the point starts
time_t end_time_s; // the time the point ends
- size_t count; // the number of original points aggregated
- size_t anomaly_count; // the number of original points found anomalous
+ uint32_t count; // the number of original points aggregated
+ uint32_t anomaly_count; // the number of original points found anomalous
SN_FLAGS flags; // flags stored with the point
} STORAGE_POINT;
@@ -482,6 +482,9 @@ typedef struct storage_point {
#define storage_point_anomaly_rate(sp) \
(NETDATA_DOUBLE)(storage_point_is_unset(sp) ? 0.0 : (NETDATA_DOUBLE)((sp).anomaly_count) * 100.0 / (NETDATA_DOUBLE)((sp).count))
+#define storage_point_average_value(sp) \
+ ((sp).count ? (sp).sum / (NETDATA_DOUBLE)((sp).count) : 0.0)
+
// ---------------------------------------------------------------------------------------------
void netdata_fix_chart_id(char *s);
diff --git a/web/api/formatters/json/json.c b/web/api/formatters/json/json.c
index 700f804d34..8d7f49da9b 100644
--- a/web/api/formatters/json/json.c
+++ b/web/api/formatters/json/json.c
@@ -247,7 +247,7 @@ void rrdr2json(RRDR *r, BUFFER *wb, RRDR_OPTIONS options, int datatable) {
void rrdr2json_v2(RRDR *r, BUFFER *wb) {
QUERY_TARGET *qt = r->internal.qt;
- RRDR_OPTIONS options = qt->request.options;
+ RRDR_OPTIONS options = qt->window.options;
bool expose_gbc = query_target_aggregatable(qt);
@@ -268,7 +268,7 @@ void rrdr2json_v2(RRDR *r, BUFFER *wb) {
buffer_json_member_add_object(wb, "point");
buffer_json_member_add_uint64(wb, "value", 0);
- buffer_json_member_add_uint64(wb, "ar", 1);
+ buffer_json_member_add_uint64(wb, "arp", 1);
buffer_json_member_add_uint64(wb, "pa", 2);
if(expose_gbc)
buffer_json_member_add_uint64(wb, "count", 3);
diff --git a/web/api/formatters/json_wrapper.c b/web/api/formatters/json_wrapper.c
index d4c1e8a5ac..b8f47ea57d 100644
--- a/web/api/formatters/json_wrapper.c
+++ b/web/api/formatters/json_wrapper.c
@@ -101,7 +101,7 @@ struct summary_total_counts {
size_t failed;
};
-static inline void aggregate_into_summary_totals(struct summary_total_counts *totals, struct query_metrics_counts *metrics) {
+static inline void aggregate_into_summary_totals(struct summary_total_counts *totals, QUERY_METRICS_COUNTS *metrics) {
if(unlikely(!totals || !metrics))
return;
@@ -139,7 +139,7 @@ static inline void query_target_total_counts(BUFFER *wb, const char *key, struct
buffer_json_object_close(wb);
}
-static inline void query_target_metric_counts(BUFFER *wb, struct query_metrics_counts *metrics) {
+static inline void query_target_metric_counts(BUFFER *wb, QUERY_METRICS_COUNTS *metrics) {
if(!metrics->selected && !metrics->queried && !metrics->failed && !metrics->excluded)
return;
@@ -160,7 +160,7 @@ static inline void query_target_metric_counts(BUFFER *wb, struct query_metrics_c
buffer_json_object_close(wb);
}
-static inline void query_target_instance_counts(BUFFER *wb, struct query_instances_counts *instances) {
+static inline void query_target_instance_counts(BUFFER *wb, QUERY_INSTANCES_COUNTS *instances) {
if(!instances->selected && !instances->queried && !instances->failed && !instances->excluded)
return;
@@ -181,7 +181,7 @@ static inline void query_target_instance_counts(BUFFER *wb, struct query_instanc
buffer_json_object_close(wb);
}
-static inline void query_target_alerts_counts(BUFFER *wb, struct query_alerts_counts *alerts, const char *name, bool array) {
+static inline void query_target_alerts_counts(BUFFER *wb, QUERY_ALERTS_COUNTS *alerts, const char *name, bool array) {
if(!alerts->clear && !alerts->other && !alerts->critical && !alerts->warning)
return;
@@ -208,40 +208,36 @@ static inline void query_target_alerts_counts(BUFFER *wb, struct query_alerts_co
buffer_json_object_close(wb);
}
-static inline void query_target_data_statistics(BUFFER *wb, QUERY_TARGET *qt, struct query_data_statistics *d) {
- if(!d->group_points)
+static inline void query_target_points_statistics(BUFFER *wb, QUERY_TARGET *qt, STORAGE_POINT *sp) {
+ if(!sp->count)
return;
buffer_json_member_add_object(wb, "sts");
- buffer_json_member_add_double(wb, "min", d->min);
- buffer_json_member_add_double(wb, "max", d->max);
+ buffer_json_member_add_double(wb, "min", sp->min);
+ buffer_json_member_add_double(wb, "max", sp->max);
if(query_target_aggregatable(qt)) {
- buffer_json_member_add_uint64(wb, "cnt", d->group_points);
+ buffer_json_member_add_uint64(wb, "cnt", sp->count);
- if(d->sum != 0.0)
- buffer_json_member_add_double(wb, "sum", d->sum);
-
- if(d->volume != 0.0)
- buffer_json_member_add_double(wb, "vol", d->volume);
+ if(sp->sum != 0.0) {
+ buffer_json_member_add_double(wb, "sum", sp->sum);
+ buffer_json_member_add_double(wb, "vol", sp->sum * (NETDATA_DOUBLE) query_view_update_every(qt));
+ }
- if(d->anomaly_sum != 0.0)
- buffer_json_member_add_double(wb, "ars", d->anomaly_sum);
+ if(sp->anomaly_count != 0)
+ buffer_json_member_add_double(wb, "ars", storage_point_anomaly_rate(*sp));
}
else {
-// buffer_json_member_add_double(wb, "min", d->min);
-// buffer_json_member_add_double(wb, "max", d->max);
-
- NETDATA_DOUBLE avg = (d->group_points) ? d->sum / (NETDATA_DOUBLE)d->group_points : 0.0;
+ NETDATA_DOUBLE avg = (sp->count) ? sp->sum / (NETDATA_DOUBLE)sp->count : 0.0;
if(avg != 0.0)
buffer_json_member_add_double(wb, "avg", avg);
- NETDATA_DOUBLE arp = (d->group_points) ? d->anomaly_sum / (NETDATA_DOUBLE)d->group_points : 0.0;
+ NETDATA_DOUBLE arp = storage_point_anomaly_rate(*sp);
if(arp != 0.0)
buffer_json_member_add_double(wb, "arp", arp);
- NETDATA_DOUBLE con = (qt->query_stats.volume > 0) ? d->volume * 100.0 / qt->query_stats.volume : 0.0;
+ NETDATA_DOUBLE con = (qt->query_points.sum > 0.0) ? sp->sum * 100.0 / qt->query_points.sum : 0.0;
if(con != 0.0)
buffer_json_member_add_double(wb, "con", con);
}
@@ -254,15 +250,11 @@ static void query_target_summary_nodes_v2(BUFFER *wb, QUERY_TARGET *qt, const ch
QUERY_NODE *qn = query_node(qt, c);
RRDHOST *host = qn->rrdhost;
buffer_json_add_array_item_object(wb);
- buffer_json_member_add_uint64(wb, "ni", qn->slot);
- buffer_json_member_add_string(wb, "mg", host->machine_guid);
- if(qn->node_id[0])
- buffer_json_member_add_string(wb, "nd", qn->node_id);
- buffer_json_member_add_string(wb, "nm", rrdhost_hostname(host));
+ buffer_json_node_add_v2(wb, host, qn->slot, qn->duration_ut);
query_target_instance_counts(wb, &qn->instances);
query_target_metric_counts(wb, &qn->metrics);
query_target_alerts_counts(wb, &qn->alerts, NULL, false);
- query_target_data_statistics(wb, qt, &qn->query_stats);
+ query_target_points_statistics(wb, qt, &qn->query_points);
buffer_json_object_close(wb);
aggregate_into_summary_totals(totals, &qn->metrics);
@@ -275,16 +267,16 @@ static size_t query_target_summary_contexts_v2(BUFFER *wb, QUERY_TARGET *qt, con
DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
struct {
- struct query_data_statistics query_stats;
- struct query_instances_counts instances;
- struct query_metrics_counts metrics;
- struct query_alerts_counts alerts;
- } x = { 0 }, *z;
+ STORAGE_POINT query_points;
+ QUERY_INSTANCES_COUNTS instances;
+ QUERY_METRICS_COUNTS metrics;
+ QUERY_ALERTS_COUNTS alerts;
+ } *z;
for (long c = 0; c < (long) qt->contexts.used; c++) {
QUERY_CONTEXT *qc = query_context(qt, c);
- z = dictionary_set(dict, rrdcontext_acquired_id(qc->rca), &x, sizeof(x));
+ z = dictionary_set(dict, rrdcontext_acquired_id(qc->rca), NULL, sizeof(*z));
z->instances.selected += qc->instances.selected;
z->instances.excluded += qc->instances.selected;
@@ -300,7 +292,7 @@ static size_t query_target_summary_contexts_v2(BUFFER *wb, QUERY_TARGET *qt, con
z->alerts.warning += qc->alerts.warning;
z->alerts.critical += qc->alerts.critical;
- query_target_merge_data_statistics(&z->query_stats, &qc->query_stats);
+ storage_point_merge_to(z->query_points, qc->query_points);
}
size_t unique_contexts = dictionary_entries(dict);
@@ -310,7 +302,7 @@ static size_t query_target_summary_contexts_v2(BUFFER *wb, QUERY_TARGET *qt, con
query_target_instance_counts(wb, &z->instances);
query_target_metric_counts(wb, &z->metrics);
query_target_alerts_counts(wb, &z->alerts, NULL, false);
- query_target_data_statistics(wb, qt, &z->query_stats);
+ query_target_points_statistics(wb, qt, &z->query_points);
buffer_json_object_close(wb);
aggregate_into_summary_totals(totals, &z->metrics);
@@ -334,8 +326,7 @@ static void query_target_summary_instances_v1(BUFFER *wb, QUERY_TARGET *qt, cons
rrdinstance_acquired_id(qi->ria),
rrdinstance_acquired_name(qi->ria));
- bool existing = 0;
- bool *set = dictionary_set(dict, name, &existing, sizeof(bool));
+ bool *set = dictionary_set(dict, name, NULL, sizeof(*set));
if (!*set) {
*set = true;
buffer_json_add_array_item_array(wb);
@@ -369,7 +360,7 @@ static void query_target_summary_instances_v2(BUFFER *wb, QUERY_TARGET *qt, cons
// buffer_json_member_add_string(wb, "nd", qh->node_id);
query_target_metric_counts(wb, &qi->metrics);
query_target_alerts_counts(wb, &qi->alerts, NULL, false);
- query_target_data_statistics(wb, qt, &qi->query_stats);
+ query_target_points_statistics(wb, qt, &qi->query_points);
buffer_json_object_close(wb);
aggregate_into_summary_totals(totals, &qi->metrics);
@@ -385,8 +376,8 @@ static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, co
struct {
const char *id;
const char *name;
- struct query_data_statistics query_stats;
- struct query_metrics_counts metrics;
+ STORAGE_POINT query_points;
+ QUERY_METRICS_COUNTS metrics;
} *z;
size_t q = 0;
for (long c = 0; c < (long) qt->dimensions.used; c++) {
@@ -426,7 +417,7 @@ static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, co
if(qm->status & RRDR_DIMENSION_QUERIED) {
z->metrics.queried++;
- query_target_merge_data_statistics(&z->query_stats, &qm->query_stats);
+ storage_point_merge_to(z->query_points, qm->query_points);
}
}
else
@@ -440,7 +431,7 @@ static void query_target_summary_dimensions_v12(BUFFER *wb, QUERY_TARGET *qt, co
buffer_json_member_add_string(wb, "nm", z->name);
query_target_metric_counts(wb, &z->metrics);
- query_target_data_statistics(wb, qt, &z->query_stats);
+ query_target_points_statistics(wb, qt, &z->query_points);
buffer_json_object_close(wb);
aggregate_into_summary_totals(totals, &z->metrics);
@@ -466,38 +457,34 @@ struct rrdlabels_formatting_v2 {
struct rrdlabels_keys_dict_entry {
const char *name;
DICTIONARY *values;
- struct query_data_statistics query_stats;
- struct query_metrics_counts metrics;
+ STORAGE_POINT query_points;
+ QUERY_METRICS_COUNTS metrics;
};
struct rrdlabels_key_value_dict_entry {
const char *key;
const char *value;
- struct query_data_statistics query_stats;
- struct query_metrics_counts metrics;
+ STORAGE_POINT query_points;
+ QUERY_METRICS_COUNTS metrics;
};
static int rrdlabels_formatting_v2(const char *name, const char *value, RRDLABEL_SRC ls __maybe_unused, void *data) {
struct rrdlabels_formatting_v2 *t = data;
- struct rrdlabels_keys_dict_entry k = {
- .name = name,
- .values = NULL,
- .metrics = (struct query_metrics_counts){ 0 },
- }, *d = dictionary_set(t->keys, name, &k, sizeof(k));
-
- if(!d->values)
+ struct rrdlabels_keys_dict_entry *d = dictionary_set(t->keys, name, NULL, sizeof(*d));
+ if(!d->values) {
+ d->name = name;
d->values = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
+ }
char n[RRD_ID_LENGTH_MAX * 2 + 2];
snprintfz(n, RRD_ID_LENGTH_MAX * 2, "%s:%s", name, value);
- struct rrdlabels_key_value_dict_entry x = {
- .key = name,
- .value = value,
- .query_stats = (struct query_data_statistics) { 0 },
- .metrics = (struct query_metrics_counts){ 0 },
- }, *z = dictionary_set(d->values, n, &x, sizeof(x));
+ struct rrdlabels_key_value_dict_entry *z = dictionary_set(d->values, n, NULL, sizeof(*z));
+ if(!z->key) {
+ z->key = name;
+ z->value = value;
+ }
if(t->v2) {
QUERY_INSTANCE *qi = t->qi;
@@ -512,8 +499,8 @@ static int rrdlabels_formatting_v2(const char *name, const char *value, RRDLABEL
d->metrics.queried += qi->metrics.queried;
d->metrics.failed += qi->metrics.failed;
- query_target_merge_data_statistics(&z->query_stats, &qi->query_stats);
- query_target_merge_data_statistics(&d->query_stats, &qi->query_stats);
+ storage_point_merge_to(z->query_points, qi->query_points);
+ storage_point_merge_to(d->query_points, qi->query_points);
}
return 1;
@@ -537,7 +524,7 @@ static void query_target_summary_labels_v12(BUFFER *wb, QUERY_TARGET *qt, const
buffer_json_add_array_item_object(wb);
buffer_json_member_add_string(wb, "id", d_dfe.name);
query_target_metric_counts(wb, &d->metrics);
- query_target_data_statistics(wb, qt, &d->query_stats);
+ query_target_points_statistics(wb, qt, &d->query_points);
aggregate_into_summary_totals(key_totals, &d->metrics);
buffer_json_member_add_array(wb, "vl");
}
@@ -547,7 +534,7 @@ static void query_target_summary_labels_v12(BUFFER *wb, QUERY_TARGET *qt, const
buffer_json_add_array_item_object(wb);
buffer_json_member_add_string(wb, "id", z->value);
query_target_metric_counts(wb, &z->metrics);
- query_target_data_statistics(wb, qt, &z->query_stats);
+ query_target_points_statistics(wb, qt, &z->query_points);
buffer_json_object_close(wb);
aggregate_into_summary_totals(value_totals, &z->metrics);
} else {
@@ -571,7 +558,7 @@ static void query_target_summary_labels_v12(BUFFER *wb, QUERY_TARGET *qt, const
static void query_target_summary_alerts_v2(BUFFER *wb, QUERY_TARGET *qt, const char *key) {
buffer_json_member_add_array(wb, key);
- struct query_alerts_counts x = { 0 }, *z;
+ QUERY_ALERTS_COUNTS *z;
DICTIONARY *dict = dictionary_create(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE);
for (long c = 0; c < (long) qt->instances.used; c++) {
@@ -581,7 +568,7 @@ static void query_target_summary_alerts_v2(BUFFER *wb, QUERY_TARGET *qt, const c
netdata_rwlock_rdlock(&st->alerts.rwlock);
if (st->alerts.base) {
for (RRDCALC *rc = st->alerts.base; rc; rc = rc->next) {
- z = dictionary_set(dict, string2str(rc->name), &x, sizeof(x));
+ z = dictionary_set(dict, string2str(rc->name), NULL, sizeof(*z));
switch(rc->status) {
case RRDCALC_STATUS_CLEAR:
@@ -720,52 +707,102 @@ static inline size_t rrdr_dimension_view_latest_values(BUFFER *wb, const char *k
return i;
}
-static inline void rrdr_dimension_view_average_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- if(!r->dv)
+static inline void rrdr_dimension_query_points_statistics(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options, bool dview) {
+ STORAGE_POINT *sp = (dview) ? r->dview : r->dqp;
+ NETDATA_DOUBLE anomaly_rate_multiplier = (dview) ? RRDR_DVIEW_ANOMALY_COUNT_MULTIPLIER : 1.0;
+
+ if(unlikely(!sp))
return;
- buffer_json_member_add_array(wb, key);
+ if(key)
+ buffer_json_member_add_object(wb, key);
+ buffer_json_member_add_array(wb, "min");
for(size_t c = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
continue;
- buffer_json_add_array_item_double(wb, r->dv[c]);
+ buffer_json_add_array_item_double(wb, sp[c].min);
}
+ buffer_json_array_close(wb);
+
+ buffer_json_member_add_array(wb, "max");
+ for(size_t c = 0; c < r->d ; c++) {
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
+ buffer_json_add_array_item_double(wb, sp[c].max);
+ }
buffer_json_array_close(wb);
-}
-static inline void rrdr_dimension_view_minimum_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- if(!r->dmin)
- return;
+ if(options & RRDR_OPTION_RETURN_RAW) {
+ buffer_json_member_add_array(wb, "sum");
+ for(size_t c = 0; c < r->d ; c++) {
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
- buffer_json_member_add_array(wb, key);
+ buffer_json_add_array_item_double(wb, sp[c].sum);
+ }
+ buffer_json_array_close(wb);
- for(size_t c = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
+ buffer_json_member_add_array(wb, "cnt");
+ for(size_t c = 0; c < r->d ; c++) {
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
+
+ buffer_json_add_array_item_uint64(wb, sp[c].count);
+ }
+ buffer_json_array_close(wb);
- buffer_json_add_array_item_double(wb, r->dmin[c]);
+ buffer_json_member_add_array(wb, "ars");
+ for(size_t c = 0; c < r->d ; c++) {
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
+
+ buffer_json_add_array_item_uint64(wb, sp[c].anomaly_count * 100 / anomaly_rate_multiplier);
+ }
+ buffer_json_array_close(wb);
}
+ else {
+ NETDATA_DOUBLE sum = 0.0;
+ for(size_t c = 0; c < r->d ; c++) {
+ if(!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
- buffer_json_array_close(wb);
-}
+ sum += ABS(sp[c].sum);
+ }
-static inline void rrdr_dimension_view_maximum_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
- if(!r->dmin)
- return;
+ buffer_json_member_add_array(wb, "avg");
+ for(size_t c = 0; c < r->d ; c++) {
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
- buffer_json_member_add_array(wb, key);
+ buffer_json_add_array_item_double(wb, storage_point_average_value(sp[c]));
+ }
+ buffer_json_array_close(wb);
- for(size_t c = 0; c < r->d ; c++) {
- if(!rrdr_dimension_should_be_exposed(r->od[c], options))
- continue;
+ buffer_json_member_add_array(wb, "arp");
+ for(size_t c = 0; c < r->d ; c++) {
+ if (!rrdr_dimension_should_be_exposed(r->od[c], options))
+ continue;
- buffer_json_add_array_item_double(wb, r->dmax[c]);
+ buffer_json_add_array_item_double(wb, storage_point_anomaly_rate(sp[c]) / anomaly_rate_multiplier);
+ }
+ buffer_json_array_close(wb);
+
+ buffer_json_member_add_array(wb, "con");
+ for(size_t c = 0;