]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] stats: replace the stats socket analyser with an SI applet
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Sep 2009 17:31:03 +0000 (19:31 +0200)
committerWilly Tarreau <w@1wt.eu>
Wed, 23 Sep 2009 21:52:17 +0000 (23:52 +0200)
We can get rid of the stats analyser by moving all the stats code
to a stream interface applet. Above being cleaner, it provides new
advantages such as the ability to process requests and responses
from the same function and work only with simple state machines.
There's no need for any hijack hack anymore.

The direct advantage for the user are the interactive mode and the
ability to chain several commands delimited by a semi-colon. Now if
the user types "prompt", he gets a prompt from which he can send
as many requests as he wants. All outputs are terminated by a
blank line followed by a new prompt, so this can be used from
external tools too.

The code is not very clean, it needs some rework, but some part
of the dirty parts are due to the remnants of the hijack mode used
in the old functions we call.

The old AN_REQ_STATS_SOCK analyser flag is now unused and has been
removed.

doc/configuration.txt
include/proto/dumpstats.h
include/types/buffers.h
src/dumpstats.c
src/proto_uxst.c
src/session.c

index 4a7c08034ca683e991d8f43341e9e27912f18c8e..79fe2fa0bc0bb7b2e0098d560346140cedac94e5 100644 (file)
@@ -6490,27 +6490,35 @@ page. Both means provide a CSV format whose fields follow.
 -------------------------
 
 The following commands are supported on the UNIX stats socket ; all of them
-must be terminated by a line feed. It is important to understand that when
-multiple haproxy processes are started on the same sockets, any process may
-pick up the request and will output its own stats.
-
-show stat [<iid> <type> <sid>]
-  Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is
-  possible to dump only selected items :
-    - <iid> is a proxy ID, -1 to dump everything
-    - <type> selects the type of dumpable objects : 1 for frontends, 2 for
-       backends, 4 for servers, -1 for everything. These values can be ORed,
-       for example:
-          1 + 2     = 3   -> frontend + backend.
-          1 + 2 + 4 = 7   -> frontend + backend + server.
-    - <sid> is a server ID, -1 to dump everything from the selected proxy.
-
-show info
-  Dump info about haproxy status on current process.
-
-show sess
-  Dump all known sessions. Avoid doing this on slow connections as this can
-  be huge.
+must be terminated by a line feed. The socket supports pipelining, so that it
+is possible to chain multiple commands at once provided they are delimited by
+a semi-colon or a line feed, although the former is more reliable as it has no
+risk of being truncated over the network. The responses themselves will each be
+followed by an empty line, so it will be easy for an external script to match a
+given response with a given request. By default one command line is processed
+then the connection closes, but there is an interactive allowing multiple lines
+to be issued one at a time.
+
+It is important to understand that when multiple haproxy processes are started
+on the same sockets, any process may pick up the request and will output its
+own stats.
+
+help
+  Print the list of known keywords and their basic usage. The same help screen
+  is also displayed for unknown commands.
+
+prompt
+  Toggle the prompt at the beginning of the line and enter or leave interactive
+  mode. In interactive mode, the connection is not closed after a command
+  completes. Instead, the prompt will appear again, indicating the user that
+  the interpreter is waiting for a new command. The prompt consists in a right
+  angle bracket followed by a space "> ". This mode is particularly convenient
+  when one wants to periodically check information such as stats or errors.
+  It is also a good idea to enter interactive mode before issuing a "help"
+  command.
+
+quit
+  Close the connection when in interactive mode.
 
 show errors [<iid>]
   Dump last known request and response errors collected by frontends and
@@ -6563,6 +6571,47 @@ show errors [<iid>]
     is the slash ('/') in header name "header/bizarre", which is not a valid
     HTTP character for a header name.
 
