Switch alarm_log to use the buffer json functions (#16360)
* Switch alarm_log to use the buffer json functions * Remove commented out code * Fix finalize when an object is not explicitly closed * Use buffer_json_member_add_boolean
Stelios Fragkakis committed
Nov 13, 2023 at 16:08 UTC
d41bf12a2b5db6e061119f4d87b9a3cd4976009f
3 files changed
+86
-128
database/sqlite/sqlite_health.c
+67
-123
@@ -1274,8 +1274,6 @@ done:
1274
1275
void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, time_t after, const char *chart)
1276
{
1277
- buffer_strcat(wb, "[");
1278
-
1277
unsigned int max = host->health_log.max;
1278
1279
static __thread sqlite3_stmt *stmt_no_chart = NULL;
@@ -1284,7 +1282,7 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, time_t after, const ch
1282
sqlite3_stmt **active_stmt;
1283
sqlite3_stmt *stmt_query;
1284
1287
- int count = 0, rc;
1285
+ int rc;
1286
1287
active_stmt = chart ? &stmt_with_chart : &stmt_no_chart;
1288
@@ -1303,7 +1301,6 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, time_t after, const ch
1301
1302
if (unlikely(rc != SQLITE_OK)) {
1303
error_report("Failed to prepare statement SQL_SELECT_HEALTH_LOG");
1306
- buffer_strcat(wb, "\n]");
1304
return;
1305
}
1306
}
@@ -1337,6 +1334,9 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, time_t after, const ch
1334
goto finish;
1335
}
1336
1337
+ buffer_json_initialize(wb, "\"", "\"", 0, false, BUFFER_JSON_OPTIONS_DEFAULT);
1338
+ buffer_json_member_add_array(wb, NULL);
1339
+
1340
while (sqlite3_step(stmt_query) == SQLITE_ROW) {
1341
char old_value_string[100 + 1];
1342
char new_value_string[100 + 1];
@@ -1352,129 +1352,73 @@ void sql_health_alarm_log2json(RRDHOST *host, BUFFER *wb, time_t after, const ch
1352
health_edit_command_from_source((char *)sqlite3_column_text(stmt_query, 16)) :
1353
strdupz("UNKNOWN=0=UNKNOWN");
1354
1355
- if (count)
1356
- buffer_sprintf(wb, ",");
1357
-
1358
- count++;
1359
-
1360
- buffer_sprintf(
1361
- wb,
1362
- "\n\t{\n"
1363
- "\t\t\"hostname\": \"%s\",\n"
1364
- "\t\t\"utc_offset\": %d,\n"
1365
- "\t\t\"timezone\": \"%s\",\n"
1366
- "\t\t\"unique_id\": %u,\n"
1367
- "\t\t\"alarm_id\": %u,\n"
1368
- "\t\t\"alarm_event_id\": %u,\n"
1369
- "\t\t\"config_hash_id\": \"%s\",\n"
1370
- "\t\t\"transition_id\": \"%s\",\n"
1371
- "\t\t\"name\": \"%s\",\n"
1372
- "\t\t\"chart\": \"%s\",\n"
1373
- "\t\t\"context\": \"%s\",\n"
1374
- "\t\t\"class\": \"%s\",\n"
1375
- "\t\t\"component\": \"%s\",\n"
1376
- "\t\t\"type\": \"%s\",\n"
1377
- "\t\t\"processed\": %s,\n"
1378
- "\t\t\"updated\": %s,\n"
1379
- "\t\t\"exec_run\": %lu,\n"
1380
- "\t\t\"exec_failed\": %s,\n"
1381
- "\t\t\"exec\": \"%s\",\n"
1382
- "\t\t\"recipient\": \"%s\",\n"
1383
- "\t\t\"exec_code\": %d,\n"
1384
- "\t\t\"source\": \"%s\",\n"
1385
- "\t\t\"command\": \"%s\",\n"
1386
- "\t\t\"units\": \"%s\",\n"
1387
- "\t\t\"when\": %lu,\n"
1388
- "\t\t\"duration\": %lu,\n"
1389
- "\t\t\"non_clear_duration\": %lu,\n"
1390
- "\t\t\"status\": \"%s\",\n"
1391
- "\t\t\"old_status\": \"%s\",\n"
1392
- "\t\t\"delay\": %d,\n"
1393
- "\t\t\"delay_up_to_timestamp\": %lu,\n"
1394
- "\t\t\"updated_by_id\": %u,\n"
1395
- "\t\t\"updates_id\": %u,\n"
1396
- "\t\t\"value_string\": \"%s\",\n"
1397
- "\t\t\"old_value_string\": \"%s\",\n"
1398
- "\t\t\"last_repeat\": %lu,\n"
1399
- "\t\t\"silenced\": \"%s\",\n",
1400
- rrdhost_hostname(host),
1401
- host->utc_offset,
1402
- rrdhost_abbrev_timezone(host),
1403
- (unsigned int)sqlite3_column_int64(stmt_query, 0),
1404
- (unsigned int)sqlite3_column_int64(stmt_query, 1),
1405
- (unsigned int)sqlite3_column_int64(stmt_query, 2),
1406
- config_hash_id,
1407
- transition_id,
1408
- sqlite3_column_text(stmt_query, 12),
1409
- sqlite3_column_text(stmt_query, 13),
1410
- sqlite3_column_text(stmt_query, 29),
1411
- sqlite3_column_text(stmt_query, 26) ? (const char *)sqlite3_column_text(stmt_query, 26) : (char *)"Unknown",
1412
- sqlite3_column_text(stmt_query, 27) ? (const char *)sqlite3_column_text(stmt_query, 27) : (char *)"Unknown",
1413
- sqlite3_column_text(stmt_query, 28) ? (const char *)sqlite3_column_text(stmt_query, 28) : (char *)"Unknown",
1414
- (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_PROCESSED) ? "true" : "false",
1415
- (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_UPDATED) ? "true" : "false",
1416
- (long unsigned int)sqlite3_column_int64(stmt_query, 10),
1417
- (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_EXEC_FAILED) ? "true" : "false",
1418
- sqlite3_column_text(stmt_query, 14) ? (const char *)sqlite3_column_text(stmt_query, 14) :
1419
- string2str(host->health.health_default_exec),
1420
- sqlite3_column_text(stmt_query, 15) ? (const char *)sqlite3_column_text(stmt_query, 15) :
1421
- string2str(host->health.health_default_recipient),
1422
- sqlite3_column_int(stmt_query, 19),
1423
- sqlite3_column_text(stmt_query, 16) ? (const char *)sqlite3_column_text(stmt_query, 16) : (char *)"Unknown",
1424
- edit_command,
1425
- sqlite3_column_text(stmt_query, 17),
1426
- (long unsigned int)sqlite3_column_int64(stmt_query, 6),
1427
- (long unsigned int)sqlite3_column_int64(stmt_query, 7),
1428
- (long unsigned int)sqlite3_column_int64(stmt_query, 8),
1429
- rrdcalc_status2string(sqlite3_column_int(stmt_query, 20)),
1430
- rrdcalc_status2string(sqlite3_column_int(stmt_query, 21)),
1431
- sqlite3_column_int(stmt_query, 22),
1432
- (long unsigned int)sqlite3_column_int64(stmt_query, 11),
1433
- (unsigned int)sqlite3_column_int64(stmt_query, 4),
1434
- (unsigned int)sqlite3_column_int64(stmt_query, 5),
1435
- sqlite3_column_type(stmt_query, 23) == SQLITE_NULL ?
1436
- "-" :
1437
- format_value_and_unit(
1438
- new_value_string, 100, sqlite3_column_double(stmt_query, 23), (char *)sqlite3_column_text(stmt_query, 17), -1),
1439
- sqlite3_column_type(stmt_query, 24) == SQLITE_NULL ?
1440
- "-" :
1441
- format_value_and_unit(
1442
- old_value_string, 100, sqlite3_column_double(stmt_query, 24), (char *)sqlite3_column_text(stmt_query, 17), -1),
1443
- (long unsigned int)sqlite3_column_int64(stmt_query, 25),
1444
- (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_SILENCED) ? "true" : "false");
1445
-
1446
- health_string2json(wb, "\t\t", "summary", (char *)sqlite3_column_text(stmt_query, 31), ",\n");
1447
- health_string2json(wb, "\t\t", "info", (char *)sqlite3_column_text(stmt_query, 18), ",\n");
1448
-
1449
- if (unlikely(sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION)) {
1450
- buffer_strcat(wb, "\t\t\"no_clear_notification\": true,\n");
1451
- }
1452
-
1453
- buffer_strcat(wb, "\t\t\"value\":");
1454
- if (sqlite3_column_type(stmt_query, 23) == SQLITE_NULL)
1455
- buffer_strcat(wb, "null");
1456
- else
1457
- buffer_print_netdata_double(wb, sqlite3_column_double(stmt_query, 23));
1458
- buffer_strcat(wb, ",\n");
1459
-
1460
- buffer_strcat(wb, "\t\t\"old_value\":");
1461
- if (sqlite3_column_type(stmt_query, 24) == SQLITE_NULL)
1462
- buffer_strcat(wb, "null");
1463
- else
1464
- buffer_print_netdata_double(wb, sqlite3_column_double(stmt_query, 24));
1465
- buffer_strcat(wb, "\n");
1466
-
1467
- buffer_strcat(wb, "\t}");
1468
-
1469
- freez(edit_command);
1470
- }
1355
+ buffer_json_add_array_item_object(wb); // this node
1356
+
1357
+ buffer_json_member_add_string_or_empty(wb, "hostname", rrdhost_hostname(host));
1358
+ buffer_json_member_add_int64(wb, "utc_offset", (int64_t)host->utc_offset);
1359
+ buffer_json_member_add_string_or_empty(wb, "timezone", rrdhost_abbrev_timezone(host));
1360
+ buffer_json_member_add_int64(wb, "unique_id", (int64_t) sqlite3_column_int64(stmt_query, 0));
1361
+ buffer_json_member_add_int64(wb, "alarm_id", (int64_t) sqlite3_column_int64(stmt_query, 1));
1362
+ buffer_json_member_add_int64(wb, "alarm_event_id", (int64_t) sqlite3_column_int64(stmt_query, 2));
1363
+ buffer_json_member_add_string_or_empty(wb, "config_hash_id", config_hash_id);
1364
+ buffer_json_member_add_string_or_empty(wb, "transition_id", transition_id);
1365
+ buffer_json_member_add_string_or_empty(wb, "name", (const char *) sqlite3_column_text(stmt_query, 12));
1366
+ buffer_json_member_add_string_or_empty(wb, "chart", (const char *) sqlite3_column_text(stmt_query, 13));
1367
+ buffer_json_member_add_string_or_empty(wb, "context", (const char *) sqlite3_column_text(stmt_query, 29));
1368
+ buffer_json_member_add_string_or_empty(wb, "class", sqlite3_column_text(stmt_query, 26) ? (const char *) sqlite3_column_text(stmt_query, 26) : (char *) "Unknown");
1369
+ buffer_json_member_add_string_or_empty(wb, "component", sqlite3_column_text(stmt_query, 27) ? (const char *) sqlite3_column_text(stmt_query, 27) : (char *) "Unknown");
1370
+ buffer_json_member_add_string_or_empty(wb, "type", sqlite3_column_text(stmt_query, 28) ? (const char *) sqlite3_column_text(stmt_query, 28) : (char *) "Unknown");
1371
+ buffer_json_member_add_boolean(wb, "processed", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_PROCESSED));
1372
+ buffer_json_member_add_boolean(wb, "updated", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_UPDATED));
1373
+ buffer_json_member_add_int64(wb, "exec_run", (int64_t)sqlite3_column_int64(stmt_query, 10));
1374
+ buffer_json_member_add_boolean(wb, "exec_failed", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_EXEC_FAILED));
1375
+ buffer_json_member_add_string_or_empty(wb, "exec", sqlite3_column_text(stmt_query, 14) ? (const char *) sqlite3_column_text(stmt_query, 14) : string2str(host->health.health_default_exec));
1376
+ buffer_json_member_add_string_or_empty(wb, "recipient", sqlite3_column_text(stmt_query, 15) ? (const char *) sqlite3_column_text(stmt_query, 15) : string2str(host->health.health_default_recipient));
1377
+ buffer_json_member_add_int64(wb, "exec_code", sqlite3_column_int(stmt_query, 19));
1378
+ buffer_json_member_add_string_or_empty(wb, "source", sqlite3_column_text(stmt_query, 16) ? (const char *) sqlite3_column_text(stmt_query, 16) : (char *) "Unknown");
1379
+ buffer_json_member_add_string_or_empty(wb, "command", edit_command);
1380
+ buffer_json_member_add_string_or_empty(wb, "units", (const char *) sqlite3_column_text(stmt_query, 17));
1381
+ buffer_json_member_add_int64(wb, "when", (int64_t)sqlite3_column_int64(stmt_query, 6));
1382
+ buffer_json_member_add_int64(wb, "duration", (int64_t)sqlite3_column_int64(stmt_query, 7));
1383
+ buffer_json_member_add_int64(wb, "non_clear_duration", (int64_t)sqlite3_column_int64(stmt_query, 8));
1384
+ buffer_json_member_add_string_or_empty(wb, "status", rrdcalc_status2string(sqlite3_column_int(stmt_query, 20)));
1385
+ buffer_json_member_add_string_or_empty(wb, "old_status", rrdcalc_status2string(sqlite3_column_int(stmt_query, 21)));
1386
+ buffer_json_member_add_int64(wb, "delay", sqlite3_column_int(stmt_query, 22));
1387
+ buffer_json_member_add_int64(wb, "delay_up_to_timestamp",(int64_t)sqlite3_column_int64(stmt_query, 11));
1388
+ buffer_json_member_add_int64(wb, "updated_by_id", (unsigned int)sqlite3_column_int64(stmt_query, 4));
1389
+ buffer_json_member_add_int64(wb, "updates_id", (unsigned int)sqlite3_column_int64(stmt_query, 5));
1390
+ buffer_json_member_add_string_or_empty(wb, "value_string", sqlite3_column_type(stmt_query, 23) == SQLITE_NULL ? "-" :
1391
+ format_value_and_unit(new_value_string, 100, sqlite3_column_double(stmt_query, 23), (char *) sqlite3_column_text(stmt_query, 17), -1));
1392
+ buffer_json_member_add_string_or_empty(wb, "old_value_string", sqlite3_column_type(stmt_query, 24) == SQLITE_NULL ? "-" :
1393
+ format_value_and_unit(old_value_string, 100, sqlite3_column_double(stmt_query, 24), (char *) sqlite3_column_text(stmt_query, 17), -1));
1394
+ buffer_json_member_add_int64(wb, "last_repeat", (int64_t)sqlite3_column_int64(stmt_query, 25));
1395
+ buffer_json_member_add_boolean(wb, "silenced", (sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_SILENCED));
1396
+ buffer_json_member_add_string_or_empty(wb, "summary", (const char *) sqlite3_column_text(stmt_query, 31));
1397
+ buffer_json_member_add_string_or_empty(wb, "info", (const char *) sqlite3_column_text(stmt_query, 18));
1398
+ buffer_json_member_add_boolean(wb, "no_clear_notification",(sqlite3_column_int64(stmt_query, 9) & HEALTH_ENTRY_FLAG_NO_CLEAR_NOTIFICATION));
1399
+
1400
+ if (sqlite3_column_type(stmt_query, 23) == SQLITE_NULL)
1401
+ buffer_json_member_add_string(wb, "value", NULL);
1402
+ else
1403
+ buffer_json_member_add_double(wb, "value", sqlite3_column_double(stmt_query, 23));
1404
+
1405
+ if (sqlite3_column_type(stmt_query, 24) == SQLITE_NULL)
1406
+ buffer_json_member_add_string(wb, "old_value", NULL);
1407
+ else
1408
+ buffer_json_member_add_double(wb, "old_value", sqlite3_column_double(stmt_query, 23));
1409
+
1410
+ freez(edit_command);
1411
+
1412
+ buffer_json_object_close(wb);
1413
+ }
1414
+
1415
+ buffer_json_array_close(wb);
1416
+ buffer_json_finalize(wb);
1417
1418
finish:
1473
- buffer_strcat(wb, "\n]");
1474
-
1419
rc = sqlite3_reset(stmt_query);
1420
if (unlikely(rc != SQLITE_OK))
1477
- error_report("Failed to finalize statement for SQL_SELECT_HEALTH_LOG");
1421
+ error_report("Failed to reset statement for SQL_SELECT_HEALTH_LOG");
1422
}
1423
1424
#define SQL_COPY_HEALTH_LOG(table) "INSERT OR IGNORE INTO health_log (host_id, alarm_id, config_hash_id, name, chart, family, exec, recipient, units, chart_context) SELECT ?1, alarm_id, config_hash_id, name, chart, family, exec, recipient, units, chart_context from %s;", table
libnetdata/buffer/buffer.c
+11
-3
@@ -301,12 +301,15 @@ void buffer_json_initialize(BUFFER *wb, const char *key_quote, const char *value
301
strncpyz(wb->json.key_quote, key_quote, BUFFER_QUOTE_MAX_SIZE);
302
strncpyz(wb->json.value_quote, value_quote, BUFFER_QUOTE_MAX_SIZE);
303
304
- wb->json.options = options;
304
wb->json.depth = (int8_t)(depth - 1);
305
_buffer_json_depth_push(wb, BUFFER_JSON_OBJECT);
306
307
if(add_anonymous_object)
308
buffer_fast_strcat(wb, "{", 1);
309
+ else
310
+ options |= BUFFER_JSON_OPTIONS_NON_ANONYMOUS;
311
+
312
+ wb->json.options = options;
313
314
wb->content_type = CT_APPLICATION_JSON;
315
buffer_no_cacheable(wb);
@@ -316,9 +319,14 @@ void buffer_json_finalize(BUFFER *wb) {
319
while(wb->json.depth >= 0) {
320
switch(wb->json.stack[wb->json.depth].type) {
321
case BUFFER_JSON_OBJECT:
319
- buffer_json_object_close(wb);
322
+ if (wb->json.depth == 0)
323
+ if (!(wb->json.options & BUFFER_JSON_OPTIONS_NON_ANONYMOUS))
324
+ buffer_json_object_close(wb);
325
+ else
326
+ _buffer_json_depth_pop(wb);
327
+ else
328
+ buffer_json_object_close(wb);
329
break;
321
-
330
case BUFFER_JSON_ARRAY:
331
buffer_json_array_close(wb);
332
break;
libnetdata/buffer/buffer.h
+8
-2
@@ -72,6 +72,7 @@ typedef enum __attribute__ ((__packed__)) {
72
BUFFER_JSON_OPTIONS_DEFAULT = 0,
73
BUFFER_JSON_OPTIONS_MINIFY = (1 << 0),
74
BUFFER_JSON_OPTIONS_NEWLINE_ON_ARRAY_ITEMS = (1 << 1),
75
+ BUFFER_JSON_OPTIONS_NON_ANONYMOUS = (1 << 2),
76
} BUFFER_JSON_OPTIONS;
77
78
typedef struct web_buffer {
@@ -809,8 +810,13 @@ static inline void buffer_json_member_add_boolean(BUFFER *wb, const char *key, b
810
811
static inline void buffer_json_member_add_array(BUFFER *wb, const char *key) {
812
buffer_print_json_comma_newline_spacing(wb);
812
- buffer_print_json_key(wb, key);
813
- buffer_fast_strcat(wb, ":[", 2);
813
+ if (key) {
814
+ buffer_print_json_key(wb, key);
815
+ buffer_fast_strcat(wb, ":[", 2);
816
+ }
817
+ else
818
+ buffer_fast_strcat(wb, "[", 1);
819
+
820
wb->json.stack[wb->json.depth].count++;
821
822
_buffer_json_depth_push(wb, BUFFER_JSON_ARRAY);