master
c 189 lines 6.63 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "jsonwrap.h"
4 #include "jsonwrap-internal.h"
5 #include "libnetdata/json/json-keys.h"
6
7 static inline long jsonwrap_v1_chart_ids(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
8 QUERY_TARGET *qt = r->internal.qt;
9 const long query_used = qt->query.used;
10 long c, i;
11
12 buffer_json_member_add_array(wb, key);
13 for (c = 0, i = 0; c < query_used; c++) {
14 if(!rrdr_dimension_should_be_exposed(r->od[c], options))
15 continue;
16
17 QUERY_METRIC *qm = query_metric(qt, c);
18 QUERY_INSTANCE *qi = query_instance(qt, qm->link.query_instance_id);
19 buffer_json_add_array_item_string(wb, rrdinstance_acquired_id(qi->ria));
20 i++;
21 }
22 buffer_json_array_close(wb);
23
24 return i;
25 }
26
27 static inline long query_target_chart_labels_filter_v1(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
28 QUERY_TARGET *qt = r->internal.qt;
29 const long query_used = qt->query.used;
30 long c, i = 0;
31
32 buffer_json_member_add_object(wb, key);
33
34 SIMPLE_PATTERN *pattern = qt->instances.chart_label_key_pattern;
35 char *label_key = NULL;
36 while (pattern && (label_key = simple_pattern_iterate(&pattern))) {
37 buffer_json_member_add_array(wb, label_key);
38
39 for (c = 0, i = 0; c < query_used; c++) {
40 if(!rrdr_dimension_should_be_exposed(r->od[c], options))
41 continue;
42
43 QUERY_METRIC *qm = query_metric(qt, c);
44 QUERY_INSTANCE *qi = query_instance(qt, qm->link.query_instance_id);
45 rrdlabels_value_to_buffer_array_item_or_null(rrdinstance_acquired_labels(qi->ria), wb, label_key);
46 i++;
47 }
48 buffer_json_array_close(wb);
49 }
50
51 buffer_json_object_close(wb);
52
53 return i;
54 }
55
56 static inline long query_target_metrics_latest_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
57 QUERY_TARGET *qt = r->internal.qt;
58 const long query_used = qt->query.used;
59 long c, i;
60
61 buffer_json_member_add_array(wb, key);
62
63 for(c = 0, i = 0; c < query_used ;c++) {
64 if(!rrdr_dimension_should_be_exposed(r->od[c], options))
65 continue;
66
67 QUERY_METRIC *qm = query_metric(qt, c);
68 QUERY_DIMENSION *qd = query_dimension(qt, qm->link.query_dimension_id);
69 buffer_json_add_array_item_double(wb, rrdmetric_acquired_last_stored_value(qd->rma));
70 i++;
71 }
72
73 buffer_json_array_close(wb);
74
75 return i;
76 }
77
78 static inline size_t rrdr_dimension_view_latest_values(BUFFER *wb, const char *key, RRDR *r, RRDR_OPTIONS options) {
79 buffer_json_member_add_array(wb, key);
80
81 size_t c, i;
82 for(c = 0, i = 0; c < r->d ; c++) {
83 if(!rrdr_dimension_should_be_exposed(r->od[c], options))
84 continue;
85
86 i++;
87
88 NETDATA_DOUBLE *cn = &r->v[ (rrdr_rows(r) - 1) * r->d ];
89 RRDR_VALUE_FLAGS *co = &r->o[ (rrdr_rows(r) - 1) * r->d ];
90 NETDATA_DOUBLE n = cn[c];
91
92 if(co[c] & RRDR_VALUE_EMPTY) {
93 if(options & RRDR_OPTION_NULL2ZERO)
94 buffer_json_add_array_item_double(wb, 0.0);
95 else
96 buffer_json_add_array_item_double(wb, NAN);
97 }
98 else
99 buffer_json_add_array_item_double(wb, n);
100 }
101
102 buffer_json_array_close(wb);
103
104 return i;
105 }
106
107 void rrdr_json_wrapper_begin(RRDR *r, BUFFER *wb) {
108 QUERY_TARGET *qt = r->internal.qt;
109 DATASOURCE_FORMAT format = qt->request.format;
110 RRDR_OPTIONS options = qt->window.options;
111
112 long rows = rrdr_rows(r);
113
114 char kq[2] = "", // key quote
115 sq[2] = ""; // string quote
116
117 if( options & RRDR_OPTION_GOOGLE_JSON ) {
118 kq[0] = '\0';
119 sq[0] = '\'';
120 }
121 else {
122 kq[0] = '"';
123 sq[0] = '"';
124 }
125
126 buffer_json_initialize(
127 wb, kq, sq, 0, true, (options & RRDR_OPTION_MINIFY) ? BUFFER_JSON_OPTIONS_MINIFY : BUFFER_JSON_OPTIONS_DEFAULT);
128
129 json_keys_init((options & RRDR_OPTION_LONG_JSON_KEYS) ? JSON_KEYS_OPTION_LONG_KEYS : 0);
130 buffer_json_member_add_uint64(wb, "api", 1);
131 buffer_json_member_add_string(wb, "id", qt->id);
132 buffer_json_member_add_string(wb, "name", qt->id);
133 buffer_json_member_add_time_t(wb, "view_update_every", r->view.update_every);
134 buffer_json_member_add_time_t(wb, "update_every", qt->db.minimum_latest_update_every_s);
135 buffer_json_member_add_time_t_formatted(wb, "first_entry", qt->db.first_time_s, options & RRDR_OPTION_RFC3339);
136 buffer_json_member_add_time_t_formatted(wb, "last_entry", qt->db.last_time_s, options & RRDR_OPTION_RFC3339);
137 buffer_json_member_add_time_t_formatted(wb, "after", r->view.after, options & RRDR_OPTION_RFC3339);
138 buffer_json_member_add_time_t_formatted(wb, "before", r->view.before, options & RRDR_OPTION_RFC3339);
139 buffer_json_member_add_string(wb, "group", time_grouping_tostring(qt->request.time_group_method));
140 rrdr_options_to_buffer_json_array(wb, "options", options);
141
142 if(!rrdr_dimension_names(wb, "dimension_names", r, options))
143 rows = 0;
144
145 if(!rrdr_dimension_ids(wb, "dimension_ids", r, options))
146 rows = 0;
147
148 if (options & RRDR_OPTION_ALL_DIMENSIONS) {
149 query_target_summary_instances_v1(wb, qt, "full_chart_list");
150 query_target_summary_dimensions_v12(wb, qt, "full_dimension_list", false, NULL);
151 query_target_summary_labels_v12(wb, qt, "full_chart_labels", false, NULL, NULL);
152 }
153
154 query_target_functions(wb, "functions", r);
155
156 if (!qt->request.st && !jsonwrap_v1_chart_ids(wb, "chart_ids", r, options))
157 rows = 0;
158
159 if (qt->instances.chart_label_key_pattern && !query_target_chart_labels_filter_v1(wb, "chart_labels", r, options))
160 rows = 0;
161
162 if(!query_target_metrics_latest_values(wb, "latest_values", r, options))
163 rows = 0;
164
165 size_t dimensions = rrdr_dimension_view_latest_values(wb, "view_latest_values", r, options);
166 if(!dimensions)
167 rows = 0;
168
169 buffer_json_member_add_uint64(wb, "dimensions", dimensions);
170 buffer_json_member_add_uint64(wb, "points", rows);
171 buffer_json_member_add_string(wb, "format", rrdr_format_to_string(format));
172
173 buffer_json_member_add_array(wb, "db_points_per_tier");
174 for(size_t tier = 0; tier < nd_profile.storage_tiers; tier++)
175 buffer_json_add_array_item_uint64(wb, qt->db.tiers[tier].points);
176 buffer_json_array_close(wb);
177
178 if(options & RRDR_OPTION_DEBUG)
179 jsonwrap_query_plan(r, wb, options);
180 }
181
182 void rrdr_json_wrapper_end(RRDR *r, BUFFER *wb) {
183 buffer_json_member_add_double(wb, "min", r->view.min);
184 buffer_json_member_add_double(wb, "max", r->view.max);
185
186 buffer_json_query_timings(wb, "timings", &r->internal.qt->timings);
187 buffer_json_finalize(wb);
188 json_keys_reset();
189 }