+show info
+  Dump info about haproxy status on current process.
+
+show sess
+  Dump all known sessions. Avoid doing this on slow connections as this can
+  be huge.
+
+show stat [<iid> <type> <sid>]
+  Dump statistics in the CSV format. By passing <id>, <type> and <sid>, it is
+  possible to dump only selected items :
+    - <iid> is a proxy ID, -1 to dump everything
+    - <type> selects the type of dumpable objects : 1 for frontends, 2 for
+       backends, 4 for servers, -1 for everything. These values can be ORed,
+       for example:
+          1 + 2     = 3   -> frontend + backend.
+          1 + 2 + 4 = 7   -> frontend + backend + server.
+    - <sid> is a server ID, -1 to dump everything from the selected proxy.
+
+  Example :
+    >>> $ echo "show info;show stat" | socat stdio unix-connect:/tmp/sock1
+        Name: HAProxy
+        Version: 1.4-dev2-49
+        Release_date: 2009/09/23
+        Nbproc: 1
+        Process_num: 1
+        (...)
+
+        # pxname,svname,qcur,qmax,scur,smax,slim,stot,bin,bout,dreq,  (...)
+        stats,FRONTEND,,,0,0,1000,0,0,0,0,0,0,,,,,OPEN,,,,,,,,,1,1,0, (...)
+        stats,BACKEND,0,0,0,0,1000,0,0,0,0,0,,0,0,0,0,UP,0,0,0,,0,250,(...)
+        (...)
+        www1,BACKEND,0,0,0,0,1000,0,0,0,0,0,,0,0,0,0,UP,1,1,0,,0,250, (...)
+
+        $
+
+    Here, two commands have been issued at once. That way it's easy to find
+    which process the stats apply to in multi-process mode. Notice the empty
+    line after the information output which marks the end of the first block.
+    A similar empty line appears at the end of the second block (stats) so that
+    the reader knows the output has not been trucated.
+
 /*
  * Local variables:
  *  fill-column: 79
index a0167a7f1f858630c3a8bdf27feb805f7b0cadfc..7a92c987da9419f37508db1a344f13ce38247f0f 100644 (file)
@@ -3,7 +3,7 @@
   This file contains definitions of some primitives to dedicated to
   statistics output.
 
-  Copyright (C) 2000-2008 Willy Tarreau - w@1wt.eu
+  Copyright (C) 2000-2009 Willy Tarreau - w@1wt.eu
 
   This library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
@@ -44,8 +44,8 @@
 #define STATS_ST_REP   2
 #define STATS_ST_CLOSE 3
 
-int stats_sock_parse_request(struct session *s, char *line);
-int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit);
+int stats_sock_parse_request(struct stream_interface *si, char *line);
+void stats_io_handler(struct stream_interface *si);
 int stats_dump_raw(struct session *s, struct buffer *rep, struct uri_auth *uri);
 void stats_dump_raw_to_buffer(struct session *s, struct buffer *req);
 int stats_dump_http(struct session *s, struct buffer *rep, struct uri_auth *uri);
index 14cb966dad5355174eaa97c8fe644d58c43037d4..c7ac91b52ce9d7f9723b8d7cbb2e961f57d22fad 100644 (file)
 #define AN_REQ_HTTP_INNER       0x00000020  /* inner processing of HTTP request */
 #define AN_REQ_HTTP_TARPIT      0x00000040  /* wait for end of HTTP tarpit */
 #define AN_REQ_HTTP_BODY        0x00000080  /* inspect HTTP request body */
-#define AN_REQ_STATS_SOCK       0x00000100  /* process stats socket request */
 
 #define AN_RTR_HTTP_HDR         0x00000200  /* inspect HTTP response headers */
 #define AN_REQ_PRST_RDP_COOKIE  0x00000400  /* persistence on rdp cookie */
index 97de0e9f26948b1b68e5361c669d2a8c2f5dadb2..390f853c5849e7ac7b1ca28011bb5cca368c0e96 100644 (file)
 
 const char stats_sock_usage_msg[] =
         "Unknown command. Please enter one of the following commands only :\n"
+        "  help        : this message\n"
+        "  prompt      : toggle interactive mode with prompt\n"
+        "  quit        : disconnect\n"
         "  show info   : report information about the running process\n"
         "  show stat   : report counters for each proxy and server\n"
         "  show errors : report last request and response errors for each proxy\n"
         "  show sess   : report the list of current sessions\n"
