]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] continous statistics
authorKrzysztof Piotr Oledzki <ole@ans.pl>
Sat, 24 Nov 2007 21:12:47 +0000 (22:12 +0100)
committerWilly Tarreau <w@1wt.eu>
Mon, 26 Nov 2007 19:21:47 +0000 (20:21 +0100)
By default, counters used for statistics calculation are incremented
only when a session finishes. It works quite well when serving small
objects, but with big ones (for example large images or archives) or
with A/V streaming, a graph generated from haproxy counters looks like
a hedgehog.

This patch implements a contstats (continous statistics) option.
When set counters get incremented continuously, during a whole session.
Recounting touches a hotpath directly so it is not enabled by default,
as it has small performance impact (~0.5%).

doc/configuration.txt
include/proto/session.h
include/types/backend.h
src/cfgparse.c
src/proto_http.c
src/proto_uxst.c
src/session.c

index f72a95b7b1b3ceb4908ea6ca0dfd0a7c220f6a35..149f330a43fb609f34d1e0ac44ded47ffedaa01b 100644 (file)
@@ -266,6 +266,7 @@ option abortonclose         X          -         X         X
 option allbackups           X          -         X         X
 option checkcache           X          -         X         X
 option clitcpka             X          X         X         -
+option contstats            X          X         X         -
 option dontlognull          X          X         X         -
 option forceclose           X          -         X         X
 option forwardfor           X          X         X         X
@@ -324,6 +325,15 @@ usesrc                      X          -         X         X
 ----------------------+----------+----------+---------+---------
 keyword                 defaults   frontend   listen    backend
 
+option contstats
+  By default, counters used for statistics calculation are incremented
+  only when a session finishes. It works quite well when serving small
+  objects, but with big ones (for example large images or archives) or
+  with A/V streaming, a graph generated from haproxy counters looks like
+  a hedgehog. With this option enabled counters get incremented continuously,
+  during a whole session. Recounting touches a hotpath directly so
+  it is not enabled by default, as it has small performance impact (~0.5%).
+
 
 2.1) using ACLs
 ---------------
index a18669e1d533ea5ea0fd84f74d81618e80699c50..4b86af28ed26ef3c34eca854879f3ae5430fe14d 100644 (file)
@@ -33,6 +33,8 @@ void session_free(struct session *s);
 /* perform minimal intializations, report 0 in case of error, 1 if OK. */
 int init_session();
 
+void session_process_counters(struct session *s);
+
 #endif /* _PROTO_SESSION_H */
 
 /*
index 908946908c0eb68e67d6849a9bfa6e8b527c8798..c0c0809a5281ca7bc9b35b7639e9c254038260a7 100644 (file)
@@ -57,6 +57,7 @@
 #define        PR_O_TPXY_CIP   0x04000000      /* bind to the client's IP address when connect()ing */
 #define        PR_O_TPXY_CLI   0x06000000      /* bind to the client's IP+port when connect()ing */
 #define        PR_O_TPXY_MASK  0x06000000      /* bind to a non-local address when connect()ing */
+
 #define        PR_O_TCPSPLICE  0x08000000      /* delegate data transfer to linux kernel's tcp_splice */
 
 /* BALANCE: exclusive values */
@@ -68,6 +69,7 @@
 #define PR_O_BALANCE_L7 0x40000000      /* mask to match layer7-based algorithms */
 #define PR_O_BALANCE    0x70000000      /* mask to extract BALANCE algorithm */
 
+#define PR_O_CONTSTATS 0x80000000      /* continous counters */
 
 #endif /* _TYPES_BACKEND_H */
 
index 9e895c4893645916391c503e952c9886fc5166f5..cd8bdbb8abe95d3cac386c6bfa5a37df8e14df38 100644 (file)
@@ -98,6 +98,7 @@ static const struct {
        { "httpclose",    PR_O_HTTP_CLOSE, PR_CAP_FE | PR_CAP_BE, 0 },
        { "nolinger",     PR_O_TCP_NOLING, PR_CAP_FE | PR_CAP_BE, 0 },
        { "logasap",      PR_O_LOGASAP,    PR_CAP_FE, 0 },
+       { "contstats",    PR_O_CONTSTATS,  PR_CAP_FE, 0 },
        { "abortonclose", PR_O_ABRT_CLOSE, PR_CAP_BE, 0 },
        { "checkcache",   PR_O_CHK_CACHE,  PR_CAP_BE, 0 },
        { "dontlognull",  PR_O_NULLNOLOG,  PR_CAP_FE, 0 },
index feed6ccf0257b499ca76258b40e3ab15d9d9dbe6..372743146a4dd50f650b4cd317d361e591ff57f7 100644 (file)
@@ -613,6 +613,10 @@ void process_session(struct task *t, struct timeval *next)
        } while (fsm_resync);
 
        if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
