alarms status API ready
Costa Tsaousis committed
Aug 25, 2016 at 12:22 UTC
623869a428da7f68df5e6270f059f80a71e47801
4 files changed
+96
-43
src/health.c
+67
-38
@@ -1414,83 +1414,112 @@ void health_init(void) {
1414
// ----------------------------------------------------------------------------
1415
// JSON generation
1416
1417
+static inline void health_string2json(BUFFER *wb, const char *prefix, const char *label, const char *value, const char *suffix) {
1418
+ if(value && *value)
1419
+ buffer_sprintf(wb, "%s\"%s\":\"%s\"%s", prefix, label, value, suffix);
1420
+ else
1421
+ buffer_sprintf(wb, "%s\"%s\":null%s", prefix, label, suffix);
1422
+}
1423
+
1424
static inline void health_rrdcalc2json_nolock(BUFFER *wb, RRDCALC *rc) {
1425
+
1426
buffer_sprintf(wb,
1419
- "\t\t\"%s.%s\": {"
1427
+ "\t\t\"%s.%s\": {\n"
1428
"\t\t\t\"name\": \"%s\",\n"
1429
"\t\t\t\"chart\": \"%s\",\n"
1422
- "\t\t\t\"dimensions\": \"%s\",\n"
1430
"\t\t\t\"exec\": \"%s\",\n"
1431
"\t\t\t\"source\": \"%s\",\n"
1425
- "\t\t\t\"calc\": \"%s\",\n"
1426
- "\t\t\t\"calc_parsed\": \"%s\",\n"
1427
- "\t\t\t\"warn\": \"%s\",\n"
1428
- "\t\t\t\"warn_parsed\": \"%s\",\n"
1429
- "\t\t\t\"crit\": \"%s\",\n"
1430
- "\t\t\t\"crit_parsed\": \"%s\",\n"
1431
- "\t\t\t\"value\": %Lf,\n"
1432
- "\t\t\t\"value_after\": %lu,\n"
1433
- "\t\t\t\"value_before\": %lu,\n"
1434
- "\t\t\t\"green\": %Lf,\n"
1435
- "\t\t\t\"red\": %Lf,\n"
1432
"\t\t\t\"status\": \"%s\",\n"
1433
"\t\t\t\"last_status_change\": %lu,\n"
1434
"\t\t\t\"last_updated\": %lu,\n"
1435
"\t\t\t\"next_update\": %lu,\n"
1436
"\t\t\t\"update_every\": %d,\n"
1441
- "\t\t\t\"lookup_method\": \"%s\",\n"
1442
- "\t\t\t\"lookup_after\": %d,\n"
1443
- "\t\t\t\"lookup_before\": %d,\n"
1444
- "\t\t\t\"lookup_options\": \""
1437
, rc->chart, rc->name
1438
, rc->name
1439
, rc->chart
1448
- , rc->dimensions?rc->dimensions:""
1440
, rc->exec?rc->exec:health_default_exec
1441
, rc->source
1451
- , rc->calculation?rc->calculation->source:""
1452
- , rc->calculation?rc->calculation->parsed_as:""
1453
- , rc->warning?rc->warning->source:""
1454
- , rc->warning?rc->warning->parsed_as:""
1455
- , rc->critical?rc->critical->source:""
1456
- , rc->critical?rc->critical->parsed_as:""
1457
- , rc->value
1458
- , (unsigned long)rc->db_after
1459
- , (unsigned long)rc->db_before
1460
- , rc->green
1461
- , rc->red
1442
, rrdcalc_status2string(rc->status)
1443
, (unsigned long)rc->last_status_change
1444
, (unsigned long)rc->last_updated
1445
, (unsigned long)rc->next_update
1446
, rc->update_every
1467
- , group_method2string(rc->group)
1468
- , rc->after
1469
- , rc->before
1447
);
1448
1472
- buffer_data_options2string(wb, rc->options);
1473
- buffer_strcat(wb, "\"\n\t}");
1449
+ if(RRDCALC_HAS_DB_LOOKUP(rc)) {
1450
+ if(rc->dimensions && *rc->dimensions)
1451
+ health_string2json(wb, "\t\t\t", "lookup_dimensions", rc->dimensions, ",\n");
1452
+
1453
+ buffer_sprintf(wb,
1454
+ "\t\t\t\"db_after\": %lu,\n"
1455
+ "\t\t\t\"db_before\": %lu,\n"
1456
+ "\t\t\t\"lookup_method\": \"%s\",\n"
1457
+ "\t\t\t\"lookup_after\": %d,\n"
1458
+ "\t\t\t\"lookup_before\": %d,\n"
1459
+ "\t\t\t\"lookup_options\": \"",
1460
+ (unsigned long) rc->db_after,
1461
+ (unsigned long) rc->db_before,
1462
+ group_method2string(rc->group),
1463
+ rc->after,
1464
+ rc->before
1465
+ );
1466
+ buffer_data_options2string(wb, rc->options);
1467
+ buffer_strcat(wb, "\",\n");
1468
+ }
1469
+
1470
+ if(rc->calculation) {
1471
+ health_string2json(wb, "\t\t\t", "calc", rc->calculation->source, ",\n");
1472
+ health_string2json(wb, "\t\t\t", "calc_parsed", rc->calculation->parsed_as, ",\n");
1473
+ }
1474
+
1475
+ if(rc->warning) {
1476
+ health_string2json(wb, "\t\t\t", "warn", rc->warning->source, ",\n");
1477
+ health_string2json(wb, "\t\t\t", "warn_parsed", rc->warning->parsed_as, ",\n");
1478
+ }
1479
+
1480
+ if(rc->critical) {
1481
+ health_string2json(wb, "\t\t\t", "crit", rc->critical->source, ",\n");
1482
+ health_string2json(wb, "\t\t\t", "crit_parsed", rc->critical->parsed_as, ",\n");
1483
+ }
1484
+
1485
+ buffer_strcat(wb, "\t\t\t\"green\":");
1486
+ buffer_rrd_value(wb, rc->green);
1487
+ buffer_strcat(wb, ",\n");
1488
+
1489
+ buffer_strcat(wb, "\t\t\t\"red\":");
1490
+ buffer_rrd_value(wb, rc->red);
1491
+ buffer_strcat(wb, ",\n");
1492
+
1493
+ buffer_strcat(wb, "\t\t\t\"value\":");
1494
+ buffer_rrd_value(wb, rc->value);
1495
+ buffer_strcat(wb, "\n");
1496
+
1497
+ buffer_strcat(wb, "\t\t}");
1498
}
1499
1500
//void health_rrdcalctemplate2json_nolock(BUFFER *wb, RRDCALCTEMPLATE *rt) {
1501
//
1502
//}
1503
1480
-void health_json(RRDHOST *host, BUFFER *wb) {
1504
+void health_alarms2json(RRDHOST *host, BUFFER *wb) {
1505
+ int i;
1506
rrdhost_rdlock(&localhost);
1507
1483
- buffer_strcat(wb, "{\n\t\"alarms\": {");
1508
+ buffer_strcat(wb, "{\n\t\"alarms\": {\n");
1509
RRDCALC *rc;
1485
- for(rc = host->alarms; rc ; rc = rc->next)
1510
+ for(i = 0, rc = host->alarms; rc ; rc = rc->next, i++) {
1511
+ if(likely(i)) buffer_strcat(wb, ",\n");
1512
health_rrdcalc2json_nolock(wb, rc);
1513
+ }
1514
1488
- buffer_strcat(wb, "\n},\n\t\"templates\": {");
1515
+ buffer_strcat(wb, "\n\t},\n\t\"templates\": {");
1516
1517
// RRDCALCTEMPLATE *rt;
1518
// for(rt = host->templates; rt ; rt = rt->next)
1519
// health_rrdcalctemplate2json_nolock(wb, rt);
1520
1521
+ buffer_strcat(wb, "\n\t}");
1522
+ buffer_sprintf(wb, ",\n\t\"now\": %lu", (unsigned long)time(NULL));
1523
buffer_strcat(wb, "\n}\n");
1524
rrdhost_unlock(&localhost);
1525
}
src/health.h
+1
@@ -263,5 +263,6 @@ extern void *health_main(void *ptr);
263
extern void health_reload(void);
264
265
extern int health_variable_lookup(const char *variable, uint32_t hash, RRDCALC *rc, calculated_number *result);
266
+extern void health_alarms2json(RRDHOST *host, BUFFER *wb);
267
268
#endif //NETDATA_HEALTH_H
src/web_buffer.c
+8
-2
@@ -117,7 +117,7 @@ void buffer_strcat(BUFFER *wb, const char *txt)
117
buffer_need_bytes(wb, 1);
118
119
char *s = &wb->buffer[wb->len], *start, *end = &wb->buffer[wb->size];
120
- long len = wb->len;
120
+ size_t len = wb->len;
121
122
start = s;
123
while(*txt && s != end)
@@ -213,7 +213,13 @@ void buffer_sprintf(BUFFER *wb, const char *fmt, ...)
213
void buffer_rrd_value(BUFFER *wb, calculated_number value)
214
{
215
buffer_need_bytes(wb, 50);
216
- wb->len += print_calculated_number(&wb->buffer[wb->len], value);
216
+
217
+ if(isnan(value) || isinf(value)) {
218
+ buffer_strcat(wb, "null");
219
+ return;
220
+ }
221
+ else
222
+ wb->len += print_calculated_number(&wb->buffer[wb->len], value);
223
224
// terminate it
225
buffer_need_bytes(wb, 1);
src/web_client.c
+20
-3
@@ -617,6 +617,9 @@ uint32_t web_client_api_request_v1_data_google_format(char *name)
617
618
const char *group_method2string(int group) {
619
switch(group) {
620
+ case GROUP_UNDEFINED:
621
+ return "";
622
+
623
case GROUP_AVERAGE:
624
return "average";
625
@@ -657,6 +660,16 @@ int web_client_api_request_v1_data_group(char *name, int def)
660
return def;
661
}
662
663
+int web_client_api_request_v1_alarms(struct web_client *w, char *url)
664
+{
665
+ (void)url;
666
+
667
+ buffer_flush(w->response.data);
668
+ w->response.data->contenttype = CT_APPLICATION_JSON;
669
+ health_alarms2json(&localhost, w->response.data);
670
+ return 200;
671
+}
672
+
673
int web_client_api_request_v1_charts(struct web_client *w, char *url)
674
{
675
if(url) { ; }
@@ -713,7 +726,7 @@ cleanup:
726
return ret;
727
}
728
716
-int web_client_api_v1_badge(struct web_client *w, char *url) {
729
+int web_client_api_request_v1_badge(struct web_client *w, char *url) {
730
int ret = 400;
731
buffer_flush(w->response.data);
732
@@ -1311,7 +1324,7 @@ int web_client_api_request_v1_registry(struct web_client *w, char *url)
1324
}
1325
1326
int web_client_api_request_v1(struct web_client *w, char *url) {
1314
- static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0;
1327
+ static uint32_t hash_data = 0, hash_chart = 0, hash_charts = 0, hash_registry = 0, hash_badge = 0, hash_alarms = 0;
1328
1329
if(unlikely(hash_data == 0)) {
1330
hash_data = simple_hash("data");
@@ -1319,6 +1332,7 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
1332
hash_charts = simple_hash("charts");
1333
hash_registry = simple_hash("registry");
1334
hash_badge = simple_hash("badge.svg");
1335
+ hash_alarms = simple_hash("alarms");
1336
}
1337
1338
// get the command
@@ -1340,7 +1354,10 @@ int web_client_api_request_v1(struct web_client *w, char *url) {
1354
return web_client_api_request_v1_registry(w, url);
1355
1356
else if(hash == hash_badge && !strcmp(tok, "badge.svg"))
1343
- return web_client_api_v1_badge(w, url);
1357
+ return web_client_api_request_v1_badge(w, url);
1358
+
1359
+ else if(hash == hash_alarms && !strcmp(tok, "alarms"))
1360
+ return web_client_api_request_v1_alarms(w, url);
1361
1362
else {
1363
buffer_flush(w->response.data);