summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWilliam Dauchy <wdauchy@gmail.com>2021-01-25 17:29:03 +0100
committerChristopher Faulet <cfaulet@haproxy.com>2021-01-26 09:24:51 +0100
commitd3a9a4992b0198b75caf0602016d8d90a3f6a6e9 (patch)
tree5ae002690a71b98456e4cd3b2653109f779a87e5
parent3c6f006dc5e3e59b9a6489d6869917d5f687035d (diff)
downloadhaproxy-d3a9a4992b0198b75caf0602016d8d90a3f6a6e9.tar.gz
MEDIUM: stats: allow to select one field in `stats_fill_sv_stats`
prometheus approach requires to output all values for a given metric name; meaning we iterate through all metrics, and then iterate in the inner loop on all objects for this metric. In order to allow more code reuse, adapt the stats API to be able to select one field or fill them all otherwise. This patch follows what has already been done on frontend and backend side. From this patch it should be possible to remove most of the duplicate code on prometheuse side for the server. A few things to note though: - state require prior calculation, so I moved that to a sort of helper `stats_fill_be_stats_computestate`. - all ST_F*TIME fields requires some minor compute, so I moved it at te beginning of the function under a condition. Signed-off-by: William Dauchy <wdauchy@gmail.com>
-rw-r--r--include/haproxy/stats.h2
-rw-r--r--src/hlua_fcn.c3
-rw-r--r--src/stats.c584
3 files changed, 368 insertions, 221 deletions
diff --git a/include/haproxy/stats.h b/include/haproxy/stats.h
index 6c04f2761..6115dca8f 100644
--- a/include/haproxy/stats.h
+++ b/include/haproxy/stats.h
@@ -51,7 +51,7 @@ int stats_fill_fe_stats(struct proxy *px, struct field *stats, int len,
int stats_fill_li_stats(struct proxy *px, struct listener *l, int flags,
struct field *stats, int len);
int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags,
- struct field *stats, int len);
+ struct field *stats, int len, enum stat_field *selected_field);
int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int len,
enum stat_field *selected_field);
diff --git a/src/hlua_fcn.c b/src/hlua_fcn.c
index d13c5344f..6dd9efb21 100644
--- a/src/hlua_fcn.c
+++ b/src/hlua_fcn.c
@@ -922,7 +922,8 @@ int hlua_server_get_stats(lua_State *L)
return 1;
}
- stats_fill_sv_stats(srv->proxy, srv, STAT_SHLGNDS, stats, STATS_LEN);
+ stats_fill_sv_stats(srv->proxy, srv, STAT_SHLGNDS, stats,
+ STATS_LEN, NULL);
lua_newtable(L);
for (i=0; i<ST_F_TOTAL_FIELDS; i++) {
diff --git a/src/stats.c b/src/stats.c
index 0a412ede5..c748c7d34 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -1963,264 +1963,409 @@ static const char *srv_hlt_st[SRV_STATS_STATE_COUNT] = {
[SRV_STATS_STATE_NO_CHECK] = "no check"
};
-/* Fill <stats> with the server statistics. <stats> is
- * preallocated array of length <len>. The length of the array
- * must be at least ST_F_TOTAL_FIELDS. If this length is less
- * then this value, the function returns 0, otherwise, it
- * returns 1. <flags> can take the value STAT_SHLGNDS.
+/* Compute server state helper
*/
-int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags,
- struct field *stats, int len)
+static void stats_fill_sv_stats_computestate(struct server *sv, struct server *ref,
+ enum srv_stats_state *state)
{
- struct server *via, *ref;
- char str[INET6_ADDRSTRLEN];
- struct buffer *out = get_trash_chunk();
- enum srv_stats_state state;
- char *fld_status;
- long long srv_samples_counter;
- unsigned int srv_samples_window = TIME_STATS_SAMPLES;
-
- if (len < ST_F_TOTAL_FIELDS)
- return 0;
-
- /* we have "via" which is the tracked server as described in the configuration,
- * and "ref" which is the checked server and the end of the chain.
- */
- via = sv->track ? sv->track : sv;
- ref = via;
- while (ref->track)
- ref = ref->track;
-
if (sv->cur_state == SRV_ST_RUNNING || sv->cur_state == SRV_ST_STARTING) {
if ((ref->check.state & CHK_ST_ENABLED) &&
(ref->check.health < ref->check.rise + ref->check.fall - 1)) {
- state = SRV_STATS_STATE_UP_GOING_DOWN;
+ *state = SRV_STATS_STATE_UP_GOING_DOWN;
} else {
- state = SRV_STATS_STATE_UP;
+ *state = SRV_STATS_STATE_UP;
}
if (sv->cur_admin & SRV_ADMF_DRAIN) {
if (ref->agent.state & CHK_ST_ENABLED)
- state = SRV_STATS_STATE_DRAIN_AGENT;
- else if (state == SRV_STATS_STATE_UP_GOING_DOWN)
- state = SRV_STATS_STATE_DRAIN_GOING_DOWN;
+ *state = SRV_STATS_STATE_DRAIN_AGENT;
+ else if (*state == SRV_STATS_STATE_UP_GOING_DOWN)
+ *state = SRV_STATS_STATE_DRAIN_GOING_DOWN;
else
- state = SRV_STATS_STATE_DRAIN;
+ *state = SRV_STATS_STATE_DRAIN;
}
- if (state == SRV_STATS_STATE_UP && !(ref->check.state & CHK_ST_ENABLED)) {
- state = SRV_STATS_STATE_NO_CHECK;
+ if (*state == SRV_STATS_STATE_UP && !(ref->check.state & CHK_ST_ENABLED)) {
+ *state = SRV_STATS_STATE_NO_CHECK;
}
}
else if (sv->cur_state == SRV_ST_STOPPING) {
if ((!(sv->check.state & CHK_ST_ENABLED) && !sv->track) ||
(ref->check.health == ref->check.rise + ref->check.fall - 1)) {
- state = SRV_STATS_STATE_NOLB;
+ *state = SRV_STATS_STATE_NOLB;
} else {
- state = SRV_STATS_STATE_NOLB_GOING_DOWN;
+ *state = SRV_STATS_STATE_NOLB_GOING_DOWN;
}
}
else { /* stopped */
if ((ref->agent.state & CHK_ST_ENABLED) && !ref->agent.health) {
- state = SRV_STATS_STATE_DOWN_AGENT;
+ *state = SRV_STATS_STATE_DOWN_AGENT;
} else if ((ref->check.state & CHK_ST_ENABLED) && !ref->check.health) {
- state = SRV_STATS_STATE_DOWN; /* DOWN */
+ *state = SRV_STATS_STATE_DOWN; /* DOWN */
} else if ((ref->agent.state & CHK_ST_ENABLED) || (ref->check.state & CHK_ST_ENABLED)) {
- state = SRV_STATS_STATE_GOING_UP;
+ *state = SRV_STATS_STATE_GOING_UP;
} else {
- state = SRV_STATS_STATE_DOWN; /* DOWN, unchecked */
+ *state = SRV_STATS_STATE_DOWN; /* DOWN, unchecked */
}
}
+}
- chunk_reset(out);
-
- stats[ST_F_PXNAME] = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id);
- stats[ST_F_SVNAME] = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, sv->id);
- stats[ST_F_MODE] = mkf_str(FO_CONFIG|FS_SERVICE, proxy_mode_str(px->mode));
- stats[ST_F_QCUR] = mkf_u32(0, sv->nbpend);
- stats[ST_F_QMAX] = mkf_u32(FN_MAX, sv->counters.nbpend_max);
- stats[ST_F_SCUR] = mkf_u32(0, sv->cur_sess);
- stats[ST_F_SMAX] = mkf_u32(FN_MAX, sv->counters.cur_sess_max);
-
- if (sv->maxconn)
- stats[ST_F_SLIM] = mkf_u32(FO_CONFIG|FN_LIMIT, sv->maxconn);
-
- stats[ST_F_SRV_ICUR] = mkf_u32(0, sv->curr_idle_conns);
- if (sv->max_idle_conns != -1)
- stats[ST_F_SRV_ILIM] = mkf_u32(FO_CONFIG|FN_LIMIT, sv->max_idle_conns);
-
- stats[ST_F_STOT] = mkf_u64(FN_COUNTER, sv->counters.cum_sess);
- stats[ST_F_BIN] = mkf_u64(FN_COUNTER, sv->counters.bytes_in);
- stats[ST_F_BOUT] = mkf_u64(FN_COUNTER, sv->counters.bytes_out);
- stats[ST_F_DRESP] = mkf_u64(FN_COUNTER, sv->counters.denied_resp);
- stats[ST_F_ECON] = mkf_u64(FN_COUNTER, sv->counters.failed_conns);
- stats[ST_F_ERESP] = mkf_u64(FN_COUNTER, sv->counters.failed_resp);
- stats[ST_F_WRETR] = mkf_u64(FN_COUNTER, sv->counters.retries);
- stats[ST_F_WREDIS] = mkf_u64(FN_COUNTER, sv->counters.redispatches);
- stats[ST_F_WREW] = mkf_u64(FN_COUNTER, sv->counters.failed_rewrites);
- stats[ST_F_EINT] = mkf_u64(FN_COUNTER, sv->counters.internal_errors);
- stats[ST_F_CONNECT] = mkf_u64(FN_COUNTER, sv->counters.connect);
- stats[ST_F_REUSE] = mkf_u64(FN_COUNTER, sv->counters.reuse);
-
- stats[ST_F_IDLE_CONN_CUR] = mkf_u32(0, sv->curr_idle_nb);
- stats[ST_F_SAFE_CONN_CUR] = mkf_u32(0, sv->curr_safe_nb);
- stats[ST_F_USED_CONN_CUR] = mkf_u32(0, sv->curr_used_conns);
- stats[ST_F_NEED_CONN_EST] = mkf_u32(0, sv->est_need_conns);
-
- /* status */
- fld_status = chunk_newstr(out);
- if (sv->cur_admin & SRV_ADMF_RMAINT)
- chunk_appendf(out, "MAINT (resolution)");
- else if (sv->cur_admin & SRV_ADMF_IMAINT)
- chunk_appendf(out, "MAINT (via %s/%s)", via->proxy->id, via->id);
- else if (sv->cur_admin & SRV_ADMF_MAINT)
- chunk_appendf(out, "MAINT");
- else
- chunk_appendf(out,
- srv_hlt_st[state],
- (ref->cur_state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
- (ref->cur_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->cur_eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv);
- stats[ST_F_UWEIGHT] = mkf_u32(FN_AVG, sv->uweight);
- 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);
-
- /* check failures: unique, fatal; last change, total downtime */
- 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_DOWNTIME] = mkf_u32(FN_COUNTER, srv_downtime(sv));
- }
-
- if (sv->maxqueue)
- stats[ST_F_QLIMIT] = mkf_u32(FO_CONFIG|FS_SERVICE, sv->maxqueue);
-
- stats[ST_F_PID] = mkf_u32(FO_KEY, relative_pid);
- stats[ST_F_IID] = mkf_u32(FO_KEY|FS_SERVICE, px->uuid);
- stats[ST_F_SID] = mkf_u32(FO_KEY|FS_SERVICE, sv->puid);
-
- if (sv->cur_state == SRV_ST_STARTING && !server_is_draining(sv))
- stats[ST_F_THROTTLE] = mkf_u32(FN_AVG, server_throttle_rate(sv));
-
- stats[ST_F_LBTOT] = mkf_u64(FN_COUNTER, sv->counters.cum_lbconn);
-
- if (sv->track) {
- char *fld_track = chunk_newstr(out);
-
- chunk_appendf(out, "%s/%s", sv->track->proxy->id, sv->track->id);
- stats[ST_F_TRACKED] = mkf_str(FO_CONFIG|FN_NAME|FS_SERVICE, fld_track);
- }
-
- stats[ST_F_TYPE] = mkf_u32(FO_CONFIG|FS_SERVICE, STATS_TYPE_SV);
- stats[ST_F_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&sv->sess_per_sec));
- stats[ST_F_RATE_MAX] = mkf_u32(FN_MAX, sv->counters.sps_max);
-
- if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED) {
- const char *fld_chksts;
-
- fld_chksts = chunk_newstr(out);
- chunk_strcat(out, "* "); // for check in progress
- chunk_strcat(out, get_check_status_info(sv->check.status));
- if (!(sv->check.state & CHK_ST_INPROGRESS))
- fld_chksts += 2; // skip "* "
- stats[ST_F_CHECK_STATUS] = mkf_str(FN_OUTPUT, fld_chksts);
-
- if (sv->check.status >= HCHK_STATUS_L57DATA)
- stats[ST_F_CHECK_CODE] = mkf_u32(FN_OUTPUT, sv->check.code);
-
- if (sv->check.status >= HCHK_STATUS_CHECKED)
- stats[ST_F_CHECK_DURATION] = mkf_u64(FN_DURATION, sv->check.duration);
-
- stats[ST_F_CHECK_DESC] = mkf_str(FN_OUTPUT, get_check_status_description(sv->check.status));
- stats[ST_F_LAST_CHK] = mkf_str(FN_OUTPUT, sv->check.desc);
- stats[ST_F_CHECK_RISE] = mkf_u32(FO_CONFIG|FS_SERVICE, ref->check.rise);
- stats[ST_F_CHECK_FALL] = mkf_u32(FO_CONFIG|FS_SERVICE, ref->check.fall);
- stats[ST_F_CHECK_HEALTH] = mkf_u32(FO_CONFIG|FS_SERVICE, ref->check.health);
- }
-
- if ((sv->agent.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED) {
- const char *fld_chksts;
-
- fld_chksts = chunk_newstr(out);
- chunk_strcat(out, "* "); // for check in progress
- chunk_strcat(out, get_check_status_info(sv->agent.status));
- if (!(sv->agent.state & CHK_ST_INPROGRESS))
- fld_chksts += 2; // skip "* "
- stats[ST_F_AGENT_STATUS] = mkf_str(FN_OUTPUT, fld_chksts);
+/* Fill <stats> with the backend statistics. <stats> is preallocated array of
+ * length <len>. If <selected_field> is != NULL, only fill this one. The length
+ * of the array must be at least ST_F_TOTAL_FIELDS. If this length is less than
+ * this value, or if the selected field is not implemented for servers, the
+ * function returns 0, otherwise, it returns 1. <flags> can take the value
+ * STAT_SHLGNDS.
+ */
+int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags,
+ struct field *stats, int len,
+ enum stat_field *selected_field)
+{
+ enum stat_field current_field = (selected_field != NULL ? *selected_field : 0);
+ struct server *via = sv->track ? sv->track : sv;
+ struct server *ref = via;
+ enum srv_stats_state state = 0;
+ char str[INET6_ADDRSTRLEN];
+ struct buffer *out = get_trash_chunk();
+ char *fld_status;
+ long long srv_samples_counter;
+ unsigned int srv_samples_window = TIME_STATS_SAMPLES;
- if (sv->agent.status >= HCHK_STATUS_L57DATA)
- stats[ST_F_AGENT_CODE] = mkf_u32(FN_OUTPUT, sv->agent.code);
+ if (len < ST_F_TOTAL_FIELDS)
+ return 0;
- if (sv->agent.status >= HCHK_STATUS_CHECKED)
- stats[ST_F_AGENT_DURATION] = mkf_u64(FN_DURATION, sv->agent.duration);
+ chunk_reset(out);
- stats[ST_F_AGENT_DESC] = mkf_str(FN_OUTPUT, get_check_status_description(sv->agent.status));
- stats[ST_F_LAST_AGT] = mkf_str(FN_OUTPUT, sv->agent.desc);
- stats[ST_F_AGENT_RISE] = mkf_u32(FO_CONFIG|FS_SERVICE, sv->agent.rise);
- stats[ST_F_AGENT_FALL] = mkf_u32(FO_CONFIG|FS_SERVICE, sv->agent.fall);
- stats[ST_F_AGENT_HEALTH] = mkf_u32(FO_CONFIG|FS_SERVICE, sv->agent.health);
+ /* compute state for later use */
+ if (selected_field == NULL || *selected_field == ST_F_STATUS ||
+ *selected_field == ST_F_CHECK_RISE || *selected_field == ST_F_CHECK_FALL ||
+ *selected_field == ST_F_CHECK_HEALTH || *selected_field == ST_F_HANAFAIL) {
+ /* we have "via" which is the tracked server as described in the configuration,
+ * and "ref" which is the checked server and the end of the chain.
+ */
+ while (ref->track)
+ ref = ref->track;
+ stats_fill_sv_stats_computestate(sv, ref, &state);
}
- /* http response: 1xx, 2xx, 3xx, 4xx, 5xx, other */
- if (px->mode == PR_MODE_HTTP) {
- stats[ST_F_REQ_TOT] = mkf_u64(FN_COUNTER, sv->counters.p.http.cum_req);
- stats[ST_F_HRSP_1XX] = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[1]);
- stats[ST_F_HRSP_2XX] = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[2]);
- stats[ST_F_HRSP_3XX] = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[3]);
- stats[ST_F_HRSP_4XX] = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[4]);
- stats[ST_F_HRSP_5XX] = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[5]);
- stats[ST_F_HRSP_OTHER] = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[0]);
+ /* compue time values for later use */
+ if (selected_field == NULL || *selected_field == ST_F_QTIME ||
+ *selected_field == ST_F_CTIME || *selected_field == ST_F_RTIME ||
+ *selected_field == ST_F_TTIME) {
+ srv_samples_counter = (px->mode == PR_MODE_HTTP) ? sv->counters.p.http.cum_req : sv->counters.cum_lbconn;
+ if (srv_samples_counter < TIME_STATS_SAMPLES && srv_samples_counter > 0)
+ srv_samples_window = srv_samples_counter;
}
- if (ref->observe)
- stats[ST_F_HANAFAIL] = mkf_u64(FN_COUNTER, sv->counters.failed_hana);
-
- stats[ST_F_CLI_ABRT] = mkf_u64(FN_COUNTER, sv->counters.cli_aborts);
- stats[ST_F_SRV_ABRT] = mkf_u64(FN_COUNTER, sv->counters.srv_aborts);
- stats[ST_F_LASTSESS] = mkf_s32(FN_AGE, srv_lastsession(sv));
-
- srv_samples_counter = (px->mode == PR_MODE_HTTP) ? sv->counters.p.http.cum_req : sv->counters.cum_lbconn;
- if (srv_samples_counter < TIME_STATS_SAMPLES && srv_samples_counter > 0)
- srv_samples_window = srv_samples_counter;
-
- stats[ST_F_QTIME] = mkf_u32(FN_AVG, swrate_avg(sv->counters.q_time, srv_samples_window));
- stats[ST_F_CTIME] = mkf_u32(FN_AVG, swrate_avg(sv->counters.c_time, srv_samples_window));
- stats[ST_F_RTIME] = mkf_u32(FN_AVG, swrate_avg(sv->counters.d_time, srv_samples_window));
- stats[ST_F_TTIME] = mkf_u32(FN_AVG, swrate_avg(sv->counters.t_time, srv_samples_window));
+ for (; current_field < ST_F_TOTAL_FIELDS; current_field++) {
+ struct field metric = { 0 };
- stats[ST_F_QT_MAX] = mkf_u32(FN_MAX, sv->counters.qtime_max);
- stats[ST_F_CT_MAX] = mkf_u32(FN_MAX, sv->counters.ctime_max);
- stats[ST_F_RT_MAX] = mkf_u32(FN_MAX, sv->counters.dtime_max);
- stats[ST_F_TT_MAX] = mkf_u32(FN_MAX, sv->counters.ttime_max);
+ switch (current_field) {
+ case ST_F_PXNAME:
+ metric = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, px->id);
+ break;
+ case ST_F_SVNAME:
+ metric = mkf_str(FO_KEY|FN_NAME|FS_SERVICE, sv->id);
+ break;
+ case ST_F_MODE:
+ metric = mkf_str(FO_CONFIG|FS_SERVICE, proxy_mode_str(px->mode));
+ case ST_F_QCUR:
+ break;
+ metric = mkf_u32(0, sv->nbpend);
+ break;
+ case ST_F_QMAX:
+ metric = mkf_u32(FN_MAX, sv->counters.nbpend_max);
+ break;
+ case ST_F_SCUR:
+ metric = mkf_u32(0, sv->cur_sess);
+ break;
+ case ST_F_SMAX:
+ metric = mkf_u32(FN_MAX, sv->counters.cur_sess_max);
+ break;
+ case ST_F_SLIM:
+ if (sv->maxconn)
+ metric = mkf_u32(FO_CONFIG|FN_LIMIT, sv->maxconn);
+ break;
+ case ST_F_SRV_ICUR:
+ metric = mkf_u32(0, sv->curr_idle_conns);
+ break;
+ case ST_F_SRV_ILIM:
+ if (sv->max_idle_conns != -1)
+ metric = mkf_u32(FO_CONFIG|FN_LIMIT, sv->max_idle_conns);
+ break;
+ case ST_F_STOT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.cum_sess);
+ break;
+ case ST_F_BIN:
+ metric = mkf_u64(FN_COUNTER, sv->counters.bytes_in);
+ break;
+ case ST_F_BOUT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.bytes_out);
+ break;
+ case ST_F_DRESP:
+ metric = mkf_u64(FN_COUNTER, sv->counters.denied_resp);
+ break;
+ case ST_F_ECON:
+ metric = mkf_u64(FN_COUNTER, sv->counters.failed_conns);
+ break;
+ case ST_F_ERESP:
+ metric = mkf_u64(FN_COUNTER, sv->counters.failed_resp);
+ break;
+ case ST_F_WRETR:
+ metric = mkf_u64(FN_COUNTER, sv->counters.retries);
+ break;
+ case ST_F_WREDIS:
+ metric = mkf_u64(FN_COUNTER, sv->counters.redispatches);
+ break;
+ case ST_F_WREW:
+ metric = mkf_u64(FN_COUNTER, sv->counters.failed_rewrites);
+ break;
+ case ST_F_EINT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.internal_errors);
+ break;
+ case ST_F_CONNECT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.connect);
+ break;
+ case ST_F_REUSE:
+ metric = mkf_u64(FN_COUNTER, sv->counters.reuse);
+ break;
+ case ST_F_IDLE_CONN_CUR:
+ metric = mkf_u32(0, sv->curr_idle_nb);
+ break;
+ case ST_F_SAFE_CONN_CUR:
+ metric = mkf_u32(0, sv->curr_safe_nb);
+ break;
+ case ST_F_USED_CONN_CUR:
+ metric = mkf_u32(0, sv->curr_used_conns);
+ break;
+ case ST_F_NEED_CONN_EST:
+ metric = mkf_u32(0, sv->est_need_conns);
+ break;
+ case ST_F_STATUS:
+ fld_status = chunk_newstr(out);
+ if (sv->cur_admin & SRV_ADMF_RMAINT)
+ chunk_appendf(out, "MAINT (resolution)");
+ else if (sv->cur_admin & SRV_ADMF_IMAINT)
+ chunk_appendf(out, "MAINT (via %s/%s)", via->proxy->id, via->id);
+ else if (sv->cur_admin & SRV_ADMF_MAINT)
+ chunk_appendf(out, "MAINT");
+ else
+ chunk_appendf(out,
+ srv_hlt_st[state],
+ (ref->cur_state != SRV_ST_STOPPED) ? (ref->check.health - ref->check.rise + 1) : (ref->check.health),
+ (ref->cur_state != SRV_ST_STOPPED) ? (ref->check.fall) : (ref->check.rise));
- if (flags & STAT_SHLGNDS) {
- switch (addr_to_str(&sv->addr, str, sizeof(str))) {
- case AF_INET:
- stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out));
- chunk_appendf(out, "%s:%d", str, sv->svc_port);
- break;
- case AF_INET6:
- stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out));
- chunk_appendf(out, "[%s]:%d", str, sv->svc_port);
- break;
- case AF_UNIX:
- stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, "unix");
- break;
- case -1:
- stats[ST_F_ADDR] = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out));
- chunk_strcat(out, strerror(errno));
- break;
- default: /* address family not supported */
- break;
+ metric = mkf_str(FO_STATUS, fld_status);
+ break;
+ case ST_F_LASTCHG:
+ metric = mkf_u32(FN_AGE, now.tv_sec - sv->last_change);
+ break;
+ case ST_F_WEIGHT:
+ metric = mkf_u32(FN_AVG, (sv->cur_eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv);
+ break;
+ case ST_F_UWEIGHT:
+ metric = mkf_u32(FN_AVG, sv->uweight);
+ break;
+ case ST_F_ACT:
+ metric = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 0 : 1);
+ break;
+ case ST_F_BCK:
+ metric = mkf_u32(FO_STATUS, (sv->flags & SRV_F_BACKUP) ? 1 : 0);
+ break;
+ case ST_F_CHKFAIL:
+ if (sv->check.state & CHK_ST_ENABLED)
+ metric = mkf_u64(FN_COUNTER, sv->counters.failed_checks);
+ break;
+ case ST_F_CHKDOWN:
+ if (sv->check.state & CHK_ST_ENABLED)
+ metric = mkf_u64(FN_COUNTER, sv->counters.down_trans);
+ break;
+ case ST_F_DOWNTIME:
+ if (sv->check.state & CHK_ST_ENABLED)
+ metric = mkf_u32(FN_COUNTER, srv_downtime(sv));
+ break;
+ case ST_F_QLIMIT:
+ if (sv->maxqueue)
+ metric = mkf_u32(FO_CONFIG|FS_SERVICE, sv->maxqueue);
+ break;
+ case ST_F_PID:
+ metric = mkf_u32(FO_KEY, relative_pid);
+ break;
+ case ST_F_IID:
+ metric = mkf_u32(FO_KEY|FS_SERVICE, px->uuid);
+ break;
+ case ST_F_SID:
+ metric = mkf_u32(FO_KEY|FS_SERVICE, sv->puid);
+ break;
+ case ST_F_THROTTLE:
+ if (sv->cur_state == SRV_ST_STARTING && !server_is_draining(sv))
+ metric = mkf_u32(FN_AVG, server_throttle_rate(sv));
+ break;
+ case ST_F_LBTOT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.cum_lbconn);
+ break;
+ case ST_F_TRACKED:
+ if (sv->track) {
+ char *fld_track = chunk_newstr(out);
+ chunk_appendf(out, "%s/%s", sv->track->proxy->id, sv->track->id);
+ metric = mkf_str(FO_CONFIG|FN_NAME|FS_SERVICE, fld_track);
+ }
+ break;
+ case ST_F_TYPE:
+ metric = mkf_u32(FO_CONFIG|FS_SERVICE, STATS_TYPE_SV);
+ break;
+ case ST_F_RATE:
+ metric = mkf_u32(FN_RATE, read_freq_ctr(&sv->sess_per_sec));
+ break;
+ case ST_F_RATE_MAX:
+ metric = mkf_u32(FN_MAX, sv->counters.sps_max);
+ break;
+ case ST_F_CHECK_STATUS:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED) {
+ const char *fld_chksts;
+
+ fld_chksts = chunk_newstr(out);
+ chunk_strcat(out, "* "); // for check in progress
+ chunk_strcat(out, get_check_status_info(sv->check.status));
+ if (!(sv->check.state & CHK_ST_INPROGRESS))
+ fld_chksts += 2; // skip "* "
+ stats[ST_F_CHECK_STATUS] = mkf_str(FN_OUTPUT, fld_chksts);
+ }
+ break;
+ case ST_F_CHECK_CODE:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED &&
+ sv->check.status >= HCHK_STATUS_L57DATA)
+ metric = mkf_u32(FN_OUTPUT, sv->check.code);
+ break;
+ case ST_F_CHECK_DURATION:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED &&
+ sv->check.status >= HCHK_STATUS_CHECKED)
+ metric = mkf_u64(FN_DURATION, sv->check.duration);
+ break;
+ case ST_F_CHECK_DESC:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED)
+ metric = mkf_str(FN_OUTPUT, get_check_status_description(sv->check.status));
+ break;
+ case ST_F_LAST_CHK:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED)
+ metric = mkf_str(FN_OUTPUT, sv->check.desc);
+ break;
+ case ST_F_CHECK_RISE:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED)
+ metric = mkf_u32(FO_CONFIG|FS_SERVICE, ref->check.rise);
+ break;
+ case ST_F_CHECK_FALL:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED)
+ metric = mkf_u32(FO_CONFIG|FS_SERVICE, ref->check.fall);
+ break;
+ case ST_F_CHECK_HEALTH:
+ if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) == CHK_ST_ENABLED)
+ metric = mkf_u32(FO_CONFIG|FS_SERVICE, ref->check.health);
+ break;
+ case ST_F_REQ_TOT:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.cum_req);
+ break;
+ case ST_F_HRSP_1XX:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[1]);
+ break;
+ case ST_F_HRSP_2XX:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[2]);
+ break;
+ case ST_F_HRSP_3XX:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[3]);
+ break;
+ case ST_F_HRSP_4XX:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[4]);
+ break;
+ case ST_F_HRSP_5XX:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[5]);
+ break;
+ case ST_F_HRSP_OTHER:
+ if (px->mode == PR_MODE_HTTP)
+ metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[0]);
+ break;
+ case ST_F_HANAFAIL:
+ if (ref->observe)
+ metric = mkf_u64(FN_COUNTER, sv->counters.failed_hana);
+ break;
+ case ST_F_CLI_ABRT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.cli_aborts);
+ break;
+ case ST_F_SRV_ABRT:
+ metric = mkf_u64(FN_COUNTER, sv->counters.srv_aborts);
+ break;
+ case ST_F_LASTSESS:
+ metric = mkf_s32(FN_AGE, srv_lastsession(sv));
+ break;
+ case ST_F_QTIME:
+ metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.q_time, srv_samples_window));
+ break;
+ case ST_F_CTIME:
+ metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.c_time, srv_samples_window));
+ break;
+ case ST_F_RTIME:
+ metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.d_time, srv_samples_window));
+ break;
+ case ST_F_TTIME:
+ metric = mkf_u32(FN_AVG, swrate_avg(sv->counters.t_time, srv_samples_window));
+ break;
+ case ST_F_QT_MAX:
+ metric = mkf_u32(FN_MAX, sv->counters.qtime_max);
+ break;
+ case ST_F_CT_MAX:
+ metric = mkf_u32(FN_MAX, sv->counters.ctime_max);
+ break;
+ case ST_F_RT_MAX:
+ metric = mkf_u32(FN_MAX, sv->counters.dtime_max);
+ break;
+ case ST_F_TT_MAX:
+ metric = mkf_u32(FN_MAX, sv->counters.ttime_max);
+ break;
+ case ST_F_ADDR:
+ if (flags & STAT_SHLGNDS) {
+ switch (addr_to_str(&sv->addr, str, sizeof(str))) {
+ case AF_INET:
+ metric = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out));
+ chunk_appendf(out, "%s:%d", str, sv->svc_port);
+ break;
+ case AF_INET6:
+ metric = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out));
+ chunk_appendf(out, "[%s]:%d", str, sv->svc_port);
+ break;
+ case AF_UNIX:
+ metric = mkf_str(FO_CONFIG|FS_SERVICE, "unix");
+ break;
+ case -1:
+ metric = mkf_str(FO_CONFIG|FS_SERVICE, chunk_newstr(out));
+ chunk_strcat(out, strerror(errno));
+ break;
+ default: /* address family not supported */
+ break;
+ }
+ }
+ break;
+ case ST_F_COOKIE:
+ if (flags & STAT_SHLGNDS && sv->cookie)
+ metric = mkf_str(FO_CONFIG|FN_NAME|FS_SERVICE, sv->cookie);
+ break;
+ default:
+ /* not used for servers. If a specific metric
+ * is requested, return an error. Otherwise continue.
+ */
+ if (selected_field != NULL)
+ return 0;
+ continue;
}
-
- if (sv->cookie)
- stats[ST_F_COOKIE] = mkf_str(FO_CONFIG|FN_NAME|FS_SERVICE, sv->cookie);
+ stats[current_field] = metric;
+ if (selected_field != NULL)
+ break;
}
-
return 1;
}
@@ -2238,7 +2383,8 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, st
memset(stats, 0, sizeof(struct field) * stat_count[STATS_DOMAIN_PROXY]);
- if (!stats_fill_sv_stats(px, sv, appctx->ctx.stats.flags, stats, ST_F_TOTAL_FIELDS))
+ if (!stats_fill_sv_stats(px, sv, appctx->ctx.stats.flags, stats,
+ ST_F_TOTAL_FIELDS, NULL))
return 0;
list_for_each_entry(mod, &stats_module_list[STATS_DOMAIN_PROXY], list) {