mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-13 06:54:37 +00:00
MINOR: cli: add support for the "show sess all" command
Sometimes when debugging haproxy, it is important to take a full snapshot of all sessions and their respective states. Till now it was complicated to do because we had to use scripts and sessions would vanish between two runs. Now with this command we have the same output as "show sess $id" but for all sessions in the table. This is a debugging command only, it should only be used by developers as it is never guaranteed to perfectly work !
This commit is contained in:
parent
95898ac211
commit
7615366c70
@ -11326,7 +11326,9 @@ show sess <id>
|
||||
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.
|
||||
freely evolve depending on demands. The special id "all" dumps the states of
|
||||
all sessions, which can be avoided as much as possible as it is highly CPU
|
||||
intensive and can take a lot of time.
|
||||
|
||||
show stat [<iid> <type> <sid>]
|
||||
Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is
|
||||
|
@ -63,7 +63,7 @@
|
||||
#endif
|
||||
|
||||
static int stats_dump_raw_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_full_sess_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct session *sess);
|
||||
static int stats_dump_sess_to_buffer(struct stream_interface *si);
|
||||
static int stats_dump_errors_to_buffer(struct stream_interface *si);
|
||||
static int stats_table_request(struct stream_interface *si, bool show);
|
||||
@ -929,7 +929,9 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||
si->applet.st0 = STAT_CLI_PRINT;
|
||||
return 1;
|
||||
}
|
||||
if (*args[2])
|
||||
if (*args[2] && strcmp(args[2], "all") == 0)
|
||||
si->applet.ctx.sess.target = (void *)-1;
|
||||
else if (*args[2])
|
||||
si->applet.ctx.sess.target = (void *)strtoul(args[2], NULL, 0);
|
||||
else
|
||||
si->applet.ctx.sess.target = NULL;
|
||||
@ -3416,23 +3418,21 @@ static int stats_dump_proxy(struct stream_interface *si, struct proxy *px, struc
|
||||
* 0 if the output buffer is full and it needs to be called again, otherwise
|
||||
* non-zero. It is designed to be called from stats_dump_sess_to_buffer() below.
|
||||
*/
|
||||
static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
|
||||
static int stats_dump_full_sess_to_buffer(struct stream_interface *si, struct session *sess)
|
||||
{
|
||||
struct tm tm;
|
||||
struct session *sess;
|
||||
extern const char *monthname[12];
|
||||
char pn[INET6_ADDRSTRLEN];
|
||||
|
||||
chunk_reset(&trash);
|
||||
sess = si->applet.ctx.sess.target;
|
||||
|
||||
if (si->applet.ctx.sess.section > 0 && si->applet.ctx.sess.uid != sess->uniq_id) {
|
||||
/* session changed, no need to go any further */
|
||||
chunk_appendf(&trash, " *** session terminated while we were watching it ***\n");
|
||||
if (bi_putchk(si->ib, &trash) == -1)
|
||||
return 0;
|
||||
si->applet.ctx.sess.target = NULL;
|
||||
si->applet.ctx.sess.uid = 0;
|
||||
si->applet.ctx.sess.section = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3695,6 +3695,7 @@ static int stats_dump_full_sess_to_buffer(struct stream_interface *si)
|
||||
}
|
||||
/* end of dump */
|
||||
si->applet.ctx.sess.uid = 0;
|
||||
si->applet.ctx.sess.section = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -3750,19 +3751,23 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si)
|
||||
curr_sess = LIST_ELEM(si->applet.ctx.sess.bref.ref, struct session *, list);
|
||||
|
||||
if (si->applet.ctx.sess.target) {
|
||||
if (si->applet.ctx.sess.target != curr_sess)
|
||||
if (si->applet.ctx.sess.target != (void *)-1 && si->applet.ctx.sess.target != curr_sess)
|
||||
goto next_sess;
|
||||
|
||||
LIST_ADDQ(&curr_sess->back_refs, &si->applet.ctx.sess.bref.users);
|
||||
/* call the proper dump() function and return if we're missing space */
|
||||
if (!stats_dump_full_sess_to_buffer(si))
|
||||
if (!stats_dump_full_sess_to_buffer(si, curr_sess))
|
||||
return 0;
|
||||
|
||||
/* session dump complete */
|
||||
LIST_DEL(&si->applet.ctx.sess.bref.users);
|
||||
LIST_INIT(&si->applet.ctx.sess.bref.users);
|
||||
si->applet.ctx.sess.target = NULL;
|
||||
break;
|
||||
if (si->applet.ctx.sess.target != (void *)-1) {
|
||||
si->applet.ctx.sess.target = NULL;
|
||||
break;
|
||||
}
|
||||
else
|
||||
goto next_sess;
|
||||
}
|
||||
|
||||
chunk_appendf(&trash,
|
||||
@ -3882,7 +3887,7 @@ static int stats_dump_sess_to_buffer(struct stream_interface *si)
|
||||
si->applet.ctx.sess.bref.ref = curr_sess->list.n;
|
||||
}
|
||||
|
||||
if (si->applet.ctx.sess.target) {
|
||||
if (si->applet.ctx.sess.target && si->applet.ctx.sess.target != (void *)-1) {
|
||||
/* specified session not found */
|
||||
if (si->applet.ctx.sess.section > 0)
|
||||
chunk_appendf(&trash, " *** session terminated while we were watching it ***\n");
|
||||
|
Loading…
Reference in New Issue
Block a user