| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #include "jsonwrap.h" |
| 4 | #include "jsonwrap-internal.h" |
| 5 | |
| 6 | static void rrdset_rrdcalc_entries_v2(BUFFER *wb, RRDINSTANCE_ACQUIRED *ria) { |
| 7 | RRDSET *st = rrdinstance_acquired_rrdset(ria); |
| 8 | if(st) { |
| 9 | rw_spinlock_read_lock(&st->alerts.spinlock); |
| 10 | if(st->alerts.base) { |
| 11 | buffer_json_member_add_object(wb, "alerts"); |
| 12 | for(RRDCALC *rc = st->alerts.base; rc ;rc = rc->next) { |
| 13 | if(rc->status < RRDCALC_STATUS_CLEAR) |
| 14 | continue; |
| 15 | |
| 16 | buffer_json_member_add_object(wb, string2str(rc->config.name)); |
| 17 | buffer_json_member_add_string(wb, JSKEY(status), rrdcalc_status2string(rc->status)); |
| 18 | buffer_json_member_add_double(wb, JSKEY(value), rc->value); |
| 19 | buffer_json_member_add_string(wb, JSKEY(units), string2str(rc->config.units)); |
| 20 | buffer_json_object_close(wb); |
| 21 | } |
| 22 | buffer_json_object_close(wb); |
| 23 | } |
| 24 | rw_spinlock_read_unlock(&st->alerts.spinlock); |
| 25 | } |
| 26 | } |
| 27 | |
| 28 | void query_target_detailed_objects_tree(BUFFER *wb, RRDR *r, RRDR_OPTIONS options) { |
| 29 | QUERY_TARGET *qt = r->internal.qt; |
| 30 | buffer_json_member_add_object(wb, "nodes"); |
| 31 | |
| 32 | time_t now_s = now_realtime_sec(); |
| 33 | RRDHOST *last_host = NULL; |
| 34 | RRDCONTEXT_ACQUIRED *last_rca = NULL; |
| 35 | RRDINSTANCE_ACQUIRED *last_ria = NULL; |
| 36 | |
| 37 | size_t h = 0, c = 0, i = 0, m = 0, q = 0; |
| 38 | for(; h < qt->nodes.used ; h++) { |
| 39 | QUERY_NODE *qn = query_node(qt, h); |
| 40 | RRDHOST *host = qn->rrdhost; |
| 41 | |
| 42 | for( ;c < qt->contexts.used ;c++) { |
| 43 | QUERY_CONTEXT *qc = query_context(qt, c); |
| 44 | RRDCONTEXT_ACQUIRED *rca = qc->rca; |
| 45 | if(!rrdcontext_acquired_belongs_to_host(rca, host)) break; |
| 46 | |
| 47 | for( ;i < qt->instances.used ;i++) { |
| 48 | QUERY_INSTANCE *qi = query_instance(qt, i); |
| 49 | RRDINSTANCE_ACQUIRED *ria = qi->ria; |
| 50 | if(!rrdinstance_acquired_belongs_to_context(ria, rca)) break; |
| 51 | |
| 52 | for( ; m < qt->dimensions.used ; m++) { |
| 53 | QUERY_DIMENSION *qd = query_dimension(qt, m); |
| 54 | RRDMETRIC_ACQUIRED *rma = qd->rma; |
| 55 | if(!rrdmetric_acquired_belongs_to_instance(rma, ria)) break; |
| 56 | |
| 57 | QUERY_METRIC *qm = NULL; |
| 58 | bool queried = false; |
| 59 | for( ; q < qt->query.used ;q++) { |
| 60 | QUERY_METRIC *tqm = query_metric(qt, q); |
| 61 | QUERY_DIMENSION *tqd = query_dimension(qt, tqm->link.query_dimension_id); |
| 62 | if(tqd->rma != rma) break; |
| 63 | |
| 64 | queried = tqm->status & RRDR_DIMENSION_QUERIED; |
| 65 | qm = tqm; |
| 66 | } |
| 67 | |
| 68 | if(!queried & !(options & RRDR_OPTION_ALL_DIMENSIONS)) |
| 69 | continue; |
| 70 | |
| 71 | if(host != last_host) { |
| 72 | if(last_host) { |
| 73 | if(last_rca) { |
| 74 | if(last_ria) { |
| 75 | buffer_json_object_close(wb); // dimensions |
| 76 | buffer_json_object_close(wb); // instance |
| 77 | last_ria = NULL; |
| 78 | } |
| 79 | buffer_json_object_close(wb); // instances |
| 80 | buffer_json_object_close(wb); // context |
| 81 | last_rca = NULL; |
| 82 | } |
| 83 | buffer_json_object_close(wb); // contexts |
| 84 | buffer_json_object_close(wb); // host |
| 85 | } |
| 86 | |
| 87 | buffer_json_member_add_object(wb, host->machine_guid); |
| 88 | if(qn->node_id[0]) |
| 89 | buffer_json_member_add_string(wb, JSKEY(node_id), qn->node_id); |
| 90 | buffer_json_member_add_uint64(wb, JSKEY(node_index), qn->slot); |
| 91 | buffer_json_member_add_string(wb, JSKEY(hostname), rrdhost_hostname(host)); |
| 92 | buffer_json_member_add_object(wb, "contexts"); |
| 93 | |
| 94 | last_host = host; |
| 95 | } |
| 96 | |
| 97 | if(rca != last_rca) { |
| 98 | if(last_rca) { |
| 99 | if(last_ria) { |
| 100 | buffer_json_object_close(wb); // dimensions |
| 101 | buffer_json_object_close(wb); // instance |
| 102 | last_ria = NULL; |
| 103 | } |
| 104 | buffer_json_object_close(wb); // instances |
| 105 | buffer_json_object_close(wb); // context |
| 106 | last_rca = NULL; |
| 107 | } |
| 108 | |
| 109 | buffer_json_member_add_object(wb, rrdcontext_acquired_id(rca)); |
| 110 | buffer_json_member_add_object(wb, "instances"); |
| 111 | |
| 112 | last_rca = rca; |
| 113 | } |
| 114 | |
| 115 | if(ria != last_ria) { |
| 116 | if(last_ria) { |
| 117 | buffer_json_object_close(wb); // dimensions |
| 118 | buffer_json_object_close(wb); // instance |
| 119 | last_ria = NULL; |
| 120 | } |
| 121 | |
| 122 | buffer_json_member_add_object(wb, rrdinstance_acquired_id(ria)); |
| 123 | buffer_json_member_add_string(wb, JSKEY(name), rrdinstance_acquired_name(ria)); |
| 124 | buffer_json_member_add_time_t(wb, JSKEY(update_every), rrdinstance_acquired_update_every(ria)); |
| 125 | RRDLABELS *labels = rrdinstance_acquired_labels(ria); |
| 126 | if(labels) { |
| 127 | buffer_json_member_add_object(wb, "labels"); |
| 128 | rrdlabels_to_buffer_json_members(labels, wb); |
| 129 | buffer_json_object_close(wb); |
| 130 | } |
| 131 | rrdset_rrdcalc_entries_v2(wb, ria); |
| 132 | buffer_json_member_add_object(wb, "dimensions"); |
| 133 | |
| 134 | last_ria = ria; |
| 135 | } |
| 136 | |
| 137 | buffer_json_member_add_object(wb, rrdmetric_acquired_id(rma)); |
| 138 | { |
| 139 | buffer_json_member_add_string(wb, JSKEY(name), rrdmetric_acquired_name(rma)); |
| 140 | buffer_json_member_add_uint64(wb, JSKEY(queried), queried ? 1 : 0); |
| 141 | time_t first_entry_s = rrdmetric_acquired_first_entry(rma); |
| 142 | time_t last_entry_s = rrdmetric_acquired_last_entry(rma); |
| 143 | buffer_json_member_add_time_t_formatted(wb, JSKEY(first_entry), first_entry_s, options & RRDR_OPTION_RFC3339); |
| 144 | buffer_json_member_add_time_t_formatted(wb, JSKEY(last_entry), last_entry_s ? last_entry_s : now_s, options & RRDR_OPTION_RFC3339); |
| 145 | |
| 146 | if(qm) { |
| 147 | if(qm->status & RRDR_DIMENSION_GROUPED) { |
| 148 | // buffer_json_member_add_string(wb, "grouped_as_id", string2str(qm->grouped_as.id)); |
| 149 | buffer_json_member_add_string(wb, "as", string2str(qm->grouped_as.name)); |
| 150 | } |
| 151 | |
| 152 | query_target_points_statistics(wb, qt, &qm->query_points); |
| 153 | |
| 154 | if(options & RRDR_OPTION_DEBUG) |
| 155 | jsonwrap_query_metric_plan(wb, qm, options); |
| 156 | } |
| 157 | } |
| 158 | buffer_json_object_close(wb); // metric |
| 159 | } |
| 160 | } |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | if(last_host) { |
| 165 | if(last_rca) { |
| 166 | if(last_ria) { |
| 167 | buffer_json_object_close(wb); // dimensions |
| 168 | buffer_json_object_close(wb); // instance |
| 169 | last_ria = NULL; |
| 170 | } |
| 171 | buffer_json_object_close(wb); // instances |
| 172 | buffer_json_object_close(wb); // context |
| 173 | last_rca = NULL; |
| 174 | } |
| 175 | buffer_json_object_close(wb); // contexts |
| 176 | buffer_json_object_close(wb); // host |
| 177 | last_host = NULL; |
| 178 | } |
| 179 | buffer_json_object_close(wb); // hosts |
| 180 | } |