Only load required charts for rrdvars (#14443)
* store only rrdvars health needs * make it simpler * only set * fix codacy
Emmanuel Vasilakis committed
Feb 8, 2023 at 15:12 UTC
18655e8f9552f70ad79cb44cc658a736239296ed
7 files changed
+142
-22
database/rrdcalc.c
+2
@@ -245,6 +245,8 @@ static void rrdcalc_link_to_rrdset(RRDSET *st, RRDCALC *rc) {
245
if(!rc->units)
246
rc->units = string_dup(st->units);
247
248
+ rrdvar_store_for_chart(host, st);
249
+
250
rrdcalc_update_info_using_rrdset_labels(rc);
251
252
time_t now = now_realtime_sec();
database/rrdhost.c
+1
@@ -1226,6 +1226,7 @@ void rrdhost_free___while_having_rrd_wrlock(RRDHOST *host, bool force) {
1226
rrdfamily_index_destroy(host);
1227
rrdfunctions_destroy(host);
1228
rrdvariables_destroy(host->rrdvars);
1229
+ rrdvariables_destroy(health_rrdvars);
1230
1231
rrdhost_destroy_rrdcontexts(host);
1232
database/rrdvar.c
+68
@@ -93,6 +93,15 @@ DICTIONARY *rrdvariables_create(void) {
93
return dict;
94
}
95
96
+DICTIONARY *health_rrdvariables_create(void) {
97
+ DICTIONARY *dict = dictionary_create_advanced(DICT_OPTION_SINGLE_THREADED, &dictionary_stats_category_rrdhealth, 0);
98
+
99
+ dictionary_register_insert_callback(dict, rrdvar_insert_callback, NULL);
100
+ dictionary_register_delete_callback(dict, rrdvar_delete_callback, NULL);
101
+
102
+ return dict;
103
+}
104
+
105
void rrdvariables_destroy(DICTIONARY *dict) {
106
dictionary_destroy(dict);
107
}
@@ -124,6 +133,19 @@ inline const RRDVAR_ACQUIRED *rrdvar_add_and_acquire(const char *scope __maybe_u
133
return (const RRDVAR_ACQUIRED *)dictionary_set_and_acquire_item_advanced(dict, string2str(name), (ssize_t)string_strlen(name) + 1, NULL, sizeof(RRDVAR), &tmp);
134
}
135
136
+inline void rrdvar_add(const char *scope __maybe_unused, DICTIONARY *dict, STRING *name, RRDVAR_TYPE type, RRDVAR_FLAGS options, void *value) {
137
+ if(unlikely(!dict || !name)) return;
138
+
139
+ struct rrdvar_constructor tmp = {
140
+ .name = name,
141
+ .value = value,
142
+ .type = type,
143
+ .options = options,
144
+ .react_action = RRDVAR_REACT_NONE,
145
+ };
146
+ dictionary_set_advanced(dict, string2str(name), (ssize_t)string_strlen(name) + 1, NULL, sizeof(RRDVAR), &tmp);
147
+}
148
+
149
void rrdvar_delete_all(DICTIONARY *dict) {
150
dictionary_flush(dict);
151
}
@@ -211,6 +233,52 @@ NETDATA_DOUBLE rrdvar2number(const RRDVAR_ACQUIRED *rva) {
233
}
234
}
235
236
+int health_variable_check(DICTIONARY *dict, RRDSET *st, RRDDIM *rd) {
237
+ if (!dict || !st || !rd) return 0;
238
+
239
+ STRING *helper_str;
240
+ char helper[RRDVAR_MAX_LENGTH + 1];
241
+ snprintfz(helper, RRDVAR_MAX_LENGTH, "%s.%s", string2str(st->name), string2str(rd->name));
242
+ helper_str = string_strdupz(helper);
243
+
244
+ const RRDVAR_ACQUIRED *rva;
245
+ rva = rrdvar_get_and_acquire(dict, helper_str);
246
+ if(rva) {
247
+ dictionary_acquired_item_release(dict, (const DICTIONARY_ITEM *)rva);
248
+ string_freez(helper_str);
249
+ return 1;
250
+ }
251
+
252
+ string_freez(helper_str);
253
+
254
+ return 0;
255
+}
256
+
257
+void rrdvar_store_for_chart(RRDHOST *host, RRDSET *st) {
258
+ if (!st) return;
259
+
260
+ if(!st->rrdfamily)
261
+ st->rrdfamily = rrdfamily_add_and_acquire(host, rrdset_family(st));
262
+
263
+ if(!st->rrdvars)
264
+ st->rrdvars = rrdvariables_create();
265
+
266
+ rrddimvar_index_init(st);
267
+
268
+ rrdsetvar_add_and_leave_released(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_FLAG_NONE);
269
+ rrdsetvar_add_and_leave_released(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, RRDVAR_FLAG_NONE);
270
+ rrdsetvar_add_and_leave_released(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, RRDVAR_FLAG_NONE);
271
+ rrdsetvar_add_and_leave_released(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_FLAG_NONE);
272
+
273
+ RRDDIM *rd;
274
+ rrddim_foreach_read(rd, st) {
275
+ rrddimvar_add_and_leave_released(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, RRDVAR_FLAG_NONE);
276
+ rrddimvar_add_and_leave_released(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, RRDVAR_FLAG_NONE);
277
+ rrddimvar_add_and_leave_released(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, RRDVAR_FLAG_NONE);
278
+ }
279
+ rrddim_foreach_done(rd);
280
+}
281
+
282
int health_variable_lookup(STRING *variable, RRDCALC *rc, NETDATA_DOUBLE *result) {
283
RRDSET *st = rc->rrdset;
284
if(!st) return 0;
database/rrdvar.h
+6
@@ -26,6 +26,7 @@ typedef enum rrdvar_options {
26
RRDVAR_FLAG_RRDCALC_FAMILY_VAR = (1 << 4), // this is a an alarm variable, attached to a family
27
RRDVAR_FLAG_RRDCALC_HOST_CHARTID_VAR = (1 << 5), // this is a an alarm variable, attached to the host, using the chart id
28
RRDVAR_FLAG_RRDCALC_HOST_CHARTNAME_VAR = (1 << 6), // this is a an alarm variable, attached to the host, using the chart name
29
+ RRDVAR_FLAG_CONFIG_VAR = (1 << 7), // this is a an alarm variable, read from alarm config
30
31
// this is 24 bit
32
// to increase it you have to set change the bitfield in
@@ -47,6 +48,7 @@ int rrdvar_fix_name(char *variable);
48
STRING *rrdvar_name_to_string(const char *name);
49
50
const RRDVAR_ACQUIRED *rrdvar_custom_host_variable_add_and_acquire(RRDHOST *host, const char *name);
51
+void rrdvar_add(const char *scope __maybe_unused, DICTIONARY *dict, STRING *name, RRDVAR_TYPE type, RRDVAR_FLAGS options, void *value);
52
void rrdvar_custom_host_variable_set(RRDHOST *host, const RRDVAR_ACQUIRED *rva, NETDATA_DOUBLE value);
53
54
int rrdvar_walkthrough_read(DICTIONARY *dict, int (*callback)(const DICTIONARY_ITEM *item, void *rrdvar, void *data), void *data);
@@ -60,8 +62,12 @@ const RRDVAR_ACQUIRED *rrdvar_add_and_acquire(const char *scope, DICTIONARY *dic
62
void rrdvar_release_and_del(DICTIONARY *dict, const RRDVAR_ACQUIRED *rva);
63
64
DICTIONARY *rrdvariables_create(void);
65
+DICTIONARY *health_rrdvariables_create(void);
66
void rrdvariables_destroy(DICTIONARY *dict);
67
68
+void rrdvar_store_for_chart(RRDHOST *host, RRDSET *st);
69
+int health_variable_check(DICTIONARY *dict, RRDSET *st, RRDDIM *rd);
70
+
71
void rrdvar_delete_all(DICTIONARY *dict);
72
73
const char *rrdvar_name(const RRDVAR_ACQUIRED *rva);
health/health.c
+10
-22
@@ -17,6 +17,11 @@
17
#error WORKER_UTILIZATION_MAX_JOB_TYPES has to be at least 10
18
#endif
19
20
+unsigned int default_health_enabled = 1;
21
+char *silencers_filename;
22
+SIMPLE_PATTERN *conf_enabled_alarms = NULL;
23
+DICTIONARY *health_rrdvars;
24
+
25
static bool prepare_command(BUFFER *wb,
26
const char *exec,
27
const char *recipient,
@@ -157,10 +162,6 @@ static bool prepare_command(BUFFER *wb,
162
return true;
163
}
164
160
-unsigned int default_health_enabled = 1;
161
-char *silencers_filename;
162
-SIMPLE_PATTERN *conf_enabled_alarms = NULL;
163
-
165
// the queue of executed alarm notifications that haven't been waited for yet
166
static struct {
167
ALARM_ENTRY *head; // oldest
@@ -925,19 +926,6 @@ static void health_execute_delayed_initializations(RRDHOST *host) {
926
927
worker_is_busy(WORKER_HEALTH_JOB_DELAYED_INIT_RRDSET);
928
928
- if(!st->rrdfamily)
929
- st->rrdfamily = rrdfamily_add_and_acquire(host, rrdset_family(st));
930
-
931
- if(!st->rrdvars)
932
- st->rrdvars = rrdvariables_create();
933
-
934
- rrddimvar_index_init(st);
935
-
936
- rrdsetvar_add_and_leave_released(st, "last_collected_t", RRDVAR_TYPE_TIME_T, &st->last_collected_time.tv_sec, RRDVAR_FLAG_NONE);
937
- rrdsetvar_add_and_leave_released(st, "green", RRDVAR_TYPE_CALCULATED, &st->green, RRDVAR_FLAG_NONE);
938
- rrdsetvar_add_and_leave_released(st, "red", RRDVAR_TYPE_CALCULATED, &st->red, RRDVAR_FLAG_NONE);
939
- rrdsetvar_add_and_leave_released(st, "update_every", RRDVAR_TYPE_INT, &st->update_every, RRDVAR_FLAG_NONE);
940
-
929
rrdcalc_link_matching_alerts_to_rrdset(st);
930
rrdcalctemplate_link_matching_templates_to_rrdset(st);
931
@@ -948,19 +936,19 @@ static void health_execute_delayed_initializations(RRDHOST *host) {
936
937
worker_is_busy(WORKER_HEALTH_JOB_DELAYED_INIT_RRDDIM);
938
951
- rrddimvar_add_and_leave_released(rd, RRDVAR_TYPE_CALCULATED, NULL, NULL, &rd->last_stored_value, RRDVAR_FLAG_NONE);
952
- rrddimvar_add_and_leave_released(rd, RRDVAR_TYPE_COLLECTED, NULL, "_raw", &rd->last_collected_value, RRDVAR_FLAG_NONE);
953
- rrddimvar_add_and_leave_released(rd, RRDVAR_TYPE_TIME_T, NULL, "_last_collected_t", &rd->last_collected_time.tv_sec, RRDVAR_FLAG_NONE);
954
-
939
RRDCALCTEMPLATE *rt;
940
foreach_rrdcalctemplate_read(host, rt) {
941
if(!rt->foreach_dimension_pattern)
942
continue;
943
960
- if(rrdcalctemplate_check_rrdset_conditions(rt, st, host))
944
+ if(rrdcalctemplate_check_rrdset_conditions(rt, st, host)) {
945
rrdcalctemplate_check_rrddim_conditions_and_link(rt, st, rd, host);
946
+ }
947
}
948
foreach_rrdcalctemplate_done(rt);
949
+
950
+ if(health_variable_check(health_rrdvars, st, rd))
951
+ rrdvar_store_for_chart(host, st);
952
}
953
rrddim_foreach_done(rd);
954
}
health/health.h
+1
@@ -32,6 +32,7 @@ extern unsigned int default_health_enabled;
32
33
extern char *silencers_filename;
34
extern SIMPLE_PATTERN *conf_enabled_alarms;
35
+extern DICTIONARY *health_rrdvars;
36
37
void health_init(void);
38
health/health_config.c
+54
@@ -185,6 +185,51 @@ static inline int health_parse_repeat(
185
return 1;
186
}
187
188
+static inline int isvariableterm(const char s) {
189
+ if(isalnum(s) || s == '.' || s == '_')
190
+ return 0;
191
+
192
+ return 1;
193
+}
194
+
195
+static inline void parse_variables_and_store_in_health_rrdvars(char *value, size_t len) {
196
+ const char *s = value;
197
+ char buffer[RRDVAR_MAX_LENGTH];
198
+
199
+ // $
200
+ while (*s) {
201
+ if(*s == '$') {
202
+ size_t i = 0;
203
+ s++;
204
+
205
+ if(*s == '{') {
206
+ // ${variable_name}
207
+
208
+ s++;
209
+ while (*s && *s != '}' && i < len)
210
+ buffer[i++] = *s++;
211
+
212
+ if(*s == '}')
213
+ s++;
214
+ }
215
+ else {
216
+ // $variable_name
217
+
218
+ while (*s && !isvariableterm(*s) && i < len)
219
+ buffer[i++] = *s++;
220
+ }
221
+
222
+ buffer[i] = '\0';
223
+
224
+ //TODO: check and try to store only variables
225
+ STRING *name_string = rrdvar_name_to_string(buffer);
226
+ rrdvar_add("health", health_rrdvars, name_string, RRDVAR_TYPE_CALCULATED, RRDVAR_FLAG_CONFIG_VAR, NULL);
227
+ string_freez(name_string);
228
+ } else
229
+ s++;
230
+ }
231
+}
232
+
233
/**
234
* Health pattern from Foreach
235
*
@@ -769,6 +814,7 @@ static int health_readfile(const char *filename, void *data) {
814
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
815
line, filename, rrdcalc_name(rc), key, value, expression_strerror(error), failed_at);
816
}
817
+ parse_variables_and_store_in_health_rrdvars(value, HEALTH_CONF_MAX_LINE);
818
}
819
else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) {
820
alert_cfg->warn = string_strdupz(value);
@@ -779,6 +825,7 @@ static int health_readfile(const char *filename, void *data) {
825
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
826
line, filename, rrdcalc_name(rc), key, value, expression_strerror(error), failed_at);
827
}
828
+ parse_variables_and_store_in_health_rrdvars(value, HEALTH_CONF_MAX_LINE);
829
}
830
else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) {
831
alert_cfg->crit = string_strdupz(value);
@@ -789,6 +836,7 @@ static int health_readfile(const char *filename, void *data) {
836
error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
837
line, filename, rrdcalc_name(rc), key, value, expression_strerror(error), failed_at);
838
}
839
+ parse_variables_and_store_in_health_rrdvars(value, HEALTH_CONF_MAX_LINE);
840
}
841
else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) {
842
alert_cfg->exec = string_strdupz(value);
@@ -1031,6 +1079,7 @@ static int health_readfile(const char *filename, void *data) {
1079
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
1080
line, filename, rrdcalctemplate_name(rt), key, value, expression_strerror(error), failed_at);
1081
}
1082
+ parse_variables_and_store_in_health_rrdvars(value, HEALTH_CONF_MAX_LINE);
1083
}
1084
else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) {
1085
alert_cfg->warn = string_strdupz(value);
@@ -1041,6 +1090,7 @@ static int health_readfile(const char *filename, void *data) {
1090
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
1091
line, filename, rrdcalctemplate_name(rt), key, value, expression_strerror(error), failed_at);
1092
}
1093
+ parse_variables_and_store_in_health_rrdvars(value, HEALTH_CONF_MAX_LINE);
1094
}
1095
else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) {
1096
alert_cfg->crit = string_strdupz(value);
@@ -1051,6 +1101,7 @@ static int health_readfile(const char *filename, void *data) {
1101
error("Health configuration at line %zu of file '%s' for template '%s' at key '%s' has unparse-able expression '%s': %s at '%s'",
1102
line, filename, rrdcalctemplate_name(rt), key, value, expression_strerror(error), failed_at);
1103
}
1104
+ parse_variables_and_store_in_health_rrdvars(value, HEALTH_CONF_MAX_LINE);
1105
}
1106
else if(hash == hash_exec && !strcasecmp(key, HEALTH_EXEC_KEY)) {
1107
alert_cfg->exec = string_strdupz(value);
@@ -1185,6 +1236,9 @@ void health_readdir(RRDHOST *host, const char *user_path, const char *stock_path
1236
stock_path = user_path;
1237
}
1238
1239
+ if (!health_rrdvars)
1240
+ health_rrdvars = health_rrdvariables_create();
1241
+
1242
recursive_config_double_dir_load(user_path, stock_path, subpath, health_readfile, (void *) host, 0);
1243
log_health("[%s]: Read health configuration.", rrdhost_hostname(host));
1244
sql_store_hashes = 0;