New alarm entities (#10041)
Co-authored-by: Joel Hans <joel.g.hans@gmail.com> Co-authored-by: Ilya Mashchenko <ilya@netdata.cloud>
thiagoftsm committed
Oct 20, 2020 at 09:00 UTC
6b2ffc355a0d450e4569f3d5412b18d709318986
6 files changed
+115
-6
database/rrdcalc.c
+19
-3
@@ -108,10 +108,22 @@ static void rrdsetcalc_link(RRDSET *st, RRDCALC *rc) {
108
}
109
}
110
111
+static inline int rrdcalc_test_additional_restriction(RRDCALC *rc, RRDSET *st){
112
+ if (rc->module_match && !simple_pattern_matches(rc->module_pattern, st->module_name))
113
+ return 0;
114
+
115
+ if (rc->plugin_match && !simple_pattern_matches(rc->plugin_pattern, st->plugin_name))
116
+ return 0;
117
+
118
+ return 1;
119
+}
120
+
121
static inline int rrdcalc_is_matching_this_rrdset(RRDCALC *rc, RRDSET *st) {
112
- if( (rc->hash_chart == st->hash && !strcmp(rc->chart, st->id)) ||
113
- (rc->hash_chart == st->hash_name && !strcmp(rc->chart, st->name)))
114
- return 1;
122
+ if(((rc->hash_chart == st->hash && !strcmp(rc->chart, st->id)) ||
123
+ (rc->hash_chart == st->hash_name && !strcmp(rc->chart, st->name))) &&
124
+ rrdcalc_test_additional_restriction(rc, st)) {
125
+ return 1;
126
+ }
127
128
return 0;
129
}
@@ -564,6 +576,10 @@ void rrdcalc_free(RRDCALC *rc) {
576
simple_pattern_free(rc->spdim);
577
freez(rc->labels);
578
simple_pattern_free(rc->splabels);
579
+ freez(rc->module_match);
580
+ simple_pattern_free(rc->module_pattern);
581
+ freez(rc->plugin_match);
582
+ simple_pattern_free(rc->plugin_pattern);
583
freez(rc);
584
}
585
database/rrdcalc.h
+7
@@ -45,6 +45,13 @@ struct rrdcalc {
45
char *chart; // the chart id this should be linked to
46
uint32_t hash_chart;
47
48
+
49
+ char *plugin_match; //the plugin name that should be linked to
50
+ SIMPLE_PATTERN *plugin_pattern;
51
+
52
+ char *module_match; //the module name that should be linked to
53
+ SIMPLE_PATTERN *module_pattern;
54
+
55
char *source; // the source of this alarm
56
char *units; // the units of the alarm
57
char *info; // a short description of the alarm
database/rrdcalctemplate.c
+22
-3
@@ -44,6 +44,19 @@ static int rrdcalctemplate_is_there_label_restriction(RRDCALCTEMPLATE *rt, RRDH
44
return ret;
45
}
46
47
+static inline int rrdcalctemplate_test_additional_restriction(RRDCALCTEMPLATE *rt, RRDSET *st) {
48
+ if (rt->family_pattern && !simple_pattern_matches(rt->family_pattern, st->family))
49
+ return 0;
50
+
51
+ if (rt->module_pattern && !simple_pattern_matches(rt->module_pattern, st->module_name))
52
+ return 0;
53
+
54
+ if (rt->plugin_pattern && !simple_pattern_matches(rt->plugin_pattern, st->plugin_name))
55
+ return 0;
56
+
57
+ return 1;
58
+}
59
+
60
// RRDCALCTEMPLATE management
61
/**
62
* RRDCALC TEMPLATE LINK MATCHING
@@ -51,9 +64,9 @@ static int rrdcalctemplate_is_there_label_restriction(RRDCALCTEMPLATE *rt, RRDH
64
* @param rt is the template used to create the chart.
65
* @param st is the chart where the alarm will be attached.
66
*/
54
-void rrdcalctemplate_link_matching_test(RRDCALCTEMPLATE *rt, RRDSET *st, RRDHOST *host ) {
55
- if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context)
56
- && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) {
67
+void rrdcalctemplate_link_matching_test(RRDCALCTEMPLATE *rt, RRDSET *st, RRDHOST *host) {
68
+ if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context) &&
69
+ rrdcalctemplate_test_additional_restriction(rt, st) ) {
70
if (!rrdcalctemplate_is_there_label_restriction(rt, host)) {
71
RRDCALC *rc = rrdcalc_create_from_template(host, rt, st->id);
72
if (unlikely(!rc))
@@ -92,6 +105,12 @@ inline void rrdcalctemplate_free(RRDCALCTEMPLATE *rt) {
105
freez(rt->family_match);
106
simple_pattern_free(rt->family_pattern);
107
108
+ freez(rt->plugin_match);
109
+ simple_pattern_free(rt->plugin_pattern);
110
+
111
+ freez(rt->module_match);
112
+ simple_pattern_free(rt->module_pattern);
113
+
114
freez(rt->name);
115
freez(rt->exec);
116
freez(rt->recipient);
database/rrdcalctemplate.h
+6
@@ -21,6 +21,12 @@ struct rrdcalctemplate {
21
char *family_match;
22
SIMPLE_PATTERN *family_pattern;
23
24
+ char *plugin_match;
25
+ SIMPLE_PATTERN *plugin_pattern;
26
+
27
+ char *module_match;
28
+ SIMPLE_PATTERN *module_pattern;
29
+
30
char *source; // the source of this alarm
31
char *units; // the units of the alarm
32
char *info; // a short description of the alarm
health/REFERENCE.md
+27
@@ -60,6 +60,8 @@ Netdata parses the following lines. Beneath the table is an in-depth explanation
60
| [`on`](#alarm-line-on) | yes | The chart this alarm should attach to. |
61
| [`os`](#alarm-line-os) | no | Which operating systems to run this chart. |
62
| [`hosts`](#alarm-line-hosts) | no | Which hostnames will run this alarm. |
63
+| [`plugin`](#alarm-line-plugin) | no | Restrict an alarm or template to only a certain plugin. |
64
+| [`module`](#alarm-line-module) | no | Restrict an alarm or template to only a certain module. |
65
| [`families`](#alarm-line-families) | no | Restrict a template to only certain families. |
66
| [`lookup`](#alarm-line-lookup) | yes | The database lookup to find and process metrics for the chart specified through `on`. |
67
| [`calc`](#alarm-line-calc) | yes (see above) | A calculation to apply to the value found via `lookup` or another variable. |
@@ -150,6 +152,31 @@ begin with `redis`.
152
hosts: server1 server2 database* !redis3 redis*
153
```
154
155
+#### Alarm line `plugin`
156
+
157
+The `plugin` line filters which plugin within the context this alarm should apply to. The value is a space-separated
158
+list of [simple patterns](/libnetdata/simple_pattern/README.md). For example,
159
+you can create a filter for an alarm that applies specifically to `python.d.plugin`:
160
+
161
+```yaml
162
+plugin: python.d.plugin
163
+```
164
+
165
+The `plugin` line is best used with other options like `module`. When used alone, the `plugin` line creates a very
166
+inclusive filter that is unlikely to be of much use in production. See [`module`](#alarm-line-module) for a
167
+comprehensive example using both.
168
+
169
+#### Alarm line `module`
170
+
171
+The `module` line filters which module within the context this alarm should apply to. The value is a space-separated
172
+list of [simple patterns](/libnetdata/simple_pattern/README.md). For
173
+example, you can create an alarm that applies only on the `isc_dhcpd` module started by `python.d.plugin`:
174
+
175
+```yaml
176
+plugin: python.d.plugin
177
+module: isc_dhcpd
178
+```
179
+
180
#### Alarm line `families`
181
182
The `families` line, used only alongside templates, filters which families within the context this alarm should apply
health/health_config.c
+34
@@ -10,6 +10,8 @@
10
#define HEALTH_HOST_KEY "hosts"
11
#define HEALTH_OS_KEY "os"
12
#define HEALTH_FAMILIES_KEY "families"
13
+#define HEALTH_PLUGIN_KEY "plugin"
14
+#define HEALTH_MODULE_KEY "module"
15
#define HEALTH_LOOKUP_KEY "lookup"
16
#define HEALTH_CALC_KEY "calc"
17
#define HEALTH_EVERY_KEY "every"
@@ -485,6 +487,8 @@ static int health_readfile(const char *filename, void *data) {
487
hash_on = 0,
488
hash_host = 0,
489
hash_families = 0,
490
+ hash_plugin = 0,
491
+ hash_module = 0,
492
hash_calc = 0,
493
hash_green = 0,
494
hash_red = 0,
@@ -510,6 +514,8 @@ static int health_readfile(const char *filename, void *data) {
514
hash_os = simple_uhash(HEALTH_OS_KEY);
515
hash_host = simple_uhash(HEALTH_HOST_KEY);
516
hash_families = simple_uhash(HEALTH_FAMILIES_KEY);
517
+ hash_plugin = simple_uhash(HEALTH_PLUGIN_KEY);
518
+ hash_module = simple_uhash(HEALTH_MODULE_KEY);
519
hash_calc = simple_uhash(HEALTH_CALC_KEY);
520
hash_lookup = simple_uhash(HEALTH_LOOKUP_KEY);
521
hash_green = simple_uhash(HEALTH_GREEN_KEY);
@@ -811,6 +817,20 @@ static int health_readfile(const char *filename, void *data) {
817
rc->labels = simple_pattern_trim_around_equal(value);
818
rc->splabels = simple_pattern_create(rc->labels, NULL, SIMPLE_PATTERN_EXACT);
819
}
820
+ else if(hash == hash_plugin && !strcasecmp(key, HEALTH_PLUGIN_KEY)) {
821
+ freez(rc->plugin_match);
822
+ simple_pattern_free(rc->plugin_pattern);
823
+
824
+ rc->plugin_match = strdupz(value);
825
+ rc->plugin_pattern = simple_pattern_create(rc->plugin_match, NULL, SIMPLE_PATTERN_EXACT);
826
+ }
827
+ else if(hash == hash_module && !strcasecmp(key, HEALTH_MODULE_KEY)) {
828
+ freez(rc->module_match);
829
+ simple_pattern_free(rc->module_pattern);
830
+
831
+ rc->module_match = strdupz(value);
832
+ rc->module_pattern = simple_pattern_create(rc->module_match, NULL, SIMPLE_PATTERN_EXACT);
833
+ }
834
else {
835
error("Health configuration at line %zu of file '%s' for alarm '%s' has unknown key '%s'.",
836
line, filename, rc->name, key);
@@ -835,6 +855,20 @@ static int health_readfile(const char *filename, void *data) {
855
rt->family_match = strdupz(value);
856
rt->family_pattern = simple_pattern_create(rt->family_match, NULL, SIMPLE_PATTERN_EXACT);
857
}
858
+ else if(hash == hash_plugin && !strcasecmp(key, HEALTH_PLUGIN_KEY)) {
859
+ freez(rt->plugin_match);
860
+ simple_pattern_free(rt->plugin_pattern);
861
+
862
+ rt->plugin_match = strdupz(value);
863
+ rt->plugin_pattern = simple_pattern_create(rt->plugin_match, NULL, SIMPLE_PATTERN_EXACT);
864
+ }
865
+ else if(hash == hash_module && !strcasecmp(key, HEALTH_MODULE_KEY)) {
866
+ freez(rt->module_match);
867
+ simple_pattern_free(rt->module_pattern);
868
+
869
+ rt->module_match = strdupz(value);
870
+ rt->module_pattern = simple_pattern_create(rt->module_match, NULL, SIMPLE_PATTERN_EXACT);
871
+ }
872
else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) {
873
health_parse_db_lookup(line, filename, value, &rt->group, &rt->after, &rt->before,
874
&rt->update_every, &rt->options, &rt->dimensions, &rt->foreachdim);