]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
[MEDIUM] measure and report session rate on frontend, backends and servers
authorWilly Tarreau <w@1wt.eu>
Thu, 5 Mar 2009 17:43:00 +0000 (18:43 +0100)
committerWilly Tarreau <w@1wt.eu>
Thu, 5 Mar 2009 17:43:00 +0000 (18:43 +0100)
With this change, all frontends, backends, and servers maintain a session
counter and a timer to compute a session rate over the last second. This
value will be very useful because it varies instantly and can be used to
check thresholds. This value is also reported in the stats in a new "rate"
column.

17 files changed:
Makefile
Makefile.bsd
Makefile.osx
doc/configuration.txt
include/common/standard.h
include/proto/freq_ctr.h [new file with mode: 0644]
include/proto/proxy.h
include/proto/server.h
include/types/freq_ctr.h [new file with mode: 0644]
include/types/proxy.h
include/types/server.h
src/backend.c
src/client.c
src/dumpstats.c
src/freq_ctr.c [new file with mode: 0644]
src/proto_http.c
src/session.c

index 855c902982845a4e00b4d266f40128899487aaa9..3d87d70e1a19950a192e733b347bb601bc59c859 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -460,7 +460,7 @@ OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
        src/proto_http.o src/stream_sock.o src/appsession.o src/backend.o \
        src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
        src/session.o src/hdr_idx.o src/ev_select.o \
-       src/acl.o src/memory.o \
+       src/acl.o src/memory.o src/freq_ctr.o \
        src/ebtree.o src/eb32tree.o
 
 haproxy: $(OBJS) $(OPTIONS_OBJS)
index 22dc3e778ff7b6936fe87fe8eec969083cfcee5e..d1f3e687673eaeec5e93086d6324ec8a81dca504 100644 (file)
@@ -106,7 +106,7 @@ OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
        src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
        src/session.o src/hdr_idx.o src/ev_select.o \
        src/ev_poll.o src/ev_kqueue.o \
-       src/acl.o src/memory.o \
+       src/acl.o src/memory.o src/freq_ctr.o \
        src/ebtree.o src/eb32tree.o
 
 all: haproxy
index cb4d4c8863afd3d5597005cc32b18c83be556ecf..b736eef16881937059cf05d59ca4c1dd76c667c3 100644 (file)
@@ -103,7 +103,7 @@ OBJS = src/haproxy.o src/sessionhash.o src/base64.o src/protocols.o \
        src/stream_interface.o src/dumpstats.o src/proto_tcp.o \
        src/session.o src/hdr_idx.o src/ev_select.o \
        src/ev_poll.o \
-       src/acl.o src/memory.o \
+       src/acl.o src/memory.o src/freq_ctr.o \
        src/ebtree.o src/eb32tree.o
 
 all: haproxy
index 0590b61f5b5a10fdd8ebd5b2c9e87c23c690cb91..84465e82bb9db0d13c0ad42aa4bf5c025346a623 100644 (file)
@@ -5778,6 +5778,9 @@ reading. Their sole purpose is to explain how to decipher them.
 2.7) CSV format
 ---------------
 
+The statistics may be consulted either from the unix socket or from the HTTP
+page. Both means provide a CSV format whose fields follow.
+
   0. pxname: proxy name
   1. svname: service name (FRONTEND for frontend, BACKEND for backend, any name
     for server)
@@ -5812,6 +5815,7 @@ reading. Their sole purpose is to explain how to decipher them.
  30. lbtot: total number of times a server was selected
  31. tracked: id of proxy/server if tracking is enabled
  32. type (0=frontend, 1=backend, 2=server)
+ 33. rate (number of sessions per second over last elapsed second)
 
 
 2.8) Unix Socket commands
