Hello, This is a follow up to the earlier v1 of the same patch. I resolved some conflicts caused by the latest csv field position updates on the stats page in the repo. At the same time move the new field to the last position in csv, html capture is here [1]. Please ignore the general process section formatting, it is an issue in the capture.
To reiterate the changes, added a field last activity to the bytes section that gives the duration since last byte was tx/rx to fe,be,srv and listener. Thank you. Regards Bhaskar [1] http://tinyurl.com/n4thkkr
From cedcbe6998d7bf5f9b7bbc0cc160d21281479824 Mon Sep 17 00:00:00 2001 From: Bhaskar Maddala <[email protected]> Date: Tue, 11 Feb 2014 07:53:55 -0500 Subject: [PATCH] Add last activity/session enhancements to stats page Summary: Added fields for last activity/session to stats page. Last session for front end tracks the last accept time where as for backends tracks the last lb connection time. Last activity on all (be/fe/listener) tracks the time of last byte. --- doc/configuration.txt | 2 ++ include/proto/backend.h | 1 + include/proto/frontend.h | 2 ++ include/proto/listener.h | 6 ++++++ include/proto/proxy.h | 8 +++++++ include/proto/server.h | 1 + include/types/counters.h | 9 ++++++-- src/backend.c | 10 +++++++++ src/dumpstats.c | 54 +++++++++++++++++++++++++++------------------- src/frontend.c | 19 ++++++++++++++++ src/listener.c | 18 ++++++++++++++++ src/server.c | 9 ++++++++ src/session.c | 21 ++++++++++++++---- 13 files changed, 132 insertions(+), 28 deletions(-) diff --git a/doc/configuration.txt b/doc/configuration.txt index c36d49f..f4427d5 100644 --- a/doc/configuration.txt +++ b/doc/configuration.txt @@ -12492,6 +12492,8 @@ page. Both means provide a CSV format whose fields follow. 53. comp_byp: number of bytes that bypassed the HTTP compressor (CPU/BW limit) 54. comp_rsp: number of HTTP responses that were compressed 55. lastsess: number of seconds since last session assigned to server/backend + number of seconds since last connection was accepted by listener/frontend + 56. lastactv: number of seconds since last byte was tx or rx 9.2. Unix Socket commands diff --git a/include/proto/backend.h b/include/proto/backend.h index 68ba3d6..cc7338b 100644 --- a/include/proto/backend.h +++ b/include/proto/backend.h @@ -45,6 +45,7 @@ void update_backend_weight(struct proxy *px); struct server *get_server_sh(struct proxy *px, const char *addr, int len); struct server *get_server_uh(struct proxy *px, char *uri, int uri_len); int be_lastsession(const struct proxy *be); +int be_lastactv(const struct proxy *be); /* set the time of last session on the backend */ static void inline be_set_sess_last(struct proxy *be) diff --git a/include/proto/frontend.h b/include/proto/frontend.h index 77d3206..c44ec47 100644 --- a/include/proto/frontend.h +++ b/include/proto/frontend.h @@ -25,6 +25,8 @@ #include <common/config.h> #include <types/session.h> +int fe_lastactv(const struct proxy *fe); +int fe_lastsession(const struct proxy *fe); int frontend_accept(struct session *s); diff --git a/include/proto/listener.h b/include/proto/listener.h index 1473bfd..a8bbfff 100644 --- a/include/proto/listener.h +++ b/include/proto/listener.h @@ -26,6 +26,12 @@ #include <types/listener.h> +/* time since last activity/byte */ +int li_lastactv(const struct listener *li); + +/* time since last accepted connection */ +int li_lastsession(const struct listener *li); + /* This function adds the specified listener's file descriptor to the polling * lists if it is in the LI_LISTEN state. The listener enters LI_READY or * LI_FULL state depending on its number of connections. diff --git a/include/proto/proxy.h b/include/proto/proxy.h index 4a4b285..5eb5f0f 100644 --- a/include/proto/proxy.h +++ b/include/proto/proxy.h @@ -85,6 +85,14 @@ static void inline proxy_inc_fe_conn_ctr(struct listener *l, struct proxy *fe) fe->fe_counters.cps_max = fe->fe_conn_per_sec.curr_ctr; } +/* set the last accept time on the designated frontend */ +static void inline proxy_set_fe_conn_last(struct listener *l, struct proxy *fe) +{ + fe->fe_counters.last_sess = now.tv_sec; + if (l->counters) + l->counters->last_sess = now.tv_sec; +} + /* increase the number of cumulated connections accepted by the designated frontend */ static void inline proxy_inc_fe_sess_ctr(struct listener *l, struct proxy *fe) { diff --git a/include/proto/server.h b/include/proto/server.h index 750d8d5..d7ae9d4 100644 --- a/include/proto/server.h +++ b/include/proto/server.h @@ -35,6 +35,7 @@ #include <proto/freq_ctr.h> int srv_downtime(const struct server *s); +int srv_lastactv(const struct server *s); int srv_lastsession(const struct server *s); int srv_getinter(const struct check *check); diff --git a/include/types/counters.h b/include/types/counters.h index ecdc7cb..6a517c2 100644 --- a/include/types/counters.h +++ b/include/types/counters.h @@ -23,13 +23,14 @@ #ifndef _TYPES_COUNTERS_H #define _TYPES_COUNTERS_H -/* maybe later we might thing about having a different struct for FE and BE */ +/* maybe later we might think about having a different struct for FE and BE */ struct pxcounters { unsigned int conn_max; /* max # of active sessions */ long long cum_conn; /* cumulated number of received connections */ long long cum_sess; /* cumulated number of accepted connections */ long long cum_lbconn; /* cumulated number of sessions processed by load balancing (BE only) */ - unsigned long last_sess; /* last session time */ + unsigned long last_sess; /* last session time (on BE tracks the last LB connection) */ + /* (on FE tracks the last accepted connection) */ unsigned int cps_max; /* maximum of new connections received per second */ unsigned int sps_max; /* maximum of new connections accepted per second (sessions) */ @@ -37,6 +38,7 @@ struct pxcounters { long long bytes_in; /* number of bytes transferred from the client to the server */ long long bytes_out; /* number of bytes transferred from the server to the client */ + unsigned long last_actv; /* last activity - tracked as last time of bytes transferred */ long long comp_in; /* input bytes fed to the compressor */ long long comp_out; /* output bytes emitted by the compressor */ @@ -70,9 +72,11 @@ struct licounters { long long cum_conn; /* cumulated number of received connections */ long long cum_sess; /* cumulated number of accepted sessions */ + unsigned long last_sess; /* last accepted connection time on the listener */ long long bytes_in; /* number of bytes transferred from the client to the server */ long long bytes_out; /* number of bytes transferred from the server to the client */ + unsigned long last_actv; /* last activity - tracked as last time of bytes transferred */ long long denied_req, denied_resp; /* blocked requests/responses because of security concerns */ long long failed_req; /* failed requests (eg: invalid or timeout) */ @@ -90,6 +94,7 @@ struct srvcounters { long long bytes_in; /* number of bytes transferred from the client to the server */ long long bytes_out; /* number of bytes transferred from the server to the client */ + unsigned long last_actv; /* last activity - tracked as last time of bytes transferred */ long long failed_conns, failed_resp; /* failed connect() and responses */ long long cli_aborts, srv_aborts; /* aborted responses during DATA phase due to client or server */ diff --git a/src/backend.c b/src/backend.c index e561919..45e78f2 100644 --- a/src/backend.c +++ b/src/backend.c @@ -52,6 +52,16 @@ #include <proto/stream_interface.h> #include <proto/task.h> +/* time since last activity/byte */ +int be_lastactv(const struct proxy *be) +{ + if (be->be_counters.last_actv) + return now.tv_sec - be->be_counters.last_actv; + + return -1; +} + +/* time since last lb connection */ int be_lastsession(const struct proxy *be) { if (be->be_counters.last_sess) diff --git a/src/dumpstats.c b/src/dumpstats.c index 1e137fb..e0239d7 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -39,6 +39,7 @@ #include <types/global.h> #include <proto/backend.h> +#include <proto/frontend.h> #include <proto/channel.h> #include <proto/checks.h> #include <proto/compression.h> @@ -448,7 +449,7 @@ static void stats_dump_csv_header() "hrsp_1xx,hrsp_2xx,hrsp_3xx,hrsp_4xx,hrsp_5xx,hrsp_other,hanafail," "req_rate,req_rate_max,req_tot," "cli_abrt,srv_abrt," - "comp_in,comp_out,comp_byp,comp_rsp,lastsess," + "comp_in,comp_out,comp_byp,comp_rsp,lastsess,lastactv," "\n"); } @@ -2470,10 +2471,11 @@ static int stats_dump_fe_stats(struct stream_interface *si, struct proxy *px) chunk_appendf(&trash, "</table></div></u></td>" /* sessions: lbtot, lastsess */ - "<td></td><td></td>" + "<td></td><td>%s</td>" /* bytes : in */ "<td>%s</td>" "", + human_time(fe_lastsession(px), 1), U2H(px->fe_counters.bytes_in)); chunk_appendf(&trash, @@ -2487,6 +2489,8 @@ static int stats_dump_fe_stats(struct stream_interface *si, struct proxy *px) (px->fe_counters.comp_in || px->fe_counters.comp_byp) ? "</u>":""); chunk_appendf(&trash, + /* last actv */ + "<td>%s</td>" /* denied: req, resp */ "<td>%s</td><td>%s</td>" /* errors : request, connect, response */ @@ -2498,6 +2502,7 @@ static int stats_dump_fe_stats(struct stream_interface *si, struct proxy *px) /* rest of server: nothing */ "<td class=ac colspan=8></td></tr>" "", + human_time(fe_lastactv(px), 1), U2H(px->fe_counters.denied_req), U2H(px->fe_counters.denied_resp), U2H(px->fe_counters.failed_req), px->state == PR_STREADY ? "OPEN" : @@ -2566,8 +2571,8 @@ static int stats_dump_fe_stats(struct stream_interface *si, struct proxy *px) chunk_appendf(&trash, "%lld,", px->fe_counters.p.http.comp_rsp); - /* lastsess */ - chunk_appendf(&trash, ","); + /* lastsess, lastactv */ + chunk_appendf(&trash, "%d,%d,", fe_lastsession(px), fe_lastactv(px)); /* finish with EOL */ chunk_appendf(&trash, "\n"); @@ -2632,13 +2637,14 @@ static int stats_dump_li_stats(struct stream_interface *si, struct proxy *px, st "<td colspan=3> </td>" /* sessions: current, max, limit, total, lbtot, lastsess */ "<td>%s</td><td>%s</td><td>%s</td>" - "<td>%s</td><td> </td><td> </td>" - /* bytes: in, out */ - "<td>%s</td><td>%s</td>" + "<td>%s</td><td> </td><td>%s</td>" + /* bytes: in, out, lastactv */ + "<td>%s</td><td>%s</td><td>%s</td>" "", (flags & ST_SHLGNDS)?"</u>":"", U2H(l->nbconn), U2H(l->counters->conn_max), U2H(l->maxconn), - U2H(l->counters->cum_conn), U2H(l->counters->bytes_in), U2H(l->counters->bytes_out)); + U2H(l->counters->cum_conn), human_time(li_lastsession(l), 1), + U2H(l->counters->bytes_in), U2H(l->counters->bytes_out), human_time(li_lastactv(l), 1)); chunk_appendf(&trash, /* denied: req, resp */ @@ -2690,8 +2696,8 @@ static int stats_dump_li_stats(struct stream_interface *si, struct proxy *px, st ",," /* compression: in, out, bypassed, comp_rsp */ ",,,," - /* lastsess */ - "," + /* lastsess,lastactv */ + "%d,%d," "\n", px->id, l->name, l->nbconn, l->counters->conn_max, @@ -2700,7 +2706,8 @@ static int stats_dump_li_stats(struct stream_interface *si, struct proxy *px, st 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); + relative_pid, px->uuid, l->luid, STATS_TYPE_SO, + li_lastsession(l), li_lastactv(l)); } return 1; } @@ -2836,14 +2843,14 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in chunk_appendf(&trash, "</table></div></u></td>" - /* sessions: lbtot, last */ + /* sessions: lbtot, lastsess */ "<td>%s</td><td>%s</td>", U2H(sv->counters.cum_lbconn), human_time(srv_lastsession(sv), 1)); chunk_appendf(&trash, - /* bytes : in, out */ - "<td>%s</td><td>%s</td>" + /* bytes : in, out, lastactv */ + "<td>%s</td><td>%s</td><td>%s</td>" /* denied: req, resp */ "<td></td><td>%s</td>" /* errors : request, connect */ @@ -2853,7 +2860,7 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in /* warnings: retries, redispatches */ "<td>%lld</td><td>%lld</td>" "", - U2H(sv->counters.bytes_in), U2H(sv->counters.bytes_out), + U2H(sv->counters.bytes_in), U2H(sv->counters.bytes_out), human_time(srv_lastactv(sv), 1), U2H(sv->counters.failed_secu), U2H(sv->counters.failed_conns), U2H(sv->counters.failed_resp), @@ -3084,8 +3091,8 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in /* compression: in, out, bypassed, comp_rsp */ chunk_appendf(&trash, ",,,,"); - /* lastsess */ - chunk_appendf(&trash, "%d,", srv_lastsession(sv)); + /* lastsess, lastactv */ + chunk_appendf(&trash, "%d,%d,", srv_lastsession(sv), srv_lastactv(sv)); /* finish with EOL */ chunk_appendf(&trash, "\n"); @@ -3208,6 +3215,8 @@ static int stats_dump_be_stats(struct stream_interface *si, struct proxy *px, in (px->be_counters.comp_in || px->be_counters.comp_byp) ? "</u>":""); chunk_appendf(&trash, + /* last actv */ + "<td>%s</td>" /* denied: req, resp */ "<td>%s</td><td>%s</td>" /* errors : request, connect */ @@ -3223,6 +3232,7 @@ static int stats_dump_be_stats(struct stream_interface *si, struct proxy *px, in "<td class=ac>%s %s</td><td class=ac> </td><td class=ac>%d</td>" "<td class=ac>%d</td><td class=ac>%d</td>" "", + human_time(be_lastsession(px), 1), U2H(px->be_counters.denied_req), U2H(px->be_counters.denied_resp), U2H(px->be_counters.failed_conns), U2H(px->be_counters.failed_resp), @@ -3317,8 +3327,8 @@ static int stats_dump_be_stats(struct stream_interface *si, struct proxy *px, in /* compression: comp_rsp */ chunk_appendf(&trash, "%lld,", px->be_counters.p.http.comp_rsp); - /* lastsess */ - chunk_appendf(&trash, "%d,", be_lastsession(px)); + /* lastsess, lastactv */ + chunk_appendf(&trash, "%d,%d,", be_lastsession(px), be_lastactv(px)); /* finish with EOL */ chunk_appendf(&trash, "\n"); @@ -3394,15 +3404,15 @@ static void stats_dump_html_px_hdr(struct stream_interface *si, struct proxy *px "<th rowspan=2></th>" "<th colspan=3>Queue</th>" "<th colspan=3>Session rate</th><th colspan=6>Sessions</th>" - "<th colspan=2>Bytes</th><th colspan=2>Denied</th>" + "<th colspan=3>Bytes</th><th colspan=2>Denied</th>" "<th colspan=3>Errors</th><th colspan=2>Warnings</th>" "<th colspan=9>Server</th>" "</tr>\n" "<tr class=\"titre\">" "<th>Cur</th><th>Max</th><th>Limit</th>" "<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>Last</th><th>In</th><th>Out</th>" - "<th>Req</th><th>Resp</th><th>Req</th><th>Conn</th>" + "<th>Limit</th><th>Total</th><th>LbTot</th><th>Last</th>" + "<th>In</th><th>Out</th><th>Last</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>LastChk</th><th>Wght</th><th>Act</th>" "<th>Bck</th><th>Chk</th><th>Dwn</th><th>Dwntme</th>" diff --git a/src/frontend.c b/src/frontend.c index f94c6ab..bee7f7a 100644 --- a/src/frontend.c +++ b/src/frontend.c @@ -46,6 +46,25 @@ #include <proto/stream_interface.h> #include <proto/task.h> +/* time since last byte */ +int fe_lastactv(const struct proxy *fe) +{ + if (fe->fe_counters.last_actv) + return now.tv_sec - fe->fe_counters.last_actv; + + return -1; + +} + +/* time since last accepted connection */ +int fe_lastsession(const struct proxy *fe) +{ + if (fe->fe_counters.last_sess) + return now.tv_sec - fe->fe_counters.last_sess; + + return -1; +} + /* Finish a session accept() for a proxy (TCP or HTTP). It returns a negative * value in case of a critical failure which must cause the listener to be * disabled, a positive value in case of success, or zero if it is a success diff --git a/src/listener.c b/src/listener.c index 7ab1a87..288636f 100644 --- a/src/listener.c +++ b/src/listener.c @@ -39,6 +39,24 @@ static struct bind_kw_list bind_keywords = { .list = LIST_HEAD_INIT(bind_keywords.list) }; +/* last activity/byte time */ +int li_lastactv(const struct listener *li) +{ + if (li->counters->last_actv) + return now.tv_sec - li->counters->last_actv; + + return -1; +} + +/* time since last accepted connection */ +int li_lastsession(const struct listener *li) +{ + if (li->counters->last_sess) + return now.tv_sec - li->counters->last_sess; + + return -1; +} + /* This function adds the specified listener's file descriptor to the polling * lists if it is in the LI_LISTEN state. The listener enters LI_READY or * LI_FULL state depending on its number of connections. diff --git a/src/server.c b/src/server.c index ccae58b..3c4f101 100644 --- a/src/server.c +++ b/src/server.c @@ -30,6 +30,15 @@ int srv_downtime(const struct server *s) return now.tv_sec - s->last_change + s->down_time; } +/* time since last activity/byte */ +int srv_lastactv(const struct server *s) +{ + if (s->counters.last_actv) + return now.tv_sec - s->counters.last_actv; + + return -1; +} + int srv_lastsession(const struct server *s) { if (s->counters.last_sess) diff --git a/src/session.c b/src/session.c index b3da759..6870cea 100644 --- a/src/session.c +++ b/src/session.c @@ -126,6 +126,7 @@ int session_accept(struct listener *l, int cfd, struct sockaddr_storage *addr) p->fe_counters.conn_max = p->feconn; proxy_inc_fe_conn_ctr(l, p); + proxy_set_fe_conn_last(l, p); /* Add the minimum callbacks to prepare the connection's control layer. * We need this so that we can safely execute the ACLs used by the @@ -688,14 +689,20 @@ void session_process_counters(struct session *s) s->logs.bytes_in = s->req->total; if (bytes) { s->fe->fe_counters.bytes_in += bytes; + s->fe->fe_counters.last_actv += now.tv_sec; s->be->be_counters.bytes_in += bytes; + s->be->be_counters.last_actv = now.tv_sec; - if (objt_server(s->target)) + if (objt_server(s->target)) { objt_server(s->target)->counters.bytes_in += bytes; + objt_server(s->target)->counters.last_actv = now.tv_sec; + } - if (s->listener->counters) + if (s->listener->counters) { s->listener->counters->bytes_in += bytes; + s->listener->counters->last_actv += now.tv_sec; + } for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!stkctr_entry(&s->stkctr[i])) @@ -722,14 +729,20 @@ void session_process_counters(struct session *s) s->logs.bytes_out = s->rep->total; if (bytes) { s->fe->fe_counters.bytes_out += bytes; + s->fe->fe_counters.last_actv = now.tv_sec; s->be->be_counters.bytes_out += bytes; + s->be->be_counters.last_actv = now.tv_sec; - if (objt_server(s->target)) + if (objt_server(s->target)) { objt_server(s->target)->counters.bytes_out += bytes; + objt_server(s->target)->counters.last_actv = now.tv_sec; + } - if (s->listener->counters) + if (s->listener->counters) { s->listener->counters->bytes_out += bytes; + s->listener->counters->last_actv = now.tv_sec; + } for (i = 0; i < MAX_SESS_STKCTR; i++) { if (!stkctr_entry(&s->stkctr[i])) -- 1.7.10.4

