]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream/cli: add an optional "older" filter for "show sess"
authorWilly Tarreau <w@1wt.eu>
Fri, 17 Nov 2023 17:32:59 +0000 (18:32 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 17 Nov 2023 18:30:04 +0000 (19:30 +0100)
It's often needed to be able to refine "show sess" when debugging, and
very often a first glance at old streams is performed, but that's a
difficult task in large dumps, and it takes lots of resources to dump
everything.

This commit adds "older <age>" to "show sess" in order to specify the
minimum age of streams that will be dumped. This should simplify the
identification of blocked ones.

doc/management.txt
src/stream.c

index 9e5d9dbc96c3ebf4c04ad00d8e17b43e01f4be28..163c04fe270b0b8f417457dc38b169c04dcd3ab4 100644 (file)
@@ -3144,17 +3144,20 @@ show sess
   the last one that was created before the command was entered; those which
   die in the mean time will not appear.
 
-show sess <id>
-  Display a lot of internal information about the specified session identifier.
-  This identifier is the first field at the beginning of the lines in the dumps
-  of "show sess" (it corresponds to the session pointer). Those information are
-  useless to most users but may be used by haproxy developers to troubleshoot a
-  complex bug. The output format is intentionally not documented so that it can
-  freely evolve depending on demands. You may find a description of all fields
-  returned in src/dumpstats.c
-
-  The special id "all" dumps the states of all sessions, which must be avoided
-  as much as possible as it is highly CPU intensive and can take a lot of time.
+show sess <id> | older <age> | all
+  Display a lot of internal information about the matching sessions. In the
+  first form, only the session matching the specified session identifier will
+  be shown. This identifier is the first field at the beginning of the lines in
+  the dumps of "show sess" (it corresponds to the session pointer). In the
+  second form, only sessions older than <age> (in seconds by default) will be
+  shown. If "all" is used instead, then all sessions will be dumped. Dumping
+  many sessions can produce a huge output, take a lot of time and be CPU
+  intensive, so it's always better to only dump the minimum needed. Those
+  information are useless to most users but may be used by haproxy developers
+  to troubleshoot a complex bug. The output format is intentionally not
+  documented so that it can freely evolve depending on demands. This output
+  is meant to be interpreted while checking function strm_dump_to_buffer() in
+  src/stream.c to figure the exact meaning of certain fields.
 
 show stat [domain <dns|proxy>] [{<iid>|<proxy>} <type> <sid>] [typed|json] \
           [desc] [up|no-maint]
index 9b9c74c17bf90143a27a451903d20a13c7b9a925..1eddd9cd59324d167bf2bfd54e560a3e7143d222 100644 (file)
@@ -3115,6 +3115,7 @@ struct show_sess_ctx {
        void *target;           /* session we want to dump, or NULL for all */
        unsigned int thr;       /* the thread number being explored (0..MAX_THREADS-1) */
        unsigned int uid;       /* if non-null, the uniq_id of the session being dumped */
+       unsigned int min_age;   /* minimum age of streams to dump */
        int section;            /* section of the session being dumped */
        int pos;                /* last position of the current session's buffer */
 };
@@ -3510,16 +3511,32 @@ static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx
        if (!cli_has_level(appctx, ACCESS_LVL_OPER))
                return 1;
 
-       if (*args[2] && strcmp(args[2], "all") == 0)
-               ctx->target = (void *)-1;
-       else if (*args[2])
-               ctx->target = (void *)strtoul(args[2], NULL, 0);
-       else
-               ctx->target = NULL;
+       /* now all sessions by default */
+       ctx->target = NULL;
+       ctx->min_age = 0;
        ctx->section = 0; /* start with stream status */
        ctx->pos = 0;
        ctx->thr = 0;
 
+       if (*args[2] && strcmp(args[2], "older") == 0) {
+               unsigned timeout;
+               const char *res;
+
+               if (!*args[3])
+                       return cli_err(appctx, "Expects a minimum age (in seconds by default).\n");
+
+               res = parse_time_err(args[3], &timeout, TIME_UNIT_S);
+               if (res != 0)
+                       return cli_err(appctx, "Invalid age.\n");
+
+               ctx->min_age = timeout;
+               ctx->target = (void *)-1; /* show all matching entries */
+       }
+       else if (*args[2] && strcmp(args[2], "all") == 0)
+               ctx->target = (void *)-1;
+       else if (*args[2])
+               ctx->target = (void *)strtoul(args[2], NULL, 0);
+
        /* The back-ref must be reset, it will be detected and set by
         * the dump code upon first invocation.
         */
@@ -3596,6 +3613,12 @@ static int cli_io_handler_dump_sess(struct appctx *appctx)
                        continue;
                }
 
+               if (ctx->min_age) {
+                       uint age = ns_to_sec(now_ns) - ns_to_sec(curr_strm->logs.request_ts);
+                       if (age < ctx->min_age)
+                               goto next_sess;
+               }
+
                if (ctx->target) {
                        if (ctx->target != (void *)-1 && ctx->target != curr_strm)
                                goto next_sess;
@@ -3822,7 +3845,7 @@ static int cli_parse_shutdown_sessions_server(char **args, char *payload, struct
 
 /* register cli keywords */
 static struct cli_kw_list cli_kws = {{ },{
-       { { "show", "sess",  NULL },             "show sess [id]                          : report the list of current sessions or dump this exact session", cli_parse_show_sess, cli_io_handler_dump_sess, cli_release_show_sess },
+       { { "show", "sess",  NULL },             "show sess [<id>|all|older <age>]        : report the list of current sessions or dump this exact session", cli_parse_show_sess, cli_io_handler_dump_sess, cli_release_show_sess },
        { { "shutdown", "session",  NULL },      "shutdown session [id]                   : kill a specific session",                                        cli_parse_shutdown_session, NULL, NULL },
        { { "shutdown", "sessions",  "server" }, "shutdown sessions server <bk>/<srv>     : kill sessions on a server",                                      cli_parse_shutdown_sessions_server, NULL, NULL },
        {{},}