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);