-       "\n";
+       "";
 
 const struct chunk stats_sock_usage = {
         .str = (char *)&stats_sock_usage_msg,
@@ -122,7 +125,7 @@ static int stats_parse_global(char **args, int section_type, struct proxy *curpx
                global.stats_sock.options = LI_O_NONE;
                global.stats_sock.accept = uxst_event_accept;
                global.stats_sock.handler = process_session;
-               global.stats_sock.analysers = AN_REQ_STATS_SOCK;
+               global.stats_sock.analysers = 0;
                global.stats_sock.nice = -64;  /* we want to boost priority for local stats */
                global.stats_sock.private = global.stats_fe; /* must point to the frontend */
 
@@ -228,12 +231,15 @@ int print_csv_header(struct chunk *msg, int size)
                            "\n");
 }
 
-/* Parses the request line in <cmd> and possibly starts dumping stats on
- * s->rep with the hijack bit set. Returns 1 if OK, 0 in case of any error.
- * The line is modified after parsing.
+/* Processes the stats interpreter on the statistics socket. This function is
+ * called from an applet running in a stream interface. Right now we still
+ * support older functions which used to emulate servers and to set
+ * STATS_ST_CLOSE upon completion, but we also support a new interactive mode.
+ * The function returns 1 if the request was understood, otherwise zero.
  */
