From: Willy Tarreau Date: Fri, 17 Nov 2023 17:32:59 +0000 (+0100) Subject: MINOR: stream/cli: add an optional "older" filter for "show sess" X-Git-Tag: v2.9-dev10~23 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3ffcf7beb12ae785d6e168f9666f222b87dd7d85;p=thirdparty%2Fhaproxy.git MINOR: stream/cli: add an optional "older" filter for "show sess" 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 " to "show sess" in order to specify the minimum age of streams that will be dumped. This should simplify the identification of blocked ones. --- diff --git a/doc/management.txt b/doc/management.txt index 9e5d9dbc96..163c04fe27 100644 --- a/doc/management.txt +++ b/doc/management.txt @@ -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 - 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 | older | 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 (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 ] [{|} ] [typed|json] \ [desc] [up|no-maint] diff --git a/src/stream.c b/src/stream.c index 9b9c74c17b..1eddd9cd59 100644 --- a/src/stream.c +++ b/src/stream.c @@ -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 [|all|older ] : 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 / : kill sessions on a server", cli_parse_shutdown_sessions_server, NULL, NULL }, {{},}