/api/v2 part 10 (#14904)
/api/v2/weights nonzero output
Costa Tsaousis committed
Apr 13, 2023 at 15:27 UTC
238cb29793398cb258efb9a56bf031e9c00a858e
3 files changed
+107
-45
libnetdata/libnetdata.h
+1
@@ -405,6 +405,7 @@ typedef struct storage_point {
405
406
#define storage_point_is_unset(x) (!(x).count)
407
#define storage_point_is_gap(x) (!netdata_double_isnumber((x).sum))
408
+#define storage_point_is_zero(x) (!(x).count || (netdata_double_is_zero((x).min) && netdata_double_is_zero((x).max) && netdata_double_is_zero((x).sum) && (x).anomaly_count == 0))
409
410
#define storage_point_merge_to(dst, src) do { \
411
if(storage_point_is_unset(dst)) \
libnetdata/storage_number/storage_number.h
+3
@@ -70,6 +70,9 @@ typedef long long collected_number;
70
#define netdata_double_isnumber(a) (fpclassify(a) != FP_NAN && fpclassify(a) != FP_INFINITE)
71
#endif
72
73
+#define netdata_double_is_zero(a) (!netdata_double_isnumber(a) || considered_equal_ndd(a, 0.0))
74
+#define netdata_double_is_nonzero(a) (!netdata_double_is_zero(a))
75
+
76
typedef uint32_t storage_number;
77
78
typedef struct storage_number_tier1 {
web/api/queries/weights.c
+103
-45
@@ -443,10 +443,10 @@ static void results_header_to_json_v2(DICTIONARY *results __maybe_unused, BUFFER
443
444
if(method == WEIGHTS_METHOD_MC_KS2 || method == WEIGHTS_METHOD_MC_VOLUME) {
445
buffer_json_member_add_object(wb, "baseline");
446
- buffer_json_member_add_time_t(wb, "baseline_after", baseline_after);
447
- buffer_json_member_add_time_t(wb, "baseline_before", baseline_before);
448
- buffer_json_member_add_time_t(wb, "baseline_duration", baseline_before - baseline_after);
449
- buffer_json_member_add_uint64(wb, "baseline_points", points << shifts);
446
+ buffer_json_member_add_time_t(wb, "after", baseline_after);
447
+ buffer_json_member_add_time_t(wb, "before", baseline_before);
448
+ buffer_json_member_add_time_t(wb, "duration", baseline_before - baseline_after);
449
+ buffer_json_member_add_uint64(wb, "points", points << shifts);
450
buffer_json_object_close(wb);
451
}
452
@@ -454,7 +454,6 @@ static void results_header_to_json_v2(DICTIONARY *results __maybe_unused, BUFFER
454
455
buffer_json_member_add_object(wb, "db");
456
{
457
- buffer_json_member_add_double(wb, "query_time_ms", (double) duration / (double) USEC_PER_MS);
457
buffer_json_member_add_uint64(wb, "db_queries", stats->db_queries);
458
buffer_json_member_add_uint64(wb, "query_result_points", stats->result_points);
459
buffer_json_member_add_uint64(wb, "binary_searches", stats->binary_searches);
@@ -671,6 +670,7 @@ static void multinode_data_schema(BUFFER *wb, RRDR_OPTIONS options __maybe_unuse
670
671
struct dict_unique_node {
672
bool existing;
673
+ bool exposed;
674
uint32_t i;
675
RRDHOST *host;
676
usec_t duration_ut;
@@ -678,12 +678,14 @@ struct dict_unique_node {
678
679
struct dict_unique_name_units {
680
bool existing;
681
+ bool exposed;
682
uint32_t i;
683
const char *units;
684
};
685
686
struct dict_unique_id_name {
687
bool existing;
688
+ bool exposed;
689
uint32_t i;
690
const char *id;
691
const char *name;
@@ -701,7 +703,7 @@ static inline struct dict_unique_node *dict_unique_node_add(DICTIONARY *dict, RR
703
return dun;
704
}
705
704
-static inline ssize_t dict_unique_name_units_add(DICTIONARY *dict, const char *name, const char *units, ssize_t *max_id) {
706
+static inline struct dict_unique_name_units *dict_unique_name_units_add(DICTIONARY *dict, const char *name, const char *units, ssize_t *max_id) {
707
struct dict_unique_name_units *dun = dictionary_set(dict, name, NULL, sizeof(struct dict_unique_name_units));
708
if(!dun->existing) {
709
dun->units = units;
@@ -710,10 +712,10 @@ static inline ssize_t dict_unique_name_units_add(DICTIONARY *dict, const char *n
712
(*max_id)++;
713
}
714
713
- return (ssize_t)dun->i;
715
+ return dun;
716
}
717
716
-static inline ssize_t dict_unique_id_name_add(DICTIONARY *dict, const char *id, const char *name, ssize_t *max_id) {
718
+static inline struct dict_unique_id_name *dict_unique_id_name_add(DICTIONARY *dict, const char *id, const char *name, ssize_t *max_id) {
719
char key[1024 + 1];
720
snprintfz(key, 1024, "%s:%s", id, name);
721
struct dict_unique_id_name *dun = dictionary_set(dict, key, NULL, sizeof(struct dict_unique_id_name));
@@ -725,8 +727,17 @@ static inline ssize_t dict_unique_id_name_add(DICTIONARY *dict, const char *id,
727
dun->name = name;
728
}
729
728
- return (ssize_t)dun->i;
730
+ return dun;
731
}
732
+
733
+static inline bool storage_point_should_be_exposed(struct aggregated_weight *aw, RRDR_OPTIONS options, bool baseline) {
734
+ if((options & RRDR_OPTION_NONZERO) && netdata_double_is_zero(aw->min) && netdata_double_is_zero(aw->max) && netdata_double_is_zero(aw->sum) &&
735
+ storage_point_is_zero(aw->hsp) && (!baseline || storage_point_is_zero(aw->bsp)))
736
+ return false;
737
+
738
+ return true;
739
+}
740
+
741
static size_t registered_results_to_json_multinode_no_group_by(
742
DICTIONARY *results, BUFFER *wb,
743
time_t after, time_t before,
@@ -760,7 +771,10 @@ static size_t registered_results_to_json_multinode_no_group_by(
771
RRDHOST *last_host = NULL;
772
RRDCONTEXT_ACQUIRED *last_rca = NULL;
773
RRDINSTANCE_ACQUIRED *last_ria = NULL;
774
+ struct dict_unique_name_units *context_dun = NULL;
775
struct dict_unique_node *node_dun = NULL;
776
+ struct dict_unique_id_name *instance_dun = NULL;
777
+ struct dict_unique_id_name *dimension_dun = NULL;
778
ssize_t di = -1, ii = -1, ci = -1, ni = -1;
779
ssize_t di_max = 0, ii_max = 0, ci_max = 0, ni_max = 0;
780
size_t total_dimensions = 0;
@@ -768,21 +782,31 @@ static size_t registered_results_to_json_multinode_no_group_by(
782
783
// close instance
784
if(t->ria != last_ria && last_ria) {
771
- storage_point_to_json(wb, WPT_INSTANCE, di, ii, ci, ni, &instance_aw, options, baseline);
785
+ if(storage_point_should_be_exposed(&instance_aw, options, baseline)) {
786
+ storage_point_to_json(wb, WPT_INSTANCE, di, ii, ci, ni, &instance_aw, options, baseline);
787
+ instance_dun->exposed = true;
788
+ }
789
+
790
last_ria = NULL;
791
instance_aw = AGGREGATED_WEIGHT_EMPTY;
792
}
793
794
// close context
795
if(t->rca != last_rca && last_rca) {
778
- storage_point_to_json(wb, WPT_CONTEXT, di, ii, ci, ni, &context_aw, options, baseline);
796
+ if(storage_point_should_be_exposed(&context_aw, options, baseline)) {
797
+ storage_point_to_json(wb, WPT_CONTEXT, di, ii, ci, ni, &context_aw, options, baseline);
798
+ context_dun->exposed = true;
799
+ }
800
last_rca = NULL;
801
context_aw = AGGREGATED_WEIGHT_EMPTY;
802
}
803
804
// close node
805
if(t->host != last_host && last_host) {
785
- storage_point_to_json(wb, WPT_NODE, di, ii, ci, ni, &node_aw, options, baseline);
806
+ if(storage_point_should_be_exposed(&node_aw, options, baseline)) {
807
+ storage_point_to_json(wb, WPT_NODE, di, ii, ci, ni, &node_aw, options, baseline);
808
+ node_dun->exposed = true;
809
+ }
810
last_host = NULL;
811
node_aw = AGGREGATED_WEIGHT_EMPTY;
812
}
@@ -797,17 +821,20 @@ static size_t registered_results_to_json_multinode_no_group_by(
821
// open context
822
if(t->rca != last_rca) {
823
last_rca = t->rca;
800
- ci = dict_unique_name_units_add(dict_contexts, rrdcontext_acquired_id(t->rca),
801
- rrdcontext_acquired_units(t->rca), &ci_max);
824
+ context_dun = dict_unique_name_units_add(dict_contexts, rrdcontext_acquired_id(t->rca),
825
+ rrdcontext_acquired_units(t->rca), &ci_max);
826
+ ci = context_dun->i;
827
}
828
829
// open instance
830
if(t->ria != last_ria) {
831
last_ria = t->ria;
807
- ii = dict_unique_id_name_add(dict_instances, rrdinstance_acquired_id(t->ria), rrdinstance_acquired_name(t->ria), &ii_max);
832
+ instance_dun = dict_unique_id_name_add(dict_instances, rrdinstance_acquired_id(t->ria), rrdinstance_acquired_name(t->ria), &ii_max);
833
+ ii = instance_dun->i;
834
}
835
810
- di = dict_unique_id_name_add(dict_dimensions, rrdmetric_acquired_id(t->rma), rrdmetric_acquired_name(t->rma), &di_max);
836
+ dimension_dun = dict_unique_id_name_add(dict_dimensions, rrdmetric_acquired_id(t->rma), rrdmetric_acquired_name(t->rma), &di_max);
837
+ di = dimension_dun->i;
838
839
struct aggregated_weight aw = {
840
.min = t->value,
@@ -817,7 +844,14 @@ static size_t registered_results_to_json_multinode_no_group_by(
844
.hsp = t->highlighted,
845
.bsp = t->baseline,
846
};
820
- storage_point_to_json(wb, WPT_DIMENSION, di, ii, ci, ni, &aw, options, baseline);
847
+
848
+ if(storage_point_should_be_exposed(&aw, options, baseline)) {
849
+ storage_point_to_json(wb, WPT_DIMENSION, di, ii, ci, ni, &aw, options, baseline);
850
+ node_dun->exposed = true;
851
+ context_dun->exposed = true;
852
+ instance_dun->exposed = true;
853
+ dimension_dun->exposed = true;
854
+ }
855
856
merge_into_aw(instance_aw, t);
857
merge_into_aw(context_aw, t);
@@ -829,16 +863,22 @@ static size_t registered_results_to_json_multinode_no_group_by(
863
dfe_done(t);
864
865
// close instance
832
- if(last_ria)
866
+ if(last_ria && storage_point_should_be_exposed(&instance_aw, options, baseline)) {
867
storage_point_to_json(wb, WPT_INSTANCE, di, ii, ci, ni, &instance_aw, options, baseline);
868
+ instance_dun->exposed = true;
869
+ }
870
871
// close context
836
- if(last_rca)
872
+ if(last_rca && storage_point_should_be_exposed(&context_aw, options, baseline)) {
873
storage_point_to_json(wb, WPT_CONTEXT, di, ii, ci, ni, &context_aw, options, baseline);
874
+ context_dun->exposed = true;
875
+ }
876
877
// close node
840
- if(last_host)
878
+ if(last_host && storage_point_should_be_exposed(&node_aw, options, baseline)) {
879
storage_point_to_json(wb, WPT_NODE, di, ii, ci, ni, &node_aw, options, baseline);
880
+ node_dun->exposed = true;
881
+ }
882
883
buffer_json_array_close(wb); // points
884
@@ -847,9 +887,12 @@ static size_t registered_results_to_json_multinode_no_group_by(
887
{
888
struct dict_unique_node *dun;
889
dfe_start_read(dict_nodes, dun) {
850
- buffer_json_add_array_item_object(wb);
851
- buffer_json_node_add_v2(wb, dun->host, dun->i, dun->duration_ut);
852
- buffer_json_object_close(wb);
890
+ if(!dun->exposed)
891
+ continue;
892
+
893
+ buffer_json_add_array_item_object(wb);
894
+ buffer_json_node_add_v2(wb, dun->host, dun->i, dun->duration_ut);
895
+ buffer_json_object_close(wb);
896
}
897
dfe_done(dun);
898
}
@@ -859,12 +902,15 @@ static size_t registered_results_to_json_multinode_no_group_by(
902
{
903
struct dict_unique_name_units *dun;
904
dfe_start_read(dict_contexts, dun) {
862
- buffer_json_add_array_item_object(wb);
863
- buffer_json_member_add_string(wb, "id", dun_dfe.name);
864
- buffer_json_member_add_string(wb, "units", dun->units);
865
- buffer_json_member_add_int64(wb, "ci", dun->i);
866
- buffer_json_object_close(wb);
867
- }
905
+ if(!dun->exposed)
906
+ continue;
907
+
908
+ buffer_json_add_array_item_object(wb);
909
+ buffer_json_member_add_string(wb, "id", dun_dfe.name);
910
+ buffer_json_member_add_string(wb, "units", dun->units);
911
+ buffer_json_member_add_int64(wb, "ci", dun->i);
912
+ buffer_json_object_close(wb);
913
+ }
914
dfe_done(dun);
915
}
916
buffer_json_array_close(wb);
@@ -873,13 +919,16 @@ static size_t registered_results_to_json_multinode_no_group_by(
919
{
920
struct dict_unique_id_name *dun;
921
dfe_start_read(dict_instances, dun) {
876
- buffer_json_add_array_item_object(wb);
877
- buffer_json_member_add_string(wb, "id", dun->id);
878
- if(dun->id != dun->name)
879
- buffer_json_member_add_string(wb, "nm", dun->name);
880
- buffer_json_member_add_int64(wb, "ii", dun->i);
881
- buffer_json_object_close(wb);
882
- }
922
+ if(!dun->exposed)
923
+ continue;
924
+
925
+ buffer_json_add_array_item_object(wb);
926
+ buffer_json_member_add_string(wb, "id", dun->id);
927
+ if(dun->id != dun->name)
928
+ buffer_json_member_add_string(wb, "nm", dun->name);
929
+ buffer_json_member_add_int64(wb, "ii", dun->i);
930
+ buffer_json_object_close(wb);
931
+ }
932
dfe_done(dun);
933
}
934
buffer_json_array_close(wb);
@@ -888,13 +937,16 @@ static size_t registered_results_to_json_multinode_no_group_by(
937
{
938
struct dict_unique_id_name *dun;
939
dfe_start_read(dict_dimensions, dun) {
891
- buffer_json_add_array_item_object(wb);
892
- buffer_json_member_add_string(wb, "id", dun->id);
893
- if(dun->id != dun->name)
894
- buffer_json_member_add_string(wb, "nm", dun->name);
895
- buffer_json_member_add_int64(wb, "di", dun->i);
896
- buffer_json_object_close(wb);
897
- }
940
+ if(!dun->exposed)
941
+ continue;
942
+
943
+ buffer_json_add_array_item_object(wb);
944
+ buffer_json_member_add_string(wb, "id", dun->id);
945
+ if(dun->id != dun->name)
946
+ buffer_json_member_add_string(wb, "nm", dun->name);
947
+ buffer_json_member_add_int64(wb, "di", dun->i);
948
+ buffer_json_object_close(wb);
949
+ }
950
dfe_done(dun);
951
}
952
buffer_json_array_close(wb);
@@ -1018,9 +1070,15 @@ static size_t registered_results_to_json_multinode_group_by(
1070
const char *k = aw_dfe.name;
1071
const char *n = aw->name;
1072
1073
+ if(!storage_point_should_be_exposed(aw, options, baseline))
1074
+ continue;
1075
+
1076
buffer_json_add_array_item_object(wb);
1077
buffer_json_member_add_string(wb, "id", k);
1023
- buffer_json_member_add_string(wb, "nm", n);
1078
+
1079
+ if(strcmp(k, n) != 0)
1080
+ buffer_json_member_add_string(wb, "nm", n);
1081
+
1082
storage_point_to_json(wb, WPT_GROUP, 0, 0, 0, 0, aw, options, baseline);
1083
buffer_json_object_close(wb);
1084
@@ -1934,7 +1992,7 @@ int web_api_v12_weights(BUFFER *wb, QUERY_WEIGHTS_REQUEST *qwr) {
1992
break;
1993
}
1994
1937
- if(!added_dimensions) {
1995
+ if(!added_dimensions && qwr->version < 2) {
1996
error = "no results produced.";
1997
resp = HTTP_RESP_NOT_FOUND;
1998
}