58
}
59
}
60
61
-struct rrdfunction_to_json_v2 {
61
+struct function_v2_entry {
62
size_t size;
63
size_t used;
64
size_t *node_ids;
65
STRING *help;
66
};
67
68
-struct rrdcontext_to_json_v2_entry {
68
+struct context_v2_entry {
69
size_t count;
70
STRING *id;
71
STRING *family;
76
FTS_MATCH match;
77
};
78
79
+struct alert_v2_entry {
80
+ RRDCALC *tmp;
81
+
82
+ STRING *name;
83
+
84
+ size_t ati;
85
+
86
+ size_t critical;
87
+ size_t warning;
88
+ size_t clear;
89
+ size_t error;
90
+
91
+ size_t instances;
92
+ DICTIONARY *nodes;
93
+ DICTIONARY *configs;
94
+};
95
+
96
+struct alert_config_v2_entry {
97
+ RRDCALC *tmp;
98
+
99
+ size_t ati;
100
+ size_t aci;
101
+ size_t alerts_using_this;
102
+};
103
+
104
typedef struct full_text_search_index {
105
size_t searches;
106
size_t string_searches;
119
return simple_pattern_matches(q, ptr);
120
}
121
122
+struct contexts_v2_node {
123
+ size_t ni;
124
+ RRDHOST *host;
125
+};
126
+
127
struct rrdcontext_to_json_v2_data {
128
time_t now;
129
130
BUFFER *wb;
101
- union {
102
- struct api_v2_contexts_request *request;
103
- struct api_v2_alerts_request *alerts_request;
104
- };
105
-
106
- DICTIONARY *ctx;
131
+ struct api_v2_contexts_request *request;
132
133
+ CONTEXTS_V2_MODE mode;
134
CONTEXTS_V2_OPTIONS options;
135
struct query_versions versions;
136
138
SIMPLE_PATTERN *scope_pattern;
139
SIMPLE_PATTERN *pattern;
140
size_t ni;
141
+ DICTIONARY *dict; // the result set
142
} nodes;
143
144
struct {
118
- Pvoid_t JudyHS;
119
-// ALERT_OPTIONS alert_options;
145
SIMPLE_PATTERN *scope_pattern;
146
SIMPLE_PATTERN *pattern;
122
-// time_t after;
123
-// time_t before;
124
- size_t li;
125
- } alerts;
147
+ size_t ci;
148
+ DICTIONARY *dict; // the result set
149
+ } contexts;
150
151
struct {
128
- SIMPLE_PATTERN *scope_pattern;
129
- SIMPLE_PATTERN *pattern;
130
- } contexts;
152
+ SIMPLE_PATTERN *alert_name_pattern;
153
+ time_t alarm_id_filter;
154
+
155
+ size_t ati;
156
+ size_t aii;
157
+ size_t aci;
158
+
159
+ DICTIONARY *alerts;
160
+ DICTIONARY *alert_instances;
161
+ DICTIONARY *alert_configs;
162
+ } alerts;
163
164
struct {
165
FTS_MATCH host_match;
169
} q;
170
171
struct {
140
- DICTIONARY *dict;
172
+ DICTIONARY *dict; // the result set
173
} functions;
174
175
struct {
182
struct query_timings timings;
183
};
184
153
-static void add_alert_index(Pvoid_t *JudyHS, uuid_t *uuid, ssize_t idx)
154
-{
155
- Pvoid_t *PValue = JudyHSIns(JudyHS, uuid, sizeof(*uuid), PJE0);
156
- if (!PValue)
157
- return;
158
- *((Word_t *) PValue) = (Word_t) idx;
185
+static void alerts_v2_add(struct alert_v2_entry *t, RRDCALC *rc) {
186
+ t->instances++;
187
+
188
+ switch(rc->status) {
189
+ case RRDCALC_STATUS_CRITICAL:
190
+ t->critical++;
191
+ break;
192
+
193
+ case RRDCALC_STATUS_WARNING:
194
+ t->warning++;
195
+ break;
196
+
197
+ case RRDCALC_STATUS_CLEAR:
198
+ t->clear++;
199
+ break;
200
+
201
+ case RRDCALC_STATUS_REMOVED:
202
+ case RRDCALC_STATUS_UNINITIALIZED:
203
+ break;
204
+
205
+ case RRDCALC_STATUS_UNDEFINED:
206
+ default:
207
+ if(!netdata_double_isnumber(rc->value))
208
+ t->error++;
209
+
210
+ break;
211
+ }
212
+
213
+ dictionary_set(t->nodes, rc->rrdset->rrdhost->machine_guid, NULL, 0);
214
+
215
+ char key[UUID_STR_LEN + 1];
216
+ uuid_unparse_lower(rc->config_hash_id, key);
217
+ dictionary_set(t->configs, key, NULL, 0);
218
+}
219
+
220
+static void alerts_v2_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data) {
221
+ struct rrdcontext_to_json_v2_data *ctl = data;
222
+ struct alert_v2_entry *t = value;
223
+ RRDCALC *rc = t->tmp;
224
+ t->name = rc->name;
225
+ t->ati = ctl->alerts.ati++;
226
+
227
+ t->nodes = dictionary_create(DICT_OPTION_SINGLE_THREADED|DICT_OPTION_VALUE_LINK_DONT_CLONE|DICT_OPTION_NAME_LINK_DONT_CLONE);
228
+ t->configs = dictionary_create(DICT_OPTION_SINGLE_THREADED|DICT_OPTION_VALUE_LINK_DONT_CLONE|DICT_OPTION_NAME_LINK_DONT_CLONE);
229
+
230
+ alerts_v2_add(t, rc);
231
}
232
161
-ssize_t get_alert_index(Pvoid_t JudyHS, uuid_t *uuid)
162
-{
163
- Pvoid_t *PValue = JudyHSGet(JudyHS, uuid, sizeof(*uuid));
164
- if (!PValue)
165
- return -1;
166
- return (ssize_t) *((Word_t *) PValue);
233
+static bool alerts_v2_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) {
234
+ struct alert_v2_entry *t = old_value, *n = new_value;
235
+ RRDCALC *rc = n->tmp;
236
+ alerts_v2_add(t, rc);
237
+ return true;
238
+}
239
+
240
+static void alerts_v2_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
241
+ struct alert_v2_entry *t = value;
242
+ dictionary_destroy(t->nodes);
243
+ dictionary_destroy(t->configs);
244
+}
245
+
246
+static void alert_configs_v2_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data) {
247
+ struct rrdcontext_to_json_v2_data *ctl = data;
248
+ struct alert_config_v2_entry *t = value;
249
+ t->aci = ctl->alerts.aci++;
250
+ t->alerts_using_this = 1;
251
+}
252
+
253
+static bool alert_configs_v2_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value __maybe_unused, void *new_value __maybe_unused, void *data __maybe_unused) {
254
+ struct alert_config_v2_entry *t = old_value;
255
+ t->alerts_using_this++;
256
+ return false;
257
+}
258
+
259
+static void alert_configs_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value __maybe_unused, void *data __maybe_unused) {
260
+ ;
261
+}
262
+
263
+static void alert_instances_v2_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data) {
264
+ struct rrdcontext_to_json_v2_data *ctl = data;
265
+ struct alert_instance_v2_entry *t = value;
266
+ RRDCALC *rc = t->tmp;
267
+
268
+ t->chart_id = rc->rrdset->id;
269
+ t->chart_name = rc->rrdset->name;
270
+ t->family = rc->rrdset->family;
271
+ t->name = rc->name;
272
+ t->status = rc->status;
273
+ t->flags = rc->run_flags;
274
+ t->info = rc->info;
275
+ t->value = rc->value;
276
+ t->last_updated = rc->last_updated;
277
+ t->last_status_change = rc->last_status_change;
278
+ t->last_status_change_value = rc->last_status_change_value;
279
+ t->host = rc->rrdset->rrdhost;
280
+ t->alarm_id = rc->id;
281
+ t->ni = ctl->nodes.ni;
282
+ t->global_id = rc->ae ? rc->ae->global_id : 0;
283
+ t->name = rc->name;
284
+ t->aii = ctl->alerts.aii++;
285
+
286
+ uuid_copy(t->config_hash_id, rc->config_hash_id);
287
+ if(rc->ae)
288
+ uuid_copy(t->last_transition_id, rc->ae->transition_id);
289
+}
290
+
291
+static bool alert_instances_v2_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value __maybe_unused, void *new_value __maybe_unused, void *data __maybe_unused) {
292
+ internal_fatal(true, "This should never happen!");
293
+ return true;
294
+}
295
+
296
+static void alert_instances_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value __maybe_unused, void *data __maybe_unused) {
297
+ ;
298
}
299
300
static FTS_MATCH rrdcontext_to_json_v2_full_text_search(struct rrdcontext_to_json_v2_data *ctl, RRDCONTEXT *rc, SIMPLE_PATTERN *q) {
367
return matched;
368
}
369
370
+static bool rrdcontext_matches_alert(struct rrdcontext_to_json_v2_data *ctl, RRDCONTEXT *rc) {
371
+ size_t matches = 0;
372
+ RRDINSTANCE *ri;
373
+ dfe_start_read(rc->rrdinstances, ri) {
374
+ if(ri->rrdset) {
375
+ RRDSET *st = ri->rrdset;
376
+ netdata_rwlock_rdlock(&st->alerts.rwlock);
377
+ for (RRDCALC *rcl = st->alerts.base; rcl; rcl = rcl->next) {
378
+ if(ctl->alerts.alert_name_pattern && !simple_pattern_matches_string(ctl->alerts.alert_name_pattern, rcl->name))
379
+ continue;
380
+
381
+ if(ctl->alerts.alarm_id_filter && ctl->alerts.alarm_id_filter != rcl->id)
382
+ continue;
383
+
384
+ size_t m = ctl->request->alerts.status & CONTEXTS_V2_ALERT_STATUSES ? 0 : 1;
385
+
386
+ if (!m) {
387
+ if ((ctl->request->alerts.status & CONTEXT_V2_ALERT_UNINITIALIZED) &&
388
+ rcl->status == RRDCALC_STATUS_UNINITIALIZED)
389
+ m++;
390
+
391
+ if ((ctl->request->alerts.status & CONTEXT_V2_ALERT_UNDEFINED) &&
392
+ rcl->status == RRDCALC_STATUS_UNDEFINED)
393
+ m++;
394
+
395
+ if ((ctl->request->alerts.status & CONTEXT_V2_ALERT_CLEAR) &&
396
+ rcl->status == RRDCALC_STATUS_CLEAR)
397
+ m++;
398
+
399
+ if ((ctl->request->alerts.status & CONTEXT_V2_ALERT_RAISED) &&
400
+ rcl->status >= RRDCALC_STATUS_RAISED)
401
+ m++;
402
+
403
+ if ((ctl->request->alerts.status & CONTEXT_V2_ALERT_WARNING) &&
404
+ rcl->status == RRDCALC_STATUS_WARNING)
405
+ m++;
406
+
407
+ if ((ctl->request->alerts.status & CONTEXT_V2_ALERT_CRITICAL) &&
408
+ rcl->status == RRDCALC_STATUS_CRITICAL)
409
+ m++;
410
+
411
+ if(!m)
412
+ continue;
413
+ }
414
+
415
+ struct alert_v2_entry t = {
416
+ .tmp = rcl,
417
+ };
418
+ struct alert_v2_entry *a2e = dictionary_set(ctl->alerts.alerts, string2str(rcl->name), &t,
419
+ sizeof(struct alert_v2_entry));
420
+ size_t ati = a2e->ati;
421
+ size_t aci = 0;
422
+ matches++;
423
+
424
+ if (ctl->options & CONTEXT_V2_OPTION_ALERT_CONFIGURATIONS) {
425
+ char key[UUID_STR_LEN + 1];
426
+ uuid_unparse_lower(rcl->config_hash_id, key);
427
+ struct alert_config_v2_entry t2 = {
428
+ .tmp = rcl,
429
+ .ati = a2e->ati,
430
+ };
431
+ struct alert_config_v2_entry *a2c = dictionary_set(ctl->alerts.alert_configs, key, &t2,
432
+ sizeof(struct alert_config_v2_entry));
433
+ aci = a2c->aci;
434
+ }
435
+
436
+ if (ctl->options & CONTEXT_V2_OPTION_ALERT_INSTANCES) {
437
+ char key[20 + 1];
438
+ snprintfz(key, 20, "%p", rcl);
439
+
440
+ struct alert_instance_v2_entry z = {
441
+ .ati = ati,
442
+ .aci = aci,
443
+ .tmp = rcl,
444
+ };
445
+ dictionary_set(ctl->alerts.alert_instances, key, &z, sizeof(z));
446
+ }
447
+ }
448
+ netdata_rwlock_unlock(&st->alerts.rwlock);
449
+ }
450
+ }
451
+ dfe_done(ri);
452
+
453
+ return matches != 0;
454
+}
455
+
456
+
457
static ssize_t rrdcontext_to_json_v2_add_context(void *data, RRDCONTEXT_ACQUIRED *rca, bool queryable_context __maybe_unused) {
458
struct rrdcontext_to_json_v2_data *ctl = data;
459
463
return 0; // continue to next context
464
465
FTS_MATCH match = ctl->q.host_match;
248
- if((ctl->options & CONTEXTS_V2_SEARCH) && ctl->q.pattern) {
466
+ if((ctl->mode & CONTEXTS_V2_SEARCH) && ctl->q.pattern) {
467
match = rrdcontext_to_json_v2_full_text_search(ctl, rc, ctl->q.pattern);
468
469
if(match == FTS_MATCHED_NONE)
470
return 0; // continue to next context
471
}
472
255
- struct rrdcontext_to_json_v2_entry t = {
256
- .count = 1,
257
- .id = rc->id,
258
- .family = string_dup(rc->family),
259
- .priority = rc->priority,
260
- .first_time_s = rc->first_time_s,
261
- .last_time_s = rc->last_time_s,
262
- .flags = rc->flags,
263
- .match = match,
264
- };
473
+ if(ctl->mode & CONTEXTS_V2_ALERTS) {
474
+ if(!rrdcontext_matches_alert(ctl, rc))
475
+ return 0; // continue to next context
476
+ }
477
266
- dictionary_set(ctl->ctx, string2str(rc->id), &t, sizeof(t));
478
+ if(ctl->contexts.dict) {
479
+ struct context_v2_entry t = {
480
+ .count = 1,
481
+ .id = rc->id,
482
+ .family = string_dup(rc->family),
483
+ .priority = rc->priority,
484
+ .first_time_s = rc->first_time_s,
485
+ .last_time_s = rc->last_time_s,
486
+ .flags = rc->flags,
487
+ .match = match,
488
+ };
489
+
490
+ dictionary_set(ctl->contexts.dict, string2str(rc->id), &t, sizeof(struct context_v2_entry));
491
+ }
492
493
return 1;
494
}
505
buffer_json_object_close(wb);
506
}
507
283
-static ssize_t alert_to_json_v2_add_context(void *data, RRDCONTEXT_ACQUIRED *rca, bool queryable_context __maybe_unused)
284
-{
285
- return rrdcontext_to_json_v2_add_context(data, rca, queryable_context);
286
-}
287
-
508
void buffer_json_node_add_v2(BUFFER *wb, RRDHOST *host, size_t ni, usec_t duration_ut, bool status) {
509
buffer_json_member_add_string(wb, "mg", host->machine_guid);
510
673
buffer_json_object_close(wb); // health
674
}
675
676
+static void rrdcontext_to_json_v2_rrdhost(BUFFER *wb, RRDHOST *host, struct rrdcontext_to_json_v2_data *ctl, size_t node_id) {
677
+ buffer_json_add_array_item_object(wb); // this node
678
+ buffer_json_node_add_v2(wb, host, node_id, 0,
679
+ (ctl->mode & CONTEXTS_V2_AGENTS) && !(ctl->mode & CONTEXTS_V2_NODES_INSTANCES));
680
+
681
+ if(ctl->mode & (CONTEXTS_V2_NODES_INFO | CONTEXTS_V2_NODES_INSTANCES)) {
682
+ RRDHOST_STATUS s;
683
+ rrdhost_status(host, ctl->now, &s);
684
+
685
+ if (ctl->mode & (CONTEXTS_V2_NODES_INFO)) {
686
+ buffer_json_member_add_string(wb, "v", rrdhost_program_version(host));
687
+
688
+ host_labels2json(host, wb, "labels");
689
+
690
+ if (host->system_info) {
691
+ buffer_json_member_add_object(wb, "hw");
692
+ {
693
+ buffer_json_member_add_string_or_empty(wb, "architecture", host->system_info->architecture);
694
+ buffer_json_member_add_string_or_empty(wb, "cpu_frequency", host->system_info->host_cpu_freq);
695
+ buffer_json_member_add_string_or_empty(wb, "cpus", host->system_info->host_cores);
696
+ buffer_json_member_add_string_or_empty(wb, "memory", host->system_info->host_ram_total);
697
+ buffer_json_member_add_string_or_empty(wb, "disk_space", host->system_info->host_disk_space);
698
+ buffer_json_member_add_string_or_empty(wb, "virtualization", host->system_info->virtualization);
699
+ buffer_json_member_add_string_or_empty(wb, "container", host->system_info->container);
700
+ }
701
+ buffer_json_object_close(wb);
702
+
703
+ buffer_json_member_add_object(wb, "os");
704
+ {
705
+ buffer_json_member_add_string_or_empty(wb, "id", host->system_info->host_os_id);
706
+ buffer_json_member_add_string_or_empty(wb, "nm", host->system_info->host_os_name);
707
+ buffer_json_member_add_string_or_empty(wb, "v", host->system_info->host_os_version);
708
+ buffer_json_member_add_object(wb, "kernel");
709
+ buffer_json_member_add_string_or_empty(wb, "nm", host->system_info->kernel_name);
710
+ buffer_json_member_add_string_or_empty(wb, "v", host->system_info->kernel_version);
711
+ buffer_json_object_close(wb);
712
+ }
713
+ buffer_json_object_close(wb);
714
+ }
715
+
716
+ // created - the node is created but never connected to cloud
717
+ // unreachable - not currently connected
718
+ // stale - connected but not having live data
719
+ // reachable - connected with live data
720
+ // pruned - not connected for some time and has been removed
721
+ buffer_json_member_add_string(wb, "state", rrdhost_state_cloud_emulation(host) ? "reachable" : "stale");
722
+
723
+ rrdhost_health_to_json_v2(wb, "health", &s);
724
+ agent_capabilities_to_json(wb, host, "capabilities");
725
+ }
726
+
727
+ if (ctl->mode & (CONTEXTS_V2_NODES_INSTANCES)) {
728
+ buffer_json_member_add_array(wb, "instances");
729
+ buffer_json_add_array_item_object(wb); // this instance
730
+ {
731
+ buffer_json_agent_status_id(wb, 0, 0);
732
+
733
+ buffer_json_member_add_object(wb, "db");
734
+ {
735
+ buffer_json_member_add_string(wb, "status", rrdhost_db_status_to_string(s.db.status));
736
+ buffer_json_member_add_string(wb, "liveness", rrdhost_db_liveness_to_string(s.db.liveness));
737
+ buffer_json_member_add_string(wb, "mode", rrd_memory_mode_name(s.db.mode));
738
+ buffer_json_member_add_time_t(wb, "first_time", s.db.first_time_s);
739
+ buffer_json_member_add_time_t(wb, "last_time", s.db.last_time_s);
740
+ buffer_json_member_add_uint64(wb, "metrics", s.db.metrics);
741
+ buffer_json_member_add_uint64(wb, "instances", s.db.instances);
742
+ buffer_json_member_add_uint64(wb, "contexts", s.db.contexts);
743
+ }
744
+ buffer_json_object_close(wb);
745
+
746
+ rrdhost_receiver_to_json(wb, &s, "ingest");
747
+ rrdhost_sender_to_json(wb, &s, "stream");
748
+
749
+ buffer_json_member_add_object(wb, "ml");
750
+ buffer_json_member_add_string(wb, "status", rrdhost_ml_status_to_string(s.ml.status));
751
+ buffer_json_member_add_string(wb, "type", rrdhost_ml_type_to_string(s.ml.type));
752
+ if (s.ml.status == RRDHOST_ML_STATUS_RUNNING) {
753
+ buffer_json_member_add_object(wb, "metrics");
754
+ {
755
+ buffer_json_member_add_uint64(wb, "anomalous", s.ml.metrics.anomalous);
756
+ buffer_json_member_add_uint64(wb, "normal", s.ml.metrics.normal);
757
+ buffer_json_member_add_uint64(wb, "trained", s.ml.metrics.trained);
758
+ buffer_json_member_add_uint64(wb, "pending", s.ml.metrics.pending);
759
+ buffer_json_member_add_uint64(wb, "silenced", s.ml.metrics.silenced);
760
+ }
761
+ buffer_json_object_close(wb); // metrics
762
+ }
763
+ buffer_json_object_close(wb); // ml
764
+
765
+ rrdhost_health_to_json_v2(wb, "health", &s);
766
+
767
+ host_functions2json(host, wb); // functions
768
+ agent_capabilities_to_json(wb, host, "capabilities");
769
+ }
770
+ buffer_json_object_close(wb); // this instance
771
+ buffer_json_array_close(wb); // instances
772
+ }
773
+ }
774
+ buffer_json_object_close(wb); // this node
775
+}
776
+
777
static ssize_t rrdcontext_to_json_v2_add_host(void *data, RRDHOST *host, bool queryable_host) {
778
if(!queryable_host || !host->rrdctx.contexts)
779
// the host matches the 'scope_host' but does not match the 'host' patterns
781
return 0; // continue to next host
782
783
struct rrdcontext_to_json_v2_data *ctl = data;
463
- BUFFER *wb = ctl->wb;
784
785
if(ctl->window.enabled && !rrdhost_matches_window(host, ctl->window.after, ctl->window.before, ctl->now))
786
// the host does not have data in the requested window
794
// interrupted
795
return -1; // stop the query
796
477
- bool host_matched = (ctl->options & CONTEXTS_V2_NODES);
478
- bool do_contexts = (ctl->options & (CONTEXTS_V2_CONTEXTS | CONTEXTS_V2_SEARCH));
797
+ bool host_matched = (ctl->mode & CONTEXTS_V2_NODES);
798
+ bool do_contexts = (ctl->mode & (CONTEXTS_V2_CONTEXTS | CONTEXTS_V2_SEARCH | CONTEXTS_V2_ALERTS));
799
800
ctl->q.host_match = FTS_MATCHED_NONE;
481
- if((ctl->options & CONTEXTS_V2_SEARCH)) {
801
+ if((ctl->mode & CONTEXTS_V2_SEARCH)) {
802
// check if we match the host itself
803
if(ctl->q.pattern && (
804
full_text_search_string(&ctl->q.fts, ctl->q.pattern, host->hostname) ||
835
if(!host_matched)
836
return 0;
837
518
- if(ctl->options & CONTEXTS_V2_FUNCTIONS) {
519
- struct rrdfunction_to_json_v2 t = {
838
+ if(ctl->mode & CONTEXTS_V2_FUNCTIONS) {
839
+ struct function_v2_entry t = {
840
.used = 1,
841
.size = 1,
842
.node_ids = &ctl->nodes.ni,
845
host_functions_to_dict(host, ctl->functions.dict, &t, sizeof(t), &t.help);
846
}
847
528
- if(ctl->options & CONTEXTS_V2_NODES) {
529
- buffer_json_add_array_item_object(wb); // this node
530
- buffer_json_node_add_v2(wb, host, ctl->nodes.ni++, 0,
531
- (ctl->options & CONTEXTS_V2_AGENTS) && !(ctl->options & CONTEXTS_V2_NODES_INSTANCES));
532
-
533
- if(ctl->options & (CONTEXTS_V2_NODES_INFO | CONTEXTS_V2_NODES_INSTANCES)) {
534
- RRDHOST_STATUS s;
535
- rrdhost_status(host, ctl->now, &s);
536
-
537
- if (ctl->options & (CONTEXTS_V2_NODES_INFO)) {
538
- buffer_json_member_add_string(wb, "v", rrdhost_program_version(host));
539
-
540
- host_labels2json(host, wb, "labels");
541
-
542
- if (host->system_info) {
543
- buffer_json_member_add_object(wb, "hw");
544
- {
545
- buffer_json_member_add_string_or_empty(wb, "architecture", host->system_info->architecture);
546
- buffer_json_member_add_string_or_empty(wb, "cpu_frequency", host->system_info->host_cpu_freq);
547
- buffer_json_member_add_string_or_empty(wb, "cpus", host->system_info->host_cores);
548
- buffer_json_member_add_string_or_empty(wb, "memory", host->system_info->host_ram_total);
549
- buffer_json_member_add_string_or_empty(wb, "disk_space", host->system_info->host_disk_space);
550
- buffer_json_member_add_string_or_empty(wb, "virtualization", host->system_info->virtualization);
551
- buffer_json_member_add_string_or_empty(wb, "container", host->system_info->container);
552
- }
553
- buffer_json_object_close(wb);
554
-
555
- buffer_json_member_add_object(wb, "os");
556
- {
557
- buffer_json_member_add_string_or_empty(wb, "id", host->system_info->host_os_id);
558
- buffer_json_member_add_string_or_empty(wb, "nm", host->system_info->host_os_name);
559
- buffer_json_member_add_string_or_empty(wb, "v", host->system_info->host_os_version);
560
- buffer_json_member_add_object(wb, "kernel");
561
- buffer_json_member_add_string_or_empty(wb, "nm", host->system_info->kernel_name);
562
- buffer_json_member_add_string_or_empty(wb, "v", host->system_info->kernel_version);
563
- buffer_json_object_close(wb);
564
- }
565
- buffer_json_object_close(wb);
566
- }
567
-
568
- // created - the node is created but never connected to cloud
569
- // unreachable - not currently connected
570
- // stale - connected but not having live data
571
- // reachable - connected with live data
572
- // pruned - not connected for some time and has been removed
573
- buffer_json_member_add_string(wb, "state", rrdhost_state_cloud_emulation(host) ? "reachable" : "stale");
574
-
575
- rrdhost_health_to_json_v2(wb, "health", &s);
576
- agent_capabilities_to_json(wb, host, "capabilities");
577
- }
578
-
579
- if (ctl->options & (CONTEXTS_V2_NODES_INSTANCES)) {
580
- buffer_json_member_add_array(wb, "instances");
581
- buffer_json_add_array_item_object(wb); // this instance
582
- {
583
- buffer_json_agent_status_id(wb, 0, 0);
584
-
585
- buffer_json_member_add_object(wb, "db");
586
- {
587
- buffer_json_member_add_string(wb, "status", rrdhost_db_status_to_string(s.db.status));
588
- buffer_json_member_add_string(wb, "liveness", rrdhost_db_liveness_to_string(s.db.liveness));
589
- buffer_json_member_add_string(wb, "mode", rrd_memory_mode_name(s.db.mode));
590
- buffer_json_member_add_time_t(wb, "first_time", s.db.first_time_s);
591
- buffer_json_member_add_time_t(wb, "last_time", s.db.last_time_s);
592
- buffer_json_member_add_uint64(wb, "metrics", s.db.metrics);
593
- buffer_json_member_add_uint64(wb, "instances", s.db.instances);
594
- buffer_json_member_add_uint64(wb, "contexts", s.db.contexts);
595
- }
596
- buffer_json_object_close(wb);
597
-
598
- rrdhost_receiver_to_json(wb, &s, "ingest");
599
- rrdhost_sender_to_json(wb, &s, "stream");
600
-
601
- buffer_json_member_add_object(wb, "ml");
602
- buffer_json_member_add_string(wb, "status", rrdhost_ml_status_to_string(s.ml.status));
603
- buffer_json_member_add_string(wb, "type", rrdhost_ml_type_to_string(s.ml.type));
604
- if (s.ml.status == RRDHOST_ML_STATUS_RUNNING) {
605
- buffer_json_member_add_object(wb, "metrics");
606
- {
607
- buffer_json_member_add_uint64(wb, "anomalous", s.ml.metrics.anomalous);
608
- buffer_json_member_add_uint64(wb, "normal", s.ml.metrics.normal);
609
- buffer_json_member_add_uint64(wb, "trained", s.ml.metrics.trained);
610
- buffer_json_member_add_uint64(wb, "pending", s.ml.metrics.pending);
611
- buffer_json_member_add_uint64(wb, "silenced", s.ml.metrics.silenced);
612
- }
613
- buffer_json_object_close(wb); // metrics
614
- }
615
- buffer_json_object_close(wb); // ml
616
-
617
- rrdhost_health_to_json_v2(wb, "health", &s);
848
+ if(ctl->mode & CONTEXTS_V2_NODES) {
849
+ struct contexts_v2_node t = {
850
+ .ni = ctl->nodes.ni++,
851
+ .host = host,
852
+ };
853
619
- host_functions2json(host, wb); // functions
620
- agent_capabilities_to_json(wb, host, "capabilities");
621
- }
622
- buffer_json_object_close(wb); // this instance
623
- buffer_json_array_close(wb); // instances
624
- }
625
- }
626
- buffer_json_object_close(wb); // this node
854
+ dictionary_set(ctl->nodes.dict, host->machine_guid, &t, sizeof(struct contexts_v2_node));
855
}
856
857
return 1;
858
}
859
632
-static ssize_t alert_to_json_v2_add_host(void *data, RRDHOST *host, bool queryable_host) {
633
- if(!queryable_host || !host->rrdctx.contexts)
634
- // the host matches the 'scope_host' but does not match the 'host' patterns
635
- // or the host does not have any contexts
636
- return 0;
637
-
638
- struct rrdcontext_to_json_v2_data *ctl = data;
639
- BUFFER *wb = ctl->wb;
640
-
641
- bool host_matched = (ctl->options & CONTEXTS_V2_NODES);
642
- bool do_contexts = (ctl->options & (CONTEXTS_V2_CONTEXTS));
643
-
644
- ctl->q.host_match = FTS_MATCHED_NONE;
645
- if((ctl->options & CONTEXTS_V2_SEARCH)) {
646
- // check if we match the host itself
647
- if(ctl->q.pattern && (
648
- full_text_search_string(&ctl->q.fts, ctl->q.pattern, host->hostname) ||
649
- full_text_search_char(&ctl->q.fts, ctl->q.pattern, host->machine_guid) ||
650
- (ctl->q.pattern && full_text_search_char(&ctl->q.fts, ctl->q.pattern, ctl->q.host_node_id_str)))) {
651
- ctl->q.host_match = FTS_MATCHED_HOST;
652
- do_contexts = true;
653
- }
654
- }
655
-
656
- if(do_contexts) {
657
- // save it
658
- SIMPLE_PATTERN *old_q = ctl->q.pattern;
659
-
660
- if(ctl->q.host_match == FTS_MATCHED_HOST)
661
- // do not do pattern matching on contexts - we matched the host itself
662
- ctl->q.pattern = NULL;
663
-
664
- ssize_t added = query_scope_foreach_context(
665
- host, ctl->alerts_request->scope_contexts,
666
- ctl->contexts.scope_pattern, ctl->contexts.pattern,
667
- alert_to_json_v2_add_context, queryable_host, ctl);
668
-
669
- // restore it
670
- ctl->q.pattern = old_q;
671
-
672
- if(added == -1)
673
- return -1;
674
-
675
- if(added)
676
- host_matched = true;
677
- }
678
-
679
- if(host_matched && (ctl->options & (CONTEXTS_V2_NODES))) {
680
- buffer_json_add_array_item_object(wb);
681
- buffer_json_node_add_v2(wb, host, ctl->nodes.ni++, 0, false);
682
-
683
- if (ctl->alerts_request->options & ALERT_OPTION_TRANSITIONS) {
684
- if (rrdhost_flag_check(host, RRDHOST_FLAG_INITIALIZED_HEALTH)) {
685
- buffer_json_member_add_array(wb, "instances");
686
- health_alert2json(host, wb, ctl->alerts_request->options, ctl->alerts.JudyHS, ctl->alerts_request->after, ctl->alerts_request->before, ctl->alerts_request->last);
687
- buffer_json_array_close(wb);
688
- }
689
- }
690
-
691
- buffer_json_object_close(wb);
692
- }
693
-
694
- return host_matched ? 1 : 0;
695
-}
696
-
697
-static inline bool alert_is_matched( struct api_v2_alerts_request *alerts_request, RRDCALC *rc)
698
-{
699
- char hash_id[UUID_STR_LEN];
700
- uuid_unparse_lower(rc->config_hash_id, hash_id);
701
-
702
- if (alerts_request->alert_id)
703
- return (rc->id == alerts_request->alert_id);
704
-
705
- SIMPLE_PATTERN_RESULT match = SP_MATCHED_POSITIVE;
706
- SIMPLE_PATTERN *match_pattern = alerts_request->config_hash_pattern;
707
- if(match_pattern) {
708
- match = simple_pattern_matches_extract(match_pattern, hash_id, NULL, 0);
709
- if(match == SP_NOT_MATCHED)
710
- return false;;
711
- }
712
-
713
- match = SP_MATCHED_POSITIVE;
714
- match_pattern = alerts_request->alert_name_pattern;
715
- if(match_pattern) {
716
- match = simple_pattern_matches_string_extract(match_pattern, rc->name, NULL, 0);
717
- if(match == SP_NOT_MATCHED)
718
- return false;
719
- }
720
-
721
- return true;
722
-}
723
-
724
-static ssize_t alert_to_json_v2_add_alert(void *data, RRDHOST *host, bool queryable_host) {
725
- if(!queryable_host || !host->rrdctx.contexts)
726
- // the host matches the 'scope_host' but does not match the 'host' patterns
727
- // or the host does not have any contexts
728
- return 0;
729
-
730
- struct rrdcontext_to_json_v2_data *ctl = data;
731
- BUFFER *wb = ctl->wb;
732
-
733
- bool host_matched = (ctl->options & CONTEXTS_V2_NODES);
734
- bool do_contexts = (ctl->options & (CONTEXTS_V2_CONTEXTS));
735
-
736
- if(do_contexts) {
737
- ssize_t added = query_scope_foreach_context(
738
- host, ctl->request->scope_contexts,
739
- ctl->contexts.scope_pattern, ctl->contexts.pattern,
740
- alert_to_json_v2_add_context, queryable_host, ctl);
741
-
742
- if(added == -1)
743
- return -1;
744
-
745
- if(added)
746
- host_matched = true;
747
- }
748
-
749
- if(host_matched && (ctl->options & (CONTEXTS_V2_NODES))) {
750
- if (rrdhost_flag_check(host, RRDHOST_FLAG_INITIALIZED_HEALTH)) {
751
-
752
- RRDCALC *rc;
753
- foreach_rrdcalc_in_rrdhost_read(host, rc) {
754
- if(unlikely(!rc->rrdset || !rc->rrdset->last_collected_time.tv_sec))
755
- continue;
756
-
757
- if (unlikely(!rrdset_is_available_for_exporting_and_alarms(rc->rrdset)))
758
- continue;
759
-
760
- if ((ctl->alerts_request->options & ALERT_OPTION_ACTIVE) &&
761
- !(rc->status == RRDCALC_STATUS_WARNING || rc->status == RRDCALC_STATUS_CRITICAL))
762
- continue;
763
-
764
- char hash_id[GUID_LEN + 1];
765
- uuid_unparse_lower(rc->config_hash_id, hash_id);
766
-
767
- if (!alert_is_matched(ctl->alerts_request, rc))
768
- continue;
769
-
770
- ssize_t idx = get_alert_index(ctl->alerts.JudyHS, &rc->config_hash_id);
771
- if (idx >= 0)
772
- continue;
773
-
774
- buffer_json_add_array_item_object(wb);
775
- add_alert_index(&ctl->alerts.JudyHS, &rc->config_hash_id, (ssize_t)ctl->alerts.li++);
776
-
777
- buffer_json_member_add_string(wb, "config_hash_id", hash_id);
778
- buffer_json_member_add_string(wb, "name", rrdcalc_name(rc));
779
- buffer_json_member_add_string(wb, "chart", rrdcalc_chart_name(rc));
780
- buffer_json_member_add_string(wb, "family", (rc->rrdset) ? rrdset_family(rc->rrdset) : "");
781
- buffer_json_member_add_string(wb, "class", rc->classification ? rrdcalc_classification(rc) : "Unknown");
782
- buffer_json_member_add_string(wb, "component", rc->component ? rrdcalc_component(rc) : "Unknown");
783
- buffer_json_member_add_string(wb, "type", rc->type ? rrdcalc_type(rc) : "Unknown");
784
- buffer_json_member_add_string(wb, "units", rrdcalc_units(rc));
785
- buffer_json_member_add_boolean(wb, "enabled", host->health.health_enabled);
786
-
787
- if (ctl->alerts_request->options & ALERT_OPTION_CONFIG) {
788
- buffer_json_member_add_object(wb, "config");
789
- {
790
- buffer_json_member_add_boolean(wb, "active", (rc->rrdset));
791
- buffer_json_member_add_boolean(wb, "disabled", (rc->run_flags & RRDCALC_FLAG_DISABLED));
792
- buffer_json_member_add_boolean(wb, "silenced", (rc->run_flags & RRDCALC_FLAG_SILENCED));
793
- buffer_json_member_add_string(
794
- wb, "exec", rc->exec ? rrdcalc_exec(rc) : string2str(host->health.health_default_exec));
795
- buffer_json_member_add_string(
796
- wb,
797
- "recipient",
798
- rc->recipient ? rrdcalc_recipient(rc) : string2str(host->health.health_default_recipient));
799
- buffer_json_member_add_string(wb, "info", rrdcalc_info(rc));
800
- buffer_json_member_add_string(wb, "source", rrdcalc_source(rc));
801
- buffer_json_member_add_time_t(wb, "update_every", rc->update_every);
802
- buffer_json_member_add_time_t(wb, "delay_up_duration", rc->delay_up_duration);
803
- buffer_json_member_add_time_t(wb, "delay_down_duration", rc->delay_down_duration);
804
- buffer_json_member_add_time_t(wb, "delay_max_duration", rc->delay_max_duration);
805
- buffer_json_member_add_double(wb, "delay_multiplier", rc->delay_multiplier);
806
- buffer_json_member_add_time_t(wb, "delay", rc->delay_last);
807
- buffer_json_member_add_time_t(wb, "warn_repeat_every", rc->warn_repeat_every);
808
- buffer_json_member_add_time_t(wb, "crit_repeat_every", rc->crit_repeat_every);
809
- if (unlikely(rc->options & RRDCALC_OPTION_NO_CLEAR_NOTIFICATION)) {
810
- buffer_json_member_add_boolean(wb, "no_clear_notification", true);
811
- }
812
-
813
- if (rc->calculation) {
814
- buffer_json_member_add_string(wb, "calc", rc->calculation->source);
815
- buffer_json_member_add_string(wb, "calc_parsed", rc->calculation->parsed_as);
816
- }
817
-
818
- if (rc->warning) {
819
- buffer_json_member_add_string(wb, "warn", rc->warning->source);
820
- buffer_json_member_add_string(wb, "warn_parsed", rc->warning->parsed_as);
821
- }
822
-
823
- if (rc->critical) {
824
- buffer_json_member_add_string(wb, "crit", rc->critical->source);
825
- buffer_json_member_add_string(wb, "crit_parsed", rc->critical->parsed_as);
826
- }
827
-
828
- if (RRDCALC_HAS_DB_LOOKUP(rc)) {
829
- if (rc->dimensions)
830
- buffer_json_member_add_string(wb, "lookup_dimensions", rrdcalc_dimensions(rc));
831
-
832
- buffer_json_member_add_string(wb, "lookup_method", time_grouping_method2string(rc->group));
833
- buffer_json_member_add_time_t(wb, "lookup_after", rc->after);
834
- buffer_json_member_add_time_t(wb, "lookup_before", rc->before);
835
-
836
- BUFFER *temp_id = buffer_create(1, NULL);
837
- buffer_data_options2string(temp_id, rc->options);
838
-
839
- buffer_json_member_add_string(wb, "lookup_options", buffer_tostring(temp_id));
840
-
841
- buffer_free(temp_id);
842
- }
843
- }
844
- buffer_json_object_close(wb); // config
845
- }
846
- buffer_json_object_close(wb); // Alert
847
- }
848
- foreach_rrdcalc_in_rrdhost_done(rc);
849
- }
850
- }
851
-
852
- return host_matched ? 1 : 0;
853
-}
854
-
855
-static void buffer_json_contexts_v2_options_to_array(BUFFER *wb, CONTEXTS_V2_OPTIONS options) {
856
- if(options & CONTEXTS_V2_DEBUG)
857
- buffer_json_add_array_item_string(wb, "debug");
858
-
859
- if(options & CONTEXTS_V2_MINIFY)
860
- buffer_json_add_array_item_string(wb, "minify");
860
+static void buffer_json_contexts_v2_mode_to_array(BUFFER *wb, const char *key, CONTEXTS_V2_MODE mode) {
861
+ buffer_json_member_add_array(wb, key);
862
862
- if(options & CONTEXTS_V2_VERSIONS)
863
+ if(mode & CONTEXTS_V2_VERSIONS)
864
buffer_json_add_array_item_string(wb, "versions");
865
865
- if(options & CONTEXTS_V2_AGENTS)
866
+ if(mode & CONTEXTS_V2_AGENTS)
867
buffer_json_add_array_item_string(wb, "agents");
868
868
- if(options & CONTEXTS_V2_AGENTS_INFO)
869
+ if(mode & CONTEXTS_V2_AGENTS_INFO)
870
buffer_json_add_array_item_string(wb, "agents-info");
871
871
- if(options & CONTEXTS_V2_NODES)
872
+ if(mode & CONTEXTS_V2_NODES)
873
buffer_json_add_array_item_string(wb, "nodes");
874
874
- if(options & CONTEXTS_V2_NODES_INFO)
875
+ if(mode & CONTEXTS_V2_NODES_INFO)
876
buffer_json_add_array_item_string(wb, "nodes-info");
877
877
- if(options & CONTEXTS_V2_NODES_INSTANCES)
878
+ if(mode & CONTEXTS_V2_NODES_INSTANCES)
879
buffer_json_add_array_item_string(wb, "nodes-instances");
880
880
- if(options & CONTEXTS_V2_CONTEXTS)
881
+ if(mode & CONTEXTS_V2_CONTEXTS)
882
buffer_json_add_array_item_string(wb, "contexts");
883
883
- if(options & CONTEXTS_V2_SEARCH)
884
+ if(mode & CONTEXTS_V2_SEARCH)
885
buffer_json_add_array_item_string(wb, "search");
886
+
887
+ if(mode & CONTEXTS_V2_ALERTS)
888
+ buffer_json_add_array_item_string(wb, "alerts");
889
+
890
+ buffer_json_array_close(wb);
891
}
892
893
void buffer_json_query_timings(BUFFER *wb, const char *key, struct query_timings *timings) {
986
}
987
988
static void functions_insert_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
983
- struct rrdfunction_to_json_v2 *t = value;
989
+ struct function_v2_entry *t = value;
990
991
// it is initialized with a static reference - we need to mallocz() the array
992
size_t *v = t->node_ids;
997
}
998
999
static bool functions_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) {
994
- struct rrdfunction_to_json_v2 *t = old_value, *n = new_value;
1000
+ struct function_v2_entry *t = old_value, *n = new_value;
1001
size_t *v = n->node_ids;
1002
1003
if(t->used >= t->size) {
1011
}
1012
1013
static void functions_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
1008
- struct rrdfunction_to_json_v2 *t = value;
1014
+ struct function_v2_entry *t = value;
1015
freez(t->node_ids);
1016
}
1017
1018
static bool contexts_conflict_callback(const DICTIONARY_ITEM *item __maybe_unused, void *old_value, void *new_value, void *data __maybe_unused) {
1013
- struct rrdcontext_to_json_v2_entry *o = old_value;
1014
- struct rrdcontext_to_json_v2_entry *n = new_value;
1019
+ struct context_v2_entry *o = old_value;
1020
+ struct context_v2_entry *n = new_value;
1021
1022
o->count++;
1023
1058
}
1059
1060
static void contexts_delete_callback(const DICTIONARY_ITEM *item __maybe_unused, void *value, void *data __maybe_unused) {
1055
- struct rrdcontext_to_json_v2_entry *z = value;
1061
+ struct context_v2_entry *z = value;
1062
string_freez(z->family);
1063
}
1064
1059
-int rrdcontext_to_json_v2(BUFFER *wb, struct api_v2_contexts_request *req, CONTEXTS_V2_OPTIONS options) {
1065
+static void rrdcontext_v2_set_transition_filter(const char *machine_guid, const char *context, time_t alarm_id, void *data) {
1066
+ struct rrdcontext_to_json_v2_data *ctl = data;
1067
+
1068
+ if(machine_guid && *machine_guid) {
1069
+ if(ctl->nodes.scope_pattern)
1070
+ simple_pattern_free(ctl->nodes.scope_pattern);
1071
+
1072
+ if(ctl->nodes.pattern)
1073
+ simple_pattern_free(ctl->nodes.pattern);
1074
+
1075
+ ctl->nodes.scope_pattern = string_to_simple_pattern(machine_guid);
1076
+ ctl->nodes.pattern = NULL;
1077
+ }
1078
+
1079
+ if(context && *context) {
1080
+ if(ctl->contexts.scope_pattern)
1081
+ simple_pattern_free(ctl->contexts.scope_pattern);
1082
+
1083
+ if(ctl->contexts.pattern)
1084
+ simple_pattern_free(ctl->contexts.pattern);
1085
+
1086
+ ctl->contexts.scope_pattern = string_to_simple_pattern(context);
1087
+ ctl->contexts.pattern = NULL;
1088
+ }
1089
+
1090
+ ctl->alerts.alarm_id_filter = alarm_id;
1091
+}
1092
+
1093
+int rrdcontext_to_json_v2(BUFFER *wb, struct api_v2_contexts_request *req, CONTEXTS_V2_MODE mode) {
1094
int resp = HTTP_RESP_OK;
1095
+ bool run = true;
1096
1062
- if(options & CONTEXTS_V2_SEARCH)
1063
- options |= CONTEXTS_V2_CONTEXTS;
1097
+ if(mode & CONTEXTS_V2_SEARCH)
1098
+ mode |= CONTEXTS_V2_CONTEXTS;
1099
1065
- if(options & (CONTEXTS_V2_NODES_INFO | CONTEXTS_V2_NODES_INSTANCES))
1066
- options |= CONTEXTS_V2_NODES;
1100
+ if(mode & (CONTEXTS_V2_AGENTS_INFO))
1101
+ mode |= CONTEXTS_V2_AGENTS;
1102
1068
- if(options & (CONTEXTS_V2_AGENTS_INFO))
1069
- options |= CONTEXTS_V2_AGENTS;
1103
+ if(mode & (CONTEXTS_V2_ALERTS | CONTEXTS_V2_FUNCTIONS | CONTEXTS_V2_CONTEXTS | CONTEXTS_V2_SEARCH | CONTEXTS_V2_NODES_INFO | CONTEXTS_V2_NODES_INSTANCES))
1104
+ mode |= CONTEXTS_V2_NODES;
1105
1106
struct rrdcontext_to_json_v2_data ctl = {
1107
.wb = wb,
1108
.request = req,
1074
- .ctx = NULL,
1075
- .options = options,
1109
+ .mode = mode,
1110
+ .options = req->options,
1111
.versions = { 0 },
1112
.nodes.scope_pattern = string_to_simple_pattern(req->scope_nodes),
1113
.nodes.pattern = string_to_simple_pattern(req->nodes),
1114
.contexts.pattern = string_to_simple_pattern(req->contexts),
1115
.contexts.scope_pattern = string_to_simple_pattern(req->scope_contexts),
1116
.q.pattern = string_to_simple_pattern_nocase(req->q),
1117
+ .alerts.alert_name_pattern = string_to_simple_pattern(req->alerts.alert),
1118
.window = {
1119
.enabled = false,
1120
.relative = false,
1126
}
1127
};
1128
1093
- if(options & CONTEXTS_V2_CONTEXTS) {
1094
- ctl.ctx = dictionary_create_advanced(
1129
+ bool debug = ctl.options & CONTEXT_V2_OPTION_DEBUG;
1130
+
1131
+ if(mode & CONTEXTS_V2_NODES) {
1132
+ ctl.nodes.dict = dictionary_create_advanced(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
1133
+ NULL, sizeof(struct contexts_v2_node));
1134
+ }
1135
+
1136
+ if(mode & CONTEXTS_V2_CONTEXTS) {
1137
+ ctl.contexts.dict = dictionary_create_advanced(
1138
DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL,
1096
- sizeof(struct rrdcontext_to_json_v2_entry));
1139
+ sizeof(struct context_v2_entry));
1140
1098
- dictionary_register_conflict_callback(ctl.ctx, contexts_conflict_callback, NULL);
1099
- dictionary_register_delete_callback(ctl.ctx, contexts_delete_callback, NULL);
1141
+ dictionary_register_conflict_callback(ctl.contexts.dict, contexts_conflict_callback, &ctl);
1142
+ dictionary_register_delete_callback(ctl.contexts.dict, contexts_delete_callback, &ctl);
1143
}
1144
1102
- if(options & CONTEXTS_V2_FUNCTIONS) {
1145
+ if(mode & CONTEXTS_V2_FUNCTIONS) {
1146
ctl.functions.dict = dictionary_create_advanced(
1147
DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL,
1105
- sizeof(struct rrdfunction_to_json_v2));
1148
+ sizeof(struct function_v2_entry));
1149
+
1150
+ dictionary_register_insert_callback(ctl.functions.dict, functions_insert_callback, &ctl);
1151
+ dictionary_register_conflict_callback(ctl.functions.dict, functions_conflict_callback, &ctl);
1152
+ dictionary_register_delete_callback(ctl.functions.dict, functions_delete_callback, &ctl);
1153
+ }
1154
+
1155
+ if(mode & CONTEXTS_V2_ALERTS) {
1156
+ if(req->alerts.transition) {
1157
+ ctl.options |= CONTEXT_V2_OPTION_ALERT_INSTANCES | CONTEXT_V2_OPTION_ALERT_CONFIGURATIONS | CONTEXT_V2_OPTION_ALERT_TRANSITIONS;
1158
+ run = sql_find_alert_transition(req->alerts.transition, rrdcontext_v2_set_transition_filter, &ctl);
1159
+ if(!run) {
1160
+ resp = HTTP_RESP_NOT_FOUND;
1161
+ goto cleanup;
1162
+ }
1163
+ }
1164
1107
- dictionary_register_insert_callback(ctl.functions.dict, functions_insert_callback, NULL);
1108
- dictionary_register_conflict_callback(ctl.functions.dict, functions_conflict_callback, NULL);
1109
- dictionary_register_delete_callback(ctl.functions.dict, functions_delete_callback, NULL);
1165
+ ctl.alerts.alerts = dictionary_create_advanced(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
1166
+ NULL, sizeof(struct alert_v2_entry));
1167
+
1168
+ dictionary_register_insert_callback(ctl.alerts.alerts, alerts_v2_insert_callback, &ctl);
1169
+ dictionary_register_conflict_callback(ctl.alerts.alerts, alerts_v2_conflict_callback, &ctl);
1170
+ dictionary_register_delete_callback(ctl.alerts.alerts, alerts_v2_delete_callback, &ctl);
1171
+
1172
+ if(ctl.options & CONTEXT_V2_OPTION_ALERT_INSTANCES) {
1173
+ ctl.alerts.alert_instances = dictionary_create_advanced(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
1174
+ NULL, sizeof(struct alert_instance_v2_entry));
1175
+
1176
+ dictionary_register_insert_callback(ctl.alerts.alert_instances, alert_instances_v2_insert_callback, &ctl);
1177
+ dictionary_register_conflict_callback(ctl.alerts.alert_instances, alert_instances_v2_conflict_callback, &ctl);
1178
+ dictionary_register_delete_callback(ctl.alerts.alert_instances, alert_instances_delete_callback, &ctl);
1179
+ }
1180
+
1181
+ if(ctl.options & CONTEXT_V2_OPTION_ALERT_CONFIGURATIONS) {
1182
+ ctl.alerts.alert_configs = dictionary_create_advanced(DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE,
1183
+ NULL, sizeof(struct alert_config_v2_entry));
1184
+
1185
+ dictionary_register_insert_callback(ctl.alerts.alert_configs, alert_configs_v2_insert_callback, &ctl);
1186
+ dictionary_register_conflict_callback(ctl.alerts.alert_configs, alert_configs_v2_conflict_callback, &ctl);
1187
+ dictionary_register_delete_callback(ctl.alerts.alert_configs, alert_configs_delete_callback, &ctl);
1188
+ }
1189
}
1190
1191
if(req->after || req->before) {
1196
ctl.now = now_realtime_sec();
1197
1198
buffer_json_initialize(wb, "\"", "\"", 0,
1120
- true, (options & CONTEXTS_V2_MINIFY) && !(options & CONTEXTS_V2_DEBUG));
1199
+ true, (req->options & CONTEXT_V2_OPTION_MINIFY) && !(req->options & CONTEXT_V2_OPTION_DEBUG));
1200
1201
buffer_json_member_add_uint64(wb, "api", 2);
1202
1124
- if(options & CONTEXTS_V2_DEBUG) {
1203
+ if(req->options & CONTEXT_V2_OPTION_DEBUG) {
1204
buffer_json_member_add_object(wb, "request");
1205
+ {
1206
+ buffer_json_contexts_v2_mode_to_array(wb, "mode", mode);
1207
+ web_client_api_request_v2_contexts_options_to_buffer_json_array(wb, "options", req->options);
1208
1127
- buffer_json_member_add_object(wb, "scope");
1128
- buffer_json_member_add_string(wb, "scope_nodes", req->scope_nodes);
1129
- buffer_json_member_add_string(wb, "scope_contexts", req->scope_contexts);
1130
- buffer_json_object_close(wb);
1131
-
1132
- buffer_json_member_add_object(wb, "selectors");
1133
- buffer_json_member_add_string(wb, "nodes", req->nodes);
1134
- buffer_json_member_add_string(wb, "contexts", req->contexts);
1135
- buffer_json_object_close(wb);
1209
+ buffer_json_member_add_object(wb, "scope");
1210
+ {
1211
+ buffer_json_member_add_string(wb, "scope_nodes", req->scope_nodes);
1212
+ if (mode & (CONTEXTS_V2_CONTEXTS | CONTEXTS_V2_SEARCH | CONTEXTS_V2_ALERTS))
1213
+ buffer_json_member_add_string(wb, "scope_contexts", req->scope_contexts);
1214
+ }
1215
+ buffer_json_object_close(wb);
1216
1137
- buffer_json_member_add_object(wb, "filters");
1138
- buffer_json_member_add_string(wb, "q", req->q);
1139
- buffer_json_member_add_time_t(wb, "after", req->after);
1140
- buffer_json_member_add_time_t(wb, "before", req->before);
1141
- buffer_json_object_close(wb);
1217
+ buffer_json_member_add_object(wb, "selectors");
1218
+ {
1219
+ buffer_json_member_add_string(wb, "nodes", req->nodes);
1220
+
1221
+ if (mode & (CONTEXTS_V2_CONTEXTS | CONTEXTS_V2_SEARCH | CONTEXTS_V2_ALERTS))
1222
+ buffer_json_member_add_string(wb, "contexts", req->contexts);
1223
+
1224
+ if(mode & CONTEXTS_V2_ALERTS) {
1225
+ buffer_json_member_add_object(wb, "alerts");
1226
+ web_client_api_request_v2_contexts_alerts_status_to_buffer_json_array(wb, "status", req->alerts.status);
1227
+ buffer_json_member_add_string(wb, "alert", req->alerts.alert);
1228
+ buffer_json_member_add_string(wb, "transition", req->alerts.transition);
1229
+ buffer_json_member_add_uint64(wb, "last", req->alerts.last);
1230
+ buffer_json_object_close(wb); // alerts
1231
+ }
1232
+ }
1233
+ buffer_json_object_close(wb);
1234
1143
- buffer_json_member_add_array(wb, "options");
1144
- buffer_json_contexts_v2_options_to_array(wb, options);
1145
- buffer_json_array_close(wb);
1235
+ buffer_json_member_add_object(wb, "filters");
1236
+ {
1237
+ if (mode & CONTEXTS_V2_SEARCH)
1238
+ buffer_json_member_add_string(wb, "q", req->q);
1239
1240
+ buffer_json_member_add_time_t(wb, "after", req->after);
1241
+ buffer_json_member_add_time_t(wb, "before", req->before);
1242
+ }
1243
+ buffer_json_object_close(wb);
1244
+ }
1245
buffer_json_object_close(wb);
1246
}
1247
1150
- if(options & CONTEXTS_V2_NODES)
1151
- buffer_json_member_add_array(wb, "nodes");
1152
-
1153
- ssize_t ret = query_scope_foreach_host(ctl.nodes.scope_pattern, ctl.nodes.pattern,
1248
+ ssize_t ret = 0;
1249
+ if(run)
1250
+ ret = query_scope_foreach_host(ctl.nodes.scope_pattern, ctl.nodes.pattern,
1251
rrdcontext_to_json_v2_add_host, &ctl,
1252
&ctl.versions, ctl.q.host_node_id_str);
1253
1265
goto cleanup;
1266
}
1267
1171
- if(options & CONTEXTS_V2_NODES)
1172
- buffer_json_array_close(wb);
1173
-
1268
ctl.timings.executed_ut = now_monotonic_usec();
1269
1176
- if(options & CONTEXTS_V2_FUNCTIONS) {
1270
+ if(mode & CONTEXTS_V2_NODES) {
1271
+ buffer_json_member_add_array(wb, "nodes");
1272
+ struct contexts_v2_node *t;
1273
+ dfe_start_read(ctl.nodes.dict, t) {
1274
+ rrdcontext_to_json_v2_rrdhost(wb, t->host, &ctl, t->ni);
1275
+ }
1276
+ dfe_done(t);
1277
+ buffer_json_array_close(wb);
1278
+ }
1279
+
1280
+ if(mode & CONTEXTS_V2_FUNCTIONS) {
1281
buffer_json_member_add_array(wb, "functions");
1282
{
1179
- struct rrdfunction_to_json_v2 *t;
1283
+ struct function_v2_entry *t;
1284
dfe_start_read(ctl.functions.dict, t) {
1285
buffer_json_add_array_item_object(wb);
1286
buffer_json_member_add_string(wb, "name", t_dfe.name);
1296
buffer_json_array_close(wb);
1297
}
1298
1195
- if(options & CONTEXTS_V2_CONTEXTS) {
1299
+ if(mode & CONTEXTS_V2_CONTEXTS) {
1300
buffer_json_member_add_object(wb, "contexts");
1301
{
1198
- struct rrdcontext_to_json_v2_entry *z;
1199
- dfe_start_read(ctl.ctx, z) {
1302
+ struct context_v2_entry *z;
1303
+ dfe_start_read(ctl.contexts.dict, z) {
1304
bool collected = z->flags & RRD_FLAG_COLLECTED;
1305
1306
buffer_json_member_add_object(wb, string2str(z->id));
1310
buffer_json_member_add_time_t(wb, "first_entry", z->first_time_s);
1311
buffer_json_member_add_time_t(wb, "last_entry", collected ? ctl.now : z->last_time_s);
1312
buffer_json_member_add_boolean(wb, "live", collected);
1209
- if (options & CONTEXTS_V2_SEARCH)
1313
+ if (mode & CONTEXTS_V2_SEARCH)
1314
buffer_json_member_add_string(wb, "match", fts_match_to_string(z->match));
1315
}
1316
buffer_json_object_close(wb);
1320
buffer_json_object_close(wb); // contexts
1321
}
1322
1219
- if(options & CONTEXTS_V2_SEARCH) {
1220
- buffer_json_member_add_object(wb, "searches");
1323
+ if(mode & CONTEXTS_V2_ALERTS) {
1324
+ buffer_json_member_add_array(wb, "alerts");
1325
{
1222
- buffer_json_member_add_uint64(wb, "strings", ctl.q.fts.string_searches);
1223
- buffer_json_member_add_uint64(wb, "char", ctl.q.fts.char_searches);
1224
- buffer_json_member_add_uint64(wb, "total", ctl.q.fts.searches);
1225
- }
1226
- buffer_json_object_close(wb);
1227
- }
1228
-
1229
- if(options & (CONTEXTS_V2_VERSIONS))
1230
- version_hashes_api_v2(wb, &ctl.versions);
1231
-
1232
- if(options & CONTEXTS_V2_AGENTS)
1233
- buffer_json_agents_array_v2(wb, &ctl.timings, ctl.now, options & (CONTEXTS_V2_AGENTS_INFO));
1234
-
1235
- buffer_json_cloud_timings(wb, "timings", &ctl.timings);
1236
-
1237
- buffer_json_finalize(wb);
1238
-
1239
-cleanup:
1240
- dictionary_destroy(ctl.functions.dict);
1241
- dictionary_destroy(ctl.ctx);
1242
- simple_pattern_free(ctl.nodes.scope_pattern);
1243
- simple_pattern_free(ctl.nodes.pattern);
1244
- simple_pattern_free(ctl.contexts.pattern);
1245
- simple_pattern_free(ctl.contexts.scope_pattern);
1246
- simple_pattern_free(ctl.q.pattern);
1247
-
1248
- return resp;
1249
-}
1326
+ struct alert_v2_entry *t;
1327
+ dfe_start_read(ctl.alerts.alerts, t){
1328
+ buffer_json_add_array_item_object(wb);
1329
+ {
1330
+ buffer_json_member_add_uint64(wb, "ati", t->ati);
1331
+ buffer_json_member_add_string(wb, "nm", string2str(t->name));
1332
1251
-int alerts_to_json_v2(BUFFER *wb, struct api_v2_alerts_request *req, CONTEXTS_V2_OPTIONS options)
1252
-{
1253
- int resp = HTTP_RESP_OK;
1333
+ buffer_json_member_add_uint64(wb, "cr", t->critical);
1334
+ buffer_json_member_add_uint64(wb, "wr", t->warning);
1335
+ buffer_json_member_add_uint64(wb, "cl", t->clear);
1336
+ buffer_json_member_add_uint64(wb, "er", t->error);
1337
1255
-// ALERT_OPTIONS alert_options = req->options;
1256
- struct rrdcontext_to_json_v2_data ctl = {
1257
- .wb = wb,
1258
- .alerts_request = req,
1259
- .ctx = NULL,
1260
- .options = options,
1261
- .versions = { 0 },
1262
- .nodes.scope_pattern = string_to_simple_pattern(req->scope_nodes),
1263
- .nodes.pattern = string_to_simple_pattern(req->nodes),
1264
- .contexts.pattern = string_to_simple_pattern(req->contexts),
1265
- .contexts.scope_pattern = string_to_simple_pattern(req->scope_contexts),
1266
- .timings = {
1267
- .received_ut = now_monotonic_usec(),
1338
+ buffer_json_member_add_uint64(wb, "in", t->instances);
1339
+ buffer_json_member_add_uint64(wb, "nd", dictionary_entries(t->nodes));
1340
+ buffer_json_member_add_uint64(wb, "cfg", dictionary_entries(t->configs));
1341
+ }
1342
+ buffer_json_object_close(wb); // alert name
1343
+ }
1344
+ dfe_done(t);
1345
}
1269
- };
1270
-
1271
- if(options & CONTEXTS_V2_CONTEXTS)
1272
- {
1273
- ctl.ctx = dictionary_create_advanced(
1274
- DICT_OPTION_SINGLE_THREADED | DICT_OPTION_DONT_OVERWRITE_VALUE | DICT_OPTION_FIXED_SIZE, NULL,
1275
- sizeof(struct rrdcontext_to_json_v2_entry));
1346
+ buffer_json_array_close(wb); // alerts
1347
1277
- dictionary_register_delete_callback(ctl.ctx, contexts_delete_callback, NULL);
1278
- }
1279
-
1280
- time_t now_s = now_realtime_sec();
1281
- buffer_json_member_add_uint64(wb, "api", 2);
1282
-
1283
- {
1284
- buffer_json_member_add_object(wb, "request");
1285
-
1286
- buffer_json_member_add_object(wb, "scope");
1287
- buffer_json_member_add_string(wb, "scope_nodes", req->scope_nodes);
1288
- buffer_json_member_add_string(wb, "scope_contexts", req->scope_contexts);
1289
- buffer_json_object_close(wb);
1290
-
1291
- buffer_json_member_add_object(wb, "selectors");
1292
- buffer_json_member_add_string(wb, "nodes", req->nodes);
1293
- buffer_json_member_add_string(wb, "contexts", req->contexts);
1294
- buffer_json_object_close(wb);
1348
+ if(req->options & CONTEXT_V2_OPTION_ALERT_INSTANCES) {
1349
+ buffer_json_member_add_array(wb, "alert_instances");
1350
+ {
1351
+ struct alert_instance_v2_entry *t;
1352
+ dfe_start_read(ctl.alerts.alert_instances, t){
1353
+ buffer_json_add_array_item_object(wb);
1354
+ {
1355
+ buffer_json_member_add_uint64(wb, "ni", t->ni);
1356
+ buffer_json_member_add_uint64(wb, "ati", t->ati);
1357
+ buffer_json_member_add_uint64(wb, "aii", t->aii);
1358
+ if(req->options & CONTEXT_V2_OPTION_ALERT_CONFIGURATIONS) {
1359
+ buffer_json_member_add_uint64(wb, "aci", t->aci);
1360
+ }
1361
+ buffer_json_member_add_uint64(wb, "gi", t->global_id);
1362
+
1363
+ if(debug)
1364
+ buffer_json_member_add_string(wb, "nm", string2str(t->name));
1365
+
1366
+ buffer_json_member_add_string(wb, "fami", string2str(t->family));
1367
+ buffer_json_member_add_string(wb, "info", string2str(t->info));
1368
+ buffer_json_member_add_string(wb, "ch", string2str(t->chart_name));
1369
+ buffer_json_member_add_string(wb, "st", rrdcalc_status2string(t->status));
1370
+ buffer_json_member_add_double(wb, "v", t->value);
1371
+ buffer_json_member_add_time_t(wb, "t", t->last_updated);
1372
+ buffer_json_member_add_uuid (wb, "tr_i", &t->last_transition_id);
1373
+ buffer_json_member_add_double(wb, "tr_v", t->last_status_change_value);
1374
+ buffer_json_member_add_time_t(wb, "tr_t", t->last_status_change);
1375
+ buffer_json_member_add_uuid (wb, "cfg", &t->config_hash_id);
1376
+ rrdcalc_flags_to_json_array (wb, "flags", t->flags);
1377
+ }
1378
+ buffer_json_object_close(wb); // alert instance
1379
+ }
1380
+ dfe_done(t);
1381
+ }
1382
+ buffer_json_array_close(wb); // alerts_instances
1383
+
1384
+ if(req->options & CONTEXT_V2_OPTION_ALERT_TRANSITIONS) {
1385
+ buffer_json_member_add_array(wb, "alert_transitions");
1386
+ sql_health_alarm_log2json_v3(
1387
+ wb,
1388
+ ctl.alerts.alert_instances,
1389
+ ctl.request->after,
1390
+ ctl.request->before,
1391
+ ctl.request->alerts.transition,
1392
+ ctl.request->alerts.last ? ctl.request->alerts.last : 1,
1393
+ debug);
1394
+ buffer_json_array_close(wb); // alerts_transitions
1395
+ }
1396
+ }
1397
1296
- buffer_json_member_add_array(wb, "options");
1297
- buffer_json_contexts_v2_options_to_array(wb, options);
1298
- buffer_json_array_close(wb);
1398
+ if(req->options & CONTEXT_V2_OPTION_ALERT_CONFIGURATIONS) {
1399
+ buffer_json_member_add_array(wb, "alert_configurations");
1400
+ {
1401
+ struct alert_config_v2_entry *t;
1402
+ dfe_start_read(ctl.alerts.alert_configs, t){
1403
+ RRDCALC *rc = t->tmp;
1404
1300
- buffer_json_object_close(wb);
1301
- }
1405
+ buffer_json_add_array_item_object(wb);
1406
+ {
1407
+ buffer_json_member_add_uint64(wb, "ati", t->ati);
1408
+ buffer_json_member_add_uint64(wb, "aci", t->aci);
1409
+ buffer_json_member_add_string(wb, "cfg", t_dfe.name);
1410
1303
- // Alert configuration
1304
- buffer_json_member_add_array(wb, "alerts");
1411
+ if(debug)
1412
+ buffer_json_member_add_string(wb, "nm", string2str(rc->name));
1413
1306
- ssize_t ret = query_scope_foreach_host(ctl.nodes.scope_pattern, ctl.nodes.pattern,
1307
- alert_to_json_v2_add_alert, &ctl, &ctl.versions, NULL);
1414
+ buffer_json_member_add_string(wb, "ctx", string2str(rc->rrdset->context));
1415
+ buffer_json_member_add_string(wb, "class", string2str(rc->classification));
1416
+ buffer_json_member_add_string(wb, "component", string2str(rc->component));
1417
+ buffer_json_member_add_string(wb, "type", string2str(rc->type));
1418
+ buffer_json_member_add_string(wb, "info", string2str(rc->original_info));
1419
1309
- if(unlikely(ret < 0)) {
1310
- buffer_flush(wb);
1420
+ buffer_json_member_add_object(wb, "v"); // value
1421
+ {
1422
+ buffer_json_member_add_uint64(wb, "update_every", rc->update_every);
1423
+ buffer_json_member_add_string(wb, "units", string2str(rc->units));
1424
+
1425
+ if (RRDCALC_HAS_DB_LOOKUP(rc) || debug) {
1426
+ buffer_json_member_add_object(wb, "db");
1427
+ {
1428
+ if (rc->dimensions || debug)
1429
+ buffer_json_member_add_string(wb, "dimensions", rrdcalc_dimensions(rc));
1430
+
1431
+ buffer_json_member_add_string(wb, "method", time_grouping_method2string(rc->group));
1432
+ buffer_json_member_add_time_t(wb, "after", rc->after);
1433
+ buffer_json_member_add_time_t(wb, "before", rc->before);
1434
+
1435
+ web_client_api_request_v1_data_options_to_buffer_json_array(wb, "options", (RRDR_OPTIONS) rc->options);
1436
+ }
1437
+ buffer_json_object_close(wb); // db
1438
+ }
1439
+
1440
+ if (rc->calculation || debug) {
1441
+ buffer_json_member_add_string(wb, "calc", rc->calculation ? rc->calculation->source : NULL);
1442
+ // buffer_json_member_add_string(wb, "calc_parsed", rc->calculation->parsed_as);
1443
+ }
1444
+ }
1445
+ buffer_json_object_close(wb); // value
1446
+
1447
+ if(rc->warning || rc->critical || debug) {
1448
+ buffer_json_member_add_object(wb, "st"); // conditions
1449
+ {
1450
+ if(!isnan(rc->green) || debug)
1451
+ buffer_json_member_add_double(wb, "green", rc->green);
1452
+
1453
+ if(!isnan(rc->red) || debug)
1454
+ buffer_json_member_add_double(wb, "red", rc->red);
1455
+
1456
+ if (rc->warning || debug) {
1457
+ buffer_json_member_add_string(wb, "warn", rc->warning ? rc->warning->source : NULL);
1458
+ // buffer_json_member_add_string(wb, "warn_parsed", rc->warning ? rc->warning->parsed_as : NULL);
1459
+ }
1460
+
1461
+ if (rc->critical || debug) {
1462
+ buffer_json_member_add_string(wb, "crit", rc->critical ? rc->critical->source : NULL);
1463
+ // buffer_json_member_add_string(wb, "crit_parsed", rc->critical ? rc->critical->parsed_as : NULL);
1464
+ }
1465
+ }
1466
+ buffer_json_object_close(wb); // conditions
1467
+ }
1468
1312
- if(ret == -2) {
1313
- buffer_strcat(wb, "query timeout");
1314
- resp = HTTP_RESP_GATEWAY_TIMEOUT;
1315
- }
1316
- else {
1317
- buffer_strcat(wb, "query interrupted");
1318
- resp = HTTP_RESP_BACKEND_FETCH_FAILED;
1469
+ buffer_json_member_add_object(wb, "nf");
1470
+ {
1471
+ buffer_json_member_add_string(wb, "type", "agent");
1472
+ buffer_json_member_add_string(wb, "method", rc->exec ? rrdcalc_exec(rc) : string2str(localhost->health.health_default_exec));
1473
+ buffer_json_member_add_string(wb, "to", rc->recipient ? string2str(rc->recipient) : string2str(rc->rrdset->rrdhost->health.health_default_recipient));
1474
+
1475
+ if(rc->delay_up_duration || rc->delay_down_duration || debug) {
1476
+ buffer_json_member_add_object(wb, "delay");
1477
+ {
1478
+ buffer_json_member_add_time_t(wb, "up", rc->delay_up_duration);
1479
+ buffer_json_member_add_time_t(wb, "down", rc->delay_down_duration);
1480
+ buffer_json_member_add_time_t(wb, "max", rc->delay_max_duration);
1481
+ buffer_json_member_add_double(wb, "multiplier", rc->delay_multiplier);
1482
+ }
1483
+ buffer_json_object_close(wb); //delay
1484
+ }
1485
+
1486
+ if(rc->warn_repeat_every || rc->crit_repeat_every || debug) {
1487
+ buffer_json_member_add_object(wb, "repeat");
1488
+ {
1489
+ if(rc->warn_repeat_every || debug)
1490
+ buffer_json_member_add_time_t(wb, "warn", rc->warn_repeat_every);
1491
+
1492
+ if(rc->crit_repeat_every || debug)
1493
+ buffer_json_member_add_time_t(wb, "crit", rc->crit_repeat_every);
1494
+ }
1495
+ buffer_json_object_close(wb); // repeat
1496
+ }
1497
+
1498
+ if (unlikely((rc->options & RRDCALC_OPTION_NO_CLEAR_NOTIFICATION) || debug))
1499
+ buffer_json_member_add_boolean(wb, "no_clear_notification", rc->options & RRDCALC_OPTION_NO_CLEAR_NOTIFICATION);
1500
+ }
1501
+ buffer_json_object_close(wb); // notification
1502
+ buffer_json_member_add_string(wb, "src", string2str(rc->source));
1503
+ }
1504
+ buffer_json_object_close(wb); // alert config
1505
+ }
1506
+ dfe_done(t);
1507
+ }
1508
+ buffer_json_array_close(wb); // alerts_configs
1509
}
1320
- goto cleanup;
1510
}
1511
1323
- buffer_json_array_close(wb); // alerts
1324
-
1325
- buffer_json_member_add_array(wb, "nodes");
1326
-
1327
- ret = query_scope_foreach_host(ctl.nodes.scope_pattern, ctl.nodes.pattern,
1328
- alert_to_json_v2_add_host, &ctl,
1329
- &ctl.versions, NULL);
1330
-
1331
- if(unlikely(ret < 0)) {
1332
- buffer_flush(wb);
1333
-
1334
- if(ret == -2) {
1335
- buffer_strcat(wb, "query timeout");
1336
- resp = HTTP_RESP_GATEWAY_TIMEOUT;
1337
- }
1338
- else {
1339
- buffer_strcat(wb, "query interrupted");
1340
- resp = HTTP_RESP_BACKEND_FETCH_FAILED;
1512
+ if(mode & CONTEXTS_V2_SEARCH) {
1513
+ buffer_json_member_add_object(wb, "searches");
1514
+ {
1515
+ buffer_json_member_add_uint64(wb, "strings", ctl.q.fts.string_searches);
1516
+ buffer_json_member_add_uint64(wb, "char", ctl.q.fts.char_searches);
1517
+ buffer_json_member_add_uint64(wb, "total", ctl.q.fts.searches);
1518
}
1342
- goto cleanup;
1519
+ buffer_json_object_close(wb);
1520
}
1521
1345
- buffer_json_array_close(wb); // Nodes
1522
+ if(mode & (CONTEXTS_V2_VERSIONS))
1523
+ version_hashes_api_v2(wb, &ctl.versions);
1524
1347
- ctl.timings.executed_ut = now_monotonic_usec();
1348
- version_hashes_api_v2(wb, &ctl.versions);
1525
+ if(mode & CONTEXTS_V2_AGENTS)
1526
+ buffer_json_agents_array_v2(wb, &ctl.timings, ctl.now, mode & (CONTEXTS_V2_AGENTS_INFO));
1527
1350
- buffer_json_agents_array_v2(wb, &ctl.timings, now_s, false);
1528
buffer_json_cloud_timings(wb, "timings", &ctl.timings);
1352
- buffer_json_finalize(wb);
1529
1354
- JudyHSFreeArray(&ctl.alerts.JudyHS, PJE0);
1530
+ buffer_json_finalize(wb);
1531
1532
cleanup:
1357
-// dictionary_destroy(ctl.ctx);
1533
+ dictionary_destroy(ctl.nodes.dict);
1534
+ dictionary_destroy(ctl.contexts.dict);
1535
+ dictionary_destroy(ctl.functions.dict);
1536
+ dictionary_destroy(ctl.alerts.alerts);
1537
+ dictionary_destroy(ctl.alerts.alert_instances);
1538
+ dictionary_destroy(ctl.alerts.alert_configs);
1539
simple_pattern_free(ctl.nodes.scope_pattern);
1540
simple_pattern_free(ctl.nodes.pattern);
1541
simple_pattern_free(ctl.contexts.pattern);
1542
simple_pattern_free(ctl.contexts.scope_pattern);
1362
- simple_pattern_free(req->config_hash_pattern);
1363
- simple_pattern_free(req->alert_name_pattern);
1543
+ simple_pattern_free(ctl.q.pattern);
1544
+ simple_pattern_free(ctl.alerts.alert_name_pattern);
1545
1546
return resp;
1547
}