@cryptotaxi247 / netdata-1 / commits / 18655e8f9

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;