index 892f516e52a23f4f597714ee0b1506b7db1ddf83..84f768cbbe7f613ac5d807da7dfaa6d92cef9580 100644 (file)
@@ -280,4 +280,13 @@ extern const char *parse_time_err(const char *text, unsigned *ret, unsigned unit
 #define TIME_UNIT_DAY  0x0005
 #define TIME_UNIT_MASK 0x0007
 
+/* Multiply the two 32-bit operands and shift the 64-bit result right 32 bits.
+ * This is used to compute fixed ratios by setting one of the operands to
+ * (2^32*ratio).
+ */
+static inline unsigned int mul32hi(unsigned int a, unsigned int b)
+{
+       return ((unsigned long long)a * b) >> 32;
+}
+
 #endif /* _COMMON_STANDARD_H */
diff --git a/include/proto/freq_ctr.h b/include/proto/freq_ctr.h
new file mode 100644 (file)
index 0000000..caa2b6b
--- /dev/null
@@ -0,0 +1,70 @@
+/*
+  include/proto/freq_ctr.h
+  This file contains macros and inline functions for frequency counters.
+
+  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
+  License as published by the Free Software Foundation, version 2.1
+  exclusively.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PROTO_FREQ_CTR_H
+#define _PROTO_FREQ_CTR_H
+
+#include <common/config.h>
+#include <types/freq_ctr.h>
+
+/* Rotate a frequency counter when current period is over. Must not be called
+ * during a valid period. It is important that it correctly initializes a null
+ * area.
+ */
+static inline void rotate_freq_ctr(struct freq_ctr *ctr)
+{
+       ctr->prev_ctr = ctr->curr_ctr;
+       if (likely(now.tv_sec - ctr->curr_sec != 1)) {
+               /* we missed more than one second */
+               ctr->prev_ctr = 0;
+       }
+       ctr->curr_sec = now.tv_sec;
+       ctr->curr_ctr = 0; /* leave it at the end to help gcc optimize it away */
+}
+
+/* Update a frequency counter by <inc> incremental units. It is automatically
+ * rotated if the period is over. It is important that it correctly initializes
+ * a null area.
+ */
+static inline void update_freq_ctr(struct freq_ctr *ctr, unsigned int inc)
+{
+       if (likely(ctr->curr_sec == now.tv_sec)) {
+               ctr->curr_ctr += inc;
+               return;
+       }
+       rotate_freq_ctr(ctr);
+       ctr->curr_ctr = inc;
+       /* Note: later we may want to propagate the update to other counters */
+}
+
+/* Read a frequency counter taking history into account for missing time in
+ * current period.
+ */
+unsigned int read_freq_ctr(struct freq_ctr *ctr);
+
+#endif /* _PROTO_FREQ_CTR_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+  */
index 30a12472e80b58e97d3b230d8a6a0e888cc4bf5f..012c1b27fe4b52b5e549eb16d9b3a1903ce19593 100644 (file)
@@ -26,6 +26,7 @@
 #include <common/ticks.h>
 #include <common/time.h>
 #include <types/proxy.h>
+#include <proto/freq_ctr.h>
 
 int start_proxies(int verbose);
 void maintain_proxies(int *next);
@@ -62,6 +63,20 @@ static inline void proxy_reset_timeouts(struct proxy *proxy)
        proxy->timeout.check = TICK_ETERNITY;
 }
 
