| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "jsonwrap.h" |
| 4 | #include "jsonwrap-internal.h" |
| 5 | |
| 6 | |
| 7 | ALWAYS_INLINE |
| 8 | size_t rrdr_dimension_names(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) { |
| 9 | const size_t dimensions = r->d; |
| 10 | size_t c, i; |
| 11 | |
| 12 | buffer_json_member_add_array(wb, key); |
| 13 | for(c = 0, i = 0; c < dimensions ; c++) { |
| 14 | if(!rrdr_dimension_should_be_exposed(r->od[c], options)) |
| 15 | continue; |
| 16 | |
| 17 | buffer_json_add_array_item_string(wb, string2str(r->dn[c])); |
| 18 | i++; |
| 19 | } |
| 20 | buffer_json_array_close(wb); |
| 21 | |
| 22 | return i; |
| 23 | } |
| 24 | |
| 25 | ALWAYS_INLINE |
| 26 | size_t rrdr_dimension_ids(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) { |
| 27 | const size_t dimensions = r->d; |
| 28 | size_t c, i; |
| 29 | |
| 30 | buffer_json_member_add_array(wb, key); |
| 31 | for(c = 0, i = 0; c < dimensions ; c++) { |
| 32 | if(!rrdr_dimension_should_be_exposed(r->od[c], options)) |
| 33 | continue; |
| 34 | |
| 35 | buffer_json_add_array_item_string(wb, string2str(r->di[c])); |
| 36 | i++; |
| 37 | } |
| 38 | buffer_json_array_close(wb); |
| 39 | |
| 40 | return i; |
| 41 | } |
| 42 | |
| 43 | ALWAYS_INLINE |
| 44 | void query_target_functions(BUFFER *wb, const char *key, RRDR *r) { |
| 45 | QUERY_TARGET *qt = r->internal.qt; |
| 46 | const long query_used = qt->query.used; |
| 47 | |
| 48 | DICTIONARY *funcs = dictionary_create(DICT_OPTION_SINGLE_THREADED|DICT_OPTION_DONT_OVERWRITE_VALUE); |
| 49 | RRDINSTANCE_ACQUIRED *ria = NULL; |
| 50 | for (long c = 0; c < query_used ; c++) { |
| 51 | QUERY_METRIC *qm = query_metric(qt, c); |
| 52 | QUERY_INSTANCE *qi = query_instance(qt, qm->link.query_instance_id); |
| 53 | if(qi->ria == ria) |
| 54 | continue; |
| 55 | |
| 56 | ria = qi->ria; |
| 57 | chart_functions_to_dict(rrdinstance_acquired_functions(ria), funcs, NULL, 0); |
| 58 | } |
| 59 | |
| 60 | buffer_json_member_add_array(wb, key); |
| 61 | void *t; (void)t; |
| 62 | dfe_start_read(funcs, t) |
| 63 | buffer_json_add_array_item_string(wb, t_dfe.name); |
| 64 | dfe_done(t); |
| 65 | dictionary_destroy(funcs); |
| 66 | buffer_json_array_close(wb); |
| 67 | } |
| 68 | |
| 69 | ALWAYS_INLINE |
| 70 | void query_target_total_counts(BUFFER *wb, const char *key, struct summary_total_counts *totals) { |
| 71 | if(!totals->selected && !totals->queried && !totals->failed && !totals->excluded) |
| 72 | return; |
| 73 | |
| 74 | buffer_json_member_add_object(wb, key); |
| 75 | |
| 76 | if(totals->selected) |
| 77 | buffer_json_member_add_uint64(wb, JSKEY(selected), totals->selected); |
| 78 | |
| 79 | if(totals->excluded) |
| 80 | buffer_json_member_add_uint64(wb, JSKEY(excluded), totals->excluded); |
| 81 | |
| 82 | if(totals->queried) |
| 83 | buffer_json_member_add_uint64(wb, JSKEY(queried), totals->queried); |
| 84 | |
| 85 | if(totals->failed) |
| 86 | buffer_json_member_add_uint64(wb, JSKEY(failed), totals->failed); |
| 87 | |
| 88 | buffer_json_object_close(wb); |
| 89 | } |
| 90 | |
| 91 | ALWAYS_INLINE |
| 92 | void query_target_metric_counts(BUFFER *wb, QUERY_METRICS_COUNTS *metrics) { |
| 93 | if(!metrics->selected && !metrics->queried && !metrics->failed && !metrics->excluded) |
| 94 | return; |
| 95 | |
| 96 | buffer_json_member_add_object(wb, JSKEY(dimensions)); |
| 97 | |
| 98 | if(metrics->selected) |
| 99 | buffer_json_member_add_uint64(wb, JSKEY(selected), metrics->selected); |
| 100 | |
| 101 | if(metrics->excluded) |
| 102 | buffer_json_member_add_uint64(wb, JSKEY(excluded), metrics->excluded); |
| 103 | |
| 104 | if(metrics->queried) |
| 105 | buffer_json_member_add_uint64(wb, JSKEY(queried), metrics->queried); |
| 106 | |
| 107 | if(metrics->failed) |
| 108 | buffer_json_member_add_uint64(wb, JSKEY(failed), metrics->failed); |
| 109 | |
| 110 | buffer_json_object_close(wb); |
| 111 | } |
| 112 | |
| 113 | ALWAYS_INLINE |
| 114 | void query_target_instance_counts(BUFFER *wb, QUERY_INSTANCES_COUNTS *instances) { |
| 115 | if(!instances->selected && !instances->queried && !instances->failed && !instances->excluded) |
| 116 | return; |
| 117 | |
| 118 | buffer_json_member_add_object(wb, JSKEY(instances)); |
| 119 | |
| 120 | if(instances->selected) |
| 121 | buffer_json_member_add_uint64(wb, JSKEY(selected), instances->selected); |
| 122 | |
| 123 | if(instances->excluded) |
| 124 | buffer_json_member_add_uint64(wb, JSKEY(excluded), instances->excluded); |
| 125 | |
| 126 | if(instances->queried) |
| 127 | buffer_json_member_add_uint64(wb, JSKEY(queried), instances->queried); |
| 128 | |
| 129 | if(instances->failed) |
| 130 | buffer_json_member_add_uint64(wb, JSKEY(failed), instances->failed); |
| 131 | |
| 132 | buffer_json_object_close(wb); |
| 133 | } |
| 134 | |
| 135 | ALWAYS_INLINE |
| 136 | void query_target_alerts_counts(BUFFER *wb, QUERY_ALERTS_COUNTS *alerts, const char *name, bool array) { |
| 137 | if(!alerts->clear && !alerts->other && !alerts->critical && !alerts->warning) |
| 138 | return; |
| 139 | |
| 140 | if(array) |
| 141 | buffer_json_add_array_item_object(wb); |
| 142 | else |
| 143 | buffer_json_member_add_object(wb, JSKEY(alerts)); |
| 144 | |
| 145 | if(name) |
| 146 | buffer_json_member_add_string(wb, JSKEY(name), name); |
| 147 | |
| 148 | if(alerts->clear) |
| 149 | buffer_json_member_add_uint64(wb, JSKEY(clear), alerts->clear); |
| 150 | |
| 151 | if(alerts->warning) |
| 152 | buffer_json_member_add_uint64(wb, JSKEY(warning), alerts->warning); |
| 153 | |
| 154 | if(alerts->critical) |
| 155 | buffer_json_member_add_uint64(wb, JSKEY(critical), alerts->critical); |
| 156 | |
| 157 | if(alerts->other) |
| 158 | buffer_json_member_add_uint64(wb, JSKEY(other), alerts->other); |
| 159 | |
| 160 | buffer_json_object_close(wb); |
| 161 | } |
| 162 | |
| 163 | ALWAYS_INLINE |
| 164 | void query_target_points_statistics(BUFFER *wb, QUERY_TARGET *qt, STORAGE_POINT *sp) { |
| 165 | if(!sp->count) |
| 166 | return; |
| 167 | |
| 168 | buffer_json_member_add_object(wb, JSKEY(statistics)); |
| 169 | |
| 170 | buffer_json_member_add_double(wb, "min", sp->min); |
| 171 | buffer_json_member_add_double(wb, "max", sp->max); |
| 172 | |
| 173 | if(query_target_aggregatable(qt)) { |
| 174 | buffer_json_member_add_uint64(wb, JSKEY(count), sp->count); |
| 175 | |
| 176 | buffer_json_member_add_double(wb, "sum", sp->sum); |
| 177 | buffer_json_member_add_double(wb, JSKEY(volume), sp->sum * (NETDATA_DOUBLE) query_view_update_every(qt)); |
| 178 | |
| 179 | buffer_json_member_add_uint64(wb, JSKEY(anomaly_count), sp->anomaly_count); |
| 180 | } |
| 181 | else { |
| 182 | NETDATA_DOUBLE avg = (sp->count) ? sp->sum / (NETDATA_DOUBLE)sp->count : 0.0; |
| 183 | buffer_json_member_add_double(wb, "avg", avg); |
| 184 | |
| 185 | NETDATA_DOUBLE arp = storage_point_anomaly_rate(*sp); |
| 186 | buffer_json_member_add_double(wb, JSKEY(anomaly_rate), arp); |
| 187 | |
| 188 | NETDATA_DOUBLE con = (qt->query_points.sum > 0.0) ? sp->sum * 100.0 / qt->query_points.sum : 0.0; |
| 189 | buffer_json_member_add_double(wb, JSKEY(contribution), con); |
| 190 | } |
| 191 | buffer_json_object_close(wb); |
| 192 | } |
| 193 | |
| 194 | ALWAYS_INLINE |
| 195 | void aggregate_metrics_counts(QUERY_METRICS_COUNTS *dst, const QUERY_METRICS_COUNTS *src) { |
| 196 | dst->selected += src->selected; |
| 197 | dst->excluded += src->excluded; |
| 198 | dst->queried += src->queried; |
| 199 | dst->failed += src->failed; |
| 200 | } |
| 201 | |
| 202 | ALWAYS_INLINE |
| 203 | void aggregate_instances_counts(QUERY_INSTANCES_COUNTS *dst, const QUERY_INSTANCES_COUNTS *src) { |
| 204 | dst->selected += src->selected; |
| 205 | dst->excluded += src->excluded; |
| 206 | dst->queried += src->queried; |
| 207 | dst->failed += src->failed; |
| 208 | } |
| 209 | |
| 210 | ALWAYS_INLINE |
| 211 | void aggregate_alerts_counts(QUERY_ALERTS_COUNTS *dst, const QUERY_ALERTS_COUNTS *src) { |
| 212 | dst->clear += src->clear; |
| 213 | dst->warning += src->warning; |
| 214 | dst->critical += src->critical; |
| 215 | dst->other += src->other; |
| 216 | } |
| 217 | |
| 218 | ALWAYS_INLINE |
| 219 | void aggregate_into_summary_totals(struct summary_total_counts *totals, QUERY_METRICS_COUNTS *metrics) { |
| 220 | if(unlikely(!totals || !metrics)) |
| 221 | return; |
| 222 | |
| 223 | if(metrics->selected) { |
| 224 | totals->selected++; |
| 225 | |
| 226 | if(metrics->queried) |
| 227 | totals->queried++; |
| 228 | |
| 229 | else if(metrics->failed) |
| 230 | totals->failed++; |
| 231 | } |
| 232 | else |
| 233 | totals->excluded++; |
| 234 | } |