mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 15:47:01 +02:00
MINOR: stream: Add an option to "show sess" command to dump the captured URI
"show sess" command now supports a list of options that can be set after all other possible arguments (<id>, all...). For now, "show-uri" is the only supported option. With this options, the captured URI, if non-null, is added to the dump of a stream, complete or now. The URI may be anonymized if necessary. This patch should fix the issue #663.
This commit is contained in:
parent
e9bc5937c9
commit
fa43ca2ed0
@ -3321,7 +3321,7 @@ show servers state [<backend>]
|
|||||||
srv_agent_addr: Server health agent address.
|
srv_agent_addr: Server health agent address.
|
||||||
srv_agent_port: Server health agent port.
|
srv_agent_port: Server health agent port.
|
||||||
|
|
||||||
show sess
|
show sess [<options>*]
|
||||||
Dump all known active streams (formerly called "sessions"). Avoid doing this
|
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
|
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
|
only be issued on sockets configured for levels "operator" or "admin". Note
|
||||||
@ -3329,8 +3329,9 @@ show sess
|
|||||||
output reports less entries than really exist because it will dump all
|
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
|
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.
|
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
|
Display a lot of internal information about the matching streams. In the
|
||||||
first form, only the stream matching the specified stream identifier will
|
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
|
be shown. This identifier is the first field at the beginning of the lines in
|
||||||
@ -3347,6 +3348,12 @@ show sess <id> | older <age> | susp | all
|
|||||||
is meant to be interpreted while checking function strm_dump_to_buffer() 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.
|
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>] \
|
show stat [domain <resolvers|proxy>] [{<iid>|<proxy>} <type> <sid>] \
|
||||||
[typed|json] [desc] [up|no-maint]
|
[typed|json] [desc] [up|no-maint]
|
||||||
Dump statistics. The domain is used to select which statistics to print; dns
|
Dump statistics. The domain is used to select which statistics to print; dns
|
||||||
|
68
src/stream.c
68
src/stream.c
@ -3249,7 +3249,8 @@ void list_services(FILE *out)
|
|||||||
|
|
||||||
/* appctx context used by the "show sess" command */
|
/* appctx context used by the "show sess" command */
|
||||||
/* flags used for show_sess_ctx.flags */
|
/* 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 show_sess_ctx {
|
||||||
struct bref bref; /* back-reference from the session being dumped */
|
struct bref bref; /* back-reference from the session being dumped */
|
||||||
@ -3264,11 +3265,13 @@ struct show_sess_ctx {
|
|||||||
|
|
||||||
/* This function appends a complete dump of a stream state onto the buffer,
|
/* This function appends a complete dump of a stream state onto the buffer,
|
||||||
* possibly anonymizing using the specified anon_key. The caller is responsible
|
* possibly anonymizing using the specified anon_key. The caller is responsible
|
||||||
* for ensuring that enough room remains in the buffer to dump a complete
|
* for ensuring that enough room remains in the buffer to dump a complete stream
|
||||||
* stream at once. Each new output line will be prefixed with <pfx> if non-null,
|
* at once. Each new output line will be prefixed with <pfx> if non-null, which
|
||||||
* which is used to preserve indenting.
|
* 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 stconn *scf, *scb;
|
||||||
struct tm tm;
|
struct tm tm;
|
||||||
@ -3411,12 +3414,16 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
|
|||||||
" age=%s)\n",
|
" age=%s)\n",
|
||||||
human_time(ns_to_sec(now_ns) - ns_to_sec(strm->logs.request_ts), 1));
|
human_time(ns_to_sec(now_ns) - ns_to_sec(strm->logs.request_ts), 1));
|
||||||
|
|
||||||
if (strm->txn)
|
if (strm->txn) {
|
||||||
chunk_appendf(buf,
|
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,
|
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),
|
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);
|
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;
|
scf = strm->scf;
|
||||||
chunk_appendf(buf, "%s scf=%p flags=0x%08x ioto=%s state=%s endp=%s,%p,0x%08x sub=%d", pfx,
|
chunk_appendf(buf, "%s scf=%p flags=0x%08x ioto=%s state=%s endp=%s,%p,0x%08x sub=%d", pfx,
|
||||||
@ -3623,6 +3630,14 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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
|
/* 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
|
* 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
|
* buffer is full and it needs to be called again, otherwise non-zero. It is
|
||||||
@ -3649,7 +3664,7 @@ static int stats_dump_full_strm_to_buffer(struct appctx *appctx, struct stream *
|
|||||||
__fallthrough;
|
__fallthrough;
|
||||||
|
|
||||||
case 1:
|
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)
|
if (applet_putchk(appctx, &trash) == -1)
|
||||||
goto full;
|
goto full;
|
||||||
|
|
||||||
@ -3667,6 +3682,7 @@ static int stats_dump_full_strm_to_buffer(struct appctx *appctx, struct stream *
|
|||||||
static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx, void *private)
|
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));
|
struct show_sess_ctx *ctx = applet_reserve_svcctx(appctx, sizeof(*ctx));
|
||||||
|
int cur_arg = 2;
|
||||||
|
|
||||||
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
|
if (!cli_has_level(appctx, ACCESS_LVL_OPER))
|
||||||
return 1;
|
return 1;
|
||||||
@ -3678,28 +3694,47 @@ static int cli_parse_show_sess(char **args, char *payload, struct appctx *appctx
|
|||||||
ctx->pos = 0;
|
ctx->pos = 0;
|
||||||
ctx->thr = 0;
|
ctx->thr = 0;
|
||||||
|
|
||||||
if (*args[2] && strcmp(args[2], "older") == 0) {
|
if (*args[cur_arg] && strcmp(args[cur_arg], "older") == 0) {
|
||||||
unsigned timeout;
|
unsigned timeout;
|
||||||
const char *res;
|
const char *res;
|
||||||
|
|
||||||
if (!*args[3])
|
if (!*args[cur_arg+1])
|
||||||
return cli_err(appctx, "Expects a minimum age (in seconds by default).\n");
|
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)
|
if (res != 0)
|
||||||
return cli_err(appctx, "Invalid age.\n");
|
return cli_err(appctx, "Invalid age.\n");
|
||||||
|
|
||||||
ctx->min_age = timeout;
|
ctx->min_age = timeout;
|
||||||
ctx->target = (void *)-1; /* show all matching entries */
|
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->flags |= CLI_SHOWSESS_F_SUSP;
|
||||||
ctx->target = (void *)-1; /* show all matching entries */
|
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;
|
ctx->target = (void *)-1;
|
||||||
else if (*args[2])
|
cur_arg++;
|
||||||
ctx->target = (void *)strtoul(args[2], NULL, 0);
|
}
|
||||||
|
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 back-ref must be reset, it will be detected and set by
|
||||||
* the dump code upon first invocation.
|
* the dump code upon first invocation.
|
||||||
@ -3897,6 +3932,9 @@ static int cli_io_handler_dump_sess(struct appctx *appctx)
|
|||||||
if (task_in_rq(curr_strm->task))
|
if (task_in_rq(curr_strm->task))
|
||||||
chunk_appendf(&trash, " run(nice=%d)", curr_strm->task->nice);
|
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");
|
chunk_appendf(&trash, "\n");
|
||||||
|
|
||||||
if (applet_putchk(appctx, &trash) == -1) {
|
if (applet_putchk(appctx, &trash) == -1) {
|
||||||
|
Loading…
Reference in New Issue
Block a user