Revert "Easily disable alarms, by persisting the silencers configuration (#6274)"
This reverts commit 60a73e90de2aa1c2eaae2ebbc45dd1fb96034df2. Emergency rollback of potential culprit as per issue #6356 Will be re-merging the change after investigation
Pavlos Emm. Katsoulakis committed
Jun 28, 2019 at 08:27 UTC
171d8f5d01f17dddbd531139b86e1a1c96f95b0d
40 files changed
+125
-1637
CMakeLists.txt
+1
-16
@@ -130,14 +130,6 @@ set(NETDATA_COMMON_CFLAGS ${NETDATA_COMMON_CFLAGS} ${OPENSSL_CFLAGS_OTHER})
130
set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} ${OPENSSL_LIBRARIES})
131
set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${OPENSSL_INCLUDE_DIRS})
132
133
-# -----------------------------------------------------------------------------
134
-# JSON-C used to health
135
-
136
-pkg_check_modules(JSON REQUIRED json-c)
137
-set(NETDATA_COMMON_CFLAGS ${NETDATA_COMMON_CFLAGS} ${JSONC_CFLAGS_OTHER})
138
-set(NETDATA_COMMON_LIBRARIES ${NETDATA_COMMON_LIBRARIES} ${JSON_LIBRARIES})
139
-set(NETDATA_COMMON_INCLUDE_DIRS ${NETDATA_COMMON_INCLUDE_DIRS} ${JSON_INCLUDE_DIRS})
140
-
133
# -----------------------------------------------------------------------------
134
# Detect libcap
135
@@ -313,15 +305,8 @@ set(LIBNETDATA_FILES
305
libnetdata/threads/threads.h
306
libnetdata/url/url.c
307
libnetdata/url/url.h
316
- libnetdata/health/health.c
317
- libnetdata/health/health.h
308
libnetdata/socket/security.c
319
- libnetdata/socket/security.h
320
- libnetdata/json/json.c
321
- libnetdata/json/json.h
322
- libnetdata/json/jsmn.c
323
- libnetdata/json/jsmn.h
324
- )
309
+ libnetdata/socket/security.h)
310
311
add_library(libnetdata OBJECT ${LIBNETDATA_FILES})
312
Makefile.am
+3
-9
@@ -159,14 +159,8 @@ LIBNETDATA_FILES = \
159
libnetdata/storage_number/storage_number.h \
160
libnetdata/threads/threads.c \
161
libnetdata/threads/threads.h \
162
- libnetdata/url/url.c \
163
- libnetdata/url/url.h \
164
- libnetdata/json/jsmn.h \
165
- libnetdata/json/jsmn.c \
166
- libnetdata/json/json.h \
167
- libnetdata/json/json.c \
168
- libnetdata/health/health.c \
169
- libnetdata/health/health.h \
162
+ libnetdata/url/url.c \
163
+ libnetdata/url/url.h \
164
$(NULL)
165
166
APPS_PLUGIN_FILES = \
@@ -512,12 +506,12 @@ endif
506
NETDATA_COMMON_LIBS = \
507
$(OPTIONAL_MATH_LIBS) \
508
$(OPTIONAL_ZLIB_LIBS) \
509
+ $(OPTIONAL_SSL_LIBS) \
510
$(OPTIONAL_UUID_LIBS) \
511
$(OPTIONAL_UV_LIBS) \
512
$(OPTIONAL_LZ4_LIBS) \
513
$(OPTIONAL_JUDY_LIBS) \
514
$(OPTIONAL_SSL_LIBS) \
520
- $(OPTIONAL_JSONC_LIBS) \
515
$(NULL)
516
517
sbin_PROGRAMS += netdata
configure.ac
-39
@@ -142,12 +142,6 @@ AC_ARG_ENABLE(
142
,
143
[enable_https="detect"]
144
)
145
-AC_ARG_ENABLE(
146
- [jsonc],
147
- [AS_HELP_STRING([--enable-jsonc], [Enable JSON-C support @<:@default autodetect@:>@])],
148
- ,
149
- [enable_jsonc="detect"]
150
-)
145
AC_ARG_ENABLE(
146
[dbengine],
147
[AS_HELP_STRING([--disable-dbengine], [disable netdata dbengine @<:@default autodetect@:>@])],
@@ -353,20 +347,6 @@ AC_CHECK_LIB(
347
OPTIONAL_SSL_CFLAGS="${SSL_CFLAGS}"
348
OPTIONAL_SSL_LIBS="${SSL_LIBS}"
349
356
-# -----------------------------------------------------------------------------
357
-# JSON-C library
358
-
359
-PKG_CHECK_MODULES([JSON],[json-c],AC_CHECK_LIB(
360
- [json-c],
361
- [json_object_get_type],
362
- [JSONC_LIBS="-ljson-c"]),AC_CHECK_LIB(
363
- [json],
364
- [json_object_get_type],
365
- [JSONC_LIBS="-ljson"])
366
- )
367
-
368
-OPTIONAL_JSONC_LIBS="${JSONC_LIBS}"
369
-
350
# -----------------------------------------------------------------------------
351
# DB engine and HTTPS
352
test "${enable_dbengine}" = "yes" -a -z "${UV_LIBS}" && \
@@ -401,22 +381,6 @@ fi
381
AC_MSG_RESULT([${enable_https}])
382
AM_CONDITIONAL([ENABLE_HTTPS], [test "${enable_https}" = "yes"])
383
404
-# -----------------------------------------------------------------------------
405
-# JSON-C
406
-test "${enable_jsonc}" = "yes" -a -z "${JSONC_LIBS}" && \
407
- AC_MSG_ERROR([JSON-C required but not found. Try installing 'libjson-c-dev' or 'json-c'.])
408
-
409
-AC_MSG_CHECKING([if json-c should be used])
410
-if test "${enable_jsonc}" != "no" -a "${JSONC_LIBS}"; then
411
- enable_jsonc="yes"
412
- AC_DEFINE([ENABLE_JSONC], [1], [netdata json-c usability])
413
-else
414
- enable_jsonc="no"
415
-fi
416
-AC_MSG_RESULT([${enable_jsonc}])
417
-AM_CONDITIONAL([ENABLE_JSONC], [test "${enable_jsonc}" = "yes"])
418
-
419
-
384
# -----------------------------------------------------------------------------
385
# compiler options
386
@@ -1011,7 +975,6 @@ AC_SUBST([OPTIONAL_UV_LIBS])
975
AC_SUBST([OPTIONAL_LZ4_LIBS])
976
AC_SUBST([OPTIONAL_JUDY_LIBS])
977
AC_SUBST([OPTIONAL_SSL_LIBS])
1014
-AC_SUBST([OPTIONAL_JSONC_LIBS])
978
AC_SUBST([OPTIONAL_NFACCT_CFLAGS])
979
AC_SUBST([OPTIONAL_NFACCT_LIBS])
980
AC_SUBST([OPTIONAL_ZLIB_CFLAGS])
@@ -1078,8 +1041,6 @@ AC_CONFIG_FILES([
1041
libnetdata/config/Makefile
1042
libnetdata/dictionary/Makefile
1043
libnetdata/eval/Makefile
1081
- libnetdata/json/Makefile
1082
- libnetdata/health/Makefile
1044
libnetdata/locks/Makefile
1045
libnetdata/log/Makefile
1046
libnetdata/popen/Makefile
health/health.c
+5
-96
@@ -1,6 +1,5 @@
1
// SPDX-License-Identifier: GPL-3.0-or-later
2
3
-#include <libnetdata/json/json.h>
3
#include "health.h"
4
5
struct health_cmdapi_thread_status {
@@ -14,79 +13,18 @@ unsigned int default_health_enabled = 1;
13
// ----------------------------------------------------------------------------
14
// health initialization
15
17
-/**
18
- * User Config directory
19
- *
20
- * Get the config directory for health and return it.
21
- *
22
- * @return a pointer to the user config directory
23
- */
16
inline char *health_user_config_dir(void) {
17
char buffer[FILENAME_MAX + 1];
18
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_user_config_dir);
19
return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer);
20
}
21
30
-/**
31
- * Stock Config Directory
32
- *
33
- * Get the Stock config directory and return it.
34
- *
35
- * @return a pointer to the stock config directory.
36
- */
22
inline char *health_stock_config_dir(void) {
23
char buffer[FILENAME_MAX + 1];
24
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_stock_config_dir);
25
return config_get(CONFIG_SECTION_HEALTH, "stock health configuration directory", buffer);
26
}
27
43
-
44
-/**
45
- * Silencers init
46
- *
47
- * Function used to initialize the silencer structure.
48
- */
49
-void health_silencers_init(void) {
50
- silencers = mallocz(sizeof(SILENCERS));
51
- silencers->all_alarms=0;
52
- silencers->stype=STYPE_NONE;
53
- silencers->silencers=NULL;
54
-
55
- char filename[FILENAME_MAX + 1];
56
- snprintfz(filename, FILENAME_MAX, "%s/health.silencers.json", netdata_configured_varlib_dir);
57
- silencers_filename = config_get(CONFIG_SECTION_HEALTH, "silencers file", filename);
58
-
59
- struct stat statbuf;
60
- if (!stat(silencers_filename,&statbuf)) {
61
- off_t length = statbuf.st_size;
62
- if (length && length < HEALTH_SILENCERS_MAX_FILE_LEN) {
63
- FILE *fd = fopen(silencers_filename, "r");
64
- if (fd) {
65
- char *str = mallocz((length+1)* sizeof(char));
66
- if(str) {
67
- fread(str, sizeof(char), length, fd);
68
- str[length] = 0x00;
69
- json_parse(str, NULL, health_silencers_json_read_callback);
70
- freez(str);
71
- info("Parsed health silencers file %s", silencers_filename);
72
- }
73
- fclose(fd);
74
- } else {
75
- error("Cannot open the file %s",silencers_filename);
76
- }
77
- } else {
78
- error("Health silencers file %s has the size %ld that is out of range[ 1 , %d ]. Aborting read.", silencers_filename, length, HEALTH_SILENCERS_MAX_FILE_LEN);
79
- }
80
- } else {
81
- error("Cannot open the file %s",silencers_filename);
82
- }
83
-}
84
-
85
-/**
86
- * Health Init
87
- *
88
- * Initialize the health thread.
89
- */
28
void health_init(void) {
29
debug(D_HEALTH, "Health configuration initializing");
30
@@ -94,20 +32,11 @@ void health_init(void) {
32
debug(D_HEALTH, "Health is disabled.");
33
return;
34
}
97
-
98
- health_silencers_init();
35
}
36
37
// ----------------------------------------------------------------------------
38
// re-load health configuration
39
104
-/**
105
- * Reload host
106
- *
107
- * Reload configuration for a specific host.
108
- *
109
- * @param host the structure of the host that the function will reload the configuration.
110
- */
40
void health_reload_host(RRDHOST *host) {
41
if(unlikely(!host->health_enabled))
42
return;
@@ -155,11 +84,6 @@ void health_reload_host(RRDHOST *host) {
84
rrdhost_unlock(host);
85
}
86
158
-/**
159
- * Reload
160
- *
161
- * Reload the host configuration for all hosts.
162
- */
87
void health_reload(void) {
88
89
rrd_rdlock();
@@ -501,16 +425,6 @@ SILENCE_TYPE check_silenced(RRDCALC *rc, char* host, SILENCERS *silencers) {
425
return STYPE_NONE;
426
}
427
504
-/**
505
- * Update Disabled Silenced
506
- *
507
- * Update the variable rrdcalc_flags of the structure RRDCALC according with the values of the host structure
508
- *
509
- * @param host structure that contains information about the host monitored.
510
- * @param rc structure with information about the alarm
511
- *
512
- * @return It returns 1 case rrdcalc_flags is DISABLED or 0 otherwise
513
- */
428
int update_disabled_silenced(RRDHOST *host, RRDCALC *rc) {
429
uint32_t rrdcalc_flags_old = rc->rrdcalc_flags;
430
// Clear the flags
@@ -540,15 +454,6 @@ int update_disabled_silenced(RRDHOST *host, RRDCALC *rc) {
454
return 0;
455
}
456
543
-/**
544
- * Health Main
545
- *
546
- * The main thread of the health system. In this function all the alarms will be processed.
547
- *
548
- * @param ptr is a pointer to the netdata_static_thread structure.
549
- *
550
- * @return It always returns NULL
551
- */
457
void *health_main(void *ptr) {
458
netdata_thread_cleanup_push(health_main_cleanup, ptr);
459
@@ -560,6 +465,11 @@ void *health_main(void *ptr) {
465
466
unsigned int loop = 0;
467
468
+ silencers = mallocz(sizeof(SILENCERS));
469
+ silencers->all_alarms=0;
470
+ silencers->stype=STYPE_NONE;
471
+ silencers->silencers=NULL;
472
+
473
while(!netdata_exit) {
474
loop++;
475
debug(D_HEALTH, "Health monitoring iteration no %u started", loop);
@@ -613,7 +523,6 @@ void *health_main(void *ptr) {
523
// the first loop is to lookup values from the db
524
for (rc = host->alarms; rc; rc = rc->next) {
525
616
- //case it is disabled I will get the next rc
526
if (update_disabled_silenced(host, rc))
527
continue;
528
health/health.h
+40
-4
@@ -35,9 +35,16 @@ extern unsigned int default_health_enabled;
35
#define HEALTH_LISTEN_BACKLOG 4096
36
#endif
37
38
-
38
+#define HEALTH_ALARM_KEY "alarm"
39
+#define HEALTH_TEMPLATE_KEY "template"
40
#define HEALTH_ON_KEY "on"
40
-
41
+#define HEALTH_CONTEXT_KEY "context"
42
+#define HEALTH_CHART_KEY "chart"
43
+#define HEALTH_HOST_KEY "hosts"
44
+#define HEALTH_OS_KEY "os"
45
+#define HEALTH_FAMILIES_KEY "families"
46
+#define HEALTH_LOOKUP_KEY "lookup"
47
+#define HEALTH_CALC_KEY "calc"
48
#define HEALTH_EVERY_KEY "every"
49
#define HEALTH_GREEN_KEY "green"
50
#define HEALTH_RED_KEY "red"
@@ -50,9 +57,38 @@ extern unsigned int default_health_enabled;
57
#define HEALTH_DELAY_KEY "delay"
58
#define HEALTH_OPTIONS_KEY "options"
59
53
-#define HEALTH_SILENCERS_MAX_FILE_LEN 10000
60
+typedef struct silencer {
61
+ char *alarms;
62
+ SIMPLE_PATTERN *alarms_pattern;
63
+
64
+ char *hosts;
65
+ SIMPLE_PATTERN *hosts_pattern;
66
+
67
+ char *contexts;
68
+ SIMPLE_PATTERN *contexts_pattern;
69
+
70
+ char *charts;
71
+ SIMPLE_PATTERN *charts_pattern;
72
+
73
+ char *families;
74
+ SIMPLE_PATTERN *families_pattern;
75
+
76
+ struct silencer *next;
77
+} SILENCER;
78
+
79
+typedef enum silence_type {
80
+ STYPE_NONE,
81
+ STYPE_DISABLE_ALARMS,
82
+ STYPE_SILENCE_NOTIFICATIONS
83
+} SILENCE_TYPE;
84
+
85
+typedef struct silencers {
86
+ int all_alarms;
87
+ SILENCE_TYPE stype;
88
+ SILENCER *silencers;
89
+} SILENCERS;
90
55
-char *silencers_filename;
91
+SILENCERS *silencers;
92
93
extern void health_init(void);
94
extern void *health_main(void *ptr);
health/health_config.c
+1
-1
@@ -481,7 +481,7 @@ static int health_readfile(const char *filename, void *data) {
481
if(append < HEALTH_CONF_MAX_LINE)
482
continue;
483
else {
484
- error("Health configuration has too long multi-line at line %zu of file '%s'.", line, filename);
484
+ error("Health configuration has too long muli-line at line %zu of file '%s'.", line, filename);
485
}
486
}
487
append = 0;
libnetdata/Makefile.am
-2
@@ -21,8 +21,6 @@ SUBDIRS = \
21
storage_number \
22
threads \
23
url \
24
- json \
25
- health \
24
$(NULL)
25
26
dist_noinst_DATA = \
libnetdata/health/Makefile.am
deleted
-8
@@ -1,8 +0,0 @@
1
-# SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-AUTOMAKE_OPTIONS = subdir-objects
4
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5
-
6
-
7
-dist_noinst_DATA = \
8
- $(NULL)
libnetdata/health/health.c
deleted
-154
@@ -1,154 +0,0 @@
1
-#include "health.h"
2
-
3
-/**
4
- * Create Silencer
5
- *
6
- * Allocate a new silencer to Netdata.
7
- *
8
- * @return It returns the address off the silencer on success and NULL otherwise
9
- */
10
-SILENCER *create_silencer(void) {
11
- SILENCER *t = callocz(1, sizeof(SILENCER));
12
- debug(D_HEALTH, "HEALTH command API: Created empty silencer");
13
-
14
- return t;
15
-}
16
-
17
-/**
18
- * Health Silencers add
19
- *
20
- * Add more one silencer to the list of silenecers.
21
- *
22
- * @param silencer
23
- */
24
-void health_silencers_add(SILENCER *silencer) {
25
- // Add the created instance to the linked list in silencers
26
- silencer->next = silencers->silencers;
27
- silencers->silencers = silencer;
28
- debug(D_HEALTH, "HEALTH command API: Added silencer %s:%s:%s:%s:%s", silencer->alarms,
29
- silencer->charts, silencer->contexts, silencer->hosts, silencer->families
30
- );
31
-}
32
-
33
-/**
34
- * Silencers Add Parameter
35
- *
36
- * Create a new silencer and adjust the variables
37
- *
38
- * @param silencer a pointer to the silencer that will be adjusted
39
- * @param key the key value sent by client
40
- * @param value the value sent to the key
41
- *
42
- * @return It returns the silencer configured on success and NULL otherwise
43
- */
44
-SILENCER *health_silencers_addparam(SILENCER *silencer, char *key, char *value) {
45
- static uint32_t
46
- hash_alarm = 0,
47
- hash_template = 0,
48
- hash_chart = 0,
49
- hash_context = 0,
50
- hash_host = 0,
51
- hash_families = 0;
52
-
53
- if (unlikely(!hash_alarm)) {
54
- hash_alarm = simple_uhash(HEALTH_ALARM_KEY);
55
- hash_template = simple_uhash(HEALTH_TEMPLATE_KEY);
56
- hash_chart = simple_uhash(HEALTH_CHART_KEY);
57
- hash_context = simple_uhash(HEALTH_CONTEXT_KEY);
58
- hash_host = simple_uhash(HEALTH_HOST_KEY);
59
- hash_families = simple_uhash(HEALTH_FAMILIES_KEY);
60
- }
61
-
62
- uint32_t hash = simple_uhash(key);
63
- if (unlikely(silencer == NULL)) {
64
- if (
65
- (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) ||
66
- (hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) ||
67
- (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) ||
68
- (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) ||
69
- (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) ||
70
- (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY))
71
- ) {
72
- silencer = create_silencer();
73
- if(!silencer) {
74
- error("Cannot add a new silencer to Netdata");
75
- return NULL;
76
- }
77
- }
78
- }
79
-
80
- if (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) {
81
- silencer->alarms = strdupz(value);
82
- silencer->alarms_pattern = simple_pattern_create(silencer->alarms, NULL, SIMPLE_PATTERN_EXACT);
83
- } else if (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) {
84
- silencer->charts = strdupz(value);
85
- silencer->charts_pattern = simple_pattern_create(silencer->charts, NULL, SIMPLE_PATTERN_EXACT);
86
- } else if (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) {
87
- silencer->contexts = strdupz(value);
88
- silencer->contexts_pattern = simple_pattern_create(silencer->contexts, NULL, SIMPLE_PATTERN_EXACT);
89
- } else if (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) {
90
- silencer->hosts = strdupz(value);
91
- silencer->hosts_pattern = simple_pattern_create(silencer->hosts, NULL, SIMPLE_PATTERN_EXACT);
92
- } else if (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) {
93
- silencer->families = strdupz(value);
94
- silencer->families_pattern = simple_pattern_create(silencer->families, NULL, SIMPLE_PATTERN_EXACT);
95
- }
96
-
97
- return silencer;
98
-}
99
-
100
-/**
101
- * JSON Read Callback
102
- *
103
- * Callback called by netdata to create the silencer.
104
- *
105
- * @param e the main json structure
106
- *
107
- * @return It always return 0.
108
- */
109
-int health_silencers_json_read_callback(JSON_ENTRY *e)
110
-{
111
- switch(e->type) {
112
- case JSON_OBJECT:
113
-#ifndef ENABLE_JSONC
114
- e->callback_function = health_silencers_json_read_callback;
115
- if(e->name && strcmp(e->name,"")) {
116
- // init silencer
117
- debug(D_HEALTH, "JSON: Got object with a name, initializing new silencer for %s",e->name);
118
-#endif
119
- e->callback_data = create_silencer();
120
- if(e->callback_data) {
121
- health_silencers_add(e->callback_data);
122
- }
123
-#ifndef ENABLE_JSONC
124
- }
125
-#endif
126
- break;
127
-
128
- case JSON_ARRAY:
129
- e->callback_function = health_silencers_json_read_callback;
130
- break;
131
-
132
- case JSON_STRING:
133
- if(!strcmp(e->name,"type")) {
134
- debug(D_HEALTH, "JSON: Processing type=%s",e->data.string);
135
- if (!strcmp(e->data.string,"SILENCE")) silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
136
- else if (!strcmp(e->data.string,"DISABLE")) silencers->stype = STYPE_DISABLE_ALARMS;
137
- } else {
138
- debug(D_HEALTH, "JSON: Adding %s=%s", e->name, e->data.string);
139
- health_silencers_addparam(e->callback_data, e->name, e->data.string);
140
- }
141
- break;
142
-
143
- case JSON_BOOLEAN:
144
- debug(D_HEALTH, "JSON: Processing all_alarms");
145
- silencers->all_alarms=e->data.boolean?1:0;
146
- break;
147
-
148
- case JSON_NUMBER:
149
- case JSON_NULL:
150
- break;
151
- }
152
-
153
- return 0;
154
-}
libnetdata/health/health.h
deleted
-54
@@ -1,54 +0,0 @@
1
-#ifndef NETDATA_HEALTH_LIB
2
-# define NETDATA_HEALTH_LIB 1
3
-
4
-# include "../libnetdata.h"
5
-
6
-#define HEALTH_ALARM_KEY "alarm"
7
-#define HEALTH_TEMPLATE_KEY "template"
8
-#define HEALTH_CONTEXT_KEY "context"
9
-#define HEALTH_CHART_KEY "chart"
10
-#define HEALTH_HOST_KEY "hosts"
11
-#define HEALTH_OS_KEY "os"
12
-#define HEALTH_FAMILIES_KEY "families"
13
-#define HEALTH_LOOKUP_KEY "lookup"
14
-#define HEALTH_CALC_KEY "calc"
15
-
16
-typedef struct silencer {
17
- char *alarms;
18
- SIMPLE_PATTERN *alarms_pattern;
19
-
20
- char *hosts;
21
- SIMPLE_PATTERN *hosts_pattern;
22
-
23
- char *contexts;
24
- SIMPLE_PATTERN *contexts_pattern;
25
-
26
- char *charts;
27
- SIMPLE_PATTERN *charts_pattern;
28
-
29
- char *families;
30
- SIMPLE_PATTERN *families_pattern;
31
-
32
- struct silencer *next;
33
-} SILENCER;
34
-
35
-typedef enum silence_type {
36
- STYPE_NONE,
37
- STYPE_DISABLE_ALARMS,
38
- STYPE_SILENCE_NOTIFICATIONS
39
-} SILENCE_TYPE;
40
-
41
-typedef struct silencers {
42
- int all_alarms;
43
- SILENCE_TYPE stype;
44
- SILENCER *silencers;
45
-} SILENCERS;
46
-
47
-SILENCERS *silencers;
48
-
49
-extern SILENCER *create_silencer(void);
50
-extern int health_silencers_json_read_callback(JSON_ENTRY *e);
51
-extern void health_silencers_add(SILENCER *silencer);
52
-extern SILENCER * health_silencers_addparam(SILENCER *silencer, char *key, char *value);
53
-
54
-#endif
libnetdata/json/Makefile.am
deleted
-9
@@ -1,9 +0,0 @@
1
-# SPDX-License-Identifier: GPL-3.0-or-later
2
-
3
-AUTOMAKE_OPTIONS = subdir-objects
4
-MAINTAINERCLEANFILES = $(srcdir)/Makefile.in
5
-
6
-
7
-dist_noinst_DATA = \
8
- README.md \
9
- $(NULL)
libnetdata/json/README.md
deleted
-5
@@ -1,5 +0,0 @@
1
-# json
2
-
3
-`json` contains a parser for json strings, based on `jsmn` (https://github.com/zserge/jsmn), but case you have installed the JSON-C library, the installation script will prefer it, you can also force its use with `--enable-jsonc` in the compilation time.
4
-
5
-[]()
libnetdata/json/jsmn.c
deleted
-326
@@ -1,326 +0,0 @@
1
-#include <stdlib.h>
2
-
3
-#include "jsmn.h"
4
-
5
-/**
6
- * Alloc token
7
- *
8
- * Allocates a fresh unused token from the token pull.
9
- *
10
- * @param parser the controller
11
- * @param tokens the tokens I am working
12
- * @param num_tokens the number total of tokens.
13
- *
14
- * @return it returns the next token to work.
15
- */
16
-static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser,
17
- jsmntok_t *tokens, size_t num_tokens) {
18
- jsmntok_t *tok;
19
- if (parser->toknext >= num_tokens) {
20
- return NULL;
21
- }
22
- tok = &tokens[parser->toknext++];
23
- tok->start = tok->end = -1;
24
- tok->size = 0;
25
-#ifdef JSMN_PARENT_LINKS
26
- tok->parent = -1;
27
-#endif
28
- return tok;
29
-}
30
-
31
-/**
32
- * Fill Token
33
- *
34
- * Fills token type and boundaries.
35
- *
36
- * @param token the structure to set the values
37
- * @param type is the token type
38
- * @param start is the first position of the value
39
- * @param end is the end of the value
40
- */
41
-static void jsmn_fill_token(jsmntok_t *token, jsmntype_t type,
42
- int start, int end) {
43
- token->type = type;
44
- token->start = start;
45
- token->end = end;
46
- token->size = 0;
47
-}
48
-
49
-/**
50
- * Parse primitive
51
- *
52
- * Fills next available token with JSON primitive.
53
- *
54
- * @param parser is the control structure
55
- * @param js is the json string
56
- * @param type is the token type
57
- */
58
-static jsmnerr_t jsmn_parse_primitive(jsmn_parser *parser, const char *js,
59
- size_t len, jsmntok_t *tokens, size_t num_tokens) {
60
- jsmntok_t *token;
61
- int start;
62
-
63
- start = parser->pos;
64
-
65
- for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
66
- switch (js[parser->pos]) {
67
-#ifndef JSMN_STRICT
68
- /* In strict mode primitive must be followed by "," or "}" or "]" */
69
- case ':':
70
-#endif
71
- case '\t' : case '\r' : case '\n' : case ' ' :
72
- case ',' : case ']' : case '}' :
73
- goto found;
74
- }
75
- if (js[parser->pos] < 32 || js[parser->pos] >= 127) {
76
- parser->pos = start;
77
- return JSMN_ERROR_INVAL;
78
- }
79
- }
80
-#ifdef JSMN_STRICT
81
- /* In strict mode primitive must be followed by a comma/object/array */
82
- parser->pos = start;
83
- return JSMN_ERROR_PART;
84
-#endif
85
-
86
- found:
87
- if (tokens == NULL) {
88
- parser->pos--;
89
- return 0;
90
- }
91
- token = jsmn_alloc_token(parser, tokens, num_tokens);
92
- if (token == NULL) {
93
- parser->pos = start;
94
- return JSMN_ERROR_NOMEM;
95
- }
96
- jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos);
97
-#ifdef JSMN_PARENT_LINKS
98
- token->parent = parser->toksuper;
99
-#endif
100
- parser->pos--;
101
- return 0;
102
-}
103
-
104
-/**
105
- * Parse string
106
- *
107
- * Fills next token with JSON string.
108
- *
109
- * @param parser is the control structure
110
- * @param js is the json string
111
- * @param len is the js length
112
- * @param tokens is structure with the tokens mapped.
113
- * @param num_tokens is the total number of tokens
114
- *
115
- * @return It returns 0 on success and another integer otherwise
116
- */
117
-static jsmnerr_t jsmn_parse_string(jsmn_parser *parser, const char *js,
118
- size_t len, jsmntok_t *tokens, size_t num_tokens) {
119
- jsmntok_t *token;
120
-
121
- int start = parser->pos;
122
-
123
- parser->pos++;
124
-
125
- /* Skip starting quote */
126
- for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
127
- char c = js[parser->pos];
128
-
129
- /* Quote: end of string */
130
- if (c == '\"') {
131
- if (tokens == NULL) {
132
- return 0;
133
- }
134
- token = jsmn_alloc_token(parser, tokens, num_tokens);
135
- if (token == NULL) {
136
- parser->pos = start;
137
- return JSMN_ERROR_NOMEM;
138
- }
139
- jsmn_fill_token(token, JSMN_STRING, start+1, parser->pos);
140
-#ifdef JSMN_PARENT_LINKS
141
- token->parent = parser->toksuper;
142
-#endif
143
- return 0;
144
- }
145
-
146
- /* Backslash: Quoted symbol expected */
147
- if (c == '\\') {
148
- parser->pos++;
149
- switch (js[parser->pos]) {
150
- /* Allowed escaped symbols */
151
- case '\"': case '/' : case '\\' : case 'b' :
152
- case 'f' : case 'r' : case 'n' : case 't' :
153
- break;
154
- /* Allows escaped symbol \uXXXX */
155
- case 'u':
156
- parser->pos++;
157
- int i = 0;
158
- for(; i < 4 && js[parser->pos] != '\0'; i++) {
159
- /* If it isn't a hex character we have an error */
160
- if(!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */
161
- (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */
162
- (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */
163
- parser->pos = start;
164
- return JSMN_ERROR_INVAL;
165
- }
166
- parser->pos++;
167
- }
168
- parser->pos--;
169
- break;
170
- /* Unexpected symbol */
171
- default:
172
- parser->pos = start;
173
- return JSMN_ERROR_INVAL;
174
- }
175
- }
176
- }
177
- parser->pos = start;
178
- return JSMN_ERROR_PART;
179
-}
180
-
181
-/**
182
- * JSMN Parse
183
- *
184
- * Parse JSON string and fill tokens.
185
- *
186
- * @param parser the auxiliar vector used to parser
187
- * @param js the string to parse
188
- * @param len the string length
189
- * @param tokens the place to map the tokens
190
- * @param num_tokens the number of tokens present in the tokens structure.
191
- *
192
- * @return It returns the number of tokens present in the string on success or a negative number otherwise
193
- */
194
-jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
195
- jsmntok_t *tokens, unsigned int num_tokens) {
196
- jsmnerr_t r;
197
- int i;
198
- jsmntok_t *token;
199
- int count = 0;
200
-
201
- for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) {
202
- char c;
203
- jsmntype_t type;
204
-
205
- c = js[parser->pos];
206
- switch (c) {
207
- case '{': case '[':
208
- count++;
209
- if (tokens == NULL) {
210
- break;
211
- }
212
- token = jsmn_alloc_token(parser, tokens, num_tokens);
213
- if (token == NULL)
214
- return JSMN_ERROR_NOMEM;
215
- if (parser->toksuper != -1) {
216
- tokens[parser->toksuper].size++;
217
-#ifdef JSMN_PARENT_LINKS
218
- token->parent = parser->toksuper;
219
-#endif
220
- }
221
- token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY);
222
- token->start = parser->pos;
223
- parser->toksuper = parser->toknext - 1;
224
- break;
225
- case '}': case ']':
226
- if (tokens == NULL)
227
- break;
228
- type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY);
229
-#ifdef JSMN_PARENT_LINKS
230
- if (parser->toknext < 1) {
231
- return JSMN_ERROR_INVAL;
232
- }
233
- token = &tokens[parser->toknext - 1];
234
- for (;;) {
235
- if (token->start != -1 && token->end == -1) {
236
- if (token->type != type) {
237
- return JSMN_ERROR_INVAL;
238
- }
239
- token->end = parser->pos + 1;
240
- parser->toksuper = token->parent;
241
- break;
242
- }
243
- if (token->parent == -1) {
244
- break;
245
- }
246
- token = &tokens[token->parent];
247
- }
248
-#else
249
- for (i = parser->toknext - 1; i >= 0; i--) {
250
- token = &tokens[i];
251
- if (token->start != -1 && token->end == -1) {
252
- if (token->type != type) {
253
- return JSMN_ERROR_INVAL;
254
- }
255
- parser->toksuper = -1;
256
- token->end = parser->pos + 1;
257
- break;
258
- }
259
- }
260
- /* Error if unmatched closing bracket */
261
- if (i == -1) return JSMN_ERROR_INVAL;
262
- for (; i >= 0; i--) {
263
- token = &tokens[i];
264
- if (token->start != -1 && token->end == -1) {
265
- parser->toksuper = i;
266
- break;
267
- }
268
- }
269
-#endif
270
- break;
271
- case '\"':
272
- r = jsmn_parse_string(parser, js, len, tokens, num_tokens);
273
- if (r < 0) return r;
274
- count++;
275
- if (parser->toksuper != -1 && tokens != NULL)
276
- tokens[parser->toksuper].size++;
277
- break;
278
- case '\t' : case '\r' : case '\n' : case ':' : case ',': case ' ':
279
- break;
280
-#ifdef JSMN_STRICT
281
- /* In strict mode primitives are: numbers and booleans */
282
- case '-': case '0': case '1' : case '2': case '3' : case '4':
283
- case '5': case '6': case '7' : case '8': case '9':
284
- case 't': case 'f': case 'n' :
285
-#else
286
- /* In non-strict mode every unquoted value is a primitive */
287
- default:
288
-#endif
289
- r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens);
290
- if (r < 0) return r;
291
- count++;
292
- if (parser->toksuper != -1 && tokens != NULL)
293
- tokens[parser->toksuper].size++;
294
- break;
295
-
296
-#ifdef JSMN_STRICT
297
- /* Unexpected char in strict mode */
298
- default:
299
- return JSMN_ERROR_INVAL;
300
-#endif
301
- }
302
- }
303
-
304
- for (i = parser->toknext - 1; i >= 0; i--) {
305
- /* Unmatched opened object or array */
306
- if (tokens[i].start != -1 && tokens[i].end == -1) {
307
- return JSMN_ERROR_PART;
308
- }
309
- }
310
-
311
- return count;
312
-}
313
-
314
-/**
315
- * JSMN Init
316
- *
317
- * Creates a new parser based over a given buffer with an array of tokens
318
- * available.
319
- *
320
- * @param parser is the structure with values to reset
321
- */
322
-void jsmn_init(jsmn_parser *parser) {
323
- parser->pos = 0;
324
- parser->toknext = 0;
325
- parser->toksuper = -1;
326
-}
\ No newline at end of file
libnetdata/json/jsmn.h
deleted
-75
@@ -1,75 +0,0 @@
1
-#ifndef __JSMN_H_
2
-#define __JSMN_H_
3
-
4
-#ifdef __cplusplus
5
-extern "C" {
6
-#endif
7
-
8
-#include <stddef.h>
9
-/**
10
- * JSON type identifier. Basic types are:
11
- * o Object
12
- * o Array
13
- * o String
14
- * o Other primitive: number, boolean (true/false) or null
15
- */
16
-typedef enum {
17
- JSMN_PRIMITIVE = 0,
18
- JSMN_OBJECT = 1,
19
- JSMN_ARRAY = 2,
20
- JSMN_STRING = 3
21
-} jsmntype_t;
22
-
23
-typedef enum {
24
- /* Not enough tokens were provided */
25
- JSMN_ERROR_NOMEM = -1,
26
- /* Invalid character inside JSON string */
27
- JSMN_ERROR_INVAL = -2,
28
- /* The string is not a full JSON packet, more bytes expected */
29
- JSMN_ERROR_PART = -3,
30
-} jsmnerr_t;
31
-
32
-/**
33
- * JSON token description.
34
- *
35
- * @param type type (object, array, string etc.)
36
- * @param start start position in JSON data string
37
- * @param end end position in JSON data string
38
- */
39
-typedef struct {
40
- jsmntype_t type;
41
- int start;
42
- int end;
43
- int size;
44
-#ifdef JSMN_PARENT_LINKS
45
- int parent;
46
-#endif
47
-} jsmntok_t;
48
-
49
-/**
50
- * JSON parser. Contains an array of token blocks available. Also stores
51
- * the string being parsed now and current position in that string
52
- */
53
-typedef struct {
54
- unsigned int pos; /* offset in the JSON string */
55
- unsigned int toknext; /* next token to allocate */
56
- int toksuper; /* superior token node, e.g parent object or array */
57
-} jsmn_parser;
58
-
59
-/**
60
- * Create JSON parser over an array of tokens
61
- */
62
-void jsmn_init(jsmn_parser *parser);
63
-
64
-/**
65
- * Run JSON parser. It parses a JSON data string into and array of tokens, each describing
66
- * a single JSON object.
67
- */
68
-jsmnerr_t jsmn_parse(jsmn_parser *parser, const char *js, size_t len,
69
- jsmntok_t *tokens, unsigned int num_tokens);
70
-
71
-#ifdef __cplusplus
72
-}
73
-#endif
74
-
75
-#endif /* __JSMN_H_ */
\ No newline at end of file
libnetdata/json/json.c
deleted
-546
@@ -1,546 +0,0 @@
1
-#include "jsmn.h"
2
-#include "../libnetdata.h"
3
-#include "json.h"
4
-#include "libnetdata/libnetdata.h"
5
-#include "../../health/health.h"
6
-
7
-#define JSON_TOKENS 1024
8
-
9
-int json_tokens = JSON_TOKENS;
10
-
11
-/**
12
- * Json Tokenise
13
- *
14
- * Map the string given inside tokens.
15
- *
16
- * @param js is the string used to create the tokens
17
- * @param len is the string length
18
- * @param count the number of tokens present in the string
19
- *
20
- * @return it returns the json parsed in tokens
21
- */
22
-#ifdef ENABLE_JSONC
23
-json_object *json_tokenise(char *js) {
24
- if(!js) {
25
- error("JSON: json string is empty.");
26
- return NULL;
27
- }
28
-
29
- json_object *token = json_tokener_parse(js);
30
- if(!token) {
31
- error("JSON: Invalid json string.");
32
- return NULL;
33
- }
34
-
35
- return token;
36
-}
37
-#else
38
-jsmntok_t *json_tokenise(char *js, size_t len, size_t *count)
39
-{
40
- int n = json_tokens;
41
- if(!js || !len) {
42
- error("JSON: json string is empty.");
43
- return NULL;
44
- }
45
-
46
- jsmn_parser parser;
47
- jsmn_init(&parser);
48
-
49
- jsmntok_t *tokens = mallocz(sizeof(jsmntok_t) * n);
50
- if(!tokens) return NULL;
51
-
52
- int ret = jsmn_parse(&parser, js, len, tokens, n);
53
- while (ret == JSMN_ERROR_NOMEM) {
54
- n *= 2;
55
- jsmntok_t *new = reallocz(tokens, sizeof(jsmntok_t) * n);
56
- if(!new) {
57
- freez(tokens);
58
- return NULL;
59
- }
60
- tokens = new;
61
- ret = jsmn_parse(&parser, js, len, tokens, n);
62
- }
63
-
64
- if (ret == JSMN_ERROR_INVAL) {
65
- error("JSON: Invalid json string.");
66
- freez(tokens);
67
- return NULL;
68
- }
69
- else if (ret == JSMN_ERROR_PART) {
70
- error("JSON: Truncated JSON string.");
71
- freez(tokens);
72
- return NULL;
73
- }
74
-
75
- if(count) *count = (size_t)ret;
76
-
77
- if(json_tokens < n) json_tokens = n;
78
- return tokens;
79
-}
80
-#endif
81
-
82
-/**
83
- * Callback Print
84
- *
85
- * Set callback print case necesary and wrinte an information inside a buffer to write in the log.
86
- *
87
- * @param e a pointer for a structure that has the complete information about json structure.
88
- *
89
- * @return It always return 0
90
- */
91
-int json_callback_print(JSON_ENTRY *e)
92
-{
93
- BUFFER *wb=buffer_create(300);
94
-
95
- buffer_sprintf(wb,"%s = ", e->name);
96
- char txt[50];
97
- switch(e->type) {
98
- case JSON_OBJECT:
99
- e->callback_function = json_callback_print;
100
- buffer_strcat(wb,"OBJECT");
101
- break;
102
-
103
- case JSON_ARRAY:
104
- e->callback_function = json_callback_print;
105
- sprintf(txt,"ARRAY[%lu]", e->data.items);
106
- buffer_strcat(wb, txt);
107
- break;
108
-
109
- case JSON_STRING:
110
- buffer_strcat(wb, e->data.string);
111
- break;
112
-
113
- case JSON_NUMBER:
114
- sprintf(txt,"%Lf", e->data.number);
115
- buffer_strcat(wb,txt);
116
-
117
- break;
118
-
119
- case JSON_BOOLEAN:
120
- buffer_strcat(wb, e->data.boolean?"TRUE":"FALSE");
121
- break;
122
-
123
- case JSON_NULL:
124
- buffer_strcat(wb,"NULL");
125
- break;
126
- }
127
- info("JSON: %s", buffer_tostring(wb));
128
- buffer_free(wb);
129
- return 0;
130
-}
131
-
132
-/**
133
- * JSONC Set String
134
- *
135
- * Set the string value of the structure JSON_ENTRY.
136
- *
137
- * @param e the output structure
138
- */
139
-static inline void json_jsonc_set_string(JSON_ENTRY *e,char *key,const char *value) {
140
- size_t length = strlen(key);
141
- e->type = JSON_STRING;
142
- memcpy(e->name,key,length);
143
- e->name[length] = 0x00;
144
- e->data.string = (char *) value;
145
-}
146
-
147
-
148
-#ifdef ENABLE_JSONC
149
-/**
150
- * JSONC set Boolean
151
- *
152
- * Set the boolean value of the structure JSON_ENTRY
153
- *
154
- * @param e the output structure
155
- * @param value the input value
156
- */
157
-static inline void json_jsonc_set_boolean(JSON_ENTRY *e,int value) {
158
- e->type = JSON_BOOLEAN;
159
- e->data.boolean = value;
160
-}
161
-
162
-/**
163
- * Parse Array
164
- *
165
- * Parse the array object.
166
- *
167
- * @param ptr the pointer for the object that we will parse.
168
- * @param callback_data additional data to be used together the callback function
169
- * @param callback_function function used to create a silencer.
170
- */
171
-static inline void json_jsonc_parse_array(json_object *ptr, void *callback_data,int (*callback_function)(struct json_entry *)) {
172
- int end = json_object_array_length(ptr);
173
- JSON_ENTRY e;
174
-
175
- if(end) {
176
- int i;
177
- i = 0;
178
-
179
- enum json_type type;
180
- do {
181
- json_object *jvalue = json_object_array_get_idx(ptr, i);
182
- if(jvalue) {
183
- e.callback_data = callback_data;
184
- e.type = JSON_OBJECT;
185
- callback_function(&e);
186
- json_object_object_foreach(jvalue, key, val) {
187
- type = json_object_get_type(val);
188
- if (type == json_type_array) {
189
- e.type = JSON_ARRAY;
190
- json_jsonc_parse_array(val, callback_data, callback_function);
191
- } else if (type == json_type_object) {
192
- json_walk(val,callback_data,callback_function);
193
- } else if (type == json_type_string) {
194
- json_jsonc_set_string(&e,key,json_object_get_string(val));
195
- callback_function(&e);
196
- } else if (type == json_type_boolean) {
197
- json_jsonc_set_boolean(&e,json_object_get_boolean(val));
198
- callback_function(&e);
199
- }
200
- }
201
- }
202
-
203
- } while (++i < end);
204
- }
205
-}
206
-#else
207
-
208
-/**
209
- * Walk string
210
- *
211
- * Set JSON_ENTRY to string and map the values from jsmntok_t.
212
- *
213
- * @param js the original string
214
- * @param t the tokens
215
- * @param start the first position
216
- * @param e the output structure.
217
- *
218
- * @return It always return 1
219
- */
220
-size_t json_walk_string(char *js, jsmntok_t *t, size_t start, JSON_ENTRY *e)
221
-{
222
- char old = js[t[start].end];
223
- js[t[start].end] = '\0';
224
- e->original_string = &js[t[start].start];
225
-
226
- e->type = JSON_STRING;
227
- e->data.string = e->original_string;
228
- if(e->callback_function) e->callback_function(e);
229
- js[t[start].end] = old;
230
- return 1;
231
-}
232
-
233
-/**
234
- * Walk Primitive
235
- *
236
- * Define the data type of the string
237
- *
238
- * @param js the original string
239
- * @param t the tokens
240
- * @param start the first position
241
- * @param e the output structure.
242
- *
243
- * @return It always return 1
244
- */
245
-size_t json_walk_primitive(char *js, jsmntok_t *t, size_t start, JSON_ENTRY *e)
246
-{
247
- char old = js[t[start].end];
248
- js[t[start].end] = '\0';
249
- e->original_string = &js[t[start].start];
250
-
251
- switch(e->original_string[0]) {
252
- case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7':
253
- case '8': case '9': case '-': case '.':
254
- e->type = JSON_NUMBER;
255
- e->data.number = strtold(e->original_string, NULL);
256
- break;
257
-
258
- case 't': case 'T':
259
- e->type = JSON_BOOLEAN;
260
- e->data.boolean = 1;
261
- break;
262
-
263
- case 'f': case 'F':
264
- e->type = JSON_BOOLEAN;
265
- e->data.boolean = 0;
266
- break;
267
-
268
- case 'n': case 'N':
269
- default:
270
- e->type = JSON_NULL;
271
- break;
272
- }
273
- if(e->callback_function) e->callback_function(e);
274
- js[t[start].end] = old;
275
- return 1;
276
-}
277
-
278
-/**
279
- * Array
280
- *
281
- * Measure the array length
282
- *
283
- * @param js the original string
284
- * @param t the tokens
285
- * @param nest the length of structure t
286
- * @param start the first position
287
- * @param e the output structure.
288
- *
289
- * @return It returns the array length
290
- */
291
-size_t json_walk_array(char *js, jsmntok_t *t, size_t nest, size_t start, JSON_ENTRY *e)
292
-{
293
- JSON_ENTRY ne = {
294
- .name = "",
295
- .fullname = "",
296
- .callback_data = NULL,
297
- .callback_function = NULL
298
- };
299
-
300
- char old = js[t[start].end];
301
- js[t[start].end] = '\0';
302
- ne.original_string = &js[t[start].start];
303
-
304
- memcpy(&ne, e, sizeof(JSON_ENTRY));
305
- ne.type = JSON_ARRAY;
306
- ne.data.items = t[start].size;
307
- ne.callback_function = NULL;
308
- ne.name[0]='\0';
309
- ne.fullname[0]='\0';
310
- if(e->callback_function) e->callback_function(&ne);
311
- js[t[start].end] = old;
312
-
313
- size_t i, init = start, size = t[start].size;
314
-
315
- start++;
316
- for(i = 0; i < size ; i++) {
317
- ne.pos = i;
318
- if (!e->name || !e->fullname || strlen(e->name) > JSON_NAME_LEN - 24 || strlen(e->fullname) > JSON_FULLNAME_LEN -24) {
319
- info("JSON: JSON walk_array ignoring element with name:%s fullname:%s",e->name, e->fullname);
320
- continue;
321
- }
322
- sprintf(ne.name, "%s[%lu]", e->name, i);
323
- sprintf(ne.fullname, "%s[%lu]", e->fullname, i);
324
-
325
- switch(t[start].type) {
326
- case JSMN_PRIMITIVE:
327
- start += json_walk_primitive(js, t, start, &ne);
328
- break;
329
-
330
- case JSMN_OBJECT:
331
- start += json_walk_object(js, t, nest + 1, start, &ne);
332
- break;
333
-
334
- case JSMN_ARRAY:
335
- start += json_walk_array(js, t, nest + 1, start, &ne);
336
- break;
337
-
338
- case JSMN_STRING:
339
- start += json_walk_string(js, t, start, &ne);
340
- break;
341
- }
342
- }
343
- return start - init;
344
-}
345
-
346
-/**
347
- * Object
348
- *
349
- * Measure the Object length
350
- *
351
- * @param js the original string
352
- * @param t the tokens
353
- * @param nest the length of structure t
354
- * @param start the first position
355
- * @param e the output structure.
356
- *
357
- * @return It returns the Object length
358
- */
359
-size_t json_walk_object(char *js, jsmntok_t *t, size_t nest, size_t start, JSON_ENTRY *e)
360
-{
361
- JSON_ENTRY ne = {
362
- .name = "",
363
- .fullname = "",
364
- .callback_data = NULL,
365
- .callback_function = NULL
366
- };
367
-
368
- char old = js[t[start].end];
369
- js[t[start].end] = '\0';
370
- ne.original_string = &js[t[start].start];
371
- memcpy(&ne, e, sizeof(JSON_ENTRY));
372
- ne.type = JSON_OBJECT;
373
- ne.callback_function = NULL;
374
- if(e->callback_function) e->callback_function(&ne);
375
- js[t[start].end] = old;
376
-
377
- int key = 1;
378
- size_t i, init = start, size = t[start].size;
379
-
380
- start++;
381
- for(i = 0; i < size ; i++) {
382
- switch(t[start].type) {
383
- case JSMN_PRIMITIVE:
384
- start += json_walk_primitive(js, t, start, &ne);
385
- key = 1;
386
- break;
387
-
388
- case JSMN_OBJECT:
389
- start += json_walk_object(js, t, nest + 1, start, &ne);
390
- key = 1;
391
- break;
392
-
393
- case JSMN_ARRAY:
394
- start += json_walk_array(js, t, nest + 1, start, &ne);
395
- key = 1;
396
- break;
397
-
398
- case JSMN_STRING:
399
- default:
400
- if(key) {
401
- int len = t[start].end - t[start].start;
402
- if (unlikely(len>JSON_NAME_LEN)) len=JSON_NAME_LEN;
403
- strncpy(ne.name, &js[t[start].start], len);
404
- ne.name[len] = '\0';
405
- len=strlen(e->fullname) + strlen(e->fullname[0]?".":"") + strlen(ne.name);
406
- char *c = mallocz((len+1)*sizeof(char));
407
- sprintf(c,"%s%s%s", e->fullname, e->fullname[0]?".":"", ne.name);
408
- if (unlikely(len>JSON_FULLNAME_LEN)) len=JSON_FULLNAME_LEN;
409
- strncpy(ne.fullname, c, len);
410
- freez(c);
411
- start++;
412
- key = 0;
413
- }
414
- else {
415
- start += json_walk_string(js, t, start, &ne);
416
- key = 1;
417
- }
418
- break;
419
- }
420
- }
421
- return start - init;
422
-}
423
-#endif
424
-
425
-/**
426
- * Tree
427
- *
428
- * Call the correct walk function according its type.
429
- *
430
- * @param t the json object to work
431
- * @param callback_data additional data to be used together the callback function
432
- * @param callback_function function used to create a silencer.
433
- *
434
- * @return It always return 1
435
- */
436
-#ifdef ENABLE_JSONC
437
-size_t json_walk(json_object *t, void *callback_data, int (*callback_function)(struct json_entry *)) {
438
- JSON_ENTRY e;
439
-
440
- e.callback_data = callback_data;
441
- enum json_type type;
442
- json_object_object_foreach(t, key, val) {
443
- type = json_object_get_type(val);
444
- if (type == json_type_array) {
445
- e.type = JSON_ARRAY;
446
- json_jsonc_parse_array(val,NULL,health_silencers_json_read_callback);
447
- } else if (type == json_type_object) {
448
- e.type = JSON_OBJECT;
449
- } else if (type == json_type_string) {
450
- json_jsonc_set_string(&e,key,json_object_get_string(val));
451
- callback_function(&e);
452
- } else if (type == json_type_boolean) {
453
- json_jsonc_set_boolean(&e,json_object_get_boolean(val));
454
- callback_function(&e);
455
- }
456
- }
457
-
458
- return 1;
459
-}
460
-#else
461
-/**
462
- * Tree
463
- *
464
- * Call the correct walk function according its type.
465
- *
466
- * @param js the original string
467
- * @param t the tokens
468
- * @param callback_data additional data to be used together the callback function
469
- * @param callback_function function used to create a silencer.
470
- *
471
- * @return It always return 1
472
- */
473
-size_t json_walk_tree(char *js, jsmntok_t *t, void *callback_data, int (*callback_function)(struct json_entry *))
474
-{
475
- JSON_ENTRY e = {
476
- .name = "",
477
- .fullname = "",
478
- .callback_data = callback_data,
479
- .callback_function = callback_function
480
- };
481
-
482
- switch (t[0].type) {
483
- case JSMN_OBJECT:
484
- e.type = JSON_OBJECT;
485
- json_walk_object(js, t, 0, 0, &e);
486
- break;
487
-
488
- case JSMN_ARRAY:
489
- e.type = JSON_ARRAY;
490
- json_walk_array(js, t, 0, 0, &e);
491
- break;
492
-
493
- case JSMN_PRIMITIVE:
494
- case JSMN_STRING:
495
- break;
496
- }
497
-
498
- return 1;
499
-}
500
-#endif
501
-
502
-/**
503
- * JSON Parse
504
- *
505
- * Parse the json message with the callback function
506
- *
507
- * @param js the string that the callback function will parse
508
- * @param callback_data additional data to be used together the callback function
509
- * @param callback_function function used to create a silencer.
510
- *
511
- * @return JSON_OK case everything happend as expected, JSON_CANNOT_PARSE case there were errors in the
512
- * parsing procces and JSON_CANNOT_DOWNLOAD case the string given(js) is NULL.
513
- */
514
-int json_parse(char *js, void *callback_data, int (*callback_function)(JSON_ENTRY *))
515
-{
516
- if(js) {
517
-#ifdef ENABLE_JSONC
518
- json_object *tokens = json_tokenise(js);
519
-#else
520
- size_t count;
521
- jsmntok_t *tokens = json_tokenise(js, strlen(js), &count);
522
-#endif
523
-
524
- if(tokens) {
525
-#ifdef ENABLE_JSONC
526
- json_walk(tokens, callback_data, callback_function);
527
- json_object_put(tokens);
528
-#else
529
- json_walk_tree(js, tokens, callback_data, callback_function);
530
- freez(tokens);
531
-#endif
532
- return JSON_OK;
533
- }
534
-
535
- return JSON_CANNOT_PARSE;
536
- }
537
-
538
- return JSON_CANNOT_DOWNLOAD;
539
-}
540
-
541
-/*
542
-int json_test(char *str)
543
-{
544
- return json_parse(str, NULL, json_callback_print);
545
-}
546
- */
\ No newline at end of file
libnetdata/json/json.h
deleted
-72
@@ -1,72 +0,0 @@
1
-#ifndef CHECKIN_JSON_H
2
-#define CHECKIN_JSON_H 1
3
-
4
-
5
-#if ENABLE_JSONC
6
-# include <json-c/json.h>
7
-#endif
8
-
9
-#include "jsmn.h"
10
-
11
-//https://www.ibm.com/support/knowledgecenter/en/SS9H2Y_7.6.0/com.ibm.dp.doc/json_parserlimits.html
12
-#define JSON_NAME_LEN 256
13
-#define JSON_FULLNAME_LEN 1024
14
-
15
-typedef enum {
16
- JSON_OBJECT = 0,
17
- JSON_ARRAY = 1,
18
- JSON_STRING = 2,
19
- JSON_NUMBER = 3,
20
- JSON_BOOLEAN = 4,
21
- JSON_NULL = 5,
22
-} JSON_ENTRY_TYPE;
23
-
24
-typedef struct json_entry {
25
- JSON_ENTRY_TYPE type;
26
- char name[JSON_NAME_LEN + 1];
27
- char fullname[JSON_FULLNAME_LEN + 1];
28
- union {
29
- char *string; // type == JSON_STRING
30
- long double number; // type == JSON_NUMBER
31
- int boolean; // type == JSON_BOOLEAN
32
- size_t items; // type == JSON_ARRAY
33
- } data;
34
- size_t pos; // the position of this item in its parent
35
-
36
- char *original_string;
37
-
38
- void *callback_data;
39
- int (*callback_function)(struct json_entry *);
40
-} JSON_ENTRY;
41
-
42
-// ----------------------------------------------------------------------------
43
-// public functions
44
-
45
-#define JSON_OK 0
46
-#define JSON_CANNOT_DOWNLOAD 1
47
-#define JSON_CANNOT_PARSE 2
48
-
49
-int json_parse(char *js, void *callback_data, int (*callback_function)(JSON_ENTRY *));
50
-
51
-
52
-// ----------------------------------------------------------------------------
53
-// private functions
54
-
55
-#ifdef ENABLE_JSONC
56
-json_object *json_tokenise(char *js);
57
-size_t json_walk(json_object *t, void *callback_data, int (*callback_function)(struct json_entry *));
58
-#else
59
-jsmntok_t *json_tokenise(char *js, size_t len, size_t *count);
60
-size_t json_walk_tree(char *js, jsmntok_t *t, void *callback_data, int (*callback_function)(struct json_entry *));
61
-#endif
62
-
63
-size_t json_walk_object(char *js, jsmntok_t *t, size_t nest, size_t start, JSON_ENTRY *e);
64
-size_t json_walk_array(char *js, jsmntok_t *t, size_t nest, size_t start, JSON_ENTRY *e);
65
-size_t json_walk_string(char *js, jsmntok_t *t, size_t start, JSON_ENTRY *e);
66
-size_t json_walk_primitive(char *js, jsmntok_t *t, size_t start, JSON_ENTRY *e);
67
-
68
-int json_callback_print(JSON_ENTRY *e);
69
-
70
-
71
-
72
-#endif
\ No newline at end of file
libnetdata/libnetdata.h
-2
@@ -310,7 +310,5 @@ extern char *netdata_configured_host_prefix;
310
#include "statistical/statistical.h"
311
#include "adaptive_resortable_list/adaptive_resortable_list.h"
312
#include "url/url.h"
313
-#include "json/json.h"
314
-#include "health/health.h"
313
314
#endif // NETDATA_LIB_H
netdata-installer.sh
-2
@@ -175,7 +175,6 @@ USAGE: ${PROGRAM} [options]
175
--libs-are-really-here If you get errors about missing zlib or libuuid but you know it is available, you might
176
have a broken pkg-config. Use this option to proceed without checking pkg-config.
177
--disable-telemetry Use this flag to opt-out from our anonymous telemetry progam.
178
- --enable-json Enable to use JSON-C library instead the internal Netdata library.
178
179
Netdata will by default be compiled with gcc optimization -O2
180
If you need to pass different CFLAGS, use something like this:
@@ -223,7 +222,6 @@ while [ -n "${1}" ]; do
222
"--disable-x86-sse") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--disable-x86-sse/} --disable-x86-sse";;
223
"--disable-telemetry") NETDATA_DISABLE_TELEMETRY=1;;
224
"--disable-go") NETDATA_DISABLE_GO=1;;
226
- "--enable-jsonc") NETDATA_CONFIGURE_OPTIONS="${NETDATA_CONFIGURE_OPTIONS//--enable-jsonc/} --enable-jsonc";;
225
"--install")
226
NETDATA_PREFIX="${2}/netdata"
227
shift 1
tests/health_mgmtapi/expected_list/ALARM_CPU_IOWAIT-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "alarm": "*10min_cpu_iowait" }, { "alarm": "*10min_cpu_usage *load_trigger" } ] }
tests/health_mgmtapi/expected_list/ALARM_CPU_USAGE-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "alarm": "*10min_cpu_usage *load_trigger", "context": "system.cpu" }, { "alarm": "*10min_cpu_usage *load_trigger", "chart": "system.load" } ] }
tests/health_mgmtapi/expected_list/CONTEXT_SYSTEM_CPU-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "DISABLE", "silencers": [ { "context": "system.cpu" }, { "chart": "system.load" } ] }
tests/health_mgmtapi/expected_list/DISABLE-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "DISABLE", "silencers": [ { "alarm": "*10min_cpu_usage *load_trigger" } ] }
tests/health_mgmtapi/expected_list/DISABLE_ALL-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": true, "type": "DISABLE", "silencers": [] }
tests/health_mgmtapi/expected_list/DISABLE_ALL_ERROR-list.json
deleted
-1
@@ -1 +0,0 @@
1
-Auth Error
tests/health_mgmtapi/expected_list/DISABLE_SYSTEM_LOAD-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "DISABLE", "silencers": [ { "chart": "system.load" } ] }
tests/health_mgmtapi/expected_list/FAMILIES_LOAD-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "None", "silencers": [ { "families": "load" } ] }
tests/health_mgmtapi/expected_list/HOSTS-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "hosts": "*" } ] }
tests/health_mgmtapi/expected_list/RESET-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "None", "silencers": [] }
tests/health_mgmtapi/expected_list/SILENCE-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "alarm": "*10min_cpu_usage *load_trigger" } ] }
tests/health_mgmtapi/expected_list/SILENCE_2-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "families": "load" } ] }
tests/health_mgmtapi/expected_list/SILENCE_3-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [] } WARNING: SILENCE or DISABLE command is ineffective without defining any alarm selectors.
tests/health_mgmtapi/expected_list/SILENCE_ALARM_CPU_USAGE-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "alarm": "*10min_cpu_usage *load_trigger", "chart": "system.load" } ] }
tests/health_mgmtapi/expected_list/SILENCE_ALARM_CPU_USAGE_LOAD_TRIGGER-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": false, "type": "SILENCE", "silencers": [ { "alarm": "*10min_cpu_usage *load_trigger" } ] }
tests/health_mgmtapi/expected_list/SILENCE_ALL-list.json
deleted
-1
@@ -1 +0,0 @@
1
-{ "all": true, "type": "SILENCE", "silencers": [] }
tests/health_mgmtapi/health-cmdapi-test.sh.in
+2
-38
@@ -27,7 +27,7 @@ check () {
27
elif [ "${r}" != "${2}" ] ; then
28
echo -e " ${GRAY}WARNING: 'Got ${r}'. Expected '${2}'"
29
iter=$((iter+1))
30
- if [ $iter -lt 10 ] ; then
30
+ if [ $iter -lt 10 ] ; then
31
echo -e " ${GRAY}Repeating test "
32
check "$1" "$2"
33
else
@@ -53,20 +53,6 @@ cmd () {
53
fi
54
}
55
56
-check_list() {
57
- RESPONSE=$(curl -s "http://$URL/api/v1/manage/health?cmd=LIST" -H "X-Auth-Token: $TOKEN" 2>&1)
58
-
59
- NAME="$1-list.json"
60
- echo $RESPONSE > $NAME
61
- diff $NAME expected_list/$NAME 1>/dev/null 2>&1
62
- if [ $? -eq 0 ]; then
63
- echo -e "${GREEN}Success: The list command got the correct answer for $NAME!"
64
- else
65
- echo -e "${RED}ERROR: the files $NAME and expected_list/$NAME does not match."
66
- exit 1
67
- fi
68
-}
69
-
56
WHITE='\033[0;37m'
57
RED='\033[0;31m'
58
GREEN='\033[0;32m'
@@ -104,13 +90,11 @@ err=0
90
# Test default state
91
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
92
check "Default State" "False False False False False False"
107
- check_list "RESET"
93
94
# Test auth failure
95
TOKEN="Wrong token"
96
cmd "cmd=DISABLE ALL" "$HEALTH_CMDAPI_MSG_AUTHERROR"
97
check "Default State" "False False False False False False"
113
- check_list "DISABLE_ALL_ERROR"
98
99
# Set correct token
100
TOKEN="${CORRECT_TOKEN}"
@@ -118,107 +102,87 @@ err=0
102
# Test disable
103
cmd "cmd=DISABLE ALL" "$HEALTH_CMDAPI_MSG_DISABLEALL"
104
check "All disabled" "True False True False True False"
121
- check_list "DISABLE_ALL"
105
106
# Reset
107
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
108
check "Default State" "False False False False False False"
126
- check_list "RESET"
109
110
# Test silence
111
cmd "cmd=SILENCE ALL" "$HEALTH_CMDAPI_MSG_SILENCEALL"
112
check "All silenced" "False True False True False True"
131
- check_list "SILENCE_ALL"
113
114
# Reset
115
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
116
check "Default State" "False False False False False False"
136
- check_list "RESET"
117
118
# Add silencer by name
119
printf -v resp "$HEALTH_CMDAPI_MSG_SILENCE\n$HEALTH_CMDAPI_MSG_ADDED"
120
cmd "cmd=SILENCE&alarm=*10min_cpu_usage *load_trigger" "${resp}"
121
check "Silence notifications for alarm1 and load_trigger" "False True False False False True"
142
- check_list "SILENCE_ALARM_CPU_USAGE_LOAD_TRIGGER"
122
123
# Convert to disable health checks
124
cmd "cmd=DISABLE" "$HEALTH_CMDAPI_MSG_DISABLE"
125
check "Disable notifications for alarm1 and load_trigger" "True False False False True False"
147
- check_list "DISABLE"
126
127
# Convert back to silence notifications
128
cmd "cmd=SILENCE" "$HEALTH_CMDAPI_MSG_SILENCE"
129
check "Silence notifications for alarm1 and load_trigger" "False True False False False True"
152
- check_list "SILENCE"
130
131
# Add second silencer by name
132
cmd "alarm=*10min_cpu_iowait" "$HEALTH_CMDAPI_MSG_ADDED"
133
check "Silence notifications for alarm1,alarm2 and load_trigger" "False True False True False True"
157
- check_list "ALARM_CPU_IOWAIT"
134
135
# Reset
136
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
161
- check_list "RESET"
137
138
# Add silencer by chart
139
printf -v resp "$HEALTH_CMDAPI_MSG_DISABLE\n$HEALTH_CMDAPI_MSG_ADDED"
140
cmd "cmd=DISABLE&chart=system.load" "${resp}"
141
check "Default State" "False False False False True False"
167
- check_list "DISABLE_SYSTEM_LOAD"
142
143
# Add silencer by context
144
cmd "context=system.cpu" "$HEALTH_CMDAPI_MSG_ADDED"
145
check "Default State" "True False True False True False"
172
- check_list "CONTEXT_SYSTEM_CPU"
146
147
# Reset
148
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
176
- check_list "RESET"
149
150
# Add second condition to a selector (AND)
151
printf -v resp "$HEALTH_CMDAPI_MSG_SILENCE\n$HEALTH_CMDAPI_MSG_ADDED"
152
cmd "cmd=SILENCE&alarm=*10min_cpu_usage *load_trigger&chart=system.load" "${resp}"
153
check "Silence notifications load_trigger" "False False False False False True"
182
- check_list "SILENCE_ALARM_CPU_USAGE"
154
155
# Add second selector with two conditions
156
cmd "alarm=*10min_cpu_usage *load_trigger&context=system.cpu" "$HEALTH_CMDAPI_MSG_ADDED"
157
check "Silence notifications load_trigger" "False True False False False True"
187
- check_list "ALARM_CPU_USAGE"
158
159
# Reset
160
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
191
- check_list "RESET"
161
162
# Add silencer without a command to disable or silence alarms
163
printf -v resp "$HEALTH_CMDAPI_MSG_ADDED\n$HEALTH_CMDAPI_MSG_STYPEWARNING"
164
cmd "families=load" "${resp}"
165
check "Family selector with no command" "False False False False False False"
197
- check_list "FAMILIES_LOAD"
166
167
# Add silence command
168
cmd "cmd=SILENCE" "$HEALTH_CMDAPI_MSG_SILENCE"
169
check "Silence family load" "False False False False False True"
202
- check_list "SILENCE_2"
170
171
# Reset
172
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
206
- check_list "RESET"
173
174
# Add command without silencers
175
printf -v resp "$HEALTH_CMDAPI_MSG_SILENCE\n$HEALTH_CMDAPI_MSG_NOSELECTORWARNING"
176
cmd "cmd=SILENCE" "${resp}"
177
check "Command with no selector" "False False False False False False"
212
- check_list "SILENCE_3"
178
179
# Add hosts silencer
180
cmd "hosts=*" "$HEALTH_CMDAPI_MSG_ADDED"
181
check "Silence all hosts" "False True False True False True"
217
- check_list "HOSTS"
182
183
# Reset
184
cmd "cmd=RESET" "$HEALTH_CMDAPI_MSG_RESET"
221
- check_list "RESET"
185
+
186
187
if [ $err -gt 0 ] ; then
188
echo "$err error(s) found"
web/api/health/README.md
+1
-50
@@ -45,7 +45,6 @@ The following will return an SVG badge of the alarm named `NAME`, attached to th
45
## Health Management API
46
47
Netdata v1.12 and beyond provides a command API to control health checks and notifications at runtime. The feature is especially useful for maintenance periods, during which you receive meaningless alarms.
48
-From Netdata v1.16.0 and beyond, the configuration controlled via the API commands is [persisted across netdata restarts](#persistence).
48
49
Specifically, the API allows you to:
50
- Disable health checks completely. Alarm conditions will not be evaluated at all and no entries will be added to the alarm log.
@@ -143,43 +142,6 @@ Example 2.2: Add one more selector, to also silence alarms for cpu1 and cpu2
142
http://localhost/api/v1/manage/health?families=cpu1 cpu2
143
```
144
146
-### List silencers
147
-
148
-The command `LIST` was added in netdata v1.16.0 and returns a JSON with the current status of the silencers.
149
-
150
-```
151
- curl "http://myserver/api/v1/manage/health?cmd=LIST" -H "X-Auth-Token: Mytoken"
152
-```
153
-
154
-As an example, the following response shows that we have two silencers configured, one for an alarm called `samplealarm` and one for alarms with context `random` on host `myhost`
155
-```
156
-json
157
-{
158
- "all": false,
159
- "type": "SILENCE",
160
- "silencers": [
161
- {
162
- "alarm": "samplealarm"
163
- },
164
- {
165
- "context": "random",
166
- "hosts": "myhost"
167
- }
168
- ]
169
-}
170
-```
171
-
172
-The response below shows that we have disabled all health checks.
173
-
174
-```
175
-json
176
-{
177
- "all": true,
178
- "type": "DISABLE",
179
- "silencers": []
180
-}
181
-```
182
-
145
### Responses
146
147
- "Auth Error" : Token authentication failed
@@ -189,21 +151,10 @@ json
151
- "Health checks disabled for alarms matching the selectors" : Added to the response for a cmd=DISABLE
152
- "Alarm notifications silenced for alarms matching the selectors" : Added to the response for a cmd=SILENCE
153
- "Alarm selector added" : Added to the response when a new selector is added
154
+- "Invalid key. Ignoring it." : Wrong name of a parameter. Added to the response and ignored.
155
- "WARNING: Added alarm selector to silence/disable alarms without a SILENCE or DISABLE command." : Added to the response if a selector is added without a selector-specific command.
156
- "WARNING: SILENCE or DISABLE command is ineffective without defining any alarm selectors." : Added to the response if a selector-specific command is issued without a selector.
157
195
-### Persistence
196
-
197
-From netdata v1.13.1 and beyond, the silencers configuration is persisted to disk and loaded when netdata starts.
198
-The JSON string returned by the [LIST command](#list-silencers) is automatically saved to the `silencers file`, every time a command alters the silencers configuration.
199
-The file's location is configurable in `netdata.conf`. The default is shown below:
200
-
201
-```
202
-[health]
203
- # silencers file = /var/lib/netdata/health.silencers.json
204
-```
205
-
206
-
158
### Further reading
159
160
The test script under [tests/health_mgmtapi](../../../tests/health_mgmtapi) contains a series of tests that you can either run or read through to understand the various calls and responses better.
web/api/health/health_cmdapi.c
+67
-107
@@ -1,16 +1,17 @@
1
//
2
-// Created by Christopher on 11/12/18.
2
+// Created by christopher on 11/12/18.
3
//
4
5
#include "health_cmdapi.h"
6
7
-/**
8
- * Free Silencers
9
- *
10
- * Clean the silencer structure
11
- *
12
- * @param t is the structure that will be cleaned.
13
- */
7
+
8
+static SILENCER *create_silencer(void) {
9
+ SILENCER *t = callocz(1, sizeof(SILENCER));
10
+ debug(D_HEALTH, "HEALTH command API: Created empty silencer");
11
+
12
+ return t;
13
+}
14
+
15
void free_silencers(SILENCER *t) {
16
if (!t) return;
17
if (t->next) free_silencers(t->next);
@@ -30,104 +31,38 @@ void free_silencers(SILENCER *t) {
31
return;
32
}
33
33
-/**
34
- * Silencers to JSON Entry
35
- *
36
- * Fill the buffer with the other values given.
37
- *
38
- * @param wb a pointer to the output buffer
39
- * @param var the json variable
40
- * @param val the json value
41
- * @param hasprev has it a previous value?
42
- *
43
- * @return
44
- */
45
-int health_silencers2json_entry(BUFFER *wb, char* var, char* val, int hasprev) {
46
- if (val) {
47
- buffer_sprintf(wb, "%s\n\t\t\t\"%s\": \"%s\"", (hasprev)?",":"", var, val);
48
- return 1;
49
- } else {
50
- return hasprev;
51
- }
52
-}
34
54
-/**
55
- * Silencer to JSON
56
- *
57
- * Write the silencer values using JSON format inside a buffer.
58
- *
59
- * @param wb is the buffer to write the silencers.
60
- */
61
-void health_silencers2json(BUFFER *wb) {
62
- buffer_sprintf(wb, "{\n\t\"all\": %s,"
63
- "\n\t\"type\": \"%s\","
64
- "\n\t\"silencers\": [",
65
- (silencers->all_alarms)?"true":"false",
66
- (silencers->stype == STYPE_NONE)?"None":((silencers->stype == STYPE_DISABLE_ALARMS)?"DISABLE":"SILENCE"));
67
-
68
- SILENCER *silencer;
69
- int i = 0, j = 0;
70
- for(silencer = silencers->silencers; silencer ; silencer = silencer->next) {
71
- if(likely(i)) buffer_strcat(wb, ",");
72
- buffer_strcat(wb, "\n\t\t{");
73
- j=health_silencers2json_entry(wb, HEALTH_ALARM_KEY, silencer->alarms, j);
74
- j=health_silencers2json_entry(wb, HEALTH_CHART_KEY, silencer->charts, j);
75
- j=health_silencers2json_entry(wb, HEALTH_CONTEXT_KEY, silencer->contexts, j);
76
- j=health_silencers2json_entry(wb, HEALTH_HOST_KEY, silencer->hosts, j);
77
- health_silencers2json_entry(wb, HEALTH_FAMILIES_KEY, silencer->families, j);
78
- j=0;
79
- buffer_strcat(wb, "\n\t\t}");
80
- i++;
81
- }
82
- if(likely(i)) buffer_strcat(wb, "\n\t");
83
- buffer_strcat(wb, "]\n}\n");
84
-}
35
86
-/**
87
- * Silencer to FILE
88
- *
89
- * Write the sliencer buffer to a file.
90
- * @param wb
91
- */
92
-void health_silencers2file(BUFFER *wb) {
93
- if (wb->len == 0) return;
94
-
95
- FILE *fd = fopen(silencers_filename, "wb");
96
- if(fd) {
97
- size_t written = (size_t)fprintf(fd, "%s", wb->buffer) ;
98
- if (written == wb->len ) {
99
- info("Silencer changes written to %s", silencers_filename);
100
- }
101
- fclose(fd);
102
- return;
103
- }
104
- error("Silencer changes could not be written to %s. Error %s", silencers_filename, strerror(errno));
105
-}
106
-
107
-/**
108
- * Request V1 MGMT Health
109
- *
110
- * Function called by api to management the health.
111
- *
112
- * @param host main structure with client information!
113
- * @param w is the structure with all information of the client request.
114
- * @param url is the url that netdata is working
115
- *
116
- * @return It returns 200 on success and another code otherwise.
117
- */
36
int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, char *url) {
37
int ret = 400;
38
(void) host;
39
40
+
41
+
42
BUFFER *wb = w->response.data;
43
buffer_flush(wb);
44
wb->contenttype = CT_TEXT_PLAIN;
45
46
buffer_flush(w->response.data);
47
128
- //Local instance of the silencer
48
+ static uint32_t
49
+ hash_alarm = 0,
50
+ hash_template = 0,
51
+ hash_chart = 0,
52
+ hash_context = 0,
53
+ hash_host = 0,
54
+ hash_families = 0;
55
+
56
+ if (unlikely(!hash_alarm)) {
57
+ hash_alarm = simple_uhash(HEALTH_ALARM_KEY);
58
+ hash_template = simple_uhash(HEALTH_TEMPLATE_KEY);
59
+ hash_chart = simple_uhash(HEALTH_CHART_KEY);
60
+ hash_context = simple_uhash(HEALTH_CONTEXT_KEY);
61
+ hash_host = simple_uhash(HEALTH_HOST_KEY);
62
+ hash_families = simple_uhash(HEALTH_FAMILIES_KEY);
63
+ }
64
+
65
SILENCER *silencer = NULL;
130
- int config_changed = 1;
66
67
if (!w->auth_bearer_token) {
68
buffer_strcat(wb, HEALTH_CMDAPI_MSG_AUTHERROR);
@@ -150,7 +85,6 @@ int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, c
85
86
// name and value are now the parameters
87
if (!strcmp(key, "cmd")) {
153
- //In this "if" we are working with the global silencers.
88
if (!strcmp(value, HEALTH_CMDAPI_CMD_SILENCEALL)) {
89
silencers->all_alarms = 1;
90
silencers->stype = STYPE_SILENCE_NOTIFICATIONS;
@@ -171,19 +105,50 @@ int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, c
105
free_silencers(silencers->silencers);
106
silencers->silencers = NULL;
107
buffer_strcat(wb, HEALTH_CMDAPI_MSG_RESET);
174
- } else if (!strcmp(value, HEALTH_CMDAPI_CMD_LIST)) {
175
- w->response.data->contenttype = CT_APPLICATION_JSON;
176
- health_silencers2json(wb);
177
- config_changed=0;
108
}
109
} else {
180
- //In this else we work with local silencer
181
- silencer = health_silencers_addparam(silencer,key,value);
110
+ uint32_t hash = simple_uhash(key);
111
+ if (unlikely(silencer == NULL)) {
112
+ if (
113
+ (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) ||
114
+ (hash == hash_template && !strcasecmp(key, HEALTH_TEMPLATE_KEY)) ||
115
+ (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) ||
116
+ (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) ||
117
+ (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) ||
118
+ (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY))
119
+ ) {
120
+ silencer = create_silencer();
121
+ }
122
+ }
123
+
124
+ if (hash == hash_alarm && !strcasecmp(key, HEALTH_ALARM_KEY)) {
125
+ silencer->alarms = strdupz(value);
126
+ silencer->alarms_pattern = simple_pattern_create(silencer->alarms, NULL, SIMPLE_PATTERN_EXACT);
127
+ } else if (hash == hash_chart && !strcasecmp(key, HEALTH_CHART_KEY)) {
128
+ silencer->charts = strdupz(value);
129
+ silencer->charts_pattern = simple_pattern_create(silencer->charts, NULL, SIMPLE_PATTERN_EXACT);
130
+ } else if (hash == hash_context && !strcasecmp(key, HEALTH_CONTEXT_KEY)) {
131
+ silencer->contexts = strdupz(value);
132
+ silencer->contexts_pattern = simple_pattern_create(silencer->contexts, NULL, SIMPLE_PATTERN_EXACT);
133
+ } else if (hash == hash_host && !strcasecmp(key, HEALTH_HOST_KEY)) {
134
+ silencer->hosts = strdupz(value);
135
+ silencer->hosts_pattern = simple_pattern_create(silencer->hosts, NULL, SIMPLE_PATTERN_EXACT);
136
+ } else if (hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) {
137
+ silencer->families = strdupz(value);
138
+ silencer->families_pattern = simple_pattern_create(silencer->families, NULL, SIMPLE_PATTERN_EXACT);
139
+ } else {
140
+ buffer_strcat(wb, HEALTH_CMDAPI_MSG_INVALID_KEY);
141
+ }
142
}
183
- }
143
144
+ }
145
if (likely(silencer)) {
186
- health_silencers_add(silencer);
146
+ // Add the created instance to the linked list in silencers
147
+ silencer->next = silencers->silencers;
148
+ silencers->silencers = silencer;
149
+ debug(D_HEALTH, "HEALTH command API: Added silencer %s:%s:%s:%s:%s", silencer->alarms,
150
+ silencer->charts, silencer->contexts, silencer->hosts, silencer->families
151
+ );
152
buffer_strcat(wb, HEALTH_CMDAPI_MSG_ADDED);
153
if (silencers->stype == STYPE_NONE) {
154
buffer_strcat(wb, HEALTH_CMDAPI_MSG_STYPEWARNING);
@@ -197,10 +162,5 @@ int web_client_api_request_v1_mgmt_health(RRDHOST *host, struct web_client *w, c
162
}
163
w->response.data = wb;
164
buffer_no_cacheable(w->response.data);
200
- if (ret == 200 && config_changed) {
201
- BUFFER *jsonb = buffer_create(200);
202
- health_silencers2json(jsonb);
203
- health_silencers2file(jsonb);
204
- }
165
return ret;
166
}
web/api/health/health_cmdapi.h
+1
-1
@@ -12,7 +12,6 @@
12
#define HEALTH_CMDAPI_CMD_SILENCE "SILENCE"
13
#define HEALTH_CMDAPI_CMD_DISABLE "DISABLE"
14
#define HEALTH_CMDAPI_CMD_RESET "RESET"
15
-#define HEALTH_CMDAPI_CMD_LIST "LIST"
15
16
#define HEALTH_CMDAPI_MSG_AUTHERROR "Auth Error\n"
17
#define HEALTH_CMDAPI_MSG_SILENCEALL "All alarm notifications are silenced\n"
@@ -21,6 +20,7 @@
20
#define HEALTH_CMDAPI_MSG_DISABLE "Health checks disabled for alarms matching the selectors\n"
21
#define HEALTH_CMDAPI_MSG_SILENCE "Alarm notifications silenced for alarms matching the selectors\n"
22
#define HEALTH_CMDAPI_MSG_ADDED "Alarm selector added\n"
23
+#define HEALTH_CMDAPI_MSG_INVALID_KEY "Invalid key. Ignoring it.\n"
24
#define HEALTH_CMDAPI_MSG_STYPEWARNING "WARNING: Added alarm selector to silence/disable alarms without a SILENCE or DISABLE command.\n"
25
#define HEALTH_CMDAPI_MSG_NOSELECTORWARNING "WARNING: SILENCE or DISABLE command is ineffective without defining any alarm selectors.\n"
26
web/api/netdata-swagger.json
+2
-3
@@ -664,7 +664,7 @@
664
{
665
"name": "cmd",
666
"in": "query",
667
- "description": "DISABLE ALL: No alarm criteria are evaluated, nothing is written in the alarm log. SILENCE ALL: No notifications are sent. RESET: Return to the default state. DISABLE/SILENCE: Set the mode to be used for the alarms matching the criteria of the alarm selectors. LIST: Show active configuration.",
667
+ "description": "DISABLE ALL: No alarm criteria are evaluated, nothing is written in the alarm log. SILENCE ALL: No notifications are sent. RESET: Return to the default state. DISABLE/SILENCE: Set the mode to be used for the alarms matching the criteria of the alarm selectors.",
668
"required": false,
669
"type": "string",
670
"enum": [
@@ -672,8 +672,7 @@
672
"SILENCE ALL",
673
"DISABLE",
674
"SILENCE",
675
- "RESET",
676
- "LIST"
675
+ "RESET"
676
]
677
},
678
{
web/api/netdata-swagger.yaml
+2
-2
@@ -437,10 +437,10 @@ paths:
437
parameters:
438
- name: cmd
439
in: query
440
- description: 'DISABLE ALL: No alarm criteria are evaluated, nothing is written in the alarm log. SILENCE ALL: No notifications are sent. RESET: Return to the default state. DISABLE/SILENCE: Set the mode to be used for the alarms matching the criteria of the alarm selectors. LIST: Show active configuration.'
440
+ description: 'DISABLE ALL: No alarm criteria are evaluated, nothing is written in the alarm log. SILENCE ALL: No notifications are sent. RESET: Return to the default state. DISABLE/SILENCE: Set the mode to be used for the alarms matching the criteria of the alarm selectors.'
441
required: false
442
type: string
443
- enum: ['DISABLE ALL', 'SILENCE ALL', 'DISABLE', 'SILENCE', 'RESET', 'LIST']
443
+ enum: ['DISABLE ALL', 'SILENCE ALL', 'DISABLE', 'SILENCE', 'RESET']
444
- name: alarm
445
in: query
446
description: 'The expression provided will match both `alarm` and `template` names.'