MINOR: counters: move last_change into counters struct

last_change was a member present in both proxy and server struct. It is
used as an age statistics to report the last update of the object.

Move last_change into fe_counters/be_counters. This is necessary to be
able to manipulate it through generic stat column and report it into
stats-file.

Note that there is a change for proxy structure with now 2 different
last_change values, on frontend and backend side. Special care was taken
to ensure that the value is initialized only on the proxy side. The
other value is set to 0 unless a listen proxy is instantiated. For the
moment, only backend counter is reported in stats. However, with now two
distinct values, stats could be extended to report it on both side.
This commit is contained in:
Amaury Denoyelle 2024-04-30 12:04:57 +02:00
parent 9b35e1f30c
commit 634cc2a5d8
16 changed files with 45 additions and 36 deletions

View File

@ -69,6 +69,8 @@ struct fe_counters {
struct freq_ctr sess_per_sec; /* sessions per second on this server */
struct freq_ctr req_per_sec; /* HTTP requests per second on the frontend */
struct freq_ctr conn_per_sec; /* received connections per second on the frontend */
unsigned long last_change; /* last time, when the state was changed */
};
/* counters used by servers and backends */
@ -76,7 +78,6 @@ struct be_counters {
unsigned int conn_max; /* max # of active sessions */
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 int cps_max; /* maximum of new connections received per second */
unsigned int sps_max; /* maximum of new connections accepted per second (sessions) */
@ -123,6 +124,9 @@ struct be_counters {
} p; /* protocol-specific stats */
struct freq_ctr sess_per_sec; /* sessions per second on this server */
unsigned long last_sess; /* last session time */
unsigned long last_change; /* last time, when the state was changed */
};
#endif /* _HAPROXY_COUNTERS_T_H */

View File

