@cryptotaxi247 / netdata-1 / commits / b42d6d9f2

allow any pattern of network interfaces and disk paths to be excluded; fixes #1556; fixes #1567

Costa Tsaousis (ktsaou) committed Jan 14, 2017 at 02:42 UTC b42d6d9f25b160e27bfb7e53942b087982f2e69e
5 files changed +147 -85
src/common.c
+125
@@ -1187,3 +1187,128 @@ int read_single_number_file(const char *filename, unsigned long long *result) {
1187 *result = strtoull(buffer, NULL, 0);
1188 return 0;
1189 }
1190 +
1191 +// ----------------------------------------------------------------------------
1192 +// simple_pattern_match
1193 +
1194 +struct simple_pattern {
1195 + const char *match;
1196 + size_t len;
1197 + NETDATA_SIMPLE_PREFIX_MODE mode;
1198 + struct simple_pattern *next;
1199 +};
1200 +
1201 +NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode) {
1202 + struct simple_pattern *root = NULL;
1203 +
1204 + if(unlikely(!list || !*list)) return root;
1205 +
1206 + char *a = strdupz(list);
1207 + if(a && *a) {
1208 + char *s = a;
1209 +
1210 + while(s && *s) {
1211 + // skip all spaces
1212 + while(isspace(*s)) s++;
1213 +
1214 + // empty string
1215 + if(unlikely(!*s)) break;
1216 +
1217 + // find the next space
1218 + char *c = s;
1219 + while(*c && !isspace(*c)) c++;
1220 +
1221 + // find the next word
1222 + char *n;
1223 + if(likely(*c)) n = c + 1;
1224 + else n = NULL;
1225 +
1226 + // terminate our string
1227 + *c = '\0';
1228 +
1229 + char buf[100 + 1];
1230 + strncpy(buf, s, 100);
1231 + buf[100] = '\0';
1232 + if(likely(n)) *c = ' ';
1233 + s = buf;
1234 +
1235 + NETDATA_SIMPLE_PREFIX_MODE mode;
1236 + size_t len = strlen(s);
1237 + if(len >= 2 && *s == '*' && s[len - 1] == '*') {
1238 + s[len - 1] = '\0';
1239 + s++;
1240 + len -= 2;
1241 + mode = NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING;
1242 + }
1243 + else if(len >= 1 && *s == '*') {
1244 + s++;
1245 + len--;
1246 + mode = NETDATA_SIMPLE_PATTERN_MODE_SUFFIX;
1247 + }
1248 + else if(len >= 1 && s[len - 1] == '*') {
1249 + s[len - 1] = '\0';
1250 + len--;
1251 + mode = NETDATA_SIMPLE_PATTERN_MODE_PREFIX;
1252 + }
1253 + else
1254 + mode = default_mode;
1255 +
1256 + if(len) {
1257 + if(*s == '*')
1258 + error("simple pattern '%s' includes '%s' that is invalid", a, s);
1259 +
1260 + // allocate the structure
1261 + struct simple_pattern *m = mallocz(sizeof(struct simple_pattern));
1262 + m->match = strdup(s);
1263 + m->len = strlen(m->match);
1264 + m->mode = mode;
1265 + m->next = root;
1266 + root = m;
1267 + }
1268 + else
1269 + error("simple pattern '%s' includes invalid matches", a);
1270 +
1271 + // prepare for next loop
1272 + s = n;
1273 + }
1274 + }
1275 +
1276 + free(a);
1277 + return (NETDATA_SIMPLE_PATTERN *)root;
1278 +}
1279 +
1280 +int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str) {
1281 + struct simple_pattern *m, *root = (struct simple_pattern *)list;
1282 +
1283 + if(unlikely(!root)) return 0;
1284 +
1285 + size_t len = strlen(str);
1286 + for(m = root; m ; m = m->next) {
1287 + if(m->len <= len) {
1288 + switch(m->mode) {
1289 + case NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING:
1290 + if(unlikely(strstr(str, m->match)))
1291 + return 1;
1292 + break;
1293 +
1294 + case NETDATA_SIMPLE_PATTERN_MODE_PREFIX:
1295 + if(unlikely(strncmp(str, m->match, m->len) == 0))
1296 + return 1;
1297 + break;
1298 +
1299 + case NETDATA_SIMPLE_PATTERN_MODE_SUFFIX:
1300 + if(unlikely(strcmp(&str[len - m->len], m->match) == 0))
1301 + return 1;
1302 + break;
1303 +
1304 + case NETDATA_SIMPLE_PATTERN_MODE_EXACT:
1305 + default:
1306 + if(unlikely(strcmp(str, m->match) == 0))
1307 + return 1;
1308 + break;
1309 + }
1310 + }
1311 + }
1312 +
1313 + return 0;
1314 +}
src/common.h
+10
@@ -277,4 +277,14 @@ extern void get_system_HZ(void);
277
278 extern int read_single_number_file(const char *filename, unsigned long long *result);
279
280 +typedef enum {
281 + NETDATA_SIMPLE_PATTERN_MODE_EXACT,
282 + NETDATA_SIMPLE_PATTERN_MODE_PREFIX,
283 + NETDATA_SIMPLE_PATTERN_MODE_SUFFIX,
284 + NETDATA_SIMPLE_PATTERN_MODE_SUBSTRING
285 +} NETDATA_SIMPLE_PREFIX_MODE;
286 +typedef void NETDATA_SIMPLE_PATTERN;
287 +extern NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NETDATA_SIMPLE_PREFIX_MODE default_mode);
288 +extern int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char *str);
289 +
290 #endif /* NETDATA_COMMON_H */
src/plugin_proc.c
+2 -7
@@ -68,12 +68,7 @@ void *proc_main(void *ptr)
68 if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
69 error("Cannot set pthread cancel state to ENABLE.");
70
71 - // disable (by default) various interface that are not needed
72 - config_get_boolean("plugin:proc:/proc/net/dev:lo", "enabled", 0);
73 - config_get_boolean("plugin:proc:/proc/net/dev:fireqos_monitor", "enabled", 0);
74 -
75 - // when ZERO, attempt to do it
76 - int vdo_cpu_netdata = !config_get_boolean("plugin:proc", "netdata server resources", 1);
71 + int vdo_cpu_netdata = config_get_boolean("plugin:proc", "netdata server resources", 1);
72
73 // check the enabled status for each module
74 int i;
@@ -116,7 +111,7 @@ void *proc_main(void *ptr)
111
112 // --------------------------------------------------------------------
113
119 - if(!vdo_cpu_netdata) {
114 + if(vdo_cpu_netdata) {
115 static RRDSET *st = NULL;
116 if(unlikely(!st)) {
117 st = rrdset_find_bytype("netdata", "plugin_proc_modules");
src/proc_diskstats.c
+3 -66
@@ -54,71 +54,6 @@ static inline void mountinfo_reload(int force) {
54 }
55
56
57 -// linked list of mount points that are by default disabled
58 -static struct excluded_mount_point {
59 - const char *prefix;
60 - size_t len;
61 - struct excluded_mount_point *next;
62 -} *excluded_mount_points = NULL;
63 -
64 -static inline int is_mount_point_excluded(const char *mount_point) {
65 - static int initialized = 0;
66 -
67 - if(unlikely(!initialized)) {
68 - initialized = 1;
69 -
70 - char *a = config_get("plugin:proc:/proc/diskstats", "exclude space metrics on paths", "/proc/ /sys/ /var/run/user/ /run/user/");
71 - if(a && *a) {
72 - char *s = a;
73 -
74 - while(s && *s) {
75 - // skip all spaces
76 - while(isspace(*s)) s++;
77 -
78 - // empty string
79 - if(unlikely(!*s)) break;
80 -
81 - // find the next space
82 - char *c = s;
83 - while(*c && !isspace(*c)) c++;
84 -
85 - char *n;
86 - if(likely(*c)) n = c + 1;
87 - else n = NULL;
88 -
89 - // terminate our string
90 - *c = '\0';
91 -
92 - // allocate the structure
93 - struct excluded_mount_point *m = mallocz(sizeof(struct excluded_mount_point));
94 - m->prefix = strdup(s);
95 - m->len = strlen(m->prefix);
96 - m->next = excluded_mount_points;
97 - excluded_mount_points = m;
98 -
99 - // prepare for next loop
100 - s = n;
101 - if(likely(n)) *c = ' ';
102 - }
103 - }
104 - }
105 -
106 - size_t len = strlen(mount_point);
107 - struct excluded_mount_point *m;
108 - for(m = excluded_mount_points; m ; m = m->next) {
109 - if(m->len <= len) {
110 - // fprintf(stderr, "SPACE: comparing '%s' with '%s'\n", mount_point, m->prefix);
111 - if(unlikely(strncmp(m->prefix, mount_point, m->len) == 0)) {
112 - // fprintf(stderr, "SPACE: excluded '%s'\n", mount_point);
113 - return 1;
114 - }
115 - }
116 - }
117 -
118 - // fprintf(stderr, "SPACE: included '%s'\n", mount_point);
119 - return 0;
120 -}
121 -
57 // Data to be stored in DICTIONARY mount_points used by do_disk_space_stats().
58 // This DICTIONARY is used to lookup the settings of the mount point on each iteration.
59 struct mount_point_metadata {
@@ -133,10 +68,12 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every, u
68 const char *disk = mi->persistent_id;
69
70 static DICTIONARY *mount_points = NULL;
71 + static NETDATA_SIMPLE_PATTERN *excluded_mountpoints = NULL;
72 int do_space, do_inodes;
73
74 if(unlikely(!mount_points)) {
75 mount_points = dictionary_create(DICTIONARY_FLAG_SINGLE_THREADED);
76 + excluded_mountpoints = netdata_simple_pattern_list_create(config_get("plugin:proc:/proc/diskstats", "exclude space metrics on paths", "/proc/ /sys/ /var/run/user/ /run/user/"), NETDATA_SIMPLE_PATTERN_MODE_PREFIX);
77 }
78
79 struct mount_point_metadata *m = dictionary_get(mount_points, mi->mount_point);
@@ -147,7 +84,7 @@ static inline void do_disk_space_stats(struct mountinfo *mi, int update_every, u
84 int def_space = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "space usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
85 int def_inodes = config_get_boolean_ondemand("plugin:proc:/proc/diskstats", "inodes usage for all disks", CONFIG_ONDEMAND_ONDEMAND);
86
150 - if(unlikely(is_mount_point_excluded(mi->mount_point))) {
87 + if(unlikely(netdata_simple_pattern_list_matches(excluded_mountpoints, mi->mount_point))) {
88 def_space = CONFIG_ONDEMAND_NO;
89 def_inodes = CONFIG_ONDEMAND_NO;
90 }
src/proc_net_dev.c
+7 -12
@@ -112,14 +112,13 @@ static struct netdev *get_netdev(const char *name) {
112 int do_proc_net_dev(int update_every, usec_t dt) {
113 (void)dt;
114
115 + static NETDATA_SIMPLE_PATTERN *disabled_list = NULL;
116 static procfile *ff = NULL;
116 - static int enable_new_interfaces = -1, enable_ifb_interfaces = -1, enable_veth_interfaces = -1;
117 + static int enable_new_interfaces = -1;
118 static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_drops = -1, do_fifo = -1, do_compressed = -1, do_events = -1;
119
120 if(unlikely(enable_new_interfaces == -1)) {
121 enable_new_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", CONFIG_ONDEMAND_ONDEMAND);
121 - enable_ifb_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable ifb interfaces", CONFIG_ONDEMAND_NO);
122 - enable_veth_interfaces = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "enable veth interfaces", enable_new_interfaces);
122
123 do_bandwidth = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
124 do_packets = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
@@ -128,6 +127,8 @@ int do_proc_net_dev(int update_every, usec_t dt) {
127 do_fifo = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "fifo for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
128 do_compressed = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
129 do_events = config_get_boolean_ondemand("plugin:proc:/proc/net/dev", "frames, collisions, carrier counters for all interfaces", CONFIG_ONDEMAND_ONDEMAND);
130 +
131 + 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);
132 }
133
134 if(unlikely(!ff)) {
@@ -153,16 +154,10 @@ int do_proc_net_dev(int update_every, usec_t dt) {
154 // remember we configured it
155 d->configured = 1;
156
156 - // start with the default enabled flag
157 d->enabled = enable_new_interfaces;
158 - if(d->enabled) {
159 - if(unlikely(!strcmp(d->name, "lo")))
160 - d->enabled = CONFIG_ONDEMAND_NO;
161 - else if(unlikely(!strncmp(d->name, "veth", 4)))
162 - d->enabled = enable_veth_interfaces;
163 - else if(unlikely(d->len >= 4 && strcmp(&d->name[d->len - 4], "-ifb") == 0))
164 - d->enabled = enable_ifb_interfaces;
165 - }
158 +
159 + if(d->enabled)
160 + d->enabled = !netdata_simple_pattern_list_matches(disabled_list, d->name);
161
162 char var_name[512 + 1];
163 snprintfz(var_name, 512, "plugin:proc:/proc/net/dev:%s", d->name);