diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:03 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-05 12:08:18 +0000 |
commit | 5da14042f70711ea5cf66e034699730335462f66 (patch) | |
tree | 0f6354ccac934ed87a2d555f45be4c831cf92f4a /src/web/api/formatters/value | |
parent | Releasing debian version 1.44.3-2. (diff) | |
download | netdata-5da14042f70711ea5cf66e034699730335462f66.tar.xz netdata-5da14042f70711ea5cf66e034699730335462f66.zip |
Merging upstream version 1.45.3+dfsg.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/web/api/formatters/value')
-rw-r--r-- | src/web/api/formatters/value/README.md | 28 | ||||
-rw-r--r-- | src/web/api/formatters/value/value.c | 153 | ||||
-rw-r--r-- | src/web/api/formatters/value/value.h | 33 |
3 files changed, 214 insertions, 0 deletions
diff --git a/src/web/api/formatters/value/README.md b/src/web/api/formatters/value/README.md new file mode 100644 index 000000000..3599a836e --- /dev/null +++ b/src/web/api/formatters/value/README.md @@ -0,0 +1,28 @@ +<!-- +title: "Value formatter" +custom_edit_url: https://github.com/netdata/netdata/edit/master/src/web/api/formatters/value/README.md +sidebar_label: "Value formatter" +learn_status: "Published" +learn_topic_type: "References" +learn_rel_path: "Developers/Web/Api/Formatters" +--> + +# Value formatter + +The Value formatter presents [results of database queries](https://github.com/netdata/netdata/blob/master/src/web/api/queries/README.md) as a single value. + +To calculate the single value to be returned, it sums the values of all dimensions. + +The Value formatter respects the following API `&options=`: + +| option | supported | description | +|:----: |:-------: |:---------- | +| `percent` | yes | to replace all values with their percentage over the row total| +| `abs` | yes | to turn all values positive, before using them | +| `min2max` | yes | to return the delta from the minimum value to the maximum value (across dimensions)| + +The Value formatter is not exposed by the API by itself. +Instead it is used by the [`ssv`](https://github.com/netdata/netdata/blob/master/src/web/api/formatters/ssv/README.md) formatter +and [health monitoring queries](https://github.com/netdata/netdata/blob/master/src/health/README.md). + + diff --git a/src/web/api/formatters/value/value.c b/src/web/api/formatters/value/value.c new file mode 100644 index 000000000..0ec1b1265 --- /dev/null +++ b/src/web/api/formatters/value/value.c @@ -0,0 +1,153 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#include "value.h" + +inline NETDATA_DOUBLE rrdr2value(RRDR *r, long i, RRDR_OPTIONS options, int *all_values_are_null, NETDATA_DOUBLE *anomaly_rate) { + size_t c; + + NETDATA_DOUBLE *cn = &r->v[ i * r->d ]; + RRDR_VALUE_FLAGS *co = &r->o[ i * r->d ]; + NETDATA_DOUBLE *ar = &r->ar[ i * r->d ]; + + NETDATA_DOUBLE sum = 0, min = NAN, max = NAN, v = NAN; + size_t dims = 0; + + NETDATA_DOUBLE total_anomaly_rate = 0; + + // for each dimension + for (c = 0; c < r->d ; c++) { + if(unlikely(!rrdr_dimension_should_be_exposed(r->od[c], options))) + continue; + + if(unlikely((co[c] & RRDR_VALUE_EMPTY))) + continue; + + NETDATA_DOUBLE n = cn[c]; + + if(unlikely(!dims)) + min = max = n; + + sum += n; + + if (n < min) min = n; + if (n > max) max = n; + + total_anomaly_rate += ar[c]; + + dims++; + } + + if(!dims) { + if(anomaly_rate) + *anomaly_rate = 0; + + if(all_values_are_null) + *all_values_are_null = 1; + + return (options & RRDR_OPTION_NULL2ZERO) ? 0 : NAN; + } + + if(anomaly_rate) + *anomaly_rate = total_anomaly_rate / (NETDATA_DOUBLE)dims; + + if(all_values_are_null) + *all_values_are_null = 0; + + if(options & RRDR_OPTION_DIMS_MIN2MAX) + v = max - min; + else if(options & RRDR_OPTION_DIMS_AVERAGE) + v = sum / (NETDATA_DOUBLE)dims; + else if(options & RRDR_OPTION_DIMS_MIN) + v = min; + else if(options & RRDR_OPTION_DIMS_MAX) + v = max; + else + v = sum; + + if((options & RRDR_OPTION_NULL2ZERO) && (isnan(v) || isinf(v))) + v = 0; + + return v; +} + +QUERY_VALUE rrdmetric2value(RRDHOST *host, + struct rrdcontext_acquired *rca, struct rrdinstance_acquired *ria, struct rrdmetric_acquired *rma, + time_t after, time_t before, + RRDR_OPTIONS options, RRDR_TIME_GROUPING time_group_method, const char *time_group_options, + size_t tier, time_t timeout, QUERY_SOURCE query_source, STORAGE_PRIORITY priority +) { + QUERY_TARGET_REQUEST qtr = { + .version = 1, + .host = host, + .rca = rca, + .ria = ria, + .rma = rma, + .after = after, + .before = before, + .points = 1, + .options = options, + .time_group_method = time_group_method, + .time_group_options = time_group_options, + .tier = tier, + .timeout_ms = timeout, + .query_source = query_source, + .priority = priority, + }; + + ONEWAYALLOC *owa = onewayalloc_create(16 * 1024); + QUERY_TARGET *qt = query_target_create(&qtr); + RRDR *r = rrd2rrdr(owa, qt); + + QUERY_VALUE qv; + + if(!r || rrdr_rows(r) == 0) { + qv = (QUERY_VALUE) { + .value = NAN, + .anomaly_rate = NAN, + .sp = { + .count = 0, + .min = NAN, + .max = NAN, + .sum = NAN, + .anomaly_count = 0, + }, + .duration_ut = (r) ? r->internal.qt->timings.executed_ut - r->internal.qt->timings.received_ut : 0, + }; + } + else { + qv = (QUERY_VALUE) { + .after = r->view.after, + .before = r->view.before, + .points_read = r->stats.db_points_read, + .result_points = r->stats.result_points_generated, + .sp = { + .count = 0, + }, + .duration_ut = r->internal.qt->timings.executed_ut - r->internal.qt->timings.received_ut, + }; + + for(size_t d = 0; d < r->internal.qt->query.used ;d++) { + if(!rrdr_dimension_should_be_exposed(r->internal.qt->query.array[d].status, options)) + continue; + + storage_point_merge_to(qv.sp, r->internal.qt->query.array[d].query_points); + } + + for(size_t t = 0; t < storage_tiers ;t++) + qv.storage_points_per_tier[t] = r->internal.qt->db.tiers[t].points; + + long i = (!(options & RRDR_OPTION_REVERSED))?(long)rrdr_rows(r) - 1:0; + int all_values_are_null = 0; + qv.value = rrdr2value(r, i, options, &all_values_are_null, &qv.anomaly_rate); + if(all_values_are_null) { + qv.value = NAN; + qv.anomaly_rate = NAN; + } + } + + rrdr_free(owa, r); + query_target_release(qt); + onewayalloc_destroy(owa); + + return qv; +} diff --git a/src/web/api/formatters/value/value.h b/src/web/api/formatters/value/value.h new file mode 100644 index 000000000..072ca14f8 --- /dev/null +++ b/src/web/api/formatters/value/value.h @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: GPL-3.0-or-later + +#ifndef NETDATA_API_FORMATTER_VALUE_H +#define NETDATA_API_FORMATTER_VALUE_H + +#include "../rrd2json.h" + +typedef struct storage_value { + NETDATA_DOUBLE value; + NETDATA_DOUBLE anomaly_rate; + time_t after; + time_t before; + size_t points_read; + size_t storage_points_per_tier[RRD_STORAGE_TIERS]; + size_t result_points; + STORAGE_POINT sp; + usec_t duration_ut; +} QUERY_VALUE; + +struct rrdmetric_acquired; +struct rrdinstance_acquired; +struct rrdcontext_acquired; + +QUERY_VALUE rrdmetric2value(RRDHOST *host, + struct rrdcontext_acquired *rca, struct rrdinstance_acquired *ria, struct rrdmetric_acquired *rma, + time_t after, time_t before, + RRDR_OPTIONS options, RRDR_TIME_GROUPING time_group_method, const char *time_group_options, + size_t tier, time_t timeout, QUERY_SOURCE query_source, STORAGE_PRIORITY priority +); + +NETDATA_DOUBLE rrdr2value(RRDR *r, long i, RRDR_OPTIONS options, int *all_values_are_null, NETDATA_DOUBLE *anomaly_rate); + +#endif //NETDATA_API_FORMATTER_VALUE_H |