From: Willy Tarreau Date: Wed, 6 Jan 2016 18:48:21 +0000 (+0100) Subject: MEDIUM: stats: make stats_dump_sv_stats() use the stats field for HTML X-Git-Tag: v1.7-dev2~41 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=164d4a9e73042cad5928532cf5ca877a247ecf71;p=thirdparty%2Fhaproxy.git MEDIUM: stats: make stats_dump_sv_stats() use the stats field for HTML Here we still have a huge amount of stuff to extract from the HTML code and even from the caller. Indeed, the calling function computes the server state and prepares a color code that will be used to determine what style to use. The operations needed to decide what field to present or not depend a lot on the server's state, admin state, health value, rise and fall etc... all of which are not easily present in the table. We also have to check the reference's values for all of the above. There are also a number of differences between the CSV and HTML outputs : - CSV always reports check duration, HTML only if not zero - regarding last_change, CSV always report the server's while the HTML considers either the server's or the reference based on the admin state. - agent and health are separate in the CSV but mixed in the HTML. - too few info on agent anyway. After careful code inspection it happens that both sv->last_change and ref->last_change are identical and can both derive from [LASTCHG]. Also, the following info are missing from the array to complete the HTML code : - cookie, address, status description, check-in-progress, srv->admin At least for now it still works but a lot of info now need to be added. --- diff --git a/src/dumpstats.c b/src/dumpstats.c index 500e56f162..16e1abfee1 100644 --- a/src/dumpstats.c +++ b/src/dumpstats.c @@ -3640,6 +3640,7 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in (ref->state != SRV_ST_STOPPED) ? (ref->check.fall) : (ref->check.rise)); stats[ST_F_STATUS] = mkf_str(FO_STATUS, fld_status); + stats[ST_F_LASTCHG] = mkf_u32(FN_AGE, now.tv_sec - sv->last_change); stats[ST_F_WEIGHT] = mkf_u32(FN_AVG, (sv->eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv); stats[ST_F_ACT] = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 0 : 1); stats[ST_F_BCK] = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 1 : 0); @@ -3648,7 +3649,6 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in if (sv->check.state & CHK_ST_ENABLED) { stats[ST_F_CHKFAIL] = mkf_u64(FN_COUNTER, sv->counters.failed_checks); stats[ST_F_CHKDOWN] = mkf_u64(FN_COUNTER, sv->counters.down_trans); - stats[ST_F_LASTCHG] = mkf_u32(FN_AGE, now.tv_sec - sv->last_change); stats[ST_F_DOWNTIME] = mkf_u32(FN_COUNTER, srv_downtime(sv)); } @@ -3735,20 +3735,20 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in else chunk_appendf(&trash, "", - (sv->flags & SRV_F_BACKUP) ? "backup" : "active", srv_stats_colour_st[colour]); + (stats[ST_F_BCK].u.u32) ? "backup" : "active", srv_stats_colour_st[colour]); if ((px->cap & PR_CAP_BE) && px->srv && (appctx->ctx.stats.flags & STAT_ADMIN)) chunk_appendf(&trash, "", - sv->id); + field_str(stats, ST_F_SVNAME)); chunk_appendf(&trash, "%s" "%s" - "", - px->id, sv->id, + "", + field_str(stats, ST_F_PXNAME), field_str(stats, ST_F_SVNAME), (flags & ST_SHLGNDS) ? "" : "", - px->id, sv->id, sv->id); + field_str(stats, ST_F_PXNAME), field_str(stats, ST_F_SVNAME), field_str(stats, ST_F_SVNAME)); if (flags & ST_SHLGNDS) { chunk_appendf(&trash, "
"); @@ -3771,13 +3771,13 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in } /* id */ - chunk_appendf(&trash, "id: %d", sv->puid); + chunk_appendf(&trash, "id: %d", stats[ST_F_SID].u.u32); /* cookie */ if (sv->cookie) { chunk_appendf(&trash, ", cookie: '"); - chunk_initlen(&src, sv->cookie, 0, strlen(sv->cookie)); + chunk_initstr(&src, sv->cookie); chunk_htmlencode(&trash, &src); chunk_appendf(&trash, "'"); @@ -3793,9 +3793,8 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in "%s%s" "", (flags & ST_SHLGNDS) ? "" : "", - U2H(sv->nbpend), U2H(sv->counters.nbpend_max), LIM2A(sv->maxqueue, "-"), - U2H(read_freq_ctr(&sv->sess_per_sec)), U2H(sv->counters.sps_max)); - + U2H(stats[ST_F_QCUR].u.u32), U2H(stats[ST_F_QMAX].u.u32), LIM2A(stats[ST_F_QLIMIT].u.u32, "-"), + U2H(stats[ST_F_RATE].u.u32), U2H(stats[ST_F_RATE_MAX].u.u32)); chunk_appendf(&trash, /* sessions: current, max, limit, total */ @@ -3803,16 +3802,20 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in "%s
" "" "", - U2H(sv->cur_sess), U2H(sv->counters.cur_sess_max), LIM2A(sv->maxconn, "-"), - U2H(sv->counters.cum_sess), - U2H(sv->counters.cum_sess)); + U2H(stats[ST_F_SCUR].u.u32), U2H(stats[ST_F_SMAX].u.u32), LIM2A(stats[ST_F_SLIM].u.u32, "-"), + U2H(stats[ST_F_STOT].u.u64), + U2H(stats[ST_F_STOT].u.u64)); /* http response (via hover): 1xx, 2xx, 3xx, 4xx, 5xx, other */ if (px->mode == PR_MODE_HTTP) { unsigned long long tot; - int i; - for (tot = i = 0; i < 6; i++) - tot += sv->counters.p.http.rsp[i]; + + tot = stats[ST_F_HRSP_OTHER].u.u64; + tot += stats[ST_F_HRSP_1XX].u.u64; + tot += stats[ST_F_HRSP_2XX].u.u64; + tot += stats[ST_F_HRSP_3XX].u.u64; + tot += stats[ST_F_HRSP_4XX].u.u64; + tot += stats[ST_F_HRSP_5XX].u.u64; chunk_appendf(&trash, "" @@ -3824,27 +3827,27 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in "" "", U2H(tot), - U2H(sv->counters.p.http.rsp[1]), tot ? (int)(100*sv->counters.p.http.rsp[1] / tot) : 0, - U2H(sv->counters.p.http.rsp[2]), tot ? (int)(100*sv->counters.p.http.rsp[2] / tot) : 0, - U2H(sv->counters.p.http.rsp[3]), tot ? (int)(100*sv->counters.p.http.rsp[3] / tot) : 0, - U2H(sv->counters.p.http.rsp[4]), tot ? (int)(100*sv->counters.p.http.rsp[4] / tot) : 0, - U2H(sv->counters.p.http.rsp[5]), tot ? (int)(100*sv->counters.p.http.rsp[5] / tot) : 0, - U2H(sv->counters.p.http.rsp[0]), tot ? (int)(100*sv->counters.p.http.rsp[0] / tot) : 0); + U2H(stats[ST_F_HRSP_1XX].u.u64), tot ? (int)(100 * stats[ST_F_HRSP_1XX].u.u64 / tot) : 0, + U2H(stats[ST_F_HRSP_2XX].u.u64), tot ? (int)(100 * stats[ST_F_HRSP_2XX].u.u64 / tot) : 0, + U2H(stats[ST_F_HRSP_3XX].u.u64), tot ? (int)(100 * stats[ST_F_HRSP_3XX].u.u64 / tot) : 0, + U2H(stats[ST_F_HRSP_4XX].u.u64), tot ? (int)(100 * stats[ST_F_HRSP_4XX].u.u64 / tot) : 0, + U2H(stats[ST_F_HRSP_5XX].u.u64), tot ? (int)(100 * stats[ST_F_HRSP_5XX].u.u64 / tot) : 0, + U2H(stats[ST_F_HRSP_OTHER].u.u64), tot ? (int)(100 * stats[ST_F_HRSP_OTHER].u.u64 / tot) : 0); } chunk_appendf(&trash, ""); - chunk_appendf(&trash, "", U2H(swrate_avg(sv->counters.q_time, TIME_STATS_SAMPLES))); - chunk_appendf(&trash, "", U2H(swrate_avg(sv->counters.c_time, TIME_STATS_SAMPLES))); + chunk_appendf(&trash, "", U2H(stats[ST_F_QTIME].u.u32)); + chunk_appendf(&trash, "", U2H(stats[ST_F_CTIME].u.u32)); if (px->mode == PR_MODE_HTTP) - chunk_appendf(&trash, "", U2H(swrate_avg(sv->counters.d_time, TIME_STATS_SAMPLES))); - chunk_appendf(&trash, "", U2H(swrate_avg(sv->counters.t_time, TIME_STATS_SAMPLES))); + chunk_appendf(&trash, "", U2H(stats[ST_F_RTIME].u.u32)); + chunk_appendf(&trash, "", U2H(stats[ST_F_TTIME].u.u32)); chunk_appendf(&trash, "
Cum. sessions:%s
Cum. HTTP responses:%s
- other responses:%s(%d%%)
Avg over last 1024 success. conn.
- Queue time:%sms
- Connect time:%sms
- Queue time:%sms
- Connect time:%sms
- Response time:%sms
- Total time:%sms
- Response time:%sms
- Total time:%sms
" /* sessions: lbtot, last */ "%s%s", - U2H(sv->counters.cum_lbconn), - human_time(srv_lastsession(sv), 1)); + U2H(stats[ST_F_LBTOT].u.u64), + human_time(stats[ST_F_LASTSESS].u.s32, 1)); chunk_appendf(&trash, /* bytes : in, out */ @@ -3858,28 +3861,36 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in /* warnings: retries, redispatches */ "%lld%lld" "", - U2H(sv->counters.bytes_in), U2H(sv->counters.bytes_out), - U2H(sv->counters.failed_secu), - U2H(sv->counters.failed_conns), - U2H(sv->counters.failed_resp), - sv->counters.cli_aborts, - sv->counters.srv_aborts, - sv->counters.retries, sv->counters.redispatches); - - /* status, lest check */ + U2H(stats[ST_F_BIN].u.u64), U2H(stats[ST_F_BOUT].u.u64), + U2H(stats[ST_F_DRESP].u.u64), + U2H(stats[ST_F_ECON].u.u64), + U2H(stats[ST_F_ERESP].u.u64), + (long long)stats[ST_F_CLI_ABRT].u.u64, + (long long)stats[ST_F_SRV_ABRT].u.u64, + (long long)stats[ST_F_WRETR].u.u64, + (long long)stats[ST_F_WREDIS].u.u64); + + /* status, last change */ chunk_appendf(&trash, ""); + /* FIXME!!!! + * LASTCHG should contain the last change for *this* server and must be computed + * properly above, as was done below, ie: this server if maint, otherwise ref server + * if tracking. Note that ref is either local or remote depending on tracking. + */ + + if (sv->admin & SRV_ADMF_MAINT) { - chunk_appendf(&trash, "%s ", human_time(now.tv_sec - sv->last_change, 1)); + chunk_appendf(&trash, "%s ", human_time(stats[ST_F_LASTCHG].u.u32, 1)); chunk_appendf(&trash, "MAINT"); } else if ((ref->agent.state & CHK_ST_ENABLED) && !(sv->agent.health) && (ref->state == SRV_ST_STOPPED)) { - chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1)); + chunk_appendf(&trash, "%s ", human_time(stats[ST_F_LASTCHG].u.u32, 1)); /* DOWN (agent) */ chunk_appendf(&trash, srv_hlt_st[1], "GCC: your -Werror=format-security is bogus, annoying, and hides real bugs, I don't thank you, really!"); } else if (ref->check.state & CHK_ST_ENABLED) { - chunk_appendf(&trash, "%s ", human_time(now.tv_sec - ref->last_change, 1)); + chunk_appendf(&trash, "%s ", human_time(stats[ST_F_LASTCHG].u.u32, 1)); chunk_appendf(&trash, srv_hlt_st[state], (ref->state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health), @@ -3901,9 +3912,9 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in chunk_appendf(&trash, "
%s", get_check_status_description(sv->agent.status)); - if (*sv->agent.desc) { + if (*field_str(stats, ST_F_LAST_AGT)) { chunk_appendf(&trash, ": "); - chunk_initlen(&src, sv->agent.desc, 0, strlen(sv->agent.desc)); + chunk_initstr(&src, field_str(stats, ST_F_LAST_AGT)); chunk_htmlencode(&trash, &src); } chunk_appendf(&trash, "
"); @@ -3912,19 +3923,19 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in chunk_appendf(&trash, " %s%s", (sv->check.state & CHK_ST_INPROGRESS) ? "* " : "", - get_check_status_info(sv->check.status)); + field_str(stats, ST_F_CHECK_STATUS)); - if (sv->check.status >= HCHK_STATUS_L57DATA) - chunk_appendf(&trash, "/%d", sv->check.code); + if (stats[ST_F_CHECK_CODE].type) + chunk_appendf(&trash, "/%d", stats[ST_F_CHECK_CODE].u.u32); - if (sv->check.status >= HCHK_STATUS_CHECKED && sv->check.duration >= 0) - chunk_appendf(&trash, " in %lums", sv->check.duration); + if (stats[ST_F_CHECK_DURATION].type && stats[ST_F_CHECK_DURATION].u.u64 >= 0) + chunk_appendf(&trash, " in %lums", (long)stats[ST_F_CHECK_DURATION].u.u64); chunk_appendf(&trash, "
%s", get_check_status_description(sv->check.status)); - if (*sv->check.desc) { + if (*field_str(stats, ST_F_LAST_CHK)) { chunk_appendf(&trash, ": "); - chunk_initlen(&src, sv->check.desc, 0, strlen(sv->check.desc)); + chunk_initstr(&src, field_str(stats, ST_F_LAST_CHK)); chunk_htmlencode(&trash, &src); } chunk_appendf(&trash, "
"); @@ -3938,36 +3949,45 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in /* act, bck */ "%s%s" "", - (sv->eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv, - (sv->flags & SRV_F_BACKUP) ? "-" : "Y", - (sv->flags & SRV_F_BACKUP) ? "Y" : "-"); + stats[ST_F_WEIGHT].u.u32, + stats[ST_F_BCK].u.u32 ? "-" : "Y", + stats[ST_F_BCK].u.u32 ? "Y" : "-"); + + /* + * FIXME!!! + * here we count failed_checks from the ref while the CSV counts + * them from the server itself. The CSV needs to be fixed to use + * the ref as well. Also HANAFAIL is only reported if ref->observe + * while there's no such limit in the CSV. + * + */ /* check failures: unique, fatal, down time */ if (sv->check.state & CHK_ST_ENABLED) { - chunk_appendf(&trash, "%lld", ref->counters.failed_checks); + chunk_appendf(&trash, "%lld", (long long)stats[ST_F_CHKFAIL].u.u64); if (ref->observe) - chunk_appendf(&trash, "/%lld", ref->counters.failed_hana); + chunk_appendf(&trash, "/%lld", (long long)stats[ST_F_HANAFAIL].u.u64); chunk_appendf(&trash, "
Failed Health Checks%s
" "%lld%s" "", ref->observe ? "/Health Analyses" : "", - ref->counters.down_trans, human_time(srv_downtime(sv), 1)); + (long long)stats[ST_F_CHKDOWN].u.u64, human_time(stats[ST_F_DOWNTIME].u.u32, 1)); } - else if (!(sv->admin & SRV_ADMF_FMAINT) && sv != ref) { + else if (!(sv->admin & SRV_ADMF_FMAINT) && field_format(stats, ST_F_TRACKED) == FF_STR) { /* tracking a server */ chunk_appendf(&trash, - "via %s/%s", - via->proxy->id, via->id, via->proxy->id, via->id); + "via %s", + field_str(stats, ST_F_TRACKED), field_str(stats, ST_F_TRACKED)); } else chunk_appendf(&trash, ""); /* throttle */ - if (sv->state == SRV_ST_STARTING && !server_is_draining(sv)) - chunk_appendf(&trash, "%d %%\n", server_throttle_rate(sv)); + if (stats[ST_F_THROTTLE].type) + chunk_appendf(&trash, "%d %%\n", stats[ST_F_THROTTLE].u.u32); else chunk_appendf(&trash, "-\n"); } @@ -4075,7 +4095,7 @@ static int stats_dump_be_stats(struct stream_interface *si, struct proxy *px, in /* cookie */ if (px->cookie_name) { chunk_appendf(&trash, ", cookie: '"); - chunk_initlen(&src, px->cookie_name, 0, strlen(px->cookie_name)); + chunk_initstr(&src, px->cookie_name); chunk_htmlencode(&trash, &src); chunk_appendf(&trash, "'"); }