>From 862c22a128e9f63b97e2fd4b6d1024bb16d8f6fc Mon Sep 17 00:00:00 2001
From: Krzysztof Piotr Oledzki <o...@ans.pl>
Date: Sun, 4 Oct 2009 15:43:17 +0200
Subject: [MEDIUM] Collect & provide separate statistics for sockets, v2

This patch allows to collect & provide separate statistics for each socket.
It can be very useful if you would like to distinguish between traffic
generate by local and remote users or between different types of remote
clients (peerings, domestic, foreign).

Currently no "Session rate" is supported, but adding it should be possible
if we found it useful.
---
 doc/configuration.txt      |   19 +++++++++
 include/proto/dumpstats.h  |    1 +
 include/proto/proxy.h      |    3 +
 include/types/proto_http.h |    1 +
 include/types/protocols.h  |    2 +
 include/types/proxy.h      |    1 +
 include/types/session.h    |    1 +
 src/cfgparse.c             |   96 ++++++++++++++++++++++++++++++++++++++-----
 src/client.c               |    5 ++
 src/dumpstats.c            |   95 +++++++++++++++++++++++++++++++++++++++++++
 src/proto_http.c           |   48 ++++++++++++++++++++++
 src/proto_tcp.c            |    4 ++
 src/session.c              |   10 +++++
 13 files changed, 274 insertions(+), 12 deletions(-)

diff --git a/doc/configuration.txt b/doc/configuration.txt
index cd3d17b..221815e 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -758,6 +758,7 @@ option httplog              X          X         X         X
 option originalto           X          X         X         X
 [no] option persist         X          -         X         X
 [no] option redispatch      X          -         X         X
+[no] option socket-stats    X          X         X         -
 option smtpchk              X          -         X         X
 [no] option splice-auto     X          X         X         X
 [no] option splice-request  X          X         X         X
@@ -1104,6 +1105,8 @@ bind [<address>]:<port> [, ...]
 bind [<address>]:<port> [, ...] interface <interface>
 bind [<address>]:<port> [, ...] mss <maxseg>
 bind [<address>]:<port> [, ...] transparent
+bind [<address>]:<port> [, ...] id <id>
+bind [<address>]:<port> [, ...] name <name>
   Define one or several listening addresses and/or ports in a frontend.
   May be used in sections :   defaults | frontend | listen | backend
                                   no   |    yes   |   yes  |   no
@@ -1137,6 +1140,13 @@ bind [<address>]:<port> [, ...] transparent
                   work on other operating systems. The commonly advertised
                   value on Ethernet networks is 1460 = 1500(MTU) - 40(IP+TCP).
 
+    <id>          is a persistent value for socket ID. Must be unique and
+                  larger than 1000, as smaller values are reserved for
+                  auto-assigned ids. Can only be used when defining only
+                  a single socket.
+
+    <name>        is an optional name provided for stats
+
     transparent   is an optional keyword which is supported only on certain
                   Linux kernels. It indicates that the addresses will be bound
                   even if they do not belong to the local machine. Any packet
@@ -2729,6 +2739,15 @@ no option redispatch
   See also : "redispatch", "retries"
 
 
+option socket-stats
+no option socket-stats
+
+  Enable or disable collecting & providing separate statistics for each socket.
+  May be used in sections:    defaults | frontend | listen
+
+  Arguments : none
+
+
 option smtpchk
 option smtpchk <hello> <domain>
   Use SMTP health checks for server testing
diff --git a/include/proto/dumpstats.h b/include/proto/dumpstats.h
index 7a92c98..f3681b9 100644
--- a/include/proto/dumpstats.h
+++ b/include/proto/dumpstats.h
@@ -38,6 +38,7 @@
 #define STATS_TYPE_FE  0
 #define STATS_TYPE_BE  1
 #define STATS_TYPE_SV  2
+#define STATS_TYPE_SO  3
 
 #define STATS_ST_INIT  0
 #define STATS_ST_REQ   1
