]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: cli: add support for the "show sess all" command
authorWilly Tarreau <w@1wt.eu>
Mon, 26 Nov 2012 00:16:39 +0000 (01:16 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 26 Nov 2012 00:18:33 +0000 (01:18 +0100)
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 !

doc/configuration.txt
src/dumpstats.c

index 362d2fa5b89d596719b7b9db2a57bd48c957b790..bbe882df806b9d0550b6fd361dc85d7ec63c96d3 100644 (file)
@@ -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
index 0fef8f4dfc8ae44ad056c6e268656fd582b1682d..0b1c64ce79c4789168028438d3b5e63d8cb26f4f 100644 (file)
@@ -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");