MEDIUM: Add DRAIN state and report it on the stats page
Add a DRAIN sub-state for a server which will be shown on the stats page instead of UP if its effective weight is zero. Also, log if a server enters or leaves the DRAIN state as the result of an agent check. Signed-off-by: Simon Horman <horms@verge.net.au>
This commit is contained in:
parent
671b6f02b5
commit
8c3d0be987
|
@ -85,6 +85,18 @@ static inline unsigned int server_throttle_rate(struct server *sv)
|
||||||
const char *server_parse_weight_change_request(struct server *sv,
|
const char *server_parse_weight_change_request(struct server *sv,
|
||||||
const char *weight_str);
|
const char *weight_str);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Update the server's drain state to reflect its user-weight. This is not
|
||||||
|
* done immediately to allow a discrepancy between the server's user-weight
|
||||||
|
* and drains state to control logging of changes in the drain state.
|
||||||
|
*/
|
||||||
|
static inline void set_server_drain_state(struct server *s)
|
||||||
|
{
|
||||||
|
if (!s->uweight)
|
||||||
|
s->state |= SRV_DRAIN;
|
||||||
|
else
|
||||||
|
s->state &= ~SRV_DRAIN;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Local variables:
|
* Local variables:
|
||||||
* c-indent-level: 8
|
* c-indent-level: 8
|
||||||
|
|
|
@ -52,7 +52,8 @@
|
||||||
#define SRV_GOINGDOWN 0x0020 /* this server says that it's going down (404) */
|
#define SRV_GOINGDOWN 0x0020 /* this server says that it's going down (404) */
|
||||||
#define SRV_WARMINGUP 0x0040 /* this server is warming up after a failure */
|
#define SRV_WARMINGUP 0x0040 /* this server is warming up after a failure */
|
||||||
#define SRV_MAINTAIN 0x0080 /* this server is in maintenance mode */
|
#define SRV_MAINTAIN 0x0080 /* this server is in maintenance mode */
|
||||||
/* unused: 0x0100, 0x0200, 0x0400 */
|
#define SRV_DRAIN 0x0100 /* this server has been requested to drain its connections */
|
||||||
|
/* unused: 0x0200, 0x0400 */
|
||||||
#define SRV_SEND_PROXY 0x0800 /* this server talks the PROXY protocol */
|
#define SRV_SEND_PROXY 0x0800 /* this server talks the PROXY protocol */
|
||||||
#define SRV_NON_STICK 0x1000 /* never add connections allocated to this server to a stick table */
|
#define SRV_NON_STICK 0x1000 /* never add connections allocated to this server to a stick table */
|
||||||
#define SRV_AGENT_CHECKED 0x2000 /* this server needs to be checked using an agent check.
|
#define SRV_AGENT_CHECKED 0x2000 /* this server needs to be checked using an agent check.
|
||||||
|
|
|
@ -4899,6 +4899,9 @@ int cfg_parse_listen(const char *file, int linenum, char **args, int kwm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Set initial drain state using now-configured weight */
|
||||||
|
set_server_drain_state(newsrv);
|
||||||
|
|
||||||
if (do_check) {
|
if (do_check) {
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
|
|
@ -236,7 +236,10 @@ static void set_server_check_status(struct check *check, short status, const cha
|
||||||
|
|
||||||
if (s->proxy->options2 & PR_O2_LOGHCHKS &&
|
if (s->proxy->options2 & PR_O2_LOGHCHKS &&
|
||||||
(((check->health != 0) && (check->result & SRV_CHK_FAILED)) ||
|
(((check->health != 0) && (check->result & SRV_CHK_FAILED)) ||
|
||||||
((check->health != check->rise + check->fall - 1) && (check->result & SRV_CHK_PASSED)) ||
|
(((check->health != check->rise + check->fall - 1) ||
|
||||||
|
(!s->uweight && !(s->state & SRV_DRAIN)) ||
|
||||||
|
(s->uweight && (s->state & SRV_DRAIN))) &&
|
||||||
|
(check->result & SRV_CHK_PASSED)) ||
|
||||||
((s->state & SRV_GOINGDOWN) && !(check->result & SRV_CHK_DISABLE)) ||
|
((s->state & SRV_GOINGDOWN) && !(check->result & SRV_CHK_DISABLE)) ||
|
||||||
(!(s->state & SRV_GOINGDOWN) && (check->result & SRV_CHK_DISABLE)))) {
|
(!(s->state & SRV_GOINGDOWN) && (check->result & SRV_CHK_DISABLE)))) {
|
||||||
|
|
||||||
|
@ -290,7 +293,7 @@ static void set_server_check_status(struct check *check, short status, const cha
|
||||||
chunk_appendf(&trash, ", status: %d/%d %s",
|
chunk_appendf(&trash, ", status: %d/%d %s",
|
||||||
(state & SRV_RUNNING) ? (health - rise + 1) : (health),
|
(state & SRV_RUNNING) ? (health - rise + 1) : (health),
|
||||||
(state & SRV_RUNNING) ? (fall) : (rise),
|
(state & SRV_RUNNING) ? (fall) : (rise),
|
||||||
(state & SRV_RUNNING)?"UP":"DOWN");
|
(state & SRV_RUNNING)?(s->eweight?"UP":"DRAIN"):"DOWN");
|
||||||
|
|
||||||
Warning("%s.\n", trash.str);
|
Warning("%s.\n", trash.str);
|
||||||
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
|
send_log(s->proxy, LOG_NOTICE, "%s.\n", trash.str);
|
||||||
|
@ -1047,6 +1050,7 @@ static void event_srv_chk_r(struct connection *conn)
|
||||||
}
|
}
|
||||||
|
|
||||||
set_server_check_status(check, status, desc);
|
set_server_check_status(check, status, desc);
|
||||||
|
set_server_drain_state(check->server);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1112,6 +1112,12 @@ static int stats_sock_parse_request(struct stream_interface *si, char *line)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
warning = server_parse_weight_change_request(sv, args[3]);
|
warning = server_parse_weight_change_request(sv, args[3]);
|
||||||
|
/*
|
||||||
|
* The user-weight may now be zero and thus
|
||||||
|
* the server considered to be draining.
|
||||||
|
* Update the server's drain state as necessary.
|
||||||
|
*/
|
||||||
|
set_server_drain_state(sv);
|
||||||
if (warning) {
|
if (warning) {
|
||||||
si->applet.ctx.cli.msg = warning;
|
si->applet.ctx.cli.msg = warning;
|
||||||
si->applet.st0 = STAT_CLI_PRINT;
|
si->applet.st0 = STAT_CLI_PRINT;
|
||||||
|
@ -2124,7 +2130,8 @@ static int stats_dump_li_stats(struct stream_interface *si, struct proxy *px, st
|
||||||
* from stream interface <si>, stats flags <flags>, and server state <state>.
|
* from stream interface <si>, stats flags <flags>, and server state <state>.
|
||||||
* The caller is responsible for clearing the trash if needed. Returns non-zero
|
* The caller is responsible for clearing the trash if needed. Returns non-zero
|
||||||
* if it emits anything, zero otherwise. The <state> parameter can take the
|
* if it emits anything, zero otherwise. The <state> parameter can take the
|
||||||
* following values : 0=DOWN, 1=going up, 2=going down, 3=UP, 4,5=NOLB, 6=unchecked.
|
* following values : 0=DOWN, 1=going up, 2=going down, 3=UP, 4,5=NOLB,
|
||||||
|
* 6,7=DRAIN, 8=unchecked.
|
||||||
*/
|
*/
|
||||||
static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, int flags, struct server *sv, int state)
|
static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, int flags, struct server *sv, int state)
|
||||||
{
|
{
|
||||||
|
@ -2134,19 +2141,21 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (si->applet.ctx.stats.flags & STAT_FMT_HTML) {
|
if (si->applet.ctx.stats.flags & STAT_FMT_HTML) {
|
||||||
static char *srv_hlt_st[7] = {
|
static char *srv_hlt_st[9] = {
|
||||||
"DOWN",
|
"DOWN",
|
||||||
"DN %d/%d ↑",
|
"DN %d/%d ↑",
|
||||||
"UP %d/%d ↓",
|
"UP %d/%d ↓",
|
||||||
"UP",
|
"UP",
|
||||||
"NOLB %d/%d ↓",
|
"NOLB %d/%d ↓",
|
||||||
"NOLB",
|
"NOLB",
|
||||||
|
"DRAIN %d/%d ↓",
|
||||||
|
"DRAIN",
|
||||||
"<i>no check</i>"
|
"<i>no check</i>"
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((sv->state & SRV_MAINTAIN) || (ref->state & SRV_MAINTAIN))
|
if ((sv->state & SRV_MAINTAIN) || (ref->state & SRV_MAINTAIN))
|
||||||
chunk_appendf(&trash, "<tr class=\"maintain\">");
|
chunk_appendf(&trash, "<tr class=\"maintain\">");
|
||||||
else if (sv->eweight == 0)
|
else if (sv->eweight == 0 && !(sv->state & SRV_DRAIN))
|
||||||
chunk_appendf(&trash, "<tr class=\"softstop\">");
|
chunk_appendf(&trash, "<tr class=\"softstop\">");
|
||||||
else
|
else
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash,
|
||||||
|
@ -2354,13 +2363,15 @@ static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, in
|
||||||
chunk_appendf(&trash, "<td class=ac>-</td></tr>\n");
|
chunk_appendf(&trash, "<td class=ac>-</td></tr>\n");
|
||||||
}
|
}
|
||||||
else { /* CSV mode */
|
else { /* CSV mode */
|
||||||
static char *srv_hlt_st[7] = {
|
static char *srv_hlt_st[9] = {
|
||||||
"DOWN,",
|
"DOWN,",
|
||||||
"DOWN %d/%d,",
|
"DOWN %d/%d,",
|
||||||
"UP %d/%d,",
|
"UP %d/%d,",
|
||||||
"UP,",
|
"UP,",
|
||||||
"NOLB %d/%d,",
|
"NOLB %d/%d,",
|
||||||
"NOLB,",
|
"NOLB,",
|
||||||
|
"DRAIN %d/%d,",
|
||||||
|
"DRAIN,",
|
||||||
"no check,"
|
"no check,"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -2964,7 +2975,7 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy
|
||||||
|
|
||||||
/* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
|
/* FIXME: produce some small strings for "UP/DOWN x/y &#xxxx;" */
|
||||||
if (!(svs->state & SRV_CHECKED))
|
if (!(svs->state & SRV_CHECKED))
|
||||||
sv_state = 6;
|
sv_state = 8;
|
||||||
else if (svs->state & SRV_RUNNING) {
|
else if (svs->state & SRV_RUNNING) {
|
||||||
if (svs->check.health == svs->check.rise + svs->check.fall - 1)
|
if (svs->check.health == svs->check.rise + svs->check.fall - 1)
|
||||||
sv_state = 3; /* UP */
|
sv_state = 3; /* UP */
|
||||||
|
@ -2973,6 +2984,8 @@ static int stats_dump_proxy_to_buffer(struct stream_interface *si, struct proxy
|
||||||
|
|
||||||
if (svs->state & SRV_GOINGDOWN)
|
if (svs->state & SRV_GOINGDOWN)
|
||||||
sv_state += 2;
|
sv_state += 2;
|
||||||
|
else if (svs->state & SRV_DRAIN)
|
||||||
|
sv_state += 4;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
if (svs->check.health)
|
if (svs->check.health)
|
||||||
|
@ -3085,14 +3098,18 @@ static void stats_dump_html_head(struct uri_auth *uri)
|
||||||
".active3 {background: #c0ffc0;}\n"
|
".active3 {background: #c0ffc0;}\n"
|
||||||
".active4 {background: #ffffa0;}\n" /* NOLB state shows same as going down */
|
".active4 {background: #ffffa0;}\n" /* NOLB state shows same as going down */
|
||||||
".active5 {background: #a0e0a0;}\n" /* NOLB state shows darker than up */
|
".active5 {background: #a0e0a0;}\n" /* NOLB state shows darker than up */
|
||||||
".active6 {background: #e0e0e0;}\n"
|
".active6 {background: #ffffa0;}\n"
|
||||||
|
".active7 {background: #cc9900;}\n"
|
||||||
|
".active8 {background: #e0e0e0;}\n"
|
||||||
".backup0 {background: #ff9090;}\n"
|
".backup0 {background: #ff9090;}\n"
|
||||||
".backup1 {background: #ff80ff;}\n"
|
".backup1 {background: #ff80ff;}\n"
|
||||||
".backup2 {background: #c060ff;}\n"
|
".backup2 {background: #c060ff;}\n"
|
||||||
".backup3 {background: #b0d0ff;}\n"
|
".backup3 {background: #b0d0ff;}\n"
|
||||||
".backup4 {background: #c060ff;}\n" /* NOLB state shows same as going down */
|
".backup4 {background: #c060ff;}\n" /* NOLB state shows same as going down */
|
||||||
".backup5 {background: #90b0e0;}\n" /* NOLB state shows same as going down */
|
".backup5 {background: #90b0e0;}\n" /* NOLB state shows same as going down */
|
||||||
".backup6 {background: #e0e0e0;}\n"
|
".backup6 {background: #c060ff;}\n"
|
||||||
|
".backup7 {background: #cc9900;}\n"
|
||||||
|
".backup8 {background: #e0e0e0;}\n"
|
||||||
".maintain {background: #c07820;}\n"
|
".maintain {background: #c07820;}\n"
|
||||||
".softstop {background: #0067FF;}\n"
|
".softstop {background: #0067FF;}\n"
|
||||||
".rls {letter-spacing: 0.2em; margin-right: 1px;}\n" /* right letter spacing (used for grouping digits) */
|
".rls {letter-spacing: 0.2em; margin-right: 1px;}\n" /* right letter spacing (used for grouping digits) */
|
||||||
|
@ -3178,7 +3195,9 @@ static void stats_dump_html_info(struct stream_interface *si, struct uri_auth *u
|
||||||
"<td class=\"backup1\"></td><td class=\"noborder\">backup DOWN, going up </td>"
|
"<td class=\"backup1\"></td><td class=\"noborder\">backup DOWN, going up </td>"
|
||||||
"</tr><tr>\n"
|
"</tr><tr>\n"
|
||||||
"<td class=\"active0\"></td><td class=\"noborder\">active or backup DOWN </td>"
|
"<td class=\"active0\"></td><td class=\"noborder\">active or backup DOWN </td>"
|
||||||
"<td class=\"active6\"></td><td class=\"noborder\">not checked </td>"
|
"<td class=\"active7\"></td><td class=\"noborder\">active or backup DRAIN </td>"
|
||||||
|
"</tr><tr>\n"
|
||||||
|
"<td class=\"active8\"></td><td class=\"noborder\">not checked </td>"
|
||||||
"</tr><tr>\n"
|
"</tr><tr>\n"
|
||||||
"<td class=\"maintain\"></td><td class=\"noborder\" colspan=\"3\">active or backup DOWN for maintenance (MAINT) </td>"
|
"<td class=\"maintain\"></td><td class=\"noborder\" colspan=\"3\">active or backup DOWN for maintenance (MAINT) </td>"
|
||||||
"</tr><tr>\n"
|
"</tr><tr>\n"
|
||||||
|
@ -3354,7 +3373,7 @@ static void stats_dump_html_info(struct stream_interface *si, struct uri_auth *u
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
chunk_appendf(&trash,
|
chunk_appendf(&trash,
|
||||||
"<p><div class=active6>"
|
"<p><div class=active8>"
|
||||||
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
"<a class=lfsb href=\"%s%s%s%s\" title=\"Remove this message\">[X]</a> "
|
||||||
"Unexpected result."
|
"Unexpected result."
|
||||||
"</div>\n", uri->uri_prefix,
|
"</div>\n", uri->uri_prefix,
|
||||||
|
|
Loading…
Reference in New Issue