diff --git a/doc/configuration.txt b/doc/configuration.txt index f72a95b7b..149f330a4 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -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 --------------- diff --git a/include/proto/session.h b/include/proto/session.h index a18669e1d..4b86af28e 100644 --- a/include/proto/session.h +++ b/include/proto/session.h @@ -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 */ /* diff --git a/include/types/backend.h b/include/types/backend.h index 908946908..c0c0809a5 100644 --- a/include/types/backend.h +++ b/include/types/backend.h @@ -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 */ diff --git a/src/cfgparse.c b/src/cfgparse.c index 9e895c489..cd8bdbb8a 100644 --- a/src/cfgparse.c +++ b/src/cfgparse.c @@ -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 }, diff --git a/src/proto_http.c b/src/proto_http.c index feed6ccf0..372743146 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -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, diff --git a/src/proto_uxst.c b/src/proto_uxst.c index 0b3f317fc..ca7e1e3c1 100644 --- a/src/proto_uxst.c +++ b/src/proto_uxst.c @@ -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 && diff --git a/src/session.c b/src/session.c index 86696f4a6..e7fd8bd76 100644 --- a/src/session.c +++ b/src/session.c @@ -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: