// SPDX-License-Identifier: GPL-3.0-or-later
#include "health.h"
#define HEALTH_CONF_MAX_LINE 4096
#define HEALTH_ALARM_KEY "alarm"
#define HEALTH_TEMPLATE_KEY "template"
#define HEALTH_ON_KEY "on"
#define HEALTH_HOST_KEY "hosts"
#define HEALTH_OS_KEY "os"
#define HEALTH_FAMILIES_KEY "families"
#define HEALTH_LOOKUP_KEY "lookup"
#define HEALTH_CALC_KEY "calc"
#define HEALTH_EVERY_KEY "every"
#define HEALTH_GREEN_KEY "green"
#define HEALTH_RED_KEY "red"
#define HEALTH_WARN_KEY "warn"
#define HEALTH_CRIT_KEY "crit"
#define HEALTH_EXEC_KEY "exec"
#define HEALTH_RECIPIENT_KEY "to"
#define HEALTH_UNITS_KEY "units"
#define HEALTH_INFO_KEY "info"
#define HEALTH_DELAY_KEY "delay"
#define HEALTH_OPTIONS_KEY "options"
#define HEALTH_REPEAT_KEY "repeat"
#define HEALTH_HOST_LABEL_KEY "host labels"
static inline int rrdcalc_add_alarm_from_config(RRDHOST *host, RRDCALC *rc) {
if(!rc->chart) {
error("Health configuration for alarm '%s' does not have a chart", rc->name);
return 0;
}
if(!rc->update_every) {
error("Health configuration for alarm '%s.%s' has no frequency (parameter 'every'). Ignoring it.", rc->chart?rc->chart:"NOCHART", rc->name);
return 0;
}
if(!RRDCALC_HAS_DB_LOOKUP(rc) && !rc->calculation && !rc->warning && !rc->critical) {
error("Health configuration for alarm '%s.%s' is useless (no db lookup, no calculation, no warning and no critical expressions)", rc->chart?rc->chart:"NOCHART", rc->name);
return 0;
}
if (rrdcalc_exists(host, rc->chart, rc->name, rc->hash_chart, rc->hash))
return 0;
rc->id = rrdcalc_get_unique_id(host, rc->chart, rc->name, &rc->next_event_id);
debug(D_HEALTH, "Health configuration adding alarm '%s.%s' (%u): exec '%s', recipient '%s', green " CALCULATED_NUMBER_FORMAT_AUTO ", red " CALCULATED_NUMBER_FORMAT_AUTO ", lookup: group %d, after %d, before %d, options %u, dimensions '%s', for each dimension '%s', update every %d, calculation '%s', warning '%s', critical '%s', source '%s', delay up %d, delay down %d, delay max %d, delay_multiplier %f, warn_repeat_every %u, crit_repeat_every %u",
rc->chart?rc->chart:"NOCHART",
rc->name,
rc->id,
(rc->exec)?rc->exec:"DEFAULT",
(rc->recipient)?rc->recipient:"DEFAULT",
rc->green,
rc->red,
(int)rc->group,
rc->after,
rc->before,
rc->options,
(rc->dimensions)?rc->dimensions:"NONE",
(rc->foreachdim)?rc->foreachdim:"NONE",
rc->update_every,
(rc->calculation)?rc->calculation->parsed_as:"NONE",
(rc->warning)?rc->warning->parsed_as:"NONE",
(rc->critical)?rc->critical->parsed_as:"NONE",
rc->source,
rc->delay_up_duration,
rc->delay_down_duration,
rc->delay_max_duration,
rc->delay_multiplier,
rc->warn_repeat_every,
rc->crit_repeat_every
);
rrdcalc_add_to_host(host, rc);
return 1;
}
static inline int rrdcalctemplate_add_template_from_config(RRDHOST *host, RRDCALCTEMPLATE *rt) {
if(unlikely(!rt->context)) {
error("Health configuration for template '%s' does not have a context", rt->name);
return 0;
}
if(unlikely(!rt->update_every)) {
error("Health configuration for template '%s' has no frequency (parameter 'every'). Ignoring it.", rt->name);
return 0;
}
if(unlikely(!RRDCALCTEMPLATE_HAS_DB_LOOKUP(rt) && !rt->calculation && !rt->warning && !rt->critical)) {
error("Health configuration for template '%s' is useless (no calculation, no warning and no critical evaluation)", rt->name);
return 0;
}
RRDCALCTEMPLATE *t, *last = NULL;
if(!rt->foreachdim) {
for (t = host->templates; t ; last = t, t = t->next) {
if(unlikely(t->hash_name == rt->hash_name
&& !strcmp(t->name, rt->name)
&&