+/* increase the number of cumulated connections on the designated frontend */
+static void inline proxy_inc_fe_ctr(struct proxy *fe)
+{
+       fe->cum_feconn++;
+       update_freq_ctr(&fe->fe_sess_per_sec, 1);
+}
+
+/* increase the number of cumulated connections on the designated backend */
+static void inline proxy_inc_be_ctr(struct proxy *be)
+{
+       be->cum_beconn++;
+       update_freq_ctr(&be->be_sess_per_sec, 1);
+}
+
 #endif /* _PROTO_PROXY_H */
 
 /*
index f3b5e16b913136886ea172dccd20abb0bd80624e..e05a4acec52fafd63566b3201778471fe0e5464e 100644 (file)
@@ -2,7 +2,7 @@
   include/proto/server.h
   This file defines everything related to servers.
 
-  Copyright (C) 2000-2006 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
 #include <types/server.h>
 
 #include <proto/queue.h>
+#include <proto/freq_ctr.h>
 
 int srv_downtime(struct server *s);
 int srv_getinter(struct server *s);
 
+/* increase the number of cumulated connections on the designated server */
+static void inline srv_inc_sess_ctr(struct server *s)
+{
+       s->cum_sess++;
+       update_freq_ctr(&s->sess_per_sec, 1);
+}
+
 #endif /* _PROTO_SERVER_H */
 
 /*
diff --git a/include/types/freq_ctr.h b/include/types/freq_ctr.h
new file mode 100644 (file)
index 0000000..a8cfbd7
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+  include/types/freq_ctr.h
+  This file contains structure declarations for frequency counters.
+
+  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
+  License as published by the Free Software Foundation, version 2.1
+  exclusively.
+
+  This library is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+  Lesser General Public License for more details.
+
+  You should have received a copy of the GNU Lesser General Public
+  License along with this library; if not, write to the Free Software
+  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _TYPES_FREQ_CTR_H
+#define _TYPES_FREQ_CTR_H
+
+#include <common/config.h>
+
+struct freq_ctr {
+       unsigned int curr_sec; /* start date of current period (seconds from now.tv_sec) */
+       unsigned int curr_ctr; /* cumulated value for current period */
+       unsigned int prev_ctr; /* value for last period */
+};
+
+#endif /* _TYPES_FREQ_CTR_H */
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
index 9adf5cde2398cd2dfad1c5557d6d878a29cbc60d..87b6f14f56a9415a277c735c96a316111c51ffcc 100644 (file)
@@ -2,7 +2,7 @@
   include/types/proxy.h
   This file defines everything related to proxies.
 
-  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
@@ -37,6 +37,7 @@
 
 #include <types/acl.h>
 #include <types/buffers.h>
+#include <types/freq_ctr.h>
 #include <types/httperr.h>
 #include <types/log.h>
 #include <types/protocols.h>