-int stats_sock_parse_request(struct session *s, char *line)
+int stats_sock_parse_request(struct stream_interface *si, char *line)
 {
+       struct session *s = si->private;
        char *args[MAX_STATS_ARGS + 1];
        int arg;
 
@@ -260,6 +266,8 @@ int stats_sock_parse_request(struct session *s, char *line)
        while (++arg <= MAX_STATS_ARGS)
                args[arg] = line;
 
+       si->st0 = 0;
+       s->data_ctx.stats.flags = 0;
        if (strcmp(args[0], "show") == 0) {
                if (strcmp(args[1], "stat") == 0) {
                        if (*args[2] && *args[3] && *args[4]) {
@@ -271,21 +279,21 @@ int stats_sock_parse_request(struct session *s, char *line)
 
                        s->data_ctx.stats.flags |= STAT_SHOW_STAT;
                        s->data_ctx.stats.flags |= STAT_FMT_CSV;
+                       s->data_state = DATA_ST_INIT;
                        s->ana_state = STATS_ST_REP;
-                       stream_int_retnclose(s->rep->cons, NULL);
-                       buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
+                       si->st0 = 3; // stats_dump_raw_to_buffer
                }
                else if (strcmp(args[1], "info") == 0) {
                        s->data_ctx.stats.flags |= STAT_SHOW_INFO;
                        s->data_ctx.stats.flags |= STAT_FMT_CSV;
+                       s->data_state = DATA_ST_INIT;
                        s->ana_state = STATS_ST_REP;
-                       stream_int_retnclose(s->rep->cons, NULL);
-                       buffer_install_hijacker(s, s->rep, stats_dump_raw_to_buffer);
+                       si->st0 = 3; // stats_dump_raw_to_buffer
                }
                else if (strcmp(args[1], "sess") == 0) {
+                       s->data_state = DATA_ST_INIT;
                        s->ana_state = STATS_ST_REP;
-                       stream_int_retnclose(s->rep->cons, NULL);
-                       buffer_install_hijacker(s, s->rep, stats_dump_sess_to_buffer);
+                       si->st0 = 4; // stats_dump_sess_to_buffer
                }
                else if (strcmp(args[1], "errors") == 0) {
                        if (*args[2])
@@ -293,9 +301,9 @@ int stats_sock_parse_request(struct session *s, char *line)
                        else
                                s->data_ctx.errors.iid  = -1;
                        s->data_ctx.errors.px = NULL;
+                       s->data_state = DATA_ST_INIT;
                        s->ana_state = STATS_ST_REP;
-                       stream_int_retnclose(s->rep->cons, NULL);
-                       buffer_install_hijacker(s, s->rep, stats_dump_errors_to_buffer);
+                       si->st0 = 5; // stats_dump_errors_to_buffer
                }
                else { /* neither "stat" nor "info" nor "sess" */
                        return 0;
@@ -307,70 +315,207 @@ int stats_sock_parse_request(struct session *s, char *line)
        return 1;
 }
 
-/* Processes the stats interpreter on the statistics socket.
- * In order to ease the transition, we simply simulate the server status
- * for now. It only knows states STATS_ST_INIT, STATS_ST_REQ, STATS_ST_REP, and
- * STATS_ST_CLOSE. It removes its analyser bit from req->analysers once done.
- * It always returns 0.
+/* This I/O handler runs as an applet embedded in a stream interface. It is
+ * used to processes I/O from/to the stats unix socket. Right now we still
+ * support older functions which used to emulate servers and to set
+ * STATS_ST_CLOSE upon completion, but we also support a new interactive mode.
+ * The system relies on a request/response flip-flop state machine. We read
+ * a request, then we process it and send the response. Then we can read again.
+ * This could be enhanced a lot but we're still bound to support older output
+ * functions which were designed to work as hijackers.
+ * At the moment, we use si->st0 as the output type, and si->st1 to indicate
+ * whether we're in prompt mode or not.
  */
-int stats_sock_req_analyser(struct session *s, struct buffer *req, int an_bit)
+void stats_io_handler(struct stream_interface *si)
 {
-       char *line, *p;
-
-       switch (s->ana_state) {
-       case STATS_ST_INIT:
-               /* Stats output not initialized yet */
-               memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
-               s->data_source = DATA_SRC_STATS;
-               s->ana_state = STATS_ST_REQ;
-               buffer_dont_connect(s->req);
-               /* fall through */
+       struct session *s = si->private;
+       struct buffer *req = si->ob;
+       struct buffer *res = si->ib;
+       int reql;
+       int len;
+
+       if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
+               goto out;
+
+       while (1) {
+               if (s->ana_state == STATS_ST_INIT) {
+                       /* Stats output not initialized yet */
+                       memset(&s->data_ctx.stats, 0, sizeof(s->data_ctx.stats));
+                       s->data_source = DATA_SRC_STATS;
+                       s->ana_state = STATS_ST_REQ;
+               }
+               else if (s->ana_state == STATS_ST_REQ) {
+                       reql = buffer_si_peekline(si->ob, trash, sizeof(trash));
+                       if (reql <= 0) { /* closed or EOL not found */
+                               if (reql == 0)
+                                       break;
+                               s->ana_state = STATS_ST_CLOSE;
+                               continue;
+                       }
 
-       case STATS_ST_REQ:
-               /* Now, stats are initialized, hijack is not set, and
-                * we are waiting for a complete request line.
-                */
+                       /* seek for a possible semi-colon. If we find one, we
+                        * replace it with an LF and skip only this part.
+                        */
+                       for (len = 0; len < reql; len++)
+                               if (trash[len] == ';') {
+                                       trash[len] = '\n';
+                                       reql = len + 1;
+                                       break;
+                               }
 
-               line = s->req->data;
-               p = memchr(line, '\n', s->req->l);
+                       /* ensure we have a full line */
+                       if (trash[reql-1] != '\n') {
+                               s->ana_state = STATS_ST_CLOSE;
+                               continue;
+                       }
 
-               if (p) {
-                       *p = '\0';
-                       if (!stats_sock_parse_request(s, line)) {
-                               /* invalid request */
-                               stream_int_retnclose(s->req->prod, &stats_sock_usage);
-                               s->ana_state = 0;
-                               req->analysers = 0;
-                               return 0;
+                       len = reql - 1;
+                       trash[len] = '\0';
+
+                       si->st0 = 1; // default to prompt
+                       if (len) {
+                               if (strcmp(trash, "quit") == 0) {
+                                       s->ana_state = STATS_ST_CLOSE;
+                                       continue;
+                               }
+                               else if (strcmp(trash, "prompt") == 0)
+                                       si->st1 = !si->st1;
+                               else if (strcmp(trash, "help") == 0 ||
+                                        !stats_sock_parse_request(si, trash))
+                                       si->st0 = 2; // help
+                       }
+                       else if (!si->st1) {
+                               /* if prompt is disabled, print help on empty lines,
+                                * so that the user at least knows how to enable
+                                * prompt and find help.
+                                */
+                               si->st0 = 2;
                        }
+
+                       /* re-adjust req buffer */
+                       buffer_skip(si->ob, reql);
+
+                       s->ana_state = STATS_ST_REP;
+                       req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
                }
+               else if (s->ana_state == STATS_ST_REP) {
+                       if (res->flags & (BF_SHUTR_NOW|BF_SHUTR)) {
+                               s->ana_state = STATS_ST_CLOSE;
+                               continue;
+                       }
+
+                       switch (si->st0) {
+                       case 2: /* help */
+                               if (buffer_feed(si->ib, stats_sock_usage.str, stats_sock_usage.len) < 0)
+                                       /* message sent or too large for buffer (!) */
+                                       si->st0 = 1; // send prompt
+                               break;
+                       case 3: /* stats/info dump, should be split later ? */
+                               stats_dump_raw_to_buffer(s, res);
+                               si->ib->flags |= BF_READ_PARTIAL; /* remove this once we use buffer_feed */
+                               if (s->ana_state == STATS_ST_CLOSE)
+                                       si->st0 = 1; // end of command, send prompt
+                               break;
+                       case 4: /* sessions dump */
+                               stats_dump_sess_to_buffer(s, res);
+                               si->ib->flags |= BF_READ_PARTIAL; /* remove this once we use buffer_feed */
+                               if (s->ana_state == STATS_ST_CLOSE)
+                                       si->st0 = 1; // end of command, send prompt
+                               break;
+                       case 5: /* errors dump */
+                               stats_dump_errors_to_buffer(s, res);
+                               si->ib->flags |= BF_READ_PARTIAL; /* remove this once we use buffer_feed */
+                               if (s->ana_state == STATS_ST_CLOSE)
+                                       si->st0 = 1; // end of command, send prompt
+                               break;
+                       default: /* abnormal state or lack of space for prompt */
+                               si->st0 = 1; // return to prompt
+                               break;
+                       }
+
+                       if (si->st0 == 1) {     /* post-command prompt (LF or LF + '> ') */
+                               if (!si->st1) { /* non-interactive mode */
+                                       if (buffer_feed(si->ib, "\n", 1) < 0)
+                                               si->st0 = 0; // end of output
+                               }
+                               else {          /* interactive mode */
+                                       if (buffer_feed(si->ib, "\n> ", 3) < 0)
+                                               si->st0 = 0; // end of output
+                               }
+                       }
+
+                       /* If the output functions are still there, it means
+                        * they require more room.
+                        */
+                       if (si->st0 > 0) {
+                               s->ana_state = STATS_ST_REP; /* some old applets still force CLOSE */
+                               si->flags |= SI_FL_WAIT_ROOM;
+                               break;
+                       }
 
-               /* processing a valid or incomplete request */
-               if ((req->flags & BF_FULL)                    || /* invalid request */
-                   (req->flags & BF_READ_ERROR)              || /* input error */
-                   (req->flags & BF_READ_TIMEOUT)            || /* read timeout */
-                   tick_is_expired(req->analyse_exp, now_ms) || /* request timeout */
-                   (req->flags & BF_SHUTR)) {                   /* input closed */
-                       buffer_shutw_now(s->rep);
+                       /* Now we close the output if one of the writers did so,
+                        * or if we're not in interactive mode and the request
+                        * buffer is empty. This still allows pipelined requests
+                        * to be sent in non-interactive mode.
+                        */
+                       if ((res->flags & (BF_SHUTW|BF_SHUTW_NOW)) || (!si->st1 && !req->send_max)) {
+                               s->ana_state = STATS_ST_CLOSE;
+                               continue;
+                       }
+
+                       /* switch state back to ST_REQ to read next requests */
+                       s->ana_state = STATS_ST_REQ;
+               }
+               else if (s->ana_state == STATS_ST_CLOSE) {
+                       /* let's close for real now. Note that we may as well
+                        * call shutw+shutr, but this is enough since the shut
+                        * conditions below will complete.
+                        */
+                       buffer_shutw(si->ob);
                        s->ana_state = 0;
-                       req->analysers = 0;
-                       return 0;
+                       break;
                }
-               /* don't forward nor abort */
-               req->flags |= BF_READ_DONTWAIT; /* we plan to read small requests */
-               return 0;
+       }
 
-       case STATS_ST_REP:
-               /* do nothing while response is being processed */
-               return 0;
+       if ((res->flags & BF_SHUTR) && (si->state == SI_ST_EST) && (s->ana_state != STATS_ST_REQ)) {
+               DPRINTF(stderr, "%s@%d: si to buf closed. req=%08x, res=%08x, st=%d\n",
+                       __FUNCTION__, __LINE__, req->flags, res->flags, si->state);
+               /* Other size has closed, let's abort if we have no more processing to do
+                * and nothing more to consume. This is comparable to a broken pipe, so
+                * we forward the close to the request side so that it flows upstream to
+                * the client.
+                */
+               si->shutw(si);
+       }
 
-       case STATS_ST_CLOSE:
-               /* end of dump */
-               s->req->analysers &= ~an_bit;
+       if ((req->flags & BF_SHUTW) && (si->state == SI_ST_EST) && (s->ana_state != STATS_ST_REP)) {
+               DPRINTF(stderr, "%s@%d: buf to si closed. req=%08x, res=%08x, st=%d\n",
+                       __FUNCTION__, __LINE__, req->flags, res->flags, si->state);
+               /* We have no more processing to do, and nothing more to send, and
+                * the client side has closed. So we'll forward this state downstream
+                * on the response buffer.
+                */
+               si->shutr(si);
+               res->flags |= BF_READ_NULL;
+       }
+
+       /* update all other flags and resync with the other side */
+       si->update(si);
+
+       /* we don't want to expire timeouts while we're processing requests */
+       si->ib->rex = TICK_ETERNITY;
+       si->ob->wex = TICK_ETERNITY;
+
+ out:
+       DPRINTF(stderr, "%s@%d: st=%d, rqf=%x, rpf=%x, rql=%d, rqs=%d, rl=%d, rs=%d\n",
+               __FUNCTION__, __LINE__,
+               si->state, req->flags, res->flags, req->l, req->send_max, res->l, res->send_max);
+
+       if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO)) {
+               /* check that we have released everything then unregister */
+               stream_int_unregister_handler(si);
                s->ana_state = 0;
-               break;
        }
-       return 0;
 }
 
 /*
index 686d85429fca7c8f8d4aa6c5fe47891f5204a5f1..695f407ea98719b5e6e143d415740c2e4808125a 100644 (file)
@@ -41,6 +41,7 @@
 #include <proto/acl.h>
 #include <proto/backend.h>
 #include <proto/buffers.h>
+#include <proto/dumpstats.h>
 #include <proto/fd.h>
 #include <proto/log.h>
 #include <proto/protocols.h>
@@ -460,16 +461,12 @@ int uxst_event_accept(int fd) {
                s->si[1].err_type = SI_ET_NONE;
                s->si[1].err_loc = NULL;
                s->si[1].owner = t;
-               s->si[1].update = stream_sock_data_finish;
-               s->si[1].shutr = stream_sock_shutr;
-               s->si[1].shutw = stream_sock_shutw;
-               s->si[1].chk_rcv = stream_sock_chk_rcv;
-               s->si[1].chk_snd = stream_sock_chk_snd;
-               s->si[1].connect = NULL;
-               s->si[1].iohandler = NULL;
                s->si[1].exp = TICK_ETERNITY;
                s->si[1].fd = -1; /* just to help with debugging */
                s->si[1].flags = SI_FL_NONE;
+               stream_int_register_handler(&s->si[1], stats_io_handler);
+               s->si[1].private = s;
+               s->si[1].st0 = s->si[1].st1 = 0;
 
                s->srv = s->prev_srv = s->srv_conn = NULL;
                s->pend_pos = NULL;
index f9b7157944e5bd56428d9eb7b571e2c6202e0bf2..e359eb1aa0ba946b72bb58b8b1d2d1f37cc945da 100644 (file)
@@ -847,12 +847,6 @@ resync_stream_interface:
                                                break;
                                }
 
-                               if (s->req->analysers & AN_REQ_STATS_SOCK) {
-                                       last_ana |= AN_REQ_STATS_SOCK;
-                                       if (!stats_sock_req_analyser(s, s->req, AN_REQ_STATS_SOCK))
-                                               break;
-                               }
-
                                if (s->req->analysers & AN_REQ_PRST_RDP_COOKIE) {
                                        last_ana |= AN_REQ_PRST_RDP_COOKIE;
                                        if (!tcp_persist_rdp_cookie(s, s->req, AN_REQ_PRST_RDP_COOKIE))