From: Amaury Denoyelle Date: Wed, 22 Nov 2023 16:27:57 +0000 (+0100) Subject: MINOR: trace: support -dt optional format X-Git-Tag: v2.9-dev12~77 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e97489a526e5ef2a48b747660e0faf3db5b052d2;p=thirdparty%2Fhaproxy.git MINOR: trace: support -dt optional format Add an optional argument for "-dt". This argument is interpreted as a list of several trace statement separated by comma. For each statement, a specific trace name can be specifed, or none to act on all sources. Using double-colon separator, it is possible to add specifications on the wanted level and verbosity. --- diff --git a/doc/management.txt b/doc/management.txt index 2f106dbbdf..f76a13e7c7 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -402,9 +402,13 @@ list of options is : the libc fails to resolve an address, the startup sequence is not interrupted. - -dt : activate traces on stderr. This enables all trace sources on error - level. This can notably be useful to detect protocol violations from - clients or servers. + -dt [,...] : activates traces on stderr. Without argument, this + enables all trace sources on error level. This can notably be useful to + detect protocol violations from clients or servers. An optional argument + can be used to specify a list of various trace configurations using ',' as + separator. Each element activates one or all trace sources. Additionnaly, + level and verbosity can be optionaly specified on each element using ':' as + inner separator with trace name. -m : limit the total allocatable memory to megabytes across all processes. This may cause some connection refusals or some slowdowns diff --git a/include/haproxy/trace.h b/include/haproxy/trace.h index e91b25dd46..703ac8dbde 100644 --- a/include/haproxy/trace.h +++ b/include/haproxy/trace.h @@ -190,7 +190,7 @@ void trace_no_cb(enum trace_level level, uint64_t mask, const struct trace_sourc void trace_register_source(struct trace_source *source); -int trace_parse_cmd(); +int trace_parse_cmd(char *arg, char **errmsg); /* return a single char to describe a trace state */ static inline char trace_state_char(enum trace_state st) diff --git a/src/haproxy.c b/src/haproxy.c index 0d26ac103a..3b5b1719b2 100644 --- a/src/haproxy.c +++ b/src/haproxy.c @@ -1708,7 +1708,17 @@ static void init_args(int argc, char **argv) kwd_dump = flag + 2; } else if (*flag == 'd' && flag[1] == 't') { - trace_parse_cmd(); + if (argc > 1 && argv[1][0] != '-') { + if (trace_parse_cmd(argv[1], &err_msg)) { + ha_alert("-dt: %s.\n", err_msg); + ha_free(&err_msg); + exit(EXIT_FAILURE); + } + argc--; argv++; + } + else { + trace_parse_cmd(NULL, NULL); + } } else if (*flag == 'd') arg_mode |= MODE_DEBUG; diff --git a/src/trace.c b/src/trace.c index 63853c6722..a233c0de1d 100644 --- a/src/trace.c +++ b/src/trace.c @@ -770,19 +770,110 @@ static int trace_parse_statement(char **args, char **msg) } +void _trace_parse_cmd(struct trace_source *src, int level, int verbosity) +{ + src->sink = sink_find("stderr"); + src->level = level >= 0 ? level : TRACE_LEVEL_ERROR; + src->verbosity = verbosity >= 0 ? verbosity : 1; + src->state = TRACE_STATE_RUNNING; +} + /* Parse a process argument specified via "-dt". * * Returns 0 on success else non-zero. */ -int trace_parse_cmd() +int trace_parse_cmd(char *arg, char **errmsg) { - struct trace_source *src; + char *str; + + if (!arg) { + /* No trace specification, activate all sources on error level. */ + struct trace_source *src = NULL; + + list_for_each_entry(src, &trace_sources, source_link) + _trace_parse_cmd(src, -1, -1); + return 0; + } + + while ((str = strtok(arg, ","))) { + struct trace_source *src = NULL; + char *field, *name; + char *sep; + int level = -1, verbosity = -1; + + /* 1. name */ + name = str; + sep = strchr(str, ':'); + if (sep) { + str = sep + 1; + *sep = '\0'; + } + else { + str = NULL; + } + + if (strlen(name)) { + src = trace_find_source(name); + if (!src) { + memprintf(errmsg, "unknown trace source '%s'", name); + return 1; + } + } + + if (!str || !strlen(str)) + goto parse; + + /* 2. level */ + field = str; + sep = strchr(str, ':'); + if (sep) { + str = sep + 1; + *sep = '\0'; + } + else { + str = NULL; + } + + if (strlen(field)) { + level = trace_parse_level(field); + if (level < 0) { + memprintf(errmsg, "no such level '%s'", field); + return 1; + } + } + + if (!str || !strlen(str)) + goto parse; + + /* 3. verbosity */ + field = str; + if (strchr(field, ':')) { + memprintf(errmsg, "too many double-colon separator"); + return 1; + } + + if (!src && strcmp(field, "quiet") != 0) { + memprintf(errmsg, "trace source must be specified for verbosity other than 'quiet'"); + return 1; + } + + verbosity = trace_source_parse_verbosity(src, field); + if (verbosity < 0) { + memprintf(errmsg, "no such verbosity '%s' for source '%s'", field, name); + return 1; + } + + parse: + if (src) { + _trace_parse_cmd(src, level, verbosity); + } + else { + list_for_each_entry(src, &trace_sources, source_link) + _trace_parse_cmd(src, level, verbosity); + } - list_for_each_entry(src, &trace_sources, source_link) { - src->sink = sink_find("stderr"); - src->level = TRACE_LEVEL_ERROR; - src->verbosity = 1; - src->state = TRACE_STATE_RUNNING; + /* Reset arg to NULL for strtok. */ + arg = NULL; } return 0;