diff options
author | Costa Tsaousis <costa@tsaousis.gr> | 2018-09-27 20:37:52 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-09-27 20:37:52 +0300 |
commit | 73608f86b4c10f72fff991fbf9bfa1a802c2d95c (patch) | |
tree | 56001d6001f5e388ff2eea8cd41a35f9e7d1b598 /src | |
parent | a440a24688f2258bba3ac2e7bbd57c112581893d (diff) |
stock configs in /usr/lib/netdata (#4283)
* makefiles install configs in /usr/lib/netdata/conf.d; #4182
* stock health config in /usr/lib/netdata/conf.d/health.d
* unit test path concatenation
* simplified health file management
* use stream.conf from stock config if it does not exist in /etc/netdata
* indicate loading of user config in function call
* load netdata.conf from stock dir if not found in /etc/netdata
* added NETDATA_USER_CONFIG_DIR
* provide defaults before loading config
* charts.d uses stock files
* fping now uses the stock config files
* tc-qos-helper.sh now uses stock configs
* cgroup-name.sh now uses stock configs too
* simplified cgroup-name.sh for user and stock config
* alarm-notify.sh uses stock configs too
* simplified fping plugin configs loading
* simplified tc-qos-helper.sh configs loading
* added error handling to charts.d.plugin
* apps.plugin used stock configs
* generalized recursive double-directory configs loading
* statsd uses stock configs
* node.d.plugin uses stock configs
* compile-time decision of netdata default paths for all files
* makeself cleans up old stock config files from user configuration directories
* fixed makeself typo
* netdata-installer.sh removes stock files from user configuration directories
* python.d.plugin user/stock configs update
* cleanup stock config files from /etc/netdata, only once
* python.d.plugin log loaded files
* fix permissions of stock config files and provide an "orig" link for quick access
* create help link on stock configs migration for static installations
* create user config directories
* example statsd synthetic charts now state they are examples
* updated configs.signatures
* spec file
* fixes in spec file
* fix typo
* install netdata after cleaning up stock configs from /etc/netdata
* python.d: add cpuidle stock conf
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 1 | ||||
-rw-r--r-- | src/apps_plugin.c | 38 | ||||
-rw-r--r-- | src/common.c | 209 | ||||
-rw-r--r-- | src/common.h | 10 | ||||
-rw-r--r-- | src/health.c | 15 | ||||
-rw-r--r-- | src/health.h | 7 | ||||
-rw-r--r-- | src/health_config.c | 243 | ||||
-rw-r--r-- | src/main.c | 79 | ||||
-rw-r--r-- | src/rrdhost.c | 2 | ||||
-rw-r--r-- | src/statsd.c | 110 | ||||
-rw-r--r-- | src/unit_test.c | 42 |
11 files changed, 485 insertions, 271 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index a794923cdc..d8505d9384 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -8,6 +8,7 @@ AM_CPPFLAGS = \ -DVARLIB_DIR="\"$(varlibdir)\"" \ -DCACHE_DIR="\"$(cachedir)\"" \ -DCONFIG_DIR="\"$(configdir)\"" \ + -DLIBCONFIG_DIR="\"$(libconfigdir)\"" \ -DLOG_DIR="\"$(logdir)\"" \ -DPLUGINS_DIR="\"$(pluginsdir)\"" \ -DRUN_DIR="\"$(localstatedir)/run/netdata\"" \ diff --git a/src/apps_plugin.c b/src/apps_plugin.c index 6525fdeb3e..569a23e929 100644 --- a/src/apps_plugin.c +++ b/src/apps_plugin.c @@ -100,8 +100,9 @@ static int include_exited_childs = 1; -// will be changed to getenv(NETDATA_CONFIG_DIR) if it exists -static char *config_dir = CONFIG_DIR; +// will be changed to getenv(NETDATA_USER_CONFIG_DIR) if it exists +static char *user_config_dir = CONFIG_DIR; +static char *stock_config_dir = LIBCONFIG_DIR; // ---------------------------------------------------------------------------- // internal flags @@ -631,11 +632,11 @@ static struct target *get_apps_groups_target(const char *id, struct target *targ } // read the apps_groups.conf file -static int read_apps_groups_conf(const char *file) +static int read_apps_groups_conf(const char *path, const char *file) { char filename[FILENAME_MAX + 1]; - snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", config_dir, file); + snprintfz(filename, FILENAME_MAX, "%s/apps_%s.conf", path, file); debug_log("process groups file: '%s'", filename); @@ -3569,10 +3570,18 @@ static void parse_args(int argc, char **argv) if(freq > 0) update_every = freq; - if(read_apps_groups_conf("groups")) { - error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", config_dir); - exit(1); + if(read_apps_groups_conf(user_config_dir, "groups")) { + error("Cannot read process groups configuration file '%s/apps_groups.conf'. Will try '%s/apps_groups.conf'", user_config_dir, stock_config_dir); + + if(read_apps_groups_conf(stock_config_dir, "groups")) { + error("Cannot read process groups '%s/apps_groups.conf'. There are no internal defaults. Failing.", stock_config_dir); + exit(1); + } + else + info("Loaded config file '%s/apps_groups.conf'", stock_config_dir); } + else + info("Loaded config file '%s/apps_groups.conf'", user_config_dir); } static int am_i_running_as_root() { @@ -3658,12 +3667,19 @@ int main(int argc, char **argv) { netdata_configured_host_prefix = getenv("NETDATA_HOST_PREFIX"); if(verify_netdata_host_prefix() == -1) exit(1); - config_dir = getenv("NETDATA_CONFIG_DIR"); - if(config_dir == NULL) { + user_config_dir = getenv("NETDATA_USER_CONFIG_DIR"); + if(user_config_dir == NULL) { + // info("NETDATA_CONFIG_DIR is not passed from netdata"); + user_config_dir = CONFIG_DIR; + } + // else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir); + + stock_config_dir = getenv("NETDATA_STOCK_CONFIG_DIR"); + if(stock_config_dir == NULL) { // info("NETDATA_CONFIG_DIR is not passed from netdata"); - config_dir = CONFIG_DIR; + stock_config_dir = LIBCONFIG_DIR; } - // else info("Found NETDATA_CONFIG_DIR='%s'", config_dir); + // else info("Found NETDATA_USER_CONFIG_DIR='%s'", user_config_dir); #ifdef NETDATA_INTERNAL_CHECKS if(debug_flags != 0) { diff --git a/src/common.c b/src/common.c index f29ebfc966..10b5af54d7 100644 --- a/src/common.c +++ b/src/common.c @@ -10,16 +10,17 @@ # define MADV_DONTFORK INHERIT_NONE #endif /* __FreeBSD__ || __APPLE__*/ -char *netdata_configured_hostname = NULL; -char *netdata_configured_config_dir = NULL; -char *netdata_configured_log_dir = NULL; -char *netdata_configured_plugins_dir = NULL; -char *netdata_configured_web_dir = NULL; -char *netdata_configured_cache_dir = NULL; -char *netdata_configured_varlib_dir = NULL; -char *netdata_configured_home_dir = NULL; -char *netdata_configured_host_prefix = NULL; -char *netdata_configured_timezone = NULL; +char *netdata_configured_hostname = NULL; +char *netdata_configured_user_config_dir = CONFIG_DIR; +char *netdata_configured_stock_config_dir = LIBCONFIG_DIR; +char *netdata_configured_log_dir = LOG_DIR; +char *netdata_configured_plugins_dir = NULL; +char *netdata_configured_web_dir = WEB_DIR; +char *netdata_configured_cache_dir = CACHE_DIR; +char *netdata_configured_varlib_dir = VARLIB_DIR; +char *netdata_configured_home_dir = CACHE_DIR; +char *netdata_configured_host_prefix = NULL; +char *netdata_configured_timezone = NULL; struct rlimit rlimit_nofile = { .rlim_cur = 1024, .rlim_max = 1024 }; int enable_ksm = 1; @@ -1431,3 +1432,191 @@ failed: netdata_configured_host_prefix = ""; return -1; } + +char *strdupz_path_subpath(const char *path, const char *subpath) { + if(unlikely(!path || !*path)) path = "."; + if(unlikely(!subpath)) subpath = ""; + + // skip trailing slashes in path + size_t len = strlen(path); + while(len > 0 && path[len - 1] == '/') len--; + + // skip leading slashes in subpath + while(subpath && subpath[0] == '/') subpath++; + + // if the last character in path is / and (there is a subpath or path is now empty) + // keep the trailing slash in path and remove the additional slash + char *slash = "/"; + if(path[len] == '/' && (*subpath || len == 0)) { + slash = ""; + len++; + } + else if(!*subpath) { + // there is no subpath + // no need for trailing slash + slash = ""; + } + + char buffer[FILENAME_MAX + 1]; + snprintfz(buffer, FILENAME_MAX, "%.*s%s%s", (int)len, path, slash, (subpath)?subpath:""); + return strdupz(buffer); +} + +int path_is_dir(const char *path, const char *subpath) { + char *s = strdupz_path_subpath(path, subpath); + + size_t max_links = 100; + + int is_dir = 0; + struct stat statbuf; + while(max_links-- && stat(s, &statbuf) == 0) { + if((statbuf.st_mode & S_IFMT) == S_IFDIR) { + is_dir = 1; + break; + } + else if((statbuf.st_mode & S_IFMT) == S_IFLNK) { + char buffer[FILENAME_MAX + 1]; + ssize_t l = readlink(s, buffer, FILENAME_MAX); + if(l > 0) { + buffer[l] = '\0'; + freez(s); + s = strdupz(buffer); + continue; + } + else { + is_dir = 0; + break; + } + } + else { + is_dir = 0; + break; + } + } + + freez(s); + return is_dir; +} + +int path_is_file(const char *path, const char *subpath) { + char *s = strdupz_path_subpath(path, subpath); + + size_t max_links = 100; + + int is_file = 0; + struct stat statbuf; + while(max_links-- && stat(s, &statbuf) == 0) { + if((statbuf.st_mode & S_IFMT) == S_IFREG) { + is_file = 1; + break; + } + else if((statbuf.st_mode & S_IFMT) == S_IFLNK) { + char buffer[FILENAME_MAX + 1]; + ssize_t l = readlink(s, buffer, FILENAME_MAX); + if(l > 0) { + buffer[l] = '\0'; + freez(s); + s = strdupz(buffer); + continue; + } + else { + is_file = 0; + break; + } + } + else { + is_file = 0; + break; + } + } + + freez(s); + return is_file; +} + +void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath, int (*callback)(const char *filename, void *data), void *data) { + char *udir = strdupz_path_subpath(user_path, subpath); + char *sdir = strdupz_path_subpath(stock_path, subpath); + + debug(D_HEALTH, "Configuration traversing user-config directory '%s', stock config directory '%s'", udir, sdir); + + DIR *dir = opendir(udir); + if (!dir) { + error("Configuration cannot open user-config directory '%s'.", udir); + } + else { + struct dirent *de = NULL; + while((de = readdir(dir))) { + if(de->d_type == DT_DIR + && ( (de->d_name[0] == '.' && de->d_name[1] == '\0') + || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') + )) { + debug(D_HEALTH, "Configuration ignoring user-config directory '%s/%s'", udir, de->d_name); + continue; + } + + if(path_is_dir(udir, de->d_name)) { + recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data); + continue; + } + + size_t len = strlen(de->d_name); + if(path_is_file(udir, de->d_name) && + len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { + char *filename = strdupz_path_subpath(udir, de->d_name); + callback(filename, data); + freez(filename); + } + + else + debug(D_HEALTH, "Health ignoring user config file '%s/%s'", udir, de->d_name); + } + + closedir(dir); + } + + debug(D_HEALTH, "Health configuration traversing stock config directory '%s', user config directory '%s'", sdir, udir); + + dir = opendir(sdir); + if (!dir) { + error("Health configuration cannot open stock config directory '%s'.", sdir); + } + else { + struct dirent *de = NULL; + while((de = readdir(dir))) { + if(de->d_type == DT_DIR + && ( (de->d_name[0] == '.' && de->d_name[1] == '\0') + || (de->d_name[0] == '.' && de->d_name[1] == '.' && de->d_name[2] == '\0') + )) { + debug(D_HEALTH, "Health ignoring stock config directory '%s/%s'", sdir, de->d_name); + continue; + } + + if(path_is_dir(sdir, de->d_name)) { + // we recurse in stock subdirectory, only when there is no corresponding + // user subdirectory - to avoid reading the files twice + + if(!path_is_dir(udir, de->d_name)) + recursive_config_double_dir_load(udir, sdir, de->d_name, callback, data); + + continue; + } + + size_t len = strlen(de->d_name); + if(path_is_file(sdir, de->d_name) && !path_is_file(udir, de->d_name) && + len > 5 && !strcmp(&de->d_name[len - 5], ".conf")) { + char *filename = strdupz_path_subpath(sdir, de->d_name); + callback(filename, data); + freez(filename); + } + + else + debug(D_HEALTH, "Health ignoring stock config file '%s/%s'", sdir, de->d_name); + } + + closedir(dir); + } + + freez(udir); + freez(sdir); +} diff --git a/src/common.h b/src/common.h index e48e3541e3..2806bd989f 100644 --- a/src/common.h +++ b/src/common.h @@ -42,6 +42,7 @@ #include <arpa/inet.h> #include <netinet/tcp.h> #include <sys/ioctl.h> +#include <libgen.h> #ifdef HAVE_NETINET_IN_H #include <netinet/in.h> @@ -349,7 +350,8 @@ typedef enum rrdcalc_status { #include "web_api_v1.h" extern char *netdata_configured_hostname; -extern char *netdata_configured_config_dir; +extern char *netdata_configured_user_config_dir; +extern char *netdata_configured_stock_config_dir; extern char *netdata_configured_log_dir; extern char *netdata_configured_plugins_dir_base; extern char *netdata_configured_plugins_dir; @@ -426,6 +428,12 @@ extern const char *os_type; extern const char *program_version; +extern char *strdupz_path_subpath(const char *path, const char *subpath); +extern int path_is_dir(const char *path, const char *subpath); +extern int path_is_file(const char *path, const char *subpath); +extern void recursive_config_double_dir_load(const char *user_path, const char *stock_path, const char *subpath + , int (*callback)(const char *filename, void *data), void *data); + /* fix for alpine linux */ #ifndef RUSAGE_THREAD #ifdef RUSAGE_CHILDREN diff --git a/src/health.c b/src/health.c index 1753ad68c5..6c689b5a0d 100644 --- a/src/health.c +++ b/src/health.c @@ -8,12 +8,18 @@ unsigned int default_health_enabled = 1; // ---------------------------------------------------------------------------- // health initialization -inline char *health_config_dir(void) { +inline char *health_user_config_dir(void) { char buffer[FILENAME_MAX + 1]; - snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_config_dir); + snprintfz(buffer, FILENAME_MAX, "%s/health.d", netdata_configured_user_config_dir); return config_get(CONFIG_SECTION_HEALTH, "health configuration directory", buffer); } +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); +} + void health_init(void) { debug(D_HEALTH, "Health configuration initializing"); @@ -30,7 +36,8 @@ void health_reload_host(RRDHOST *host) { if(unlikely(!host->health_enabled)) return; - char *path = health_config_dir(); + char *user_path = health_user_config_dir(); + char *stock_path = health_stock_config_dir(); // free all running alarms rrdhost_wrlock(host); @@ -61,7 +68,7 @@ void health_reload_host(RRDHOST *host) { // load the new alarms rrdhost_wrlock(host); - health_readdir(host, path); + health_readdir(host, user_path, stock_path, NULL); // link the loaded alarms to their charts rrdset_foreach_write(st, host) { diff --git a/src/health.h b/src/health.h index 11a5327cb7..741dfcf659 100644 --- a/src/health.h +++ b/src/health.h @@ -1,5 +1,7 @@ // SPDX-License-Identifier: GPL-3.0+ +#include "common.h" + #ifndef NETDATA_HEALTH_H #define NETDATA_HEALTH_H 1 @@ -415,8 +417,9 @@ extern void health_alarm_log( uint32_t flags ); -extern void health_readdir(RRDHOST *host, const char *path); -extern char *health_config_dir(void); +extern void health_readdir(RRDHOST *host, const char *user_path, const char *stock_path, const char *subpath); +extern char *health_user_config_dir(void); +extern char *health_stock_config_dir(void); extern void health_reload_host(RRDHOST *host); extern void health_alarm_log_free(RRDHOST *host); diff --git a/src/health_config.c b/src/health_config.c index 709935656d..9f1b06eaa0 100644 --- a/src/health_config.c +++ b/src/health_config.c @@ -178,7 +178,7 @@ static inline int health_parse_duration(char *string, int *result) { } static inline int health_parse_delay( - size_t line, const char *path, const char *file, char *string, + size_t line, const char *filename, char *string, int *delay_up_duration, int *delay_down_duration, int *delay_max_duration, @@ -204,36 +204,36 @@ static inline int health_parse_delay( if(!strcasecmp(key, "up")) { if (!health_parse_duration(value, delay_up_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_up = 1; } else if(!strcasecmp(key, "down")) { if (!health_parse_duration(value, delay_down_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_down = 1; } else if(!strcasecmp(key, "multiplier")) { *delay_multiplier = strtof(value, NULL); if(isnan(*delay_multiplier) || isinf(*delay_multiplier) || islessequal(*delay_multiplier, 0)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_multiplier = 1; } else if(!strcasecmp(key, "max")) { if (!health_parse_duration(value, delay_max_duration)) { - error("Health configuration at line %zu of file '%s/%s': invalid value '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid value '%s' for '%s' keyword", + line, filename, value, key); } else given_max = 1; } else { - error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", - line, path, file, key); + error("Health configuration at line %zu of file '%s': unknown keyword '%s'", + line, filename, key); } } @@ -287,11 +287,11 @@ static inline uint32_t health_parse_options(const char *s) { } static inline int health_parse_db_lookup( - size_t line, const char *path, const char *file, char *string, + size_t line, const char *filename, char *string, int *group_method, int *after, int *before, int *every, uint32_t *options, char **dimensions ) { - debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s/%s: %s", line, path, file, string); + debug(D_HEALTH, "Health configuration parsing database lookup %zu@%s: %s", line, filename, string); if(*dimensions) freez(*dimensions); *dimensions = NULL; @@ -307,14 +307,14 @@ static inline int health_parse_db_lookup( while(*s && !isspace(*s)) s++; while(*s && isspace(*s)) *s++ = '\0'; if(!*s) { - error("Health configuration invalid chart calculation at line %zu of file '%s/%s': expected group method followed by the 'after' time, but got '%s'", - line, path, file, key); + error("Health configuration invalid chart calculation at line %zu of file '%s': expected group method followed by the 'after' time, but got '%s'", + line, filename, key); return 0; } if((*group_method = web_client_api_request_v1_data_group(key, -1)) == -1) { - error("Health configuration at line %zu of file '%s/%s': invalid group method '%s'", - line, path, file, key); + error("Health configuration at line %zu of file '%s': invalid group method '%s'", + line, filename, key); return 0; } @@ -324,8 +324,8 @@ static inline int health_parse_db_lookup( while(*s && isspace(*s)) *s++ = '\0'; if(!health_parse_duration(key, after)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' after group method", - line, path, file, key); + error("Health configuration at line %zu of file '%s': invalid duration '%s' after group method", + line, filename, key); return 0; } @@ -345,8 +345,8 @@ static inline int health_parse_db_lookup( while(*s && isspace(*s)) *s++ = '\0'; if (!health_parse_duration(value, before)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid duration '%s' for '%s' keyword", + line, filename, value, key); } } else if(!strcasecmp(key, HEALTH_EVERY_KEY)) { @@ -355,8 +355,8 @@ static inline int health_parse_db_lookup( while(*s && isspace(*s)) *s++ = '\0'; if (!health_parse_duration(value, every)) { - error("Health configuration at line %zu of file '%s/%s': invalid duration '%s' for '%s' keyword", - line, path, file, value, key); + error("Health configuration at line %zu of file '%s': invalid duration '%s' for '%s' keyword", + line, filename, value, key); } } else if(!strcasecmp(key, "absolute") || !strcasecmp(key, "abs") || !strcasecmp(key, "absolute_sum")) { @@ -386,17 +386,17 @@ static inline int health_parse_db_lookup( break; } else { - error("Health configuration at line %zu of file '%s/%s': unknown keyword '%s'", - line, path, file, key); + error("Health configuration at line %zu of file '%s': unknown keyword '%s'", + line, filename, key); } } return 1; } -static inline char *health_source_file(size_t line, const char *path, const char *filename) { +static inline char *health_source_file(size_t line, const char *file) { char buffer[FILENAME_MAX + 1]; - snprintfz(buffer, FILENAME_MAX, "%zu@%s/%s", line, path, filename); + snprintfz(buffer, FILENAME_MAX, "%zu@%s", line, file); return strdupz(buffer); } @@ -407,8 +407,10 @@ static inline void strip_quotes(char *s) { } } -int health_readfile(RRDHOST *host, const char *path, const char *filename) { - debug(D_HEALTH, "Health configuration reading file '%s/%s'", path, filename); +static int health_readfile(const char *filename, void *data) { + RRDHOST *host = (RRDHOST *)data; + + debug(D_HEALTH, "Health configuration reading file '%s'", filename); static uint32_t hash_alarm = 0, @@ -455,10 +457,9 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { hash_options = simple_uhash(HEALTH_OPTIONS_KEY); } - snprintfz(buffer, HEALTH_CONF_MAX_LINE, "%s/%s", path, filename); - FILE *fp = fopen(buffer, "r"); + FILE *fp = fopen(filename, "r"); if(!fp) { - error("Health configuration cannot read file '%s'.", buffer); + error("Health configuration cannot read file '%s'.", filename); return 0; } @@ -481,7 +482,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(append < HEALTH_CONF_MAX_LINE) continue; else { - error("Health configuration has too long muli-line at line %zu of file '%s/%s'.", line, path, filename); + error("Health configuration has too long muli-line at line %zu of file '%s'.", line, filename); } } append = 0; @@ -489,7 +490,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { char *key = s; while(*s && *s != ':') s++; if(!*s) { - error("Health configuration has invalid line %zu of file '%s/%s'. It does not contain a ':'. Ignoring it.", line, path, filename); + error("Health configuration has invalid line %zu of file '%s'. It does not contain a ':'. Ignoring it.", line, filename); continue; } *s = '\0'; @@ -500,12 +501,12 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { value = trim_all(value); if(!key) { - error("Health configuration has invalid line %zu of file '%s/%s'. Keyword is empty. Ignoring it.", line, path, filename); + error("Health configuration has invalid line %zu of file '%s'. Keyword is empty. Ignoring it.", line, filename); continue; } if(!value) { - error("Health configuration has invalid line %zu of file '%s/%s'. value is empty. Ignoring it.", line, path, filename); + error("Health configuration has invalid line %zu of file '%s'. value is empty. Ignoring it.", line, filename); continue; } @@ -526,7 +527,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rc->next_event_id = 1; rc->name = strdupz(value); rc->hash = simple_hash(rc->name); - rc->source = health_source_file(line, path, filename); + rc->source = health_source_file(line, filename); rc->green = NAN; rc->red = NAN; rc->value = NAN; @@ -552,7 +553,7 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rt = callocz(1, sizeof(RRDCALCTEMPLATE)); rt->name = strdupz(value); rt->hash_name = simple_hash(rt->name); - rt->source = health_source_file(line, path, filename); + rt->source = health_source_file(line, filename); rt->green = NAN; rt->red = NAN; rt->delay_multiplier = 1.0; @@ -568,10 +569,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(!simple_pattern_matches(os_pattern, host->os)) { if(rc) - debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rc->name, line, path, filename, os_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rc->name, line, filename, os_match); if(rt) - debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: host O/S does not match '%s'", host->hostname, rt->name, line, path, filename, os_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: host O/S does not match '%s'", host->hostname, rt->name, line, filename, os_match); ignore_this = 1; } @@ -584,10 +585,10 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(!simple_pattern_matches(host_pattern, host->hostname)) { if(rc) - debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rc->name, line, path, filename, host_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring alarm '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rc->name, line, filename, host_match); if(rt) - debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s/%s: hostname does not match '%s'", host->hostname, rt->name, line, path, filename, host_match); + debug(D_HEALTH, "HEALTH on '%s' ignoring template '%s' defined at %zu@%s: hostname does not match '%s'", host->hostname, rt->name, line, filename, host_match); ignore_this = 1; } @@ -598,8 +599,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { if(hash == hash_on && !strcasecmp(key, HEALTH_ON_KEY)) { if(rc->chart) { if(strcmp(rc->chart, value) != 0) - 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); + error("Health configuration at line %zu of file '%s' for alarm '%s' has key '%s' twice, once with value '%s' and later with value '%s'. Using ('%s').", + line, filename, rc->name, key, rc->chart, value, value); freez(rc->chart); } @@ -607,29 +608,29 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { rc->hash_chart = simple_hash(rc->chart); } else if(hash == hash_lookup && !strcasecmp(key, HEALTH_LOOKUP_KEY)) { - health_parse_db_lookup(line, path, filename, value, &rc->group, &rc->after, &rc->before, + health_parse_db_lookup(line, filename, value, &rc->group, &rc->after, &rc->before, &rc->update_every, &rc->options, &rc->dimensions); } else if(hash == hash_every && !strcasecmp(key, HEALTH_EVERY_KEY)) { if(!health_parse_duration(value, &rc->update_every)) - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", - line, path, filename, rc->name, key, value); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' cannot parse duration: '%s'.", + line, filename, rc->name, key, value); } else if(hash == hash_green && !strcasecmp(key, HEALTH_GREEN_KEY)) { char *e; rc->green = str2ld(value, &e); if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rc->name, key, e); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", + line, filename, rc->name, key, e); } } else if(hash == hash_red && !strcasecmp(key, HEALTH_RED_KEY)) { char *e; rc->red = str2ld(value, &e); if(e && *e) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", - line, path, filename, rc->name, key, e); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' leaves this string unmatched: '%s'.", + line, filename, rc->name, key, e); } } else if(hash == hash_calc && !strcasecmp(key, HEALTH_CALC_KEY)) { @@ -637,8 +638,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rc->calculation = expression_parse(value, &failed_at, &error); if(!rc->calculation) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_warn && !strcasecmp(key, HEALTH_WARN_KEY)) { @@ -646,8 +647,8 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rc->warning = expression_parse(value, &failed_at, &error); if(!rc->warning) { - error("Health configuration at line %zu of file '%s/%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", - line, path, filename, rc->name, key, value, expression_strerror(error), failed_at); + error("Health configuration at line %zu of file '%s' for alarm '%s' at key '%s' has unparse-able expression '%s': %s at '%s'", + line, filename, rc->name, key, value, expression_strerror(error), failed_at); } } else if(hash == hash_crit && !strcasecmp(key, HEALTH_CRIT_KEY)) { @@ -655,15 +656,15 @@ int health_readfile(RRDHOST *host, const char *path, const char *filename) { int error = 0; rc->critical = expression_par |