@@ -220,6 +221,8 @@ struct proxy {
        int totpend;                            /* total number of pending connections on this instance (for stats) */
        unsigned int feconn, feconn_max;        /* # of active frontend sessions */
        unsigned int beconn, beconn_max;        /* # of active backend sessions */
+       struct freq_ctr fe_sess_per_sec;        /* sessions per second on the frontend */
+       struct freq_ctr be_sess_per_sec;        /* sessions per second on the backend */
        unsigned int cum_feconn, cum_beconn;    /* cumulated number of processed sessions */
        unsigned int cum_lbconn;                /* cumulated number of sessions processed by load balancing */
        unsigned int maxconn;                   /* max # of active sessions on the frontend */
index 5c0186a88469f05573e19f54214db9d743ee8956..8fb8a1f66bb1c07be7d1a5b499ede3cd48c7ced7 100644 (file)
@@ -2,7 +2,7 @@
   include/types/server.h
   This file defines everything related to servers.
 
-  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
@@ -30,6 +30,7 @@
 #include <common/mini-clist.h>
 
 #include <types/buffers.h>
+#include <types/freq_ctr.h>
 #include <types/proxy.h>
 #include <types/queue.h>
 #include <types/task.h>
@@ -122,6 +123,7 @@ struct server {
        unsigned failed_conns, failed_resp;     /* failed connect() and responses */
        unsigned retries, redispatches;         /* retried and redispatched connections */
        unsigned failed_secu;                   /* blocked responses because of security concerns */
+       struct freq_ctr sess_per_sec;           /* sessions per second on this server */
        unsigned cum_sess;                      /* cumulated number of sessions really sent to this server */
        unsigned cum_lbconn;                    /* cumulated number of sessions directed by load balancing */
 
index e1911c5e3b5d07cafbb8c85ce2d8f1ffdcf2dd96..ed291dacf777bb3b51c5de9b8b21118178b67642 100644 (file)
@@ -36,6 +36,7 @@
 #include <proto/proto_http.h>
 #include <proto/proto_tcp.h>
 #include <proto/queue.h>
+#include <proto/server.h>
 #include <proto/session.h>
 #include <proto/stream_sock.h>
 #include <proto/task.h>
@@ -1912,7 +1913,7 @@ int srv_redispatch_connect(struct session *t)
                }
 
                if (t->srv)
-                       t->srv->cum_sess++;
+                       srv_inc_sess_ctr(t->srv);
                if (t->srv)
                        t->srv->failed_conns++;
                t->be->failed_conns++;
index 4cc3d7ea03038957fe1a3dfbc8838f5b4244e334..3e1ff58404a75bab14c0848ab45fbf18db5a8a8f 100644 (file)
@@ -33,6 +33,7 @@
 #include <proto/log.h>
 #include <proto/hdr_idx.h>
 #include <proto/proto_http.h>
+#include <proto/proxy.h>
 #include <proto/session.h>
 #include <proto/stream_interface.h>
 #include <proto/stream_sock.h>
@@ -236,7 +237,7 @@ int event_accept(int fd) {
                s->data_source = DATA_SRC_NONE;
 
                s->uniq_id = totalconn;
-               p->cum_feconn++;        /* cum_beconn will be increased once assigned */
+               proxy_inc_fe_ctr(p);    /* note: cum_beconn will be increased once assigned */
 
                txn = &s->txn;
                txn->flags = 0;
@@ -444,7 +445,7 @@ int event_accept(int fd) {
                        p->feconn_max = p->feconn;
 
                if (s->flags & SN_BE_ASSIGNED) {
-                       s->be->cum_beconn++;
+                       proxy_inc_be_ctr(s->be);
                        s->be->beconn++;
                        if (s->be->beconn > s->be->beconn_max)
                                s->be->beconn_max = s->be->beconn;
index dd047b76c249b71f710cd0afd84f273fc6b41431..97443a122ff83bb59b2c0ad7babcb52a863977e5 100644 (file)
@@ -41,6 +41,7 @@
 #include <proto/buffers.h>
 #include <proto/dumpstats.h>
 #include <proto/fd.h>
+#include <proto/freq_ctr.h>
 #include <proto/pipe.h>
 #include <proto/proto_uxst.h>
 #include <proto/session.h>
@@ -173,7 +174,7 @@ int print_csv_header(struct chunk *msg, int size)
                            "wretr,wredis,"
                            "status,weight,act,bck,"
                            "chkfail,chkdown,lastchg,downtime,qlimit,"
-                           "pid,iid,sid,throttle,lbtot,tracked,type,"
+                           "pid,iid,sid,throttle,lbtot,tracked,type,rate,"
                            "\n");
 }
 
@@ -650,21 +651,21 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                if (!(s->data_ctx.stats.flags & STAT_FMT_CSV)) {
                        /* print a new table */
                        chunk_printf(&msg, sizeof(trash),
-                                    "<table cols=\"26\" class=\"tbl\" width=\"100%%\">\n"
+                                    "<table cols=\"27\" class=\"tbl\" width=\"100%%\">\n"
                                     "<tr align=\"center\" class=\"titre\">"
                                     "<th colspan=2 class=\"pxname\">%s</th>"
-                                    "<th colspan=24 class=\"empty\"></th>"
+                                    "<th colspan=25 class=\"empty\"></th>"
                                     "</tr>\n"
                                     "<tr align=\"center\" class=\"titre\">"
                                     "<th rowspan=2></th>"
-                                    "<th colspan=3>Queue</th><th colspan=5>Sessions</th>"
+                                    "<th colspan=3>Queue</th><th colspan=6>Sessions</th>"
                                     "<th colspan=2>Bytes</th><th colspan=2>Denied</th>"
                                     "<th colspan=3>Errors</th><th colspan=2>Warnings</th>"
                                     "<th colspan=8>Server</th>"
                                     "</tr>\n"
                                     "<tr align=\"center\" class=\"titre\">"
                                     "<th>Cur</th><th>Max</th><th>Limit</th><th>Cur</th><th>Max</th>"
-                                    "<th>Limit</th><th>Total</th><th>LbTot</th><th>In</th><th>Out</th>"
+                                    "<th>Limit</th><th>Rate</th><th>Total</th><th>LbTot</th><th>In</th><th>Out</th>"
                                     "<th>Req</th><th>Resp</th><th>Req</th><th>Conn</th>"
                                     "<th>Resp</th><th>Retr</th><th>Redis</th>"
                                     "<th>Status</th><th>Wght</th><th>Act</th>"
@@ -688,10 +689,10 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                chunk_printf(&msg, sizeof(trash),
                                     /* name, queue */
                                     "<tr align=center class=\"frontend\"><td>Frontend</td><td colspan=3></td>"
-                                    /* sessions : current, max, limit, total, lbtot */
+                                    /* sessions : current, max, limit, rate, total, lbtot */
                                     "<td align=right>%d</td><td align=right>%d</td>"
                                     "<td align=right>%d</td><td align=right>%d</td>"
-                                    "<td align=right></td>"
+                                    "<td align=right>%d</td><td align=right></td>"
                                     /* bytes : in, out */
                                     "<td align=right>%lld</td><td align=right>%lld</td>"
                                     /* denied: req, resp */
@@ -705,7 +706,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     /* rest of server: nothing */
                                     "<td align=center colspan=7></td></tr>"
                                     "",
-                                    px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
+                                    px->feconn, px->feconn_max, px->maxconn,
+                                    read_freq_ctr(&px->fe_sess_per_sec), px->cum_feconn,
                                     px->bytes_in, px->bytes_out,
                                     px->denied_req, px->denied_resp,
                                     px->failed_req,
@@ -731,6 +733,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     ",,,,,,,,"
                                     /* pid, iid, sid, throttle, lbtot, tracked, type */
                                     "%d,%d,0,,,,%d,"
+                                    /* rate */
+                                    "%u,"
                                     "\n",
                                     px->id,
                                     px->feconn, px->feconn_max, px->maxconn, px->cum_feconn,
@@ -739,7 +743,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     px->failed_req,
                                     px->state == PR_STRUN ? "OPEN" :
                                     px->state == PR_STIDLE ? "FULL" : "STOP",
-                                    relative_pid, px->uuid, STATS_TYPE_FE);
+                                    relative_pid, px->uuid, STATS_TYPE_FE,
+                                    read_freq_ctr(&px->fe_sess_per_sec));
                        }
 
                        if (buffer_write_chunk(rep, &msg) >= 0)
@@ -805,10 +810,10 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     "<tr align=\"center\" class=\"%s%d\"><td>%s</td>"
                                     /* queue : current, max, limit */
                                     "<td align=right>%d</td><td align=right>%d</td><td align=right>%s</td>"
-                                    /* sessions : current, max, limit, total, lbtot */
+                                    /* sessions : current, max, limit, rate, total, lbtot */
                                     "<td align=right>%d</td><td align=right>%d</td>"
                                     "<td align=right>%s</td><td align=right>%d</td>"
-                                    "<td align=right>%d</td>"
+                                    "<td align=right>%d</td><td align=right>%d</td>"
                                     /* bytes : in, out */
                                     "<td align=right>%lld</td><td align=right>%lld</td>"
                                     /* denied: req, resp */
@@ -822,6 +827,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     sv_state, sv->id,
                                     sv->nbpend, sv->nbpend_max, LIM2A0(sv->maxqueue, "-"),
                                     sv->cur_sess, sv->cur_sess_max, LIM2A1(sv->maxconn, "-"),
+                                    read_freq_ctr(&sv->sess_per_sec),
                                     sv->cum_sess, sv->cum_lbconn,
                                     sv->bytes_in, sv->bytes_out,
                                     sv->failed_secu,
@@ -956,8 +962,14 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                else
                                        chunk_printf(&msg, sizeof(trash), ",");
 
-                               /* type, then EOL */
-                               chunk_printf(&msg, sizeof(trash), "%d,\n", STATS_TYPE_SV);
+                               /* type */
+                               chunk_printf(&msg, sizeof(trash), "%d,", STATS_TYPE_SV);
+
+                               /* rate */
+                               chunk_printf(&msg, sizeof(trash), "%u,", read_freq_ctr(&sv->sess_per_sec));
+
+                               /* finish with EOL */
+                               chunk_printf(&msg, sizeof(trash), "\n");
                        }
                        if (buffer_write_chunk(rep, &msg) >= 0)
                                return 0;
@@ -976,10 +988,10 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     "<tr align=center class=\"backend\"><td>Backend</td>"
                                     /* queue : current, max */
                                     "<td align=right>%d</td><td align=right>%d</td><td></td>"
-                                    /* sessions : current, max, limit, total, lbtot */
+                                    /* sessions : current, max, limit, rate, total, lbtot */
+                                    "<td align=right>%d</td><td align=right>%d</td>"
                                     "<td align=right>%d</td><td align=right>%d</td>"
                                     "<td align=right>%d</td><td align=right>%d</td>"
-                                    "<td align=right>%d</td>"
                                     /* bytes : in, out */
                                     "<td align=right>%lld</td><td align=right>%lld</td>"
                                     /* denied: req, resp */
@@ -995,7 +1007,9 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     "<td align=center nowrap>%s %s</td><td align=center>%d</td>"
                                     "<td align=center>%d</td><td align=center>%d</td>",
                                     px->nbpend /* or px->totpend ? */, px->nbpend_max,
-                                    px->beconn, px->beconn_max, px->fullconn, px->cum_beconn, px->cum_lbconn,
+                                    px->beconn, px->beconn_max, px->fullconn,
+                                    read_freq_ctr(&px->be_sess_per_sec),
+                                    px->cum_beconn, px->cum_lbconn,
                                     px->bytes_in, px->bytes_out,
                                     px->denied_req, px->denied_resp,
                                     px->failed_conns, px->failed_resp,
@@ -1040,6 +1054,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     ",%d,%d,%d,,"
                                     /* pid, iid, sid, throttle, lbtot, tracked, type */
                                     "%d,%d,0,,%d,,%d,"
+                                    /* rate */
+                                    "%u,"
                                     "\n",
                                     px->id,
                                     px->nbpend /* or px->totpend ? */, px->nbpend_max,
@@ -1054,7 +1070,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px, struct uri_auth *uri)
                                     px->down_trans, now.tv_sec - px->last_change,
                                     px->srv?be_downtime(px):0,
                                     relative_pid, px->uuid,
