]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream/cli: make "show sess" support filtering on front/back/server
authorWilly Tarreau <w@1wt.eu>
Fri, 7 Mar 2025 09:34:19 +0000 (10:34 +0100)
committerWilly Tarreau <w@1wt.eu>
Fri, 7 Mar 2025 09:38:12 +0000 (10:38 +0100)
With "show sess", particularly "show sess all", we're often missing the
ability to inspect only streams attached to a frontend, backend or server.
Let's just add these filters to the command. Only one at a time may be set.

One typical use case could be to dump streams attached to a server after
issuing "shutdown sessions server XXX" to figure why any wouldn't stop
for example.

doc/management.txt
src/stream.c

index b4bfcf93719a1c30e36e1c1bb356f2e848461e1a..e02fd7664c6b43758b51774e2f61d4697610d40a 100644 (file)
@@ -3363,7 +3363,10 @@ show sess [<id> | all | help] [<options>*]
 
   It is possible to set some options to customize the dump or apply some
   filters. Here are the supported options:
+    - backend <b>  only display streams attached to this backend
+    - frontend <f> only display streams attached to this frontend
     - older <age>  only display streams older than <age> seconds
+    - server <b/s> only show streams attached to this backend+server
     - show-uri     dump the transaction URI, as captured during the request
                    analysis. It is only displayed if it was captured.
     - susp         only show streams considered as suspicious by the developers
index c7ba90d948bc6cbbfd24507cff404525b49e70a9..2f3a381af2e90747b4bfa5915990496dd359ffe5 100644 (file)
@@ -3269,10 +3269,14 @@ void list_services(FILE *out)
 /* flags used for show_sess_ctx.flags */
 #define CLI_SHOWSESS_F_SUSP     0x00000001   /* show only suspicious streams */
 #define CLI_SHOWSESS_F_DUMP_URI 0x00000002   /* Dump TXN's uri if available in dump */
+#define CLI_SHOWSESS_F_SERVER   0x00000004   /* show only streams attached to this server */
+#define CLI_SHOWSESS_F_BACKEND  0x00000008   /* show only streams attached to this backend */
+#define CLI_SHOWSESS_F_FRONTEND 0x00000010   /* show only streams attached to this frontend */
 
 struct show_sess_ctx {
        struct bref bref;       /* back-reference from the session being dumped */
        void *target;           /* session we want to dump, or NULL for all */
+       void *filter;           /* element to filter on (e.g. server if CLI_SHOWSESS_F_SERVER) */
        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 */
@@ -3779,6 +3783,9 @@ static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx
                             "Available options: \n"
                             "   show-uri     also display the transaction URI, if available\n"
                             "   older <age>  only display streams older than <age> seconds\n"
+                            "   server <b/s> only show streams attached to this backend+server\n"
+                            "   backend <b>  only show streams attached to this backend\n"
+                            "   frontend <f> only show streams attached to this frontend\n"
                             "Without any argument, all streams are dumped in a shorter format.");
                return cli_err(appctx, trash.area);
        }
@@ -3796,6 +3803,63 @@ static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx
                else if (*args[cur_arg] && strcmp(args[cur_arg], "susp") == 0) {
                        ctx->flags |= CLI_SHOWSESS_F_SUSP;
                }
+               else if (*args[cur_arg] && strcmp(args[cur_arg], "server") == 0) {
+                       struct ist be_name, sv_name;
+                       struct proxy *be;
+                       struct server *sv;
+
+                       if (ctx->flags & (CLI_SHOWSESS_F_FRONTEND|CLI_SHOWSESS_F_BACKEND|CLI_SHOWSESS_F_SERVER))
+                               return cli_err(appctx, "Only one of backend, frontend or server may be set.\n");
+
+                       if (!*args[cur_arg + 1])
+                               return cli_err(appctx, "Missing server name (<backend>/<server>).\n");
+
+                       sv_name = ist(args[cur_arg + 1]);
+                       be_name = istsplit(&sv_name, '/');
+                       if (!istlen(sv_name))
+                               return cli_err(appctx, "Require 'backend/server'.\n");
+
+                       if (!(be = proxy_be_by_name(ist0(be_name))))
+                               return cli_err(appctx, "No such backend.\n");
+
+                       if (!(sv = server_find_by_name(be, ist0(sv_name))))
+                               return cli_err(appctx, "No such server.\n");
+                       ctx->flags |= CLI_SHOWSESS_F_SERVER;
+                       ctx->filter = sv;
+                       cur_arg++;
+               }
+               else if (*args[cur_arg] && strcmp(args[cur_arg], "backend") == 0) {
+                       struct proxy *be;
+
+                       if (ctx->flags & (CLI_SHOWSESS_F_FRONTEND|CLI_SHOWSESS_F_BACKEND|CLI_SHOWSESS_F_SERVER))
+                               return cli_err(appctx, "Only one of backend, frontend or server may be set.\n");
+
+                       if (!*args[cur_arg + 1])
+                               return cli_err(appctx, "Missing backend name.\n");
+
+                       if (!(be = proxy_be_by_name(args[cur_arg + 1])))
+                               return cli_err(appctx, "No such backend.\n");
+
+                       ctx->flags |= CLI_SHOWSESS_F_BACKEND;
+                       ctx->filter = be;
+                       cur_arg++;
+               }
+               else if (*args[cur_arg] && strcmp(args[cur_arg], "frontend") == 0) {
+                       struct proxy *fe;
+
+                       if (ctx->flags & (CLI_SHOWSESS_F_FRONTEND|CLI_SHOWSESS_F_BACKEND|CLI_SHOWSESS_F_SERVER))
+                               return cli_err(appctx, "Only one of backend, frontend or server may be set.\n");
+
+                       if (!*args[cur_arg + 1])
+                               return cli_err(appctx, "Missing frontend name.\n");
+
+                       if (!(fe = proxy_fe_by_name(args[cur_arg + 1])))
+                               return cli_err(appctx, "No such frontend.\n");
+
+                       ctx->flags |= CLI_SHOWSESS_F_FRONTEND;
+                       ctx->filter = fe;
+                       cur_arg++;
+               }
                else {
                        chunk_printf(&trash, "Unsupported option '%s', try 'help' for more info.\n", args[cur_arg]);
                        return cli_err(appctx, trash.area);
@@ -3873,6 +3937,16 @@ static int cli_io_handler_dump_sess(struct appctx *appctx)
                                goto next_sess;
                }
 
+               if ((ctx->flags & CLI_SHOWSESS_F_SERVER) &&
+                   (!(curr_strm->be->cap & PR_CAP_BE) || curr_strm->target != ctx->filter))
+                       goto next_sess;
+
+               if ((ctx->flags & CLI_SHOWSESS_F_BACKEND) && (curr_strm->be != ctx->filter))
+                       goto next_sess;
+
+               if ((ctx->flags & CLI_SHOWSESS_F_FRONTEND) && (curr_strm->sess->fe != ctx->filter))
+                       goto next_sess;
+
                if (ctx->flags & CLI_SHOWSESS_F_SUSP) {
                        /* only show suspicious streams. Non-suspicious ones have a valid
                         * expiration date in the future and a valid front endpoint.