srv_agent_addr: Server health agent address.
srv_agent_port: Server health agent port.
-show sess
+show sess [<options>*]
Dump all known active streams (formerly called "sessions"). Avoid doing this
on slow connections as this can be huge. This command is restricted and can
only be issued on sockets configured for levels "operator" or "admin". Note
output reports less entries than really exist because it will dump all
existing streams up to the last one that was created before the command was
entered; those which die in the mean time will not appear.
+ For supported opitons, see below.
-show sess <id> | older <age> | susp | all
+show sess [<id> | older <age> | susp | all] [<options>*]
Display a lot of internal information about the matching streams. In the
first form, only the stream matching the specified stream identifier will
be shown. This identifier is the first field at the beginning of the lines in
is meant to be interpreted while checking function strm_dump_to_buffer() in
src/stream.c to figure the exact meaning of certain fields.
+ It is possible to set some options to customize the dump. Here are the
+ supported options:
+
+ - show-uri: Dump the transaction URI, as captured during the request
+ analysis. It is only displayed if it was captured.
+
show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
[typed|json] [desc] [up|no-maint]
Dump statistics. The domain is used to select which statistics to print; dns
/* appctx context used by the "show sess" command */
/* flags used for show_sess_ctx.flags */
-#define CLI_SHOWSESS_F_SUSP 0x00000001 /* show only suspicious streams */
+#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 */
struct show_sess_ctx {
struct bref bref; /* back-reference from the session being dumped */
/* This function appends a complete dump of a stream state onto the buffer,
* possibly anonymizing using the specified anon_key. The caller is responsible
- * for ensuring that enough room remains in the buffer to dump a complete
- * stream at once. Each new output line will be prefixed with <pfx> if non-null,
- * which is used to preserve indenting.
+ * for ensuring that enough room remains in the buffer to dump a complete stream
+ * at once. Each new output line will be prefixed with <pfx> if non-null, which
+ * is used to preserve indenting. The context <ctx>, if non-null, will be used
+ * to customize the dump.
*/
-void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const char *pfx, uint32_t anon_key)
+static void __strm_dump_to_buffer(struct buffer *buf, const struct show_sess_ctx *ctx,
+ const struct stream *strm, const char *pfx, uint32_t anon_key)
{
struct stconn *scf, *scb;
struct tm tm;
" age=%s)\n",
human_time(ns_to_sec(now_ns) - ns_to_sec(strm->logs.request_ts), 1));
- if (strm->txn)
+ if (strm->txn) {
chunk_appendf(buf,
- "%s txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s req.f=0x%02x rsp.f=0x%02x\n", pfx,
+ "%s txn=%p flags=0x%x meth=%d status=%d req.st=%s rsp.st=%s req.f=0x%02x rsp.f=0x%02x", pfx,
strm->txn, strm->txn->flags, strm->txn->meth, strm->txn->status,
h1_msg_state_str(strm->txn->req.msg_state), h1_msg_state_str(strm->txn->rsp.msg_state),
strm->txn->req.flags, strm->txn->rsp.flags);
+ if (ctx && (ctx->flags & CLI_SHOWSESS_F_DUMP_URI) && strm->txn->uri)
+ chunk_appendf(buf, " uri=\"%s\"", HA_ANON_STR(anon_key, strm->txn->uri));
+ chunk_memcat(buf, "\n", 1);
+ }
scf = strm->scf;
chunk_appendf(buf, "%s scf=%p flags=0x%08x ioto=%s state=%s endp=%s,%p,0x%08x sub=%d", pfx,
}
}
+/* Context-less function to append a complet dump of a stream state onto the
+ * buffer. It relies on __strm_dump_to_buffer.
+ */
+void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const char *pfx, uint32_t anon_key)
+{
+ __strm_dump_to_buffer(buf, NULL, strm, pfx, anon_key);
+}
+
/* This function dumps a complete stream state onto the stream connector's
* read buffer. The stream has to be set in strm. It returns 0 if the output
* buffer is full and it needs to be called again, otherwise non-zero. It is
__fallthrough;
case 1:
- strm_dump_to_buffer(&trash, strm, "", appctx->cli_anon_key);
+ __strm_dump_to_buffer(&trash, ctx, strm, "", appctx->cli_anon_key);
if (applet_putchk(appctx, &trash) == -1)
goto full;
static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx, void *private)
{
struct show_sess_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
+ int cur_arg = 2;
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
return 1;
ctx->pos = 0;
ctx->thr = 0;
- if (*args[2] && strcmp(args[2], "older") == 0) {
+ if (*args[cur_arg] && strcmp(args[cur_arg], "older") == 0) {
unsigned timeout;
const char *res;
- if (!*args[3])
+ if (!*args[cur_arg+1])
return cli_err(appctx, "Expects a minimum age (in seconds by default).\n");
- res = parse_time_err(args[3], &timeout, TIME_UNIT_S);
+ res = parse_time_err(args[cur_arg+1], &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 */
+ cur_arg +=2;
}
- else if (*args[2] && strcmp(args[2], "susp") == 0) {
+ else if (*args[cur_arg] && strcmp(args[cur_arg], "susp") == 0) {
ctx->flags |= CLI_SHOWSESS_F_SUSP;
ctx->target = (void *)-1; /* show all matching entries */
+ cur_arg++;
}
- else if (*args[2] && strcmp(args[2], "all") == 0)
+ else if (*args[cur_arg] && strcmp(args[cur_arg], "all") == 0) {
ctx->target = (void *)-1;
- else if (*args[2])
- ctx->target = (void *)strtoul(args[2], NULL, 0);
+ cur_arg++;
+ }
+ else if (*args[cur_arg]) {
+ ctx->target = (void *)strtoul(args[cur_arg], NULL, 0);
+ if (ctx->target)
+ cur_arg++;
+ }
+
+ /* show-sess options parsing */
+ while (*args[cur_arg]) {
+ if (*args[cur_arg] && strcmp(args[cur_arg], "show-uri") == 0) {
+ ctx->flags |= CLI_SHOWSESS_F_DUMP_URI;
+ }
+ else {
+ chunk_printf(&trash, "Unsupported option '%s'.\n", args[cur_arg]);
+ return cli_err(appctx, trash.area);
+ }
+ cur_arg++;
+ }
/* The back-ref must be reset, it will be detected and set by
* the dump code upon first invocation.
if (task_in_rq(curr_strm->task))
chunk_appendf(&trash, " run(nice=%d)", curr_strm->task->nice);
+ if ((ctx->flags & CLI_SHOWSESS_F_DUMP_URI) && curr_strm->txn && curr_strm->txn->uri)
+ chunk_appendf(&trash, " uri=\"%s\"", HA_ANON_CLI(curr_strm->txn->uri));
+
chunk_appendf(&trash, "\n");
if (applet_putchk(appctx, &trash) == -1) {