RRDCALCTEMPLATE *rt;
for(rt = st->rrdhost->templates; rt ; rt = rt->next) {
- if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context)) {
+ if(rt->hash_context == st->hash_context && !strcmp(rt->context, st->context)
+ && (!rt->family_pattern || simple_pattern_matches(rt->family_pattern, st->family))) {
RRDCALC *rc = rrdcalc_create(st->rrdhost, rt, st->id);
if(unlikely(!rc))
error("Health tried to create alarm from template '%s', but it failed", rt->name);
expression_free(rt->warning);
expression_free(rt->critical);
+ freez(rt->family_match);
+ simple_pattern_free(rt->family_pattern);
+
freez(rt->name);
freez(rt->exec);
freez(rt->recipient);
#define HEALTH_ALARM_KEY "alarm"
#define HEALTH_TEMPLATE_KEY "template"
#define HEALTH_ON_KEY "on"
+#define HEALTH_FAMILIES_KEY "families"
#define HEALTH_LOOKUP_KEY "lookup"
#define HEALTH_CALC_KEY "calc"
#define HEALTH_EVERY_KEY "every"
int health_readfile(const char *path, const char *filename) {
debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename);
- static uint32_t hash_alarm = 0, hash_template = 0, hash_on = 0, hash_calc = 0, hash_green = 0, hash_red = 0, hash_warn = 0, hash_crit = 0, hash_exec = 0, hash_every = 0, hash_lookup = 0, hash_units = 0, hash_info = 0, hash_recipient = 0, hash_delay = 0;
+ static uint32_t hash_alarm = 0, hash_template = 0, hash_on = 0, hash_families = 0, hash_calc = 0, hash_green = 0, hash_red = 0, hash_warn = 0, hash_crit = 0, hash_exec = 0, hash_every = 0, hash_lookup = 0, hash_units = 0, hash_info = 0, hash_recipient = 0, hash_delay = 0;
char buffer[HEALTH_CONF_MAX_LINE + 1];
if(unlikely(!hash_alarm)) {
hash_alarm = simple_uhash(HEALTH_ALARM_KEY);
hash_template = simple_uhash(HEALTH_TEMPLATE_KEY);
hash_on = simple_uhash(HEALTH_ON_KEY);
+ hash_families = simple_uhash(HEALTH_FAMILIES_KEY);
hash_calc = simple_uhash(HEALTH_CALC_KEY);
hash_lookup = simple_uhash(HEALTH_LOOKUP_KEY);
hash_green = simple_uhash(HEALTH_GREEN_KEY);
if(rc->chart) {
if(strcmp(rc->chart, value))
error("Health configuration at line %zu of file '%s/%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rc->name, key, rc->chart, value, value);
+ line, path, filename, rc->name, key, rc->chart, value, value);
freez(rc->chart);
}
if(rt->context) {
if(strcmp(rt->context, value))
error("Health configuration at line %zu of file '%s/%s' for template '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').",
- line, path, filename, rt->name, key, rt->context, value, value);
+ line, path, filename, rt->name, key, rt->context, value, value);
freez(rt->context);
}
rt->context = tabs2spaces(strdupz(value));
rt->hash_context = simple_hash(rt->context);
}
+ else if(hash == hash_families && !strcasecmp(key, HEALTH_FAMILIES_KEY)) {
+ freez(rt->family_match);
+ simple_pattern_free(rt->family_pattern);
+
+ rt->family_match = tabs2spaces(strdupz(value));
+ rt->family_pattern = simple_pattern_create(rt->family_match, SIMPLE_PATTERN_EXACT);
+ }
else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) {
health_parse_db_lookup(line, path, filename, value, &rt->group, &rt->after, &rt->before,
- &rt->update_every,
- &rt->options, &rt->dimensions);
+ &rt->update_every, &rt->options, &rt->dimensions);
}
else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) {
if(!health_parse_duration(value, &rt->update_every))
char *context;
uint32_t hash_context;
+ char *family_match;
+ SIMPLE_PATTERN *family_pattern;
+
char *source; // the source of this alarm
char *units; // the units of the alarm
char *info; // a short description of the alarm
const char *heystack = argv[optind];
const char *needle = argv[optind + 1];
- NETDATA_SIMPLE_PATTERN *p = netdata_simple_pattern_list_create(heystack, NETDATA_SIMPLE_PATTERN_MODE_EXACT);
- int ret = netdata_simple_pattern_list_matches(p, needle);
- netdata_simple_pattern_free(p);
+ SIMPLE_PATTERN *p = simple_pattern_create(heystack
+ , SIMPLE_PATTERN_EXACT);
+ int ret = simple_pattern_matches(p, needle);
+ simple_pattern_free(p);
if(ret) {
fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s'\n", heystack, needle);
const char *disk = mi->persistent_id;
static DICTIONARY *mount_points = NULL;
- static NETDATA_SIMPLE_PATTERN *excluded_mountpoints = NULL;
+ static SIMPLE_PATTERN *excluded_mountpoints = NULL;
int do_space, do_inodes;
if(unlikely(!mount_points)) {
const char *s;
- NETDATA_SIMPLE_PREFIX_MODE mode = NETDATA_SIMPLE_PATTERN_MODE_EXACT;
+ SIMPLE_PREFIX_MODE mode = SIMPLE_PATTERN_EXACT;
if(config_exists("plugin:proc:/proc/diskstats", "exclude space metrics on paths") && !config_exists("plugin:proc:diskspace", "exclude space metrics on paths")) {
// the config exists in the old section
s = config_get("plugin:proc:/proc/diskstats", "exclude space metrics on paths", DELAULT_EXLUDED_PATHS);
- mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
+ mode = SIMPLE_PATTERN_PREFIX;
}
else
s = config_get("plugin:proc:diskspace", "exclude space metrics on paths", DELAULT_EXLUDED_PATHS);
mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
- excluded_mountpoints = netdata_simple_pattern_list_create(s, mode);
+ excluded_mountpoints = simple_pattern_create(s, mode);
}
struct mount_point_metadata *m = dictionary_get(mount_points, mi->mount_point);
int def_space = config_get_boolean_ondemand("plugin:proc:diskspace", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
int def_inodes = config_get_boolean_ondemand("plugin:proc:diskspace", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
- if(unlikely(netdata_simple_pattern_list_matches(excluded_mountpoints, mi->mount_point))) {
+ if(unlikely(simple_pattern_matches(excluded_mountpoints, mi->mount_point))) {
def_space = CONFIG_ONDEMAND_NO;
def_inodes = CONFIG_ONDEMAND_NO;
}
int do_proc_net_dev(int update_every, usec_t dt) {
(void)dt;
- static NETDATA_SIMPLE_PATTERN *disabled_list = NULL;
+ static SIMPLE_PATTERN *disabled_list = NULL;
static procfile *ff = NULL;
static int enable_new_interfaces = -1;
static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
- disabled_list = netdata_simple_pattern_list_create(config_get("plugin:proc:/proc/net/dev", "disable by default interfaces matching", "lo fireqos* *-ifb"), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
+ disabled_list = simple_pattern_create(
+ config_get("plugin:proc:/proc/net/dev", "disable by default interfaces matching", "lo fireqos* *-ifb")
+ , SIMPLE_PATTERN_EXACT);
}
if(unlikely(!ff)) {
d->enabled = enable_new_interfaces;
if(d->enabled)
- d->enabled = !netdata_simple_pattern_list_matches(disabled_list, d->name);
+ d->enabled = !simple_pattern_matches(disabled_list, d->name);
char var_name[512 + 1];
snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", d->name);
const char *match;
size_t len;
- NETDATA_SIMPLE_PREFIX_MODE mode;
+ SIMPLE_PREFIX_MODE mode;
char negative;
struct simple_pattern *child;
struct simple_pattern *next;
};
-static inline struct simple_pattern *parse_pattern(const char *str, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
- /*
- * DEBUG
- info(">>>> PARSE: '%s'", str);
- */
-
- NETDATA_SIMPLE_PREFIX_MODE mode;
+static inline struct simple_pattern *parse_pattern(const char *str, SIMPLE_PREFIX_MODE default_mode) {
+ SIMPLE_PREFIX_MODE mode;
struct simple_pattern *child = NULL;
char *buf = strdupz(str);
if(len >= 2 && *s == '*' && s[len - 1] == '*') {
s[len - 1] = '\0';
s++;
- mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
+ mode = SIMPLE_PATTERN_SUBSTRING;
}
else if(len >= 1 && *s == '*') {
s++;
- mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
+ mode = SIMPLE_PATTERN_SUFFIX;
}
else if(len >= 1 && s[len - 1] == '*') {
s[len - 1] = '\0';
- mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
+ mode = SIMPLE_PATTERN_PREFIX;
}
else
mode = default_mode;
m->mode = mode;
}
else {
- m->mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
+ m->mode = SIMPLE_PATTERN_SUBSTRING;
}
m->child = child;
freez(buf);
- /*
- * DEBUG
- info("PATTERN '%s' is composed by", str);
- struct simple_pattern *p;
- for(p = m; p ; p = p->child)
- info(">>>> COMPONENT: '%s%s%s' (len %zu type %u)",
- (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- p->match,
- (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- p->len,
- p->mode);
- */
-
return m;
}
-NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
+SIMPLE_PATTERN *simple_pattern_create(const char *list, SIMPLE_PREFIX_MODE default_mode) {
struct simple_pattern *root = NULL, *last = NULL;
if(unlikely(!list || !*list)) return root;
}
freez(buf);
- return (NETDATA_SIMPLE_PATTERN *)root;
+ return (SIMPLE_PATTERN *)root;
}
static inline int match_pattern(struct simple_pattern *m, const char *str, size_t len) {
- /*
- * DEBUG
- *
- info("CHECK string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
- (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- m->match,
- (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- m->len, m->mode);
- */
-
char *s;
if(m->len <= len) {
switch(m->mode) {
- case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
+ case SIMPLE_PATTERN_SUBSTRING:
if(!m->len) return 1;
if((s = strstr(str, m->match))) {
if(!m->child) return 1;
}
break;
- case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
+ case SIMPLE_PATTERN_PREFIX:
if(unlikely(strncmp(str, m->match, m->len) == 0)) {
if(!m->child) return 1;
return match_pattern(m->child, &str[m->len], len - m->len);
}
break;
- case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
+ case SIMPLE_PATTERN_SUFFIX:
if(unlikely(strcmp(&str[len - m->len], m->match) == 0)) {
if(!m->child) return 1;
return 0;
}
break;
- case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
+ case SIMPLE_PATTERN_EXACT:
default:
if(unlikely(strcmp(str, m->match) == 0)) {
if(!m->child) return 1;
return 0;
}
-int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
+int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str) {
struct simple_pattern *m, *root = (struct simple_pattern *)list;
if(unlikely(!root)) return 0;
size_t len = strlen(str);
for(m = root; m ; m = m->next)
if(match_pattern(m, str, len)) {
- /*
- * DEBUG
- *
- info("MATCHED string '%s' (len %zu) with pattern '%s%s%s' (len %zu type %u)", str, len,
- (m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- m->match,
- (m->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || m->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- m->len, m->mode);
-
- struct simple_pattern *p;
- for(p = m; p ; p = p->child)
- info(">>>> MATCHED COMPONENT: '%s%s%s' (len %zu type %u)",
- (p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUFFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- p->match,
- (p->mode == NETDATA_SIMPLE_PATTERN_MODE_PREFIX || p->mode == NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING)?"*":"",
- p->len,
- p->mode);
- */
-
if(m->negative) return 0;
return 1;
}
freez(m);
}
-void netdata_simple_pattern_free(NETDATA_SIMPLE_PATTERN *list) {
+void simple_pattern_free(SIMPLE_PATTERN *list) {
+ if(!list) return;
+
free_pattern(((struct simple_pattern *)list)->next);
}
#define NETDATA_SIMPLE_PATTERN_H
typedef enum {
- NETDATA_SIMPLE_PATTERN_MODE_EXACT,
- NETDATA_SIMPLE_PATTERN_MODE_PREFIX,
- NETDATA_SIMPLE_PATTERN_MODE_SUFFIX,
- NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING
-} NETDATA_SIMPLE_PREFIX_MODE;
+ SIMPLE_PATTERN_EXACT,
+ SIMPLE_PATTERN_PREFIX,
+ SIMPLE_PATTERN_SUFFIX,
+ SIMPLE_PATTERN_SUBSTRING
+} SIMPLE_PREFIX_MODE;
-typedef void NETDATA_SIMPLE_PATTERN;
-extern NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode);
-extern int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str);
-extern void netdata_simple_pattern_free(NETDATA_SIMPLE_PATTERN *list);
+typedef void SIMPLE_PATTERN;
+
+// create a simple_pattern from the string given
+// default_mode is used in cases where EXACT matches, without an asterisk,
+// should be considered PREFIX matches.
+extern SIMPLE_PATTERN *simple_pattern_create(const char *list, SIMPLE_PREFIX_MODE default_mode);
+
+// test if string str is matched from the pattern
+extern int simple_pattern_matches(SIMPLE_PATTERN *list, const char *str);
+
+// free a simple_pattern that was created with simple_pattern_create()
+// list can be NULL, in which case, this does nothing.
+extern void simple_pattern_free(SIMPLE_PATTERN *list);
#endif //NETDATA_SIMPLE_PATTERN_H
static int cgroup_root_max = 500;
static int cgroup_max_depth = 0;
-static NETDATA_SIMPLE_PATTERN *disabled_cgroups_patterns = NULL;
-static NETDATA_SIMPLE_PATTERN *disabled_cgroup_paths = NULL;
-static NETDATA_SIMPLE_PATTERN *disabled_cgroup_renames = NULL;
-static NETDATA_SIMPLE_PATTERN *systemd_services_cgroups = NULL;
+static SIMPLE_PATTERN *disabled_cgroups_patterns = NULL;
+static SIMPLE_PATTERN *disabled_cgroup_paths = NULL;
+static SIMPLE_PATTERN *disabled_cgroup_renames = NULL;
+static SIMPLE_PATTERN *systemd_services_cgroups = NULL;
static char *cgroups_rename_script = PLUGINS_DIR "/cgroup-name.sh";
cgroup_enable_new_cgroups_detected_at_runtime = config_get_boolean("plugin:cgroups", "enable new cgroups detected at run time", cgroup_enable_new_cgroups_detected_at_runtime);
- disabled_cgroups_patterns = netdata_simple_pattern_list_create(
- config_get("plugin:cgroups", "disable by default cgroups matching",
- " *.mount "
+ disabled_cgroups_patterns = simple_pattern_create(
+ config_get("plugin:cgroups", "disable by default cgroups matching", " *.mount "
" *.partition "
" *.service "
" *.slice "
" /systemd "
" /user "
" /user.slice "
- ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
-
- disabled_cgroup_paths = netdata_simple_pattern_list_create(
- config_get("plugin:cgroups", "do not search for cgroups in paths matching",
- " *-qemu " // #345
- " /init.scope "
- " /system "
- " /systemd "
- " /user "
- " /user.slice "
- ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
+ ), SIMPLE_PATTERN_EXACT);
+
+ disabled_cgroup_paths = simple_pattern_create(
+ config_get("plugin:cgroups", "do not search for cgroups in paths matching"
+ , " *-qemu " // #345
+ " /init.scope "
+ " /system "
+ " /systemd "
+ " /user "
+ " /user.slice "
+ ), SIMPLE_PATTERN_EXACT);
cgroups_rename_script = config_get("plugin:cgroups", "script to get cgroup names", cgroups_rename_script);
- disabled_cgroup_renames = netdata_simple_pattern_list_create(
- config_get("plugin:cgroups", "do not run script to rename cgroups matching",
- " / "
+ disabled_cgroup_renames = simple_pattern_create(
+ config_get("plugin:cgroups", "do not run script to rename cgroups matching", " / "
" *.mount "
" *.partition "
" *.scope "
" *.slice "
" *.swap "
" *.user "
- ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
+ ), SIMPLE_PATTERN_EXACT);
if(cgroup_enable_systemd_services)
- systemd_services_cgroups = netdata_simple_pattern_list_create(
- config_get("plugin:cgroups", "cgroups to match as systemd services",
- " !/system.slice/*/*.service /system.slice/*.service "
- ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
+ systemd_services_cgroups = simple_pattern_create(
+ config_get("plugin:cgroups", "cgroups to match as systemd services"
+ , " !/system.slice/*/*.service /system.slice/*.service "
+ ), SIMPLE_PATTERN_EXACT);
mountinfo_free(root);
}
return NULL;
}
- int def = netdata_simple_pattern_list_matches(disabled_cgroups_patterns, id)?0:cgroup_enable_new_cgroups_detected_at_runtime;
+ int def = simple_pattern_matches(disabled_cgroups_patterns, id)?0:cgroup_enable_new_cgroups_detected_at_runtime;
struct cgroup *cg = callocz(1, sizeof(struct cgroup));
cg->id = strdupz(id);
cgroup_root_count++;
// fix the chart_id and title by calling the external script
- if(!netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->id) &&
- !netdata_simple_pattern_list_matches(disabled_cgroup_renames, cg->chart_id)) {
+ if(!simple_pattern_matches(disabled_cgroup_renames, cg->id) &&
+ !simple_pattern_matches(disabled_cgroup_renames, cg->chart_id)) {
cgroup_get_chart_name(cg);
// check if this cgroup should be a systemd service
if(cgroup_enable_systemd_services) {
- if(netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->id) ||
- netdata_simple_pattern_list_matches(systemd_services_cgroups, cg->chart_id)) {
+ if(simple_pattern_matches(systemd_services_cgroups, cg->id) ||
+ simple_pattern_matches(systemd_services_cgroups, cg->chart_id)) {
debug(D_CGROUP, "cgroup '%s' with chart id '%s' (title: '%s') matches systemd services cgroups", cg->id, cg->chart_id, cg->chart_title);
char buffer[CGROUP_CHARTID_LINE_MAX + 1];
// do not decent in directories we are not interested
int def = 1;
- if(netdata_simple_pattern_list_matches(disabled_cgroup_paths, r))
+ if(simple_pattern_matches(disabled_cgroup_paths, r))
def = 0;
// we check for this option here