-                                    px->cum_lbconn, STATS_TYPE_BE);
+                                    px->cum_lbconn, STATS_TYPE_BE,
+                                    read_freq_ctr(&px->be_sess_per_sec));
                        }
                        if (buffer_write_chunk(rep, &msg) >= 0)
                                return 0;
diff --git a/src/freq_ctr.c b/src/freq_ctr.c
new file mode 100644 (file)
index 0000000..4522ff3
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * Event rate calculation functions.
+ *
+ * Copyright 2000-2009 Willy Tarreau <w@1wt.eu>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+#include <common/config.h>
+#include <common/standard.h>
+#include <common/time.h>
+#include <proto/freq_ctr.h>
+
+/* Read a frequency counter taking history into account for missing time in
+ * current period. Current second is sub-divided in 1000 chunks of one ms,
+ * and the missing ones are read proportionally from previous value. The
+ * return value has the same precision as one input data sample, so low rates
+ * will be inaccurate still appropriate for max checking. One trick we use for
+ * low values is to specially handle the case where the rate is between 0 and 1
+ * in order to avoid flapping while waiting for the next event.
+ */
+unsigned int read_freq_ctr(struct freq_ctr *ctr)
+{
+       unsigned int cur;
+       if (unlikely(ctr->curr_sec != now.tv_sec))
+               rotate_freq_ctr(ctr);
+
+       cur = ctr->curr_ctr;
+       if (ctr->prev_ctr <= 1 && !ctr->curr_ctr)
+               return ctr->prev_ctr; /* very low rate, avoid flapping */
+
+       return cur + mul32hi(ctr->prev_ctr, ~curr_sec_ms_scaled);
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 8
+ *  c-basic-offset: 8
+ * End:
+ */
index 6acb0b7b284ad4ca8cd5273c4a8861e183ef3e26..a8ade23c14cedc20f41afb0b3ae5f2d7d957a692 100644 (file)
@@ -47,7 +47,9 @@
 #include <proto/hdr_idx.h>
 #include <proto/proto_tcp.h>
 #include <proto/proto_http.h>
+#include <proto/proxy.h>
 #include <proto/queue.h>
+#include <proto/server.h>
 #include <proto/session.h>
 #include <proto/stream_interface.h>
 #include <proto/stream_sock.h>
@@ -692,7 +694,7 @@ void perform_http_redirect(struct session *s, struct stream_interface *si)
 
        /* FIXME: we should increase a counter of redirects per server and per backend. */
        if (s->srv)
-               s->srv->cum_sess++;
+               srv_inc_sess_ctr(s->srv);
 }
 
 /* Return the error message corresponding to si->err_type. It is assumed
@@ -1943,7 +1945,7 @@ int http_process_request(struct session *s, struct buffer *req)
                        s->be->beconn++;
                        if (s->be->beconn > s->be->beconn_max)
                                s->be->beconn_max = s->be->beconn;
-                       s->be->cum_beconn++;
+                       proxy_inc_be_ctr(s->be);
                        s->flags |= SN_BE_ASSIGNED;
                }
 
@@ -2046,7 +2048,7 @@ int http_process_request(struct session *s, struct buffer *req)
                                        s->be->beconn++;
                                        if (s->be->beconn > s->be->beconn_max)
                                                s->be->beconn_max = s->be->beconn;
-                                       s->be->cum_beconn++;
+                                       proxy_inc_be_ctr(s->be);
 
                                        /* assign new parameters to the session from the new backend */
                                        s->rep->rto = s->req->wto = s->be->timeout.server;
