]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: traces: enumerate the list of levels/verbosities when not found
authorWilly Tarreau <w@1wt.eu>
Wed, 22 May 2024 09:12:32 +0000 (11:12 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 22 May 2024 09:17:57 +0000 (11:17 +0200)
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
src/trace.c

index 4f3207bb34122dfe44ccf78b3b31072262bcfb09..d0360185f543430d7bec3f450e44106aa5256772 100644 (file)
@@ -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> : limit allocatable memory, which is used to keep process's data,
     to <limit> megabytes. This may cause some connection refusals or some
index d3a0b95ce27c5f8635b705518d56af7a5139a371..861ec9b013a38735a7f864169c1c839ee0792371 100644 (file)
@@ -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;
                }