@ -361,7 +361,6 @@ struct proxy {
unsigned int retry_type; /* Type of retry allowed */
int redispatch_after; /* number of retries before redispatch */
unsigned down_time; /* total time the proxy was down */
time_t last_change; /* last time, when the state was changed */
int (*accept)(struct stream *s); /* application layer's accept() */
struct conn_src conn_src; /* connection source settings */
enum obj_type *default_target; /* default target to use for accepted streams or NULL */

View File

@ -381,7 +381,6 @@ struct server {
struct xprt_ops *xprt; /* transport-layer operations */
unsigned int svc_port; /* the port to connect to (for relevant families) */
unsigned down_time; /* total time the server was down */
time_t last_change; /* last time, when the state was changed */
int puid; /* proxy-unique server ID, used for SNMP, and "first" LB algo */
int tcp_ut; /* for TCP, user timeout */

View File

@ -2566,7 +2566,7 @@ void back_handle_st_rdy(struct stream *s)
*/
void set_backend_down(struct proxy *be)
{
be->last_change = ns_to_sec(now_ns);
be->be_counters.last_change = ns_to_sec(now_ns);
_HA_ATOMIC_INC(&be->be_counters.down_trans);
if (!(global.mode & MODE_STARTING)) {
@ -2639,10 +2639,10 @@ no_cookie:
}
int be_downtime(struct proxy *px) {
if (px->lbprm.tot_weight && px->last_change < ns_to_sec(now_ns)) // ignore negative time
if (px->lbprm.tot_weight && px->be_counters.last_change < ns_to_sec(now_ns)) // ignore negative time
return px->down_time;
return ns_to_sec(now_ns) - px->last_change + px->down_time;
return ns_to_sec(now_ns) - px->be_counters.last_change + px->down_time;
}
/*

View File

@ -1031,9 +1031,9 @@ int httpchk_build_status_header(struct server *s, struct buffer *buf)
s->queue.length);
if ((s->cur_state == SRV_ST_STARTING) &&
ns_to_sec(now_ns) < s->last_change + s->slowstart &&
ns_to_sec(now_ns) >= s->last_change) {
ratio = MAX(1, 100 * (ns_to_sec(now_ns) - s->last_change) / s->slowstart);
ns_to_sec(now_ns) < s->counters.last_change + s->slowstart &&
ns_to_sec(now_ns) >= s->counters.last_change) {
ratio = MAX(1, 100 * (ns_to_sec(now_ns) - s->counters.last_change) / s->slowstart);
chunk_appendf(buf, "; throttle=%d%%", ratio);
}

View File

@ -455,7 +455,7 @@ static struct proxy *cli_alloc_fe(const char *name, const char *file, int line)
init_new_proxy(fe);
fe->next = proxies_list;
proxies_list = fe;
fe->last_change = ns_to_sec(now_ns);
fe->fe_counters.last_change = ns_to_sec(now_ns);
fe->id = strdup("GLOBAL");
fe->cap = PR_CAP_FE|PR_CAP_INT;
fe->maxconn = 10; /* default to 10 concurrent connections */

View File

@ -3014,7 +3014,7 @@ spoe_init(struct proxy *px, struct flt_conf *fconf)
/* conf->agent_fe was already initialized during the config
* parsing. Finish initialization. */
conf->agent_fe.last_change = ns_to_sec(now_ns);
conf->agent_fe.fe_counters.last_change = ns_to_sec(now_ns);
conf->agent_fe.cap = PR_CAP_FE;
conf->agent_fe.mode = PR_MODE_TCP;
conf->agent_fe.maxconn = 0;

View File

@ -5525,7 +5525,7 @@ int cfg_parse_log_forward(const char *file, int linenum, char **args, int kwm)
px->conf.file = strdup(file);
px->conf.line = linenum;
px->mode = PR_MODE_SYSLOG;
px->last_change = ns_to_sec(now_ns);
px->fe_counters.last_change = ns_to_sec(now_ns);
px->cap = PR_CAP_FE;
px->maxconn = 10;
px->timeout.client = TICK_ETERNITY;

View File

@ -3219,7 +3219,7 @@ static void peer_session_forceshutdown(struct peer *peer)
/* Pre-configures a peers frontend to accept incoming connections */
void peers_setup_frontend(struct proxy *fe)
{
fe->last_change = ns_to_sec(now_ns);
fe->fe_counters.last_change = ns_to_sec(now_ns);
fe->cap = PR_CAP_FE | PR_CAP_BE;
fe->mode = PR_MODE_PEERS;
fe->maxconn = 0;

View File

@ -1570,6 +1570,7 @@ void proxy_unref_defaults(struct proxy *px)
*/
struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg)
{
uint last_change;
struct proxy *curproxy;
if ((curproxy = calloc(1, sizeof(*curproxy))) == NULL) {
@ -1578,7 +1579,13 @@ struct proxy *alloc_new_proxy(const char *name, unsigned int cap, char **errmsg)
}
init_new_proxy(curproxy);
curproxy->last_change = ns_to_sec(now_ns);
last_change = ns_to_sec(now_ns);
if (cap & PR_CAP_FE)
curproxy->fe_counters.last_change = last_change;
if (cap & PR_CAP_BE)
curproxy->be_counters.last_change = last_change;
curproxy->id = strdup(name);
curproxy->cap = cap;
@ -2723,7 +2730,7 @@ static int dump_servers_state(struct appctx *appctx)
dump_server_addr(&srv->check.addr, srv_check_addr);
dump_server_addr(&srv->agent.addr, srv_agent_addr);
srv_time_since_last_change = ns_to_sec(now_ns) - srv->last_change;
srv_time_since_last_change = ns_to_sec(now_ns) - srv->counters.last_change;
bk_f_forced_id = px->options & PR_O_FORCED_ID ? 1 : 0;
srv_f_forced_id = srv->flags & SRV_F_FORCED_ID ? 1 : 0;

View File

@ -114,10 +114,10 @@ unsigned int srv_dynamic_maxconn(const struct server *s)
s->proxy->beconn * s->maxconn / s->proxy->fullconn);
if ((s->cur_state == SRV_ST_STARTING) &&
ns_to_sec(now_ns) < s->last_change + s->slowstart &&
ns_to_sec(now_ns) >= s->last_change) {
ns_to_sec(now_ns) < s->counters.last_change + s->slowstart &&
ns_to_sec(now_ns) >= s->counters.last_change) {
unsigned int ratio;
ratio = 100 * (ns_to_sec(now_ns) - s->last_change) / s->slowstart;
ratio = 100 * (ns_to_sec(now_ns) - s->counters.last_change) / s->slowstart;
max = MAX(1, max * ratio / 100);
}
return max;

View File

@ -3324,7 +3324,7 @@ int check_action_do_resolve(struct act_rule *rule, struct proxy *px, char **err)
void resolvers_setup_proxy(struct proxy *px)
{
px->last_change = ns_to_sec(now_ns);
px->fe_counters.last_change = px->be_counters.last_change = ns_to_sec(now_ns);
px->cap = PR_CAP_FE | PR_CAP_BE;
px->maxconn = 0;
px->conn_retries = 1;

View File

@ -141,10 +141,10 @@ const char *srv_op_st_chg_cause(enum srv_op_st_chg_cause cause)
int srv_downtime(const struct server *s)
{
if ((s->cur_state != SRV_ST_STOPPED) || s->last_change >= ns_to_sec(now_ns)) // ignore negative time
if ((s->cur_state != SRV_ST_STOPPED) || s->counters.last_change >= ns_to_sec(now_ns)) // ignore negative time
return s->down_time;
return ns_to_sec(now_ns) - s->last_change + s->down_time;
return ns_to_sec(now_ns) - s->counters.last_change + s->down_time;
}
int srv_lastsession(const struct server *s)
@ -2336,7 +2336,7 @@ void server_recalc_eweight(struct server *sv, int must_update)
struct proxy *px = sv->proxy;
unsigned w;
if (ns_to_sec(now_ns) < sv->last_change || ns_to_sec(now_ns) >= sv->last_change + sv->slowstart) {
if (ns_to_sec(now_ns) < sv->counters.last_change || ns_to_sec(now_ns) >= sv->counters.last_change + sv->slowstart) {
/* go to full throttle if the slowstart interval is reached unless server is currently down */
if ((sv->cur_state != SRV_ST_STOPPED) && (sv->next_state == SRV_ST_STARTING))
sv->next_state = SRV_ST_RUNNING;
@ -2348,7 +2348,7 @@ void server_recalc_eweight(struct server *sv, int must_update)
if ((sv->cur_state == SRV_ST_STOPPED) && (sv->next_state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN))
w = 1;
else if ((sv->next_state == SRV_ST_STARTING) && (px->lbprm.algo & BE_LB_PROP_DYN))
w = (px->lbprm.wdiv * (ns_to_sec(now_ns) - sv->last_change) + sv->slowstart) / sv->slowstart;
w = (px->lbprm.wdiv * (ns_to_sec(now_ns) - sv->counters.last_change) + sv->slowstart) / sv->slowstart;
else
w = px->lbprm.wdiv;
@ -2868,7 +2868,7 @@ struct server *new_server(struct proxy *proxy)
srv->rid = 0; /* rid defaults to 0 */
srv->next_state = SRV_ST_RUNNING; /* early server setup */
srv->last_change = ns_to_sec(now_ns);
srv->counters.last_change = ns_to_sec(now_ns);
srv->check.obj_type = OBJ_TYPE_CHECK;
srv->check.status = HCHK_STATUS_INI;
@ -5496,7 +5496,7 @@ static int srv_alloc_lb(struct server *sv, struct proxy *be)
/* updates the server's weight during a warmup stage. Once the final weight is
* reached, the task automatically stops. Note that any server status change
* must have updated s->last_change accordingly.
* must have updated s->counters.last_change accordingly.
*/
static struct task *server_warmup(struct task *t, void *context, unsigned int state)
{
@ -5552,7 +5552,7 @@ static int init_srv_slowstart(struct server *srv)
if (srv->next_state == SRV_ST_STARTING) {
task_schedule(srv->warmup,
tick_add(now_ms,
MS_TO_TICKS(MAX(1000, (ns_to_sec(now_ns) - srv->last_change)) / 20)));
MS_TO_TICKS(MAX(1000, (ns_to_sec(now_ns) - srv->counters.last_change)) / 20)));
}
}
@ -6685,8 +6685,8 @@ static void srv_update_status(struct server *s, int type, int cause)
if (srv_prev_state != s->cur_state) {
if (srv_prev_state == SRV_ST_STOPPED) {
/* server was down and no longer is */
if (s->last_change < ns_to_sec(now_ns)) // ignore negative times
s->down_time += ns_to_sec(now_ns) - s->last_change;
if (s->counters.last_change < ns_to_sec(now_ns)) // ignore negative times
s->down_time += ns_to_sec(now_ns) - s->counters.last_change;
_srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_UP, cb_data.common, s);
}
else if (s->cur_state == SRV_ST_STOPPED) {
@ -6694,7 +6694,7 @@ static void srv_update_status(struct server *s, int type, int cause)
s->counters.down_trans++;
_srv_event_hdl_publish(EVENT_HDL_SUB_SERVER_DOWN, cb_data.common, s);
}
s->last_change = ns_to_sec(now_ns);
s->counters.last_change = ns_to_sec(now_ns);
/* publish the state change */
_srv_event_hdl_prepare_state(&cb_data.state,
@ -6709,9 +6709,9 @@ static void srv_update_status(struct server *s, int type, int cause)
/* backend was down and is back up again:
* no helper function, updating last_change and backend downtime stats
*/
if (s->proxy->last_change < ns_to_sec(now_ns)) // ignore negative times
s->proxy->down_time += ns_to_sec(now_ns) - s->proxy->last_change;
s->proxy->last_change = ns_to_sec(now_ns);
if (s->proxy->be_counters.last_change < ns_to_sec(now_ns)) // ignore negative times
s->proxy->down_time += ns_to_sec(now_ns) - s->proxy->be_counters.last_change;
s->proxy->be_counters.last_change = ns_to_sec(now_ns);
}
}

View File

@ -321,7 +321,7 @@ static void srv_state_srv_update(struct server *srv, int version, char **params)
srv_adm_set_drain(srv);
}
srv->last_change = ns_to_sec(now_ns) - srv_last_time_change;
srv->counters.last_change = ns_to_sec(now_ns) - srv_last_time_change;
srv->check.status = srv_check_status;
srv->check.result = srv_check_result;

View File

@ -332,7 +332,7 @@ static int cli_parse_show_events(char **args, char *payload, struct appctx *appc
/* Pre-configures a ring proxy to emit connections */
void sink_setup_proxy(struct proxy *px)
{
px->last_change = ns_to_sec(now_ns);
px->be_counters.last_change = ns_to_sec(now_ns);
px->cap = PR_CAP_BE;
px->maxconn = 0;
px->conn_retries = 1;

View File

@ -1311,7 +1311,7 @@ int stats_fill_sv_line(struct proxy *px, struct server *sv, int flags,
field = mkf_str(FO_STATUS, fld_status);
break;
case ST_I_PX_LASTCHG:
field = mkf_u32(FN_AGE, ns_to_sec(now_ns) - sv->last_change);
field = mkf_u32(FN_AGE, ns_to_sec(now_ns) - sv->counters.last_change);
break;
case ST_I_PX_WEIGHT:
field = mkf_u32(FN_AVG, (sv->cur_eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv);
@ -1684,7 +1684,7 @@ int stats_fill_be_line(struct proxy *px, int flags, struct field *line, int len,
field = mkf_u32(0, px->srv_bck);
break;
case ST_I_PX_LASTCHG:
field = mkf_u32(FN_AGE, ns_to_sec(now_ns) - px->last_change);
field = mkf_u32(FN_AGE, ns_to_sec(now_ns) - px->be_counters.last_change);
break;
case ST_I_PX_DOWNTIME:
if (px->srv)