master
c 218 lines 8.68 KB
Raw
1 // SPDX-License-Identifier: GPL-3.0-or-later
2
3 #include "health.h"
4 #include "health_internals.h"
5
6 struct health_plugin_globals health_globals = {
7 .initialization = {
8 .spinlock = SPINLOCK_INITIALIZER,
9 .done = false,
10 },
11 .config = {
12 .enabled = true,
13 .stock_enabled = true,
14 .use_summary_for_notifications = true,
15
16 .health_log_entries_max = HEALTH_LOG_ENTRIES_DEFAULT,
17 .health_log_retention_s = HEALTH_LOG_RETENTION_DEFAULT,
18
19 .default_warn_repeat_every = 0,
20 .default_crit_repeat_every = 0,
21
22 .run_at_least_every_seconds = 10,
23 .postpone_alarms_during_hibernation_for_seconds = 60,
24 .notification_execution_timeout_seconds = 120,
25 },
26 .prototypes = {
27 .dict = NULL,
28 .registering = false,
29 }
30 };
31
32 bool health_plugin_enabled(void) {
33 return health_globals.config.enabled;
34 }
35
36 void health_plugin_disable(void) {
37 health_globals.config.enabled = false;
38 }
39
40
41 void health_load_config_defaults(void) {
42 static bool done = false;
43 if(done) return;
44 done = true;
45
46 char filename[FILENAME_MAX + 1];
47
48 health_globals.config.enabled =
49 inicfg_get_boolean(&netdata_config, CONFIG_SECTION_HEALTH,
50 "enabled",
51 health_globals.config.enabled);
52
53 health_globals.config.stock_enabled =
54 inicfg_get_boolean(&netdata_config, CONFIG_SECTION_HEALTH,
55 "enable stock health configuration",
56 health_globals.config.stock_enabled);
57
58 health_globals.config.use_summary_for_notifications =
59 inicfg_get_boolean(&netdata_config, CONFIG_SECTION_HEALTH,
60 "use summary for notifications",
61 health_globals.config.use_summary_for_notifications);
62
63 health_globals.config.default_warn_repeat_every =
64 inicfg_get_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH, "default repeat warning", 0);
65
66 health_globals.config.default_crit_repeat_every =
67 inicfg_get_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH, "default repeat critical", 0);
68
69 health_globals.config.health_log_entries_max =
70 inicfg_get_number(&netdata_config, CONFIG_SECTION_HEALTH, "in memory max health log entries",
71 health_globals.config.health_log_entries_max);
72
73 health_globals.config.health_log_retention_s =
74 inicfg_get_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH, "health log retention", HEALTH_LOG_RETENTION_DEFAULT);
75
76 snprintfz(filename, FILENAME_MAX, "%s/alarm-notify.sh", netdata_configured_primary_plugins_dir);
77 health_globals.config.default_exec =
78 string_strdupz(inicfg_get_filename(&netdata_config, CONFIG_SECTION_HEALTH, "script to execute on alarm", filename));
79
80 health_globals.config.enabled_alerts =
81 simple_pattern_create(inicfg_get(&netdata_config, CONFIG_SECTION_HEALTH, "enabled alarms", "*"),
82 NULL, SIMPLE_PATTERN_EXACT, true);
83
84 health_globals.config.run_at_least_every_seconds =
85 (int)inicfg_get_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH, "run at least every",
86 health_globals.config.run_at_least_every_seconds);
87
88 health_globals.config.postpone_alarms_during_hibernation_for_seconds =
89 inicfg_get_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH,
90 "postpone alarms during hibernation for",
91 health_globals.config.postpone_alarms_during_hibernation_for_seconds);
92
93 time_t notification_execution_timeout =
94 inicfg_get_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH,
95 "notification execution timeout",
96 health_globals.config.notification_execution_timeout_seconds);
97 // clamp to [0, INT32_MAX] before narrowing to int32: the upper clamp prevents a huge
98 // value from overflowing into a negative, the lower clamp normalizes negatives to 0.
99 // 0 means "wait forever".
100 if(notification_execution_timeout < 0) notification_execution_timeout = 0;
101 if(notification_execution_timeout > INT32_MAX) notification_execution_timeout = INT32_MAX;
102 health_globals.config.notification_execution_timeout_seconds = (int32_t)notification_execution_timeout;
103
104 health_globals.config.default_recipient =
105 string_strdupz("root");
106
107 // ------------------------------------------------------------------------
108 // verify after loading
109
110 if(health_globals.config.run_at_least_every_seconds < 1)
111 health_globals.config.run_at_least_every_seconds = 1;
112
113 if(health_globals.config.health_log_entries_max < HEALTH_LOG_ENTRIES_MIN) {
114 nd_log(NDLS_DAEMON, NDLP_WARNING,
115 "Health configuration has invalid max log entries %u, using minimum of %u",
116 health_globals.config.health_log_entries_max,
117 HEALTH_LOG_ENTRIES_MIN);
118
119 health_globals.config.health_log_entries_max = HEALTH_LOG_ENTRIES_MIN;
120 inicfg_set_number(&netdata_config, CONFIG_SECTION_HEALTH, "in memory max health log entries",
121 (long)health_globals.config.health_log_entries_max);
122 }
123 else if(health_globals.config.health_log_entries_max > HEALTH_LOG_ENTRIES_MAX) {
124 nd_log(NDLS_DAEMON, NDLP_WARNING,
125 "Health configuration has invalid max log entries %u, using maximum of %u",
126 health_globals.config.health_log_entries_max,
127 HEALTH_LOG_ENTRIES_MAX);
128
129 health_globals.config.health_log_entries_max = HEALTH_LOG_ENTRIES_MAX;
130 inicfg_set_number(&netdata_config, CONFIG_SECTION_HEALTH, "in memory max health log entries",
131 (long)health_globals.config.health_log_entries_max);
132 }
133
134 if (health_globals.config.health_log_retention_s < HEALTH_LOG_MINIMUM_HISTORY) {
135 nd_log(NDLS_DAEMON, NDLP_WARNING,
136 "Health configuration has invalid health log retention %u. Using minimum %d",
137 health_globals.config.health_log_retention_s, HEALTH_LOG_MINIMUM_HISTORY);
138
139 health_globals.config.health_log_retention_s = HEALTH_LOG_MINIMUM_HISTORY;
140 inicfg_set_duration_seconds(&netdata_config, CONFIG_SECTION_HEALTH, "health log retention", health_globals.config.health_log_retention_s);
141 }
142
143 nd_log(NDLS_DAEMON, NDLP_DEBUG,
144 "Health log history is set to %u seconds (%u days)",
145 health_globals.config.health_log_retention_s, health_globals.config.health_log_retention_s / 86400);
146 }
147
148 inline const char *health_user_config_dir(void) {
149 char buffer[FILENAME_MAX + 1];
150 snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_user_config_dir);
151 return inicfg_get_path(&netdata_config, CONFIG_SECTION_DIRECTORIES, "health config", buffer);
152 }
153
154 inline const char *health_stock_config_dir(void) {
155 char buffer[FILENAME_MAX + 1];
156 snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_stock_config_dir);
157 return inicfg_get_path(&netdata_config, CONFIG_SECTION_DIRECTORIES, "stock health config", buffer);
158 }
159
160 void health_plugin_init(void) {
161 spinlock_lock(&health_globals.initialization.spinlock);
162
163 if(health_globals.initialization.done)
164 goto cleanup;
165
166 health_globals.initialization.done = true;
167
168 health_alarm_entry_aral_init();
169 health_init_prototypes();
170 health_load_config_defaults();
171
172 if(!health_plugin_enabled())
173 goto cleanup;
174
175 health_reload_prototypes();
176 health_silencers_init();
177
178 cleanup:
179 spinlock_unlock(&health_globals.initialization.spinlock);
180 }
181
182 void health_plugin_destroy(void) {
183 if(!health_globals.initialization.done)
184 return;
185
186 spinlock_lock(&health_globals.initialization.spinlock);
187
188 // Clean up health prototypes dictionary
189 if(health_globals.prototypes.dict) {
190 dictionary_destroy(health_globals.prototypes.dict);
191 health_globals.prototypes.dict = NULL;
192 }
193
194 // Free allocated strings
195 string_freez(health_globals.config.default_exec);
196 string_freez(health_globals.config.default_recipient);
197 string_freez(health_globals.config.silencers_filename);
198
199 // Free the enabled_alerts pattern
200 simple_pattern_free(health_globals.config.enabled_alerts);
201
202 // Reset pointers to NULL
203 health_globals.config.default_exec = NULL;
204 health_globals.config.default_recipient = NULL;
205 health_globals.config.silencers_filename = NULL;
206 health_globals.config.enabled_alerts = NULL;
207
208 alert_variable_lookup_cleanup();
209
210 health_globals.initialization.done = false;
211
212 spinlock_unlock(&health_globals.initialization.spinlock);
213 }
214
215 void health_plugin_reload(void) {
216 health_reload_prototypes();
217 health_apply_prototypes_to_all_hosts();
218 }