From 5b9503ed33ddee84469624219159b2a2fbf2d1c3 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Wed, 22 May 2024 11:12:32 +0200 Subject: [PATCH] MINOR: traces: enumerate the list of levels/verbosities when not found It's quite frustrating, particularly on the command line, not to have access to the list of available levels and verbosities when one does not exist for a given source, because there's no easy way to find them except by starting without and connecting to the CLI. Let's enumerate the list of supported levels and verbosities when a name does not match. For example: $ ./haproxy -db -f quic-repro.cfg -dt h2:help [NOTICE] (9602) : haproxy version is 3.0-dev12-60496e-27 [NOTICE] (9602) : path to executable is ./haproxy [ALERT] (9602) : -dt: no such trace level 'help', available levels are 'error', 'user', 'proto', 'state', 'data', and 'developer'. $ ./haproxy -db -f quic-repro.cfg -dt h2:user:help [NOTICE] (9604) : haproxy version is 3.0-dev12-60496e-27 [NOTICE] (9604) : path to executable is ./haproxy [ALERT] (9604) : -dt: no such trace verbosity 'help' for source 'h2', available verbosities for this source are: 'quiet', 'clean', 'minimal', 'simple', 'advanced', and 'complete'. The same is done for the CLI where the existing help message is always displayed when entering an invalid verbosity or level. --- doc/management.txt | 6 ++++-- src/trace.c | 51 +++++++++++++++++++++++++--------------------- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/doc/management.txt b/doc/management.txt index 4f3207bb3..d0360185f 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -414,8 +414,10 @@ list of options is : 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. Additionally, - level and verbosity can be optionally specified on each element using ':' as - inner separator with trace name. + level and verbosity can be optionally specified on each element using ':' + as inner separator with trace name. When entering an invalid verbosity or + level name, the list of available keywords is presented. For example it can + be convenient to pass 'help' for each field to consult the list first. -m : limit allocatable memory, which is used to keep process's data, to megabytes. This may cause some connection refusals or some diff --git a/src/trace.c b/src/trace.c index d3a0b95ce..861ec9b01 100644 --- a/src/trace.c +++ b/src/trace.c @@ -566,10 +566,16 @@ static int trace_parse_statement(char **args, char **msg) } else if (strcmp(args[2], "level") == 0) { const char *name = args[3]; - int level; + int level = -1; - if (!*name) { - chunk_printf(&trash, "Supported trace levels for source %s:\n", src->name.ptr); + if (*name) + level = trace_parse_level(name); + + if (level < 0) { + chunk_reset(&trash); + if (*name) + chunk_appendf(&trash, "No such trace level '%s'. ", name); + chunk_appendf(&trash, "Supported trace levels for source %s:\n", src->name.ptr); chunk_appendf(&trash, " %c error : report errors\n", src->level == TRACE_LEVEL_ERROR ? '*' : ' '); chunk_appendf(&trash, " %c user : also information useful to the end user\n", @@ -584,13 +590,7 @@ static int trace_parse_statement(char **args, char **msg) src->level == TRACE_LEVEL_DEVELOPER ? '*' : ' '); trash.area[trash.data] = 0; *msg = strdup(trash.area); - return LOG_WARNING; - } - - level = trace_parse_level(name); - if (level < 0) { - memprintf(msg, "No such trace level '%s'", name); - return LOG_ERR; + return *name ? LOG_ERR : LOG_WARNING; } HA_ATOMIC_STORE(&src->level, level); @@ -734,10 +734,16 @@ static int trace_parse_statement(char **args, char **msg) else if (strcmp(args[2], "verbosity") == 0) { const char *name = args[3]; const struct name_desc *nd; - int verbosity; + int verbosity = -1; - if (!*name) { - chunk_printf(&trash, "Supported trace verbosities for source %s:\n", src->name.ptr); + if (*name) + verbosity = trace_source_parse_verbosity(src, name); + + if (verbosity < 0) { + chunk_reset(&trash); + if (*name) + chunk_appendf(&trash, "No such verbosity level '%s'. ", name); + chunk_appendf(&trash, "Supported trace verbosities for source %s:\n", src->name.ptr); chunk_appendf(&trash, " %c quiet : only report basic information with no decoding\n", src->verbosity == 0 ? '*' : ' '); if (!src->decoding || !src->decoding[0].name) { @@ -751,13 +757,7 @@ static int trace_parse_statement(char **args, char **msg) } trash.area[trash.data] = 0; *msg = strdup(trash.area); - return LOG_WARNING; - } - - verbosity = trace_source_parse_verbosity(src, name); - if (verbosity < 0) { - memprintf(msg, "No such verbosity level '%s'", name); - return LOG_ERR; + return *name ? LOG_ERR : LOG_WARNING; } HA_ATOMIC_STORE(&src->verbosity, verbosity); @@ -837,7 +837,7 @@ int trace_parse_cmd(char *arg, char **errmsg) if (strlen(field)) { level = trace_parse_level(field); if (level < 0) { - memprintf(errmsg, "no such level '%s'", field); + memprintf(errmsg, "no such trace level '%s', available levels are 'error', 'user', 'proto', 'state', 'data', and 'developer'", field); return 1; } } @@ -848,7 +848,7 @@ int trace_parse_cmd(char *arg, char **errmsg) /* 3. verbosity */ field = str; if (strchr(field, ':')) { - memprintf(errmsg, "too many double-colon separator"); + memprintf(errmsg, "too many double-colon separators in trace definition"); return 1; } @@ -859,7 +859,12 @@ int trace_parse_cmd(char *arg, char **errmsg) verbosity = trace_source_parse_verbosity(src, field); if (verbosity < 0) { - memprintf(errmsg, "no such verbosity '%s' for source '%s'", field, name); + const struct name_desc *nd; + + memprintf(errmsg, "no such trace verbosity '%s' for source '%s', available verbosities for this source are: 'quiet'", field, name); + for (nd = src->decoding; nd->name && nd->desc; nd++) + memprintf(errmsg, "%s, %s'%s'", *errmsg, (nd + 1)->name ? "" : "and ", nd->name); + return 1; }