diff --git a/include/proto/proxy.h b/include/proto/proxy.h
index f293b1b..c0ce2a3 100644
--- a/include/proto/proxy.h
+++ b/include/proto/proxy.h
@@ -69,6 +69,9 @@ static inline void proxy_reset_timeouts(struct proxy *proxy)
 static void inline proxy_inc_fe_ctr(struct listener *l, struct proxy *fe)
 {
        fe->counters.cum_feconn++;
+       if (l->counters)
+               l->counters->cum_conn++;
+
        update_freq_ctr(&fe->fe_sess_per_sec, 1);
        if (fe->fe_sess_per_sec.curr_ctr > fe->fe_sps_max)
                fe->fe_sps_max = fe->fe_sess_per_sec.curr_ctr;
diff --git a/include/types/proto_http.h b/include/types/proto_http.h
index c0350d2..a9acfdd 100644
--- a/include/types/proto_http.h
+++ b/include/types/proto_http.h
@@ -159,6 +159,7 @@ enum {
        DATA_ST_PX_INIT = 0,
        DATA_ST_PX_TH,
        DATA_ST_PX_FE,
+       DATA_ST_PX_LI,
        DATA_ST_PX_SV,
        DATA_ST_PX_BE,
        DATA_ST_PX_END,
diff --git a/include/types/protocols.h b/include/types/protocols.h
index 14aee79..c89deb3 100644
--- a/include/types/protocols.h
+++ b/include/types/protocols.h
@@ -30,6 +30,7 @@
 #include <common/config.h>
 #include <common/mini-clist.h>
 
+#include <types/counters.h>
 #include <types/task.h>
 
 /* max length of a protcol name, including trailing zero */
@@ -80,6 +81,7 @@ struct listener {
        int luid;                       /* listener universally unique ID, used 
for SNMP */
        int state;                      /* state: NEW, INIT, ASSIGNED, LISTEN, 
READY, FULL */
        int options;                    /* socket options : LI_O_* */
+       struct licounters *counters;    /* statistics counters */
        struct sockaddr_storage addr;   /* the address we listen to */
        struct protocol *proto;         /* protocol this listener belongs to */
        int nbconn;                     /* current number of connections on 
this listener */
diff --git a/include/types/proxy.h b/include/types/proxy.h
index 432111b..1c73d24 100644
--- a/include/types/proxy.h
+++ b/include/types/proxy.h
@@ -121,6 +121,7 @@
 #define PR_O2_CLFLOG   0x00000400      /* log into clf format */
 #define PR_O2_LOGHCHKS 0x00000800      /* log health checks */
 #define PR_O2_INDEPSTR 0x00001000      /* independant streams, don't update 
rex on write */
+#define PR_O2_SOCKSTAT 0x00002000      /* collect & provide separate 
statistics for sockets */
 
 struct error_snapshot {
        struct timeval when;            /* date of this event, (tv_sec == 0) 
means "never" */
diff --git a/include/types/session.h b/include/types/session.h
index 356bdee..c5e6d65 100644
--- a/include/types/session.h
+++ b/include/types/session.h
@@ -197,6 +197,7 @@ struct session {
                struct {
                        struct proxy *px;
                        struct server *sv;
+                       struct listener *l;
                        short px_st, sv_st;     /* DATA_ST_INIT or DATA_ST_DATA 
*/
                        unsigned int flags;     /* STAT_* */
                        int iid, type, sid;     /* proxy id, type and service 
id if bounding of stats is enabled */
diff --git a/src/cfgparse.c b/src/cfgparse.c
index ebb0713..c666cda 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -139,6 +139,7 @@ static const struct cfg_opt cfg_opts2[] =
        { "dontlog-normal",               PR_O2_NOLOGNORM, PR_CAP_FE, 0 },
        { "log-separate-errors",          PR_O2_LOGERRORS, PR_CAP_FE, 0 },
        { "log-health-checks",            PR_O2_LOGHCHKS,  PR_CAP_BE, 0 },
+       { "socket-stats",                 PR_O2_SOCKSTAT,  PR_CAP_FE, 0 },
        { "tcp-smart-accept",             PR_O2_SMARTACC,  PR_CAP_FE, 0 },
        { "tcp-smart-connect",            PR_O2_SMARTCON,  PR_CAP_BE, 0 },
        { "independant-streams",          PR_O2_INDEPSTR,  PR_CAP_FE|PR_CAP_BE, 
0 },
@@ -162,17 +163,16 @@ static struct cfg_kw_list cfg_keywords = {
  *  - <port> is a numerical port from 1 to 65535 ;
  *  - <end> indicates to use the range from <port> to <end> instead 
(inclusive).
  * This can be repeated as many times as necessary, separated by a coma.
- * The <tail> argument is a pointer to a current list which should be appended
- * to the tail of the new list. The pointer to the new list is returned.
+ * Function returns 1 for success or 0 if error.
  */
-static struct listener *str2listener(char *str, struct listener *tail)
+static int str2listener(char *str, struct proxy *curproxy)
 {
        struct listener *l;
        char *c, *next, *range, *dupstr;
        int port, end;
 
        next = dupstr = strdup(str);
-    
+
        while (next && *next) {
                struct sockaddr_storage ss;
 
@@ -243,8 +243,8 @@ static struct listener *str2listener(char *str, struct 
listener *tail)
 
                for (; port <= end; port++) {
                        l = (struct listener *)calloc(1, sizeof(struct 
listener));
-                       l->next = tail;
-                       tail = l;
+                       l->next = curproxy->listen;
+                       curproxy->listen = l;
 
                        l->fd = -1;
                        l->addr = ss;
@@ -257,14 +257,16 @@ static struct listener *str2listener(char *str, struct 
listener *tail)
                                ((struct sockaddr_in *)(&l->addr))->sin_port = 
htons(port);
                                tcpv4_add_listener(l);
                        }
+
+                       l->luid = curproxy->next_lid++;
                        listeners++;
                } /* end for(port) */
        } /* end while(next) */
        free(dupstr);
-       return tail;
+       return 1;
  fail:
        free(dupstr);
-       return NULL;
+       return 0;
 }
 
 /*
@@ -893,8 +895,7 @@ int cfg_parse_listen(const char *file, int linenum, char 
**args, int kwm)
 
                /* parse the listener address if any */
                if ((curproxy->cap & PR_CAP_FE) && *args[2]) {
-                       curproxy->listen = str2listener(args[2], 
curproxy->listen);
-                       if (!curproxy->listen) {
+                       if(!str2listener(args[2], curproxy)) {
                                err_code |= ERR_FATAL;
                                goto out;
                        }
@@ -1004,6 +1005,7 @@ int cfg_parse_listen(const char *file, int linenum, char 
**args, int kwm)
                curproxy->grace  = defproxy.grace;
                curproxy->uuid = next_pxid++;   /* generate a uuid for this 
proxy */
                curproxy->next_svid = 1;        /* server id 0 is reserved */
+               curproxy->next_lid  = 1;        /* listener id 0 is reserved */
 
                goto out;
        }
@@ -1061,8 +1063,7 @@ int cfg_parse_listen(const char *file, int linenum, char 
**args, int kwm)
                }
 
                last_listen = curproxy->listen;
-               curproxy->listen = str2listener(args[1], last_listen);
-               if (!curproxy->listen) {
+               if (!str2listener(args[1], curproxy)) {
                        err_code |= ERR_ALERT | ERR_FATAL;
                        goto out;
                }
@@ -1142,6 +1143,54 @@ int cfg_parse_listen(const char *file, int linenum, char 
**args, int kwm)
                                goto out;
 #endif
                        }
+
+                       if (!strcmp(args[cur_arg], "name")) {
+                               struct listener *l;
+
+                               for (l = curproxy->listen; l != last_listen; l 
= l->next)
+                                       l->name = strdup(args[cur_arg + 1]);
+
+                               cur_arg += 2;
+                               continue;
+                       }
+
+                       if (!strcmp(args[cur_arg], "id")) {
+                               struct listener *l;
+
+                               if (curproxy->listen->next != last_listen) {
+                                       Alert("parsing [%s:%d]: '%s' can be 
only used with a single socket.\n",
+                                               file, linenum, args[cur_arg]);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+
+                               if (!*args[cur_arg + 1]) {
+                                       Alert("parsing [%s:%d]: '%s' expects an 
integer argument.\n",
+                                               file, linenum, args[cur_arg]);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+
+                               curproxy->listen->luid = atol(args[cur_arg + 
1]);
+
+                               if (curproxy->listen->luid < 1001) {
+                                       Alert("parsing [%s:%d]: custom id has 
to be > 1000\n",
+                                               file, linenum);
+                                       err_code |= ERR_ALERT | ERR_FATAL;
+                                       goto out;
+                               }
+
+                               for (l = curproxy->listen; l != last_listen; l 
= l->next)
+                                       if (curproxy->listen != l && l->luid == 
curproxy->listen->luid) {
+                                               Alert("parsing [%s:%d]: custom 
id has to be unique but is duplicated in %s.\n",
+                                                       file, linenum, args[1]);
+                                               err_code |= ERR_ALERT | 
ERR_FATAL;
+                                               goto out;
+                                       }
+                               cur_arg += 2;
+                               continue;
+                       }
+
                        Alert("parsing [%s:%d] : '%s' only supports the 
'transparent' and 'interface' options.\n",
                              file, linenum, args[0]);
                        err_code |= ERR_ALERT | ERR_FATAL;
@@ -4352,9 +4401,32 @@ int check_config_validity()
                                curproxy->be_req_ana |= AN_REQ_PRST_RDP_COOKIE;
                }
 
+               listener = NULL;
+               while (curproxy->listen) {
+                       struct listener *next;
+
+                       next = curproxy->listen->next;
+                       curproxy->listen->next = listener;
+                       listener = curproxy->listen;
+               
+                       if (!next)
+                               break;
+
+                       curproxy->listen = next;
+               }
+
                /* adjust this proxy's listeners */
                listener = curproxy->listen;
                while (listener) {
+                       /* enable separate counters */
+                       if (curproxy->options2 & PR_O2_SOCKSTAT) {
+                               listener->counters = (struct licounters 
*)calloc(1, sizeof(struct licounters));
+                               if (!listener->name) {
+                                       sprintf(trash, "sock-%d", 
listener->luid);
+                                       listener->name = strdup(trash);
+                               }
+                       }
+
                        if (curproxy->options & PR_O_TCP_NOLING)
                                listener->options |= LI_O_NOLINGER;
                        listener->maxconn = curproxy->maxconn;
diff --git a/src/client.c b/src/client.c
index 7d76752..ef2655c 100644
--- a/src/client.c
+++ b/src/client.c
@@ -492,6 +492,11 @@ int event_accept(int fd) {
                if (p->feconn > p->counters.feconn_max)
                        p->counters.feconn_max = p->feconn;
 
+               if (l->counters) {
+                       if (l->nbconn > l->counters->conn_max)
+                               l->counters->conn_max = l->nbconn;
+               }
+
                actconn++;
                totalconn++;
 
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 2b704af..29b9252 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -313,12 +313,16 @@ int stats_sock_parse_request(struct stream_interface *si, 
char *line)
                if (strcmp(args[1], "counters") == 0) {
                        struct proxy *px;
                        struct server *sv;
+                       struct listener *li;
 
                        for (px = proxy; px; px = px->next) {
                                memset(&px->counters, 0, sizeof(px->counters));
 
                                for (sv = px->srv; sv; sv = sv->next)
                                        memset(&sv->counters, 0, 
sizeof(sv->counters));
+
+                               for (li = px->listen; li; li = li->next)
+                                       memset(li->counters, 0, 
sizeof(*li->counters));
                        }
 
                        return 1;
@@ -781,6 +785,7 @@ int stats_dump_http(struct session *s, struct buffer *rep, 
struct uri_auth *uri)
                             ".titre    {background: #20D0D0;color: #000000; 
font-weight: bold;}\n"
                             ".total    {background: #20D0D0;color: #ffff80;}\n"
                             ".frontend {background: #e8e8d0;}\n"
+                            ".socket   {background: #d0d0d0;}\n"
                             ".backend  {background: #e8e8d0;}\n"
                             ".active0  {background: #ff9090;}\n"
                             ".active1  {background: #ffd020;}\n"
@@ -983,6 +988,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, 
struct uri_auth *uri)
 {
        struct buffer *rep = s->rep;
        struct server *sv, *svs;        /* server and server-state, 
server-state=server or server->tracked */
+       struct listener *l;
        struct chunk msg;
 
        chunk_init(&msg, trash, sizeof(trash));
@@ -1139,6 +1145,95 @@ int stats_dump_proxy(struct session *s, struct proxy 
*px, struct uri_auth *uri)
                                return 0;
                }
 
+               s->data_ctx.stats.l = px->listen; /* may be NULL */
+               s->data_ctx.stats.px_st = DATA_ST_PX_LI;
+               /* fall through */
+
+       case DATA_ST_PX_LI:
+               /* stats.l has been initialized above */
+               for (; s->data_ctx.stats.l != NULL; s->data_ctx.stats.l = 
l->next) {
+                       l = s->data_ctx.stats.l;
+                       if (!l->counters)
+                               continue;
+
+                       if (s->data_ctx.stats.flags & STAT_BOUND) {
+                               if (!(s->data_ctx.stats.type & (1 << 
STATS_TYPE_SO)))
+                                       break;
+
+                               if (s->data_ctx.stats.sid != -1 && l->luid != 
s->data_ctx.stats.sid)
+                                       continue;
+                       }
+
+                       if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
+                               chunk_printf(&msg,
+                                    /* name, queue */
+                                    "<tr align=center 
class=\"socket\"><td>%s</td><td colspan=3></td>"
+                                    /* sessions rate: current, max, limit */
+                                    "<td align=right colspan=3>&nbsp;</td>"
+                                    /* sessions: current, max, limit, total, 
lbtot */
+                                    "<td align=right>%s</td><td 
align=right>%s</td><td align=right>%s</td>"
+                                    "<td align=right>%s</td><td 
align=right>&nbsp;</td>"
+                                    /* bytes: in, out */
+                                    "<td align=right>%s</td><td 
align=right>%s</td>"
+                                    "",
+                                    l->name,
+                                    U2H3(l->nbconn), 
U2H4(l->counters->conn_max), U2H5(l->maxconn),
+                                    U2H6(l->counters->cum_conn), 
U2H7(l->counters->bytes_in), U2H8(l->counters->bytes_out));
+
+                               chunk_printf(&msg,
+                                    /* denied: req, resp */
+                                    "<td align=right>%s</td><td 
align=right>%s</td>"
+                                    /* errors: request, connect, response */
+                                    "<td align=right>%s</td><td 
align=right></td><td align=right></td>"
+                                    /* warnings: retries, redispatches */
+                                    "<td align=right></td><td 
align=right></td>"
+                                    /* server status: reflect listener status 
*/
+                                    "<td align=center>%s</td>"
+                                    /* rest of server: nothing */
+                                    "<td align=center colspan=8></td></tr>"
+                                    "",
+                                    U2H0(l->counters->denied_req), 
U2H1(l->counters->denied_resp),
+                                    U2H2(l->counters->failed_req),
+                                    (l->nbconn < l->maxconn) ? "OPEN" : 
"FULL");
+                       } else {
+                               chunk_printf(&msg,
+                                    /* pxid, name, queue cur, queue max, */
+                                    "%s,%s,,,"
+                                    /* sessions: current, max, limit, total */
+                                    "%d,%d,%d,%lld,"
+                                    /* bytes: in, out */
+                                    "%lld,%lld,"
+                                    /* denied: req, resp */
+                                    "%lld,%lld,"
+                                    /* errors: request, connect, response */
+                                    "%lld,,,"
+                                    /* warnings: retries, redispatches */
+                                    ",,"
+                                    /* server status: reflect listener status 
*/
+                                    "%s,"
+                                    /* rest of server: nothing */
+                                    ",,,,,,,,"
+                                    /* pid, iid, sid, throttle, lbtot, 
tracked, type */
+                                    "%d,%d,%d,,,,%d,"
+                                    /* rate, rate_lim, rate_max */
+                                    ",,,"
+                                    /* check_status, check_code, 
check_duration */
+                                    ",,,"
+                                    "\n",
+                                    px->id, l->name,
+                                    l->nbconn, l->counters->conn_max,
+                                    l->maxconn, l->counters->cum_conn,
+                                    l->counters->bytes_in, 
l->counters->bytes_out,
+                                    l->counters->denied_req, 
l->counters->denied_resp,
+                                    l->counters->failed_req,
+                                    (l->nbconn < l->maxconn) ? "OPEN" : "FULL",
+                                    relative_pid, px->uuid, l->luid, 
STATS_TYPE_SO);
+                       }
+
+                       if (buffer_write_chunk(rep, &msg) >= 0)
+                               return 0;
+               }
+
                s->data_ctx.stats.sv = px->srv; /* may be NULL */
                s->data_ctx.stats.px_st = DATA_ST_PX_SV;
                /* fall through */
diff --git a/src/proto_http.c b/src/proto_http.c
index 5319172..6cd0b40 100644
--- a/src/proto_http.c
+++ b/src/proto_http.c
@@ -1843,7 +1843,11 @@ int http_wait_for_request(struct session *s, struct 
buffer *req, int an_bit)
                                http_capture_bad_message(&s->fe->invalid_req, 
s, req, msg, s->fe);
                        msg->msg_state = HTTP_MSG_ERROR;
                        req->analysers = 0;
+
                        s->fe->counters.failed_req++;
+                       if (s->listener->counters)
+                               s->listener->counters->failed_req++;
+
                        if (!(s->flags & SN_ERR_MASK))
                                s->flags |= SN_ERR_CLICL;
                        if (!(s->flags & SN_FINST_MASK))
@@ -1860,7 +1864,11 @@ int http_wait_for_request(struct session *s, struct 
buffer *req, int an_bit)
                        stream_int_retnclose(req->prod, error_message(s, 
HTTP_ERR_408));
                        msg->msg_state = HTTP_MSG_ERROR;
                        req->analysers = 0;
+
                        s->fe->counters.failed_req++;
+                       if (s->listener->counters)
+                               s->listener->counters->failed_req++;
+
                        if (!(s->flags & SN_ERR_MASK))
                                s->flags |= SN_ERR_CLITO;
                        if (!(s->flags & SN_FINST_MASK))
@@ -1876,7 +1884,11 @@ int http_wait_for_request(struct session *s, struct 
buffer *req, int an_bit)
                        stream_int_retnclose(req->prod, error_message(s, 
HTTP_ERR_400));
                        msg->msg_state = HTTP_MSG_ERROR;
                        req->analysers = 0;
+
                        s->fe->counters.failed_req++;
+                       if (s->listener->counters)
+                               s->listener->counters->failed_req++;
+
                        if (!(s->flags & SN_ERR_MASK))
                                s->flags |= SN_ERR_CLICL;
                        if (!(s->flags & SN_FINST_MASK))
@@ -2005,7 +2017,10 @@ int http_wait_for_request(struct session *s, struct 
buffer *req, int an_bit)
        txn->req.msg_state = HTTP_MSG_ERROR;
        txn->status = 400;
        stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
+
        s->fe->counters.failed_req++;
+       if (s->listener->counters)
+               s->listener->counters->failed_req++;
 
  return_prx_cond:
        if (!(s->flags & SN_ERR_MASK))
@@ -2291,7 +2306,10 @@ int http_process_req_common(struct session *s, struct 
buffer *req, int an_bit, s
        txn->req.msg_state = HTTP_MSG_ERROR;
        txn->status = 400;
        stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
+
        s->fe->counters.failed_req++;
+       if (s->listener->counters)
+               s->listener->counters->failed_req++;
 
  return_prx_cond:
        if (!(s->flags & SN_ERR_MASK))
@@ -2599,7 +2617,10 @@ int http_process_request(struct session *s, struct 
buffer *req, int an_bit)
        txn->status = 400;
        req->analysers = 0;
        stream_int_retnclose(req->prod, error_message(s, HTTP_ERR_400));
+
        s->fe->counters.failed_req++;
+       if (s->listener->counters)
+               s->listener->counters->failed_req++;
 
        if (!(s->flags & SN_ERR_MASK))
                s->flags |= SN_ERR_PRXCOND;
@@ -2640,7 +2661,10 @@ int http_process_tarpit(struct session *s, struct buffer 
*req, int an_bit)
 
        req->analysers = 0;
        req->analyse_exp = TICK_ETERNITY;
+
        s->fe->counters.failed_req++;
+       if (s->listener->counters)
+               s->listener->counters->failed_req++;
 
        if (!(s->flags & SN_ERR_MASK))
                s->flags |= SN_ERR_PRXCOND;
@@ -3016,7 +3040,11 @@ int process_response(struct session *t)
                        if (txn->flags & TX_SVDENY) {
                                if (t->srv)
                                        t->srv->counters.failed_secu++;
+
                                cur_proxy->counters.denied_resp++;
+                               if (t->listener->counters)
+                                       t->listener->counters->denied_resp++;
+
                                goto return_srv_prx_502;
                        }
 
@@ -3157,7 +3185,11 @@ int process_response(struct session *t)
                         */
                        if (t->srv)
                                t->srv->counters.failed_secu++;
+
                        cur_proxy->counters.denied_resp++;
+                       if (t->listener->counters)
+                               t->listener->counters->denied_resp++;
+
                        Alert("Blocking cacheable cookie in response from 
instance %s, server %s.\n",
                              t->be->id, t->srv?t->srv->id:"<dispatch>");
                        send_log(t->be, LOG_ALERT,
@@ -3342,13 +3374,21 @@ int apply_filter_to_req_headers(struct session *t, 
struct buffer *req, struct hd
                        case ACT_DENY:
                                txn->flags |= TX_CLDENY;
                                last_hdr = 1;
+
                                t->be->counters.denied_req++;
+                               if (t->listener->counters)
+                                       t->listener->counters->denied_resp++;
+
                                break;
 
                        case ACT_TARPIT:
                                txn->flags |= TX_CLTARPIT;
                                last_hdr = 1;
+
                                t->be->counters.denied_req++;
+                               if (t->listener->counters)
+                                       t->listener->counters->denied_resp++;
+
                                break;
 
                        case ACT_REPLACE:
@@ -3453,13 +3493,21 @@ int apply_filter_to_req_line(struct session *t, struct 
buffer *req, struct hdr_e
 
                case ACT_DENY:
                        txn->flags |= TX_CLDENY;
+
                        t->be->counters.denied_req++;
+                       if (t->listener->counters)
+                               t->listener->counters->denied_resp++;
+
                        done = 1;
                        break;
 
                case ACT_TARPIT:
                        txn->flags |= TX_CLTARPIT;
+
                        t->be->counters.denied_req++;
+                       if (t->listener->counters)
+                               t->listener->counters->denied_resp++;
+
                        done = 1;
                        break;
 
diff --git a/src/proto_tcp.c b/src/proto_tcp.c
index df6d034..7bb5d7e 100644
--- a/src/proto_tcp.c
+++ b/src/proto_tcp.c
@@ -686,7 +686,11 @@ int tcp_inspect_request(struct session *s, struct buffer 
*req, int an_bit)
                                buffer_abort(req);
                                buffer_abort(s->rep);
                                req->analysers = 0;
+
                                s->fe->counters.failed_req++;
+                               if (s->listener->counters)
+                                       s->listener->counters->failed_req++;
+
                                if (!(s->flags & SN_ERR_MASK))
                                        s->flags |= SN_ERR_PRXCOND;
                                if (!(s->flags & SN_FINST_MASK))
diff --git a/src/session.c b/src/session.c
index 9d46fe6..447660e 100644
--- a/src/session.c
+++ b/src/session.c
@@ -146,6 +146,9 @@ void session_process_counters(struct session *s)
 
                        if (s->srv)
                                s->srv->counters.bytes_in               += 
bytes;
+
+                       if (s->listener->counters)
+                               s->listener->counters->bytes_in         += 
bytes;
                }
        }
 
@@ -160,6 +163,9 @@ void session_process_counters(struct session *s)
 
                        if (s->srv)
                                s->srv->counters.bytes_out              += 
bytes;
+
+                       if (s->listener->counters)
+                               s->listener->counters->bytes_out        += 
bytes;
                }
        }
 }
@@ -1309,7 +1315,11 @@ void sess_set_term_flags(struct session *s)
 {
        if (!(s->flags & SN_FINST_MASK)) {
                if (s->si[1].state < SI_ST_REQ) {
+
                        s->fe->counters.failed_req++;
+                       if (s->listener->counters)
+                               s->listener->counters->failed_req++;
+
                        s->flags |= SN_FINST_R;
                }
                else if (s->si[1].state == SI_ST_QUE)
-- 
1.6.4.2


Reply via email to