+
+               if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
+                       session_process_counters(s);
+
                s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
                s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 
@@ -651,21 +655,7 @@ void process_session(struct task *t, struct timeval *next)
        }
 
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
-       if (s->req != NULL)
-               s->logs.bytes_in = s->req->total;
-       if (s->rep != NULL)
-               s->logs.bytes_out = s->rep->total;
-
-       s->fe->bytes_in  += s->logs.bytes_in;
-       s->fe->bytes_out += s->logs.bytes_out;
-       if (s->be != s->fe) {
-               s->be->bytes_in  += s->logs.bytes_in;
-               s->be->bytes_out += s->logs.bytes_out;
-       }
-       if (s->srv) {
-               s->srv->bytes_in  += s->logs.bytes_in;
-               s->srv->bytes_out += s->logs.bytes_out;
-       }
+       session_process_counters(s);
 
        /* let's do a final log if we need it */
        if (s->logs.logwait && 
@@ -3096,6 +3086,7 @@ int process_srv(struct session *t)
                                http_sess_log(t);
                        else
                                tcp_sess_log(t);
+                       t->logs.bytes_in = 0;
                }
 
                /* Note: we must not try to cheat by jumping directly to DATA,
index 0b3f317fc2e9268477fe218df5a890ba8f8794fb..ca7e1e3c14eb57bdff96458da0e94f1fb0996fe9 100644 (file)
@@ -1300,6 +1300,10 @@ void process_uxst_session(struct task *t, struct timeval *next)
        } while (fsm_resync);
 
        if (likely(s->cli_state != CL_STCLOSE || s->srv_state != SV_STCLOSE)) {
+
+               if ((s->fe->options & PR_O_CONTSTATS) && (s->flags & SN_BE_ASSIGNED))
+                       session_process_counters(s);
+
                s->req->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
                s->rep->flags &= BF_CLEAR_READ & BF_CLEAR_WRITE;
 
@@ -1332,23 +1336,7 @@ void process_uxst_session(struct task *t, struct timeval *next)
        }
 
        s->logs.t_close = tv_ms_elapsed(&s->logs.tv_accept, &now);
-       if (s->req != NULL)
-               s->logs.bytes_in = s->req->total;
-       if (s->rep != NULL)
-               s->logs.bytes_out = s->rep->total;
-
-       if (s->fe) {
-               s->fe->bytes_in  += s->logs.bytes_in;
-               s->fe->bytes_out += s->logs.bytes_out;
-       }
-       if (s->be && (s->be != s->fe)) {
-               s->be->bytes_in  += s->logs.bytes_in;
-               s->be->bytes_out += s->logs.bytes_out;
-       }
-       if (s->srv) {
-               s->srv->bytes_in  += s->logs.bytes_in;
-               s->srv->bytes_out += s->logs.bytes_out;
-       }
+       session_process_counters(s);
 
        /* let's do a final log if we need it */
        if (s->logs.logwait && 
index 86696f4a6d736b31d1544e4d5c1ea36dd12a15a2..e7fd8bd762783f444db8a5e8124351d8d1c40b15 100644 (file)
@@ -102,6 +102,38 @@ int init_session()
        return pool2_session != NULL;
 }
 
+void session_process_counters(struct session *s) {
+
+       unsigned long long bytes;
+
+       if (s->req && s->req->total != s->logs.bytes_in) {
+               bytes = s->req->total - s->logs.bytes_in;
+
+               s->fe->bytes_in         += bytes;
+
+               if (s->be != s->fe)
+                       s->be->bytes_in += bytes;
+
+               if (s->srv)
+                       s->srv->bytes_in += bytes;
+
+               s->logs.bytes_in = s->req->total;
+       }
+
+       if (s->rep && s->rep->total != s->logs.bytes_out) {
+               bytes = s->rep->total - s->logs.bytes_out;
+
+               s->fe->bytes_out        += bytes;
+
+               if (s->be != s->fe)
+                       s->be->bytes_out += bytes;
+
+               if (s->srv)
+                       s->srv->bytes_out += bytes;
+
+               s->logs.bytes_out = s->rep->total;
+       }
+}
 
 /*
  * Local variables: