@cryptotaxi247 / netdata-1 / commits / 1fc3b1fd4

support negative simple patterns; improved help options; added command line option to test simple patterns

Costa Tsaousis (ktsaou) committed Jan 15, 2017 at 17:51 UTC 1fc3b1fd4c3d293dcf7ea959440824ad333266f0
3 files changed +125 -24
src/main.c
+107 -19
@@ -214,20 +214,19 @@ void kill_childs()
214 }
215
216 struct option_def options[] = {
217 - // opt description arg name default value
218 - {'c', "Load alternate configuration file", "config_file", CONFIG_DIR "/" CONFIG_FILENAME},
219 - {'D', "Disable fork into background", NULL, NULL},
220 - {'h', "Display help message", NULL, NULL},
221 - {'P', "File to save a pid while running", "FILE", NULL},
222 - {'i', "The IP address to listen to.", "address", "All addresses"},
223 - {'k', "Check daemon configuration.", NULL, NULL},
224 - {'p', "Port to listen. Can be from 1 to 65535.", "port_number", "19999"},
225 - {'s', "Path to access host /proc and /sys when running in a container.", "PATH", NULL},
226 - {'t', "The frequency in seconds, for data collection. \
227 -Same as 'update every' config file option.", "seconds", "1"},
228 - {'u', "System username to run as.", "username", "netdata"},
229 - {'v', "Version of the program", NULL, NULL},
230 - {'W', "vendor options.", "stacksize=N|unittest|debug_flags=N", NULL},
217 + // opt description arg name default value
218 + { 'c', "Configuration file to load.", "filename", CONFIG_DIR "/" CONFIG_FILENAME},
219 + { 'D', "Do not fork. Run in the foreground.", NULL, "run in the background"},
220 + { 'h', "Display this help message.", NULL, NULL},
221 + { 'P', "File to save a pid while running.", "filename", "do not save pid to a file"},
222 + { 'i', "The IP address to listen to.", "IP", "all IP addresses IPv4 and IPv6"},
223 + { 'k', "Check health configuration and exit.", NULL, NULL},
224 + { 'p', "API/Web port to use.", "port", "19999"},
225 + { 's', "Prefix for /proc and /sys (for containers).", "path", "no prefix"},
226 + { 't', "The internal clock of netdata.", "seconds", "1"},
227 + { 'u', "Run as user.", "username", "netdata"},
228 + { 'v', "Print netdata version and exit.", NULL, NULL},
229 + { 'W', "See Advanced options below.", "options", NULL},
230 };
231
232 void help(int exitcode) {
@@ -249,20 +248,63 @@ void help(int exitcode) {
248 }
249 }
250
252 - fprintf(stream, "SYNOPSIS: netdata [options]\n");
251 + if(max_len_arg > 30) max_len_arg = 30;
252 + if(max_len_arg < 20) max_len_arg = 20;
253 +
254 + fprintf(stream, "\n"
255 + " ^\n"
256 + " |.-. .-. .-. .-. . netdata \n"
257 + " | '-' '-' '-' '-' real-time performance monitoring, done right! \n"
258 + " +----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+--->\n"
259 + "\n"
260 + " Copyright (C) 2017, Costa Tsaousis <costa@tsaousis.gr>\n"
261 + " Released under GNU Public License v3 or later.\n"
262 + " All rights reserved.\n"
263 + "\n"
264 + " Home Page : https://my-netdata.io\n"
265 + " Source Code: https://github.com/firehol/netdata\n"
266 + " Wiki / Docs: https://github.com/firehol/netdata/wiki\n"
267 + " Support : https://github.com/firehol/netdata/issues\n"
268 + " License : https://github.com/firehol/netdata/blob/master/LICENSE.md\n"
269 + "\n"
270 + " Twitter : https://twitter.com/linuxnetdata\n"
271 + " Facebook : https://www.facebook.com/linuxnetdata/\n"
272 + "\n"
273 + " netdata is a https://firehol.org project.\n"
274 + "\n"
275 + "\n"
276 + );
277 +
278 + fprintf(stream, " SYNOPSIS: netdata [options]\n");
279 fprintf(stream, "\n");
254 - fprintf(stream, "Options:\n");
280 + fprintf(stream, " Options:\n\n");
281
282 // Output options description.
283 for( i = 0; i < num_opts; i++ ) {
284 fprintf(stream, " -%c %-*s %s", options[i].val, max_len_arg, options[i].arg_name ? options[i].arg_name : "", options[i].description);
285 if(options[i].default_value) {
260 - fprintf(stream, " Default: %s\n", options[i].default_value);
286 + fprintf(stream, "\n %c %-*s Default: %s\n", ' ', max_len_arg, "", options[i].default_value);
287 } else {
288 fprintf(stream, "\n");
289 }
290 + fprintf(stream, "\n");
291 }
292
293 + fprintf(stream, "\n Advanced options:\n\n"
294 + " -W stacksize=N Set the stacksize (in bytes).\n\n"
295 + " -W debug_flags=N Set runtime tracing to debug.log.\n\n"
296 + " -W unittest Run internal unittests and exit.\n\n"
297 + " -W simple-pattern pattern string\n"
298 + " Check if string matches pattern and exit.\n\n"
299 + );
300 +
301 + fprintf(stream, "\n Signals netdata handles:\n\n"
302 + " - HUP Close and reopen log files.\n"
303 + " - USR1 Save internal DB to disk.\n"
304 + " - USR2 Reload health configuration.\n"
305 + "\n"
306 + );
307 +
308 fflush(stream);
309 exit(exitcode);
310 }
@@ -347,6 +389,9 @@ int main(int argc, char **argv)
389 string_i++;
390 }
391 }
392 + // terminate optstring
393 + optstring[string_i] ='\0';
394 + optstring[(num_opts *2)] ='\0';
395
396 int opt;
397 while( (opt = getopt(argc, argv, optstring)) != -1 ) {
@@ -404,10 +449,53 @@ int main(int argc, char **argv)
449 if(unit_test_storage()) exit(1);
450 fprintf(stderr, "\n\nALL TESTS PASSED\n\n");
451 exit(0);
407 - } else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
452 + }
453 + else if(strcmp(optarg, "simple-pattern") == 0) {
454 + if(optind + 2 > argc) {
455 + fprintf(stderr, "%s", "\nUSAGE: -W simple-pattern 'pattern' 'string'\n\n"
456 + " Checks if 'pattern' matches the given 'string'.\n"
457 + " - 'pattern' can be one or more space separated words.\n"
458 + " - each 'word' can contain one or more asterisks.\n"
459 + " - words starting with '!' give negative matches.\n"
460 + " - words are processed left to right\n"
461 + "\n"
462 + "Examples:\n"
463 + "\n"
464 + " > match all veth interfaces, except veth0:\n"
465 + "\n"
466 + " -W simple-pattern '!veth0 veth*' 'veth12'\n"
467 + "\n"
468 + "\n"
469 + " > match all *.ext files directly in /path/:\n"
470 + " (this will not match *.ext files in a subdir of /path/)\n"
471 + "\n"
472 + " -W simple-pattern '!/path/*/*.ext /path/*.ext' '/path/test.ext'\n"
473 + "\n"
474 + );
475 + exit(1);
476 + }
477 +
478 + const char *heystack = argv[optind];
479 + const char *needle = argv[optind + 1];
480 +
481 + NETDATA_SIMPLE_PATTERN *p = netdata_simple_pattern_list_create(heystack, NETDATA_SIMPLE_PATTERN_MODE_EXACT);
482 + int ret = netdata_simple_pattern_list_matches(p, needle);
483 + netdata_simple_pattern_free(p);
484 +
485 + if(ret) {
486 + fprintf(stdout, "RESULT: MATCHED - pattern '%s' matches '%s'\n", heystack, needle);
487 + exit(0);
488 + }
489 + else {
490 + fprintf(stdout, "RESULT: NOT MATCHED - pattern '%s' does not match '%s'\n", heystack, needle);
491 + exit(1);
492 + }
493 + }
494 + else if(strncmp(optarg, stacksize_string, strlen(stacksize_string)) == 0) {
495 optarg += strlen(stacksize_string);
496 config_set("global", "pthread stack size", optarg);
410 - } else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
497 + }
498 + else if(strncmp(optarg, debug_flags_string, strlen(debug_flags_string)) == 0) {
499 optarg += strlen(debug_flags_string);
500 config_set("global", "debug flags", optarg);
501 debug_flags = strtoull(optarg, NULL, 0);
src/simple_pattern.c
+17 -4
@@ -3,7 +3,9 @@
3 struct simple_pattern {
4 const char *match;
5 size_t len;
6 +
7 NETDATA_SIMPLE_PREFIX_MODE mode;
8 + char negative;
9
10 struct simple_pattern *child;
11
@@ -26,7 +28,7 @@ static inline struct simple_pattern *parse_pattern(const char *str, NETDATA_SIMP
28 while(*c == '*') c++;
29
30 // find the next asterisk
29 - while(*c && *c != '*') c++ ;
31 + while(*c && *c != '*') c++;
32
33 // do we have an asterisk in the middle?
34 if(*c == '*' && c[1] != '\0') {
@@ -57,7 +59,7 @@ static inline struct simple_pattern *parse_pattern(const char *str, NETDATA_SIMP
59 // allocate the structure
60 struct simple_pattern *m = callocz(1, sizeof(struct simple_pattern));
61 if(*s) {
60 - m->match = strdup(s);
62 + m->match = strdupz(s);
63 m->len = strlen(m->match);
64 m->mode = mode;
65 }
@@ -67,7 +69,7 @@ static inline struct simple_pattern *parse_pattern(const char *str, NETDATA_SIMP
69
70 m->child = child;
71
70 - free(buf);
72 + freez(buf);
73
74 /*
75 * DEBUG
@@ -95,9 +97,16 @@ NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NET
97 char *s = buf;
98
99 while(s && *s) {
100 + char negative = 0;
101 +
102 // skip all spaces
103 while(isspace(*s)) s++;
104
105 + if(*s == '!') {
106 + negative = 1;
107 + s++;
108 + }
109 +
110 // empty string
111 if(unlikely(!*s)) break;
112
@@ -114,6 +123,7 @@ NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NET
123 *c = '\0';
124
125 struct simple_pattern *m = parse_pattern(s, default_mode);
126 + m->negative = negative;
127
128 if(likely(n)) *c = ' ';
129
@@ -130,7 +140,7 @@ NETDATA_SIMPLE_PATTERN *netdata_simple_pattern_list_create(const char *list, NET
140 }
141 }
142
133 - free(buf);
143 + freez(buf);
144 return (NETDATA_SIMPLE_PATTERN *)root;
145 }
146
@@ -211,6 +221,7 @@ int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char
221 p->mode);
222 */
223
224 + if(m->negative) return 0;
225 return 1;
226 }
227
@@ -218,6 +229,8 @@ int netdata_simple_pattern_list_matches(NETDATA_SIMPLE_PATTERN *list, const char
229 }
230
231 static inline void free_pattern(struct simple_pattern *m) {
232 + if(!m) return;
233 +
234 if(m->next) free_pattern(m->next);
235 if(m->child) free_pattern(m->child);
236 freez((void *)m->match);
src/sys_fs_cgroup.c
+1 -1
@@ -144,7 +144,7 @@ void read_cgroup_plugin_configuration() {
144 if(cgroup_enable_systemd_services)
145 systemd_services_cgroups = netdata_simple_pattern_list_create(
146 config_get("plugin:cgroups", "cgroups to match as systemd services",
147 - " /system.slice/*.service "
147 + " !/system.slice/*/*.service /system.slice/*.service "
148 ), NETDATA_SIMPLE_PATTERN_MODE_EXACT);
149
150 mountinfo_free(root);