@cryptotaxi247 / netdata-1 / commits / d41bf12a2

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);