@@ -2067,7 +2069,7 @@ int http_process_request(struct session *s, struct buffer *req)
                        s->be->beconn++;
                        if (s->be->beconn > s->be->beconn_max)
                                s->be->beconn_max = s->be->beconn;
-                       s->be->cum_beconn++;
+                       proxy_inc_be_ctr(s->be);
 
                        /* assign new parameters to the session from the new backend */
                        s->rep->rto = s->req->wto = s->be->timeout.server;
@@ -2085,7 +2087,7 @@ int http_process_request(struct session *s, struct buffer *req)
                s->be->beconn++;
                if (s->be->beconn > s->be->beconn_max)
                        s->be->beconn_max = s->be->beconn;
-               s->be->cum_beconn++;
+               proxy_inc_be_ctr(s->be);
                s->flags |= SN_BE_ASSIGNED;
        }
 
index 8ced9b8bf30b8987a3fbe62ec71b7d9fc14a0afe..b3c50ca3464131a1fb16225ac8ef3969d8577e7c 100644 (file)
@@ -28,6 +28,7 @@
 #include <proto/proto_http.h>
 #include <proto/proto_tcp.h>
 #include <proto/queue.h>
+#include <proto/server.h>
 #include <proto/stream_interface.h>
 #include <proto/stream_sock.h>
 #include <proto/task.h>
@@ -367,7 +368,7 @@ void sess_update_stream_int(struct session *s, struct stream_interface *si)
                if (conn_err == SN_ERR_NONE) {
                        /* state = SI_ST_CON now */
                        if (s->srv)
-                               s->srv->cum_sess++;
+                               srv_inc_sess_ctr(s->srv);
                        return;
                }
 
@@ -381,7 +382,7 @@ void sess_update_stream_int(struct session *s, struct stream_interface *si)
                        }
 
                        if (s->srv)
-                               s->srv->cum_sess++;
+                               srv_inc_sess_ctr(s->srv);
                        if (s->srv)
                                s->srv->failed_conns++;
                        s->be->failed_conns++;