// SPDX-License-Identifier: GPL-3.0-or-later
#include "health.h"
struct health_cmdapi_thread_status {
int status;
;
struct rusage rusage;
};
unsigned int default_health_enabled = 1;
char *silencers_filename;
// ----------------------------------------------------------------------------
// health initialization
/**
* User Config directory
*
* Get the config directory for health and return it.
*
* @return a pointer to the user config directory
*/
inline char *health_user_config_dir(void) {
char buffer[FILENAME_MAX + 1];
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_user_config_dir);
return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer);
}
/**
* Stock Config Directory
*
* Get the Stock config directory and return it.
*
* @return a pointer to the stock config directory.
*/
inline char *health_stock_config_dir(void) {
char buffer[FILENAME_MAX + 1];
snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_stock_config_dir);
return config_get(CONFIG_SECTION_HEALTH, "stock health configuration directory", buffer);
}
/**
* Silencers init
*
* Function used to initialize the silencer structure.
*/
void health_silencers_init(void) {
FILE *fd = fopen(silencers_filename, "r");
if (fd) {
fseek(fd, 0 , SEEK_END);
off_t length = (off_t) ftell(fd);
fseek(fd, 0 , SEEK_SET);
if (length > 0 && length < HEALTH_SILENCERS_MAX_FILE_LEN) {
char *str = mallocz((length+1)* sizeof(char));
if(str) {
size_t copied;
copied = fread(str, sizeof(char), length, fd);
if (copied == (length* sizeof(char))) {
str[length] = 0x00;
json_parse(str, NULL, health_silencers_json_read_callback);
info("Parsed health silencers file %s", silencers_filename);
} else {
error("Cannot read the data from health silencers file %s", silencers_filename);
}
freez(str);
}
} else {
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);
}
fclose(fd);
} else {
info("Cannot open the file %s, so Netdata will work with the default health configuration.",silencers_filename);
}
}
/**
* Health Init
*
* Initialize the health thread.
*/
void health_init(void) {
debug(D_HEALTH, "Health configuration initializing");
if(!(default_health_enabled = (unsigned int)config_get_boolean(CONFIG_SECTION_HEALTH, "enabled", default_health_enabled))) {
debug(D_HEALTH, "Health is disabled.");
return;
}
health_silencers_init();
}
// ----------------------------------------------------------------------------
// re-load health configuration
/**
* Reload host
*
* Reload configuration for a specific host.
*
* @param host the structure of the host that the function will reload the configuration.
*/
void health_reload_host(RRDHOST *host) {
if(unlikely(!host->health_enabled))
return;
char *user_path = health_user_config_dir();
char *stock_path = health_stock_config_dir();
// free all running alarms
rrdhost_wrlock(host);
while(host->templates)
rrdcalctemplate_unlink_and_free(host, host->templates);
RRDCALCTEMPLATE *rt,*next;
for(rt = host->alarms_template_with_foreach; rt ; rt = next) {
next = rt->next;
rrdcalctemplate_free(rt);
}
host->alarms_template_with_foreach = NULL;
while(host->alarms)
rrdcalc_unlink_and_free(host, host->alarms);
RRDCALC *rc,*nc;
for(rc = host->alarms_with_foreach; rc ; rc = nc) {
nc = rc->next;
rrdcalc_free(rc);
}
host->alarms_with_foreach = NULL;
rrdhost_unlock(host);
// invalidate all previous entries in the alarm log
ALARM_ENTRY *t;
for(t = host->health_log.alarms