>From cbfda2a0808cd5d5cbf17ec7f0d04f7091bec9cb Mon Sep 17 00:00:00 2001
From: Krzysztof Piotr Oledzki <[email protected]>
Date: Mon, 31 Aug 2009 21:04:02 +0200
Subject: [MEDIUM] Collect & show information about last health check
Collect information about last health check result,
including L5-7 code if possible (for example http or smtp
return code) and time took to finish last check.
Health check info is provided on both stats pages (html & csv)
and logged when a server is marekd UP or DOWN. Currently active
check are marked with an asterisk, but only in html mode.
Currently there are 9 status:
UNK -> unknown
SOCKERR -> socket error
L14OK -> check passed on layer 1-4, no upper layers testing enabled
L14TMOUT -> layer 1-4 timeout
L14UNR -> layer 1-4 unreachable, for example
"Connection refused" (tcp rst) or "No route to host" (icmp)
L57OK -> check passed on layer 5-7
L57TMOUT -> layer 5-7 (HTTP/SMTP/SSL) timeout
L57INVRSP -> layer 5-7 invalid response - protocol error
L57RSPERR -> layer 5-7 response error, for example HTTP 5xx
---
doc/configuration.txt | 13 ++++
include/proto/checks.h | 2 +
include/types/checks.h | 31 ++++++++
include/types/server.h | 8 ++-
src/checks.c | 178 ++++++++++++++++++++++++++++++++++++++++++++----
src/dumpstats.c | 39 +++++++++--
6 files changed, 250 insertions(+), 21 deletions(-)
create mode 100644 include/types/checks.h
diff --git a/doc/configuration.txt b/doc/configuration.txt
index 84fc9c9..52bee56 100644
--- a/doc/configuration.txt
+++ b/doc/configuration.txt
@@ -6438,6 +6438,19 @@ page. Both means provide a CSV format whose fields
follow.
31. tracked: id of proxy/server if tracking is enabled
32. type (0=frontend, 1=backend, 2=server)
33. rate (number of sessions per second over last elapsed second)
+ 36. check_status: status of last health check, one of:
+ UNK -> unknown
+ SOCKERR -> socket error
+ L14OK -> check passed on layer 1-4, no upper layers testing enabled
+ L14TMOUT -> layer 1-4 timeout
+ L14UNR -> layer 1-4 unreachable, for example "Connection refused"
+ (tcp rst) or "No route to host" (icmp)
+ L57OK -> check passed on layer 5-7
+ L57TMOUT -> layer 5-7 (HTTP/SMTP/SSL) timeout
+ L57INVRSP -> layer 5-7 invalid response - protocol error
+ L57RSPERR -> layer 5-7 response error, for example HTTP 5xx
+ 37. check_code: layer5-7 code, if available
+ 38. check_duration: time in ms took to finish last health check
9.2. Unix Socket commands
diff --git a/include/proto/checks.h b/include/proto/checks.h
index 6f0aa8b..bd70164 100644
--- a/include/proto/checks.h
+++ b/include/proto/checks.h
@@ -25,6 +25,8 @@
#include <types/task.h>
#include <common/config.h>
+const char *get_check_status_description(short check_status);
+const char *get_check_status_info(short check_status);
struct task *process_chk(struct task *t);
int start_checks();
diff --git a/include/types/checks.h b/include/types/checks.h
new file mode 100644
index 0000000..910a9a3
--- /dev/null
+++ b/include/types/checks.h
@@ -0,0 +1,31 @@
+/*
+ * Health-checks.
+ *
+ * Copyright 2008-2009 Krzysztof Piotr Oledzki <[email protected]>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ *
+ */
+
+/* check status */
+enum {
+ HCHK_STATUS_UNKNOWN = 0, /* Unknown */
+
+ HCHK_STATUS_SOCKERR, /* Socket error */
+
+ HCHK_STATUS_L14OK, /* L1-4 check passed, for example tcp
connect */
+ HCHK_STATUS_L14TMOUT, /* L1-4 timeout */
+ HCHK_STATUS_L14UNR, /* L1-4 unreachable, for example
"Connection refused" (tcp rst) or "No route to host" (icmp) */
+ HCHK_STATUS_L57OK, /* Check passed */
+ HCHK_STATUS_L57TMOUT, /* L5-7 (HTTP/SMTP/SSL) timeout */
+ HCHK_STATUS_L57INVRSP, /* L5-7 invalid response - protocol
error */
+
+ HCHK_STATUS_L57DATA, /* Below we have layer 5-7 data
avaliable */
+ HCHK_STATUS_L57OKD, /* L5-7 check passed */
+ HCHK_STATUS_L57RSPERR, /* L5-7 response error, for example
HTTP 5xx */
+
+ HCHK_STATUS_SIZE
+};
diff --git a/include/types/server.h b/include/types/server.h
index f634b8a..3304004 100644
--- a/include/types/server.h
+++ b/include/types/server.h
@@ -35,6 +35,7 @@
#include <types/proxy.h>
#include <types/queue.h>
#include <types/task.h>
+#include <types/checks.h>
/* server flags */
@@ -74,7 +75,7 @@ struct server {
struct server *next;
int state; /* server state (SRV_*) */
int prev_state; /* server state before last
change (SRV_*) */
- int cklen; /* the len of the cookie, to
speed up checks */
+ int cklen; /* the len of the cookie, to
speed up checks */
int rdr_len; /* the length of the
redirection prefix */
char *cookie; /* the id set in the cookie */
char *rdr_pfx; /* the redirection prefix */
@@ -121,9 +122,12 @@ struct server {
long long failed_checks, down_trans; /* failed checks and up-down
transitions */
unsigned down_time; /* total time the server was
down */
time_t last_change; /* last time, when the state
was changed */
+ struct timeval check_start; /* last health check start time
*/
+ unsigned long check_duration; /* time in ms took to finish
last health check */
+ short check_status, check_code; /* check result, check code */
long long failed_conns, failed_resp; /* failed connect() and
responses */
- long long retries, redispatches; /* retried and
redispatched connections */
+ long long retries, redispatches; /* retried and redispatched
connections */
long long failed_secu; /* blocked responses because of
security concerns */
struct freq_ctr sess_per_sec; /* sessions per second on this
server */
unsigned int sps_max; /* maximum of new sessions per
second seen on this server */
diff --git a/src/checks.c b/src/checks.c
index 99c2122..0f8661c 100644
--- a/src/checks.c
+++ b/src/checks.c
@@ -2,7 +2,7 @@
* Health-checks functions.
*
* Copyright 2000-2009 Willy Tarreau <[email protected]>
- * Copyright 2007-2008 Krzysztof Piotr Oledzki <[email protected]>
+ * Copyright 2007-2009 Krzysztof Piotr Oledzki <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -12,6 +12,7 @@
*/
#include <assert.h>
+#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
@@ -34,6 +35,7 @@
#include <types/global.h>
#include <proto/backend.h>
+#include <proto/checks.h>
#include <proto/buffers.h>
#include <proto/fd.h>
#include <proto/log.h>
@@ -45,6 +47,90 @@
#include <proto/server.h>
#include <proto/task.h>
+const char *check_status_description[HCHK_STATUS_SIZE] = {
+ [HCHK_STATUS_UNKNOWN] = "Unknown",
+
+ [HCHK_STATUS_SOCKERR] = "Socket error",
+
+ [HCHK_STATUS_L14OK] = "Layer1-4 check passed",
+ [HCHK_STATUS_L14TMOUT] = "Layer1-4 timeout",
+ [HCHK_STATUS_L14UNR] = "Layer1-4 unreachable",
+
+ [HCHK_STATUS_L57OK] = "Layer5-7 check passed",
+ [HCHK_STATUS_L57TMOUT] = "Layer5-7 timeout",
+ [HCHK_STATUS_L57INVRSP] = "Layer5-7 invalid response",
+
+ [HCHK_STATUS_L57OKD] = "Layer5-7 check passed",
+ [HCHK_STATUS_L57RSPERR] = "Layer5-7 response error",
+};
+
+
+const char *check_status_info[HCHK_STATUS_SIZE] = {
+ [HCHK_STATUS_UNKNOWN] = "UNK",
+
+ [HCHK_STATUS_SOCKERR] = "SOCKERR",
+
+ [HCHK_STATUS_L14OK] = "L14OK",
+ [HCHK_STATUS_L14TMOUT] = "L14TMOUT",
+ [HCHK_STATUS_L14UNR] = "L14UNR",
+
+ [HCHK_STATUS_L57OK] = "L57OK",
+ [HCHK_STATUS_L57TMOUT] = "L57TMOUT",
+ [HCHK_STATUS_L57INVRSP] = "L57INVRSP",
+
+ [HCHK_STATUS_L57OKD] = "L57OK",
+ [HCHK_STATUS_L57RSPERR] = "L57RSPERR",
+};
+
+/*
+ * Convert check_status code to description
+ */
+const char *get_check_status_description(short check_status) {
+
+ const char *desc;
+
+ if (check_status < HCHK_STATUS_SIZE)
+ desc = check_status_description[check_status];
+ else
+ desc = NULL;
+
+ if (desc && *desc)
+ return desc;
+ else
+ return check_status_description[HCHK_STATUS_UNKNOWN];
+}
+
+/*
+ * Convert check_status code to short info
+ */
+const char *get_check_status_info(short check_status) {
+
+ const char *info;
+
+ if (check_status < HCHK_STATUS_SIZE)
+ info = check_status_info[check_status];
+ else
+ info = NULL;
+
+ if (info && *info)
+ return info;
+ else
+ return check_status_info[HCHK_STATUS_UNKNOWN];
+}
+
+/*
+ * Set check_status and update check_duration
+ */
+static void set_server_check_status(struct server *s, short status) {
+
+ if (tv_iszero(&s->check_start))
+ return;
+
+ s->check_status = status;
+ s->check_duration = tv_ms_elapsed(&s->check_start, &now);
+ tv_zero(&s->check_start);
+}
+
/* sends a log message when a backend goes down, and also sets last
* change date.
*/
@@ -145,6 +231,12 @@ static void set_server_down(struct server *s)
chunk_printf(&msg, sizeof(trash), " via %s/%s",
s->tracked->proxy->id, s->tracked->id);
+ chunk_printf(&msg, sizeof(trash), ", reason: %s",
get_check_status_description(s->check_status));
+ if (s->check_status >= HCHK_STATUS_L57DATA)
+ chunk_printf(&msg, sizeof(trash), ", code: %d",
s->check_code);
+
+ chunk_printf(&msg, sizeof(trash), ", check duration: %lums",
s->check_duration);
+
chunk_printf(&msg, sizeof(trash), ". %d active and %d backup
servers left.%s"
" %d sessions active, %d requeued, %d remaining in
queue.\n",
s->proxy->srv_act, s->proxy->srv_bck,
@@ -220,6 +312,10 @@ static void set_server_up(struct server *s) {
chunk_printf(&msg, sizeof(trash), " via %s/%s",
s->tracked->proxy->id, s->tracked->id);
+ chunk_printf(&msg, sizeof(trash), ", reason: %s",
get_check_status_description(s->check_status));
+ if (s->check_status >= HCHK_STATUS_L57DATA)
+ chunk_printf(&msg, sizeof(trash), ", code: %d",
s->check_code);
+
chunk_printf(&msg, sizeof(trash), ". %d active and %d backup
servers online.%s"
" %d sessions requeued, %d total in queue.\n",
s->proxy->srv_act, s->proxy->srv_bck,
@@ -339,8 +435,10 @@ static int event_srv_chk_w(int fd)
struct server *s = t->context;
//fprintf(stderr, "event_srv_chk_w, state=%ld\n",
unlikely(fdtab[fd].state));
- if (unlikely(fdtab[fd].state == FD_STERROR || (fdtab[fd].ev &
FD_POLL_ERR)))
+ if (unlikely(fdtab[fd].state == FD_STERROR || (fdtab[fd].ev &
FD_POLL_ERR))) {
+ set_server_check_status(s, HCHK_STATUS_L14UNR);
goto out_error;
+ }
/* here, we know that the connection is established */
@@ -370,8 +468,10 @@ static int event_srv_chk_w(int fd)
}
else if (ret == 0 || errno == EAGAIN)
goto out_poll;
- else
+ else {
+ set_server_check_status(s, HCHK_STATUS_SOCKERR);
goto out_error;
+ }
}
else {
/* We have no data to send to check the connection, and
@@ -395,8 +495,10 @@ static int event_srv_chk_w(int fd)
if (errno == EALREADY || errno == EINPROGRESS)
goto out_poll;
- if (errno && errno != EISCONN)
+ if (errno && errno != EISCONN) {
+ set_server_check_status(s, HCHK_STATUS_L14UNR);
goto out_error;
+ }
/* good TCP connection is enough */
s->result |= SRV_CHK_RUNNING;
@@ -448,7 +550,12 @@ static int event_srv_chk_r(int fd)
(getsockopt(fd, SOL_SOCKET, SO_ERROR, &skerr, &lskerr) ==
-1) ||
(skerr != 0))) {
/* in case of TCP only, this tells us if the connection failed
*/
+
+ if (!(s->result & SRV_CHK_ERROR))
+ set_server_check_status(s, HCHK_STATUS_SOCKERR);
+
s->result |= SRV_CHK_ERROR;
+
goto out_wakeup;
}
@@ -467,40 +574,67 @@ static int event_srv_chk_r(int fd)
if (s->proxy->options & PR_O_HTTP_CHK) {
/* Check if the server speaks HTTP 1.X */
if ((len < strlen("HTTP/1.0 000\r")) ||
- (memcmp(trash, "HTTP/1.", 7) != 0)) {
+ (memcmp(trash, "HTTP/1.", 7) != 0 ||
+ (trash[12] != ' ' && trash[12] != '\r')) ||
+ !isdigit(trash[9]) || !isdigit(trash[10]) ||
!isdigit(trash[11])) {
s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s, HCHK_STATUS_L57INVRSP);
goto out_wakeup;
}
+ s->check_code = str2uic(&trash[9]);
+
/* check the reply : HTTP/1.X 2xx and 3xx are OK */
- if (trash[9] == '2' || trash[9] == '3')
+ if (trash[9] == '2' || trash[9] == '3') {
s->result |= SRV_CHK_RUNNING;
- else if ((s->proxy->options & PR_O_DISABLE404) &&
+ set_server_check_status(s, HCHK_STATUS_L57OKD);
+ } else if ((s->proxy->options & PR_O_DISABLE404) &&
(s->state & SRV_RUNNING) &&
- (memcmp(&trash[9], "404", 3) == 0)) {
+ (s->check_code == 404)) {
/* 404 may be accepted as "stopping" only if the server
was up */
s->result |= SRV_CHK_RUNNING | SRV_CHK_DISABLE;
+ set_server_check_status(s, HCHK_STATUS_L57OKD);
}
- else
+ else {
s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s, HCHK_STATUS_L57RSPERR);
+ }
}
else if (s->proxy->options & PR_O_SSL3_CHK) {
/* Check for SSLv3 alert or handshake */
- if ((len >= 5) && (trash[0] == 0x15 || trash[0] == 0x16))
+ if ((len >= 5) && (trash[0] == 0x15 || trash[0] == 0x16)) {
s->result |= SRV_CHK_RUNNING;
- else
+ set_server_check_status(s, HCHK_STATUS_L57OK);
+ } else {
s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s, HCHK_STATUS_L57INVRSP);
+ }
}
else if (s->proxy->options & PR_O_SMTP_CHK) {
+ /* Check if the server speaks SMTP */
+ if ((len < strlen("000\r")) ||
+ (trash[3] != ' ' && trash[3] != '\r') ||
+ !isdigit(trash[0]) || !isdigit(trash[1]) ||
!isdigit(trash[2])) {
+ s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s, HCHK_STATUS_L57INVRSP);
+ goto out_wakeup;
+ }
+
+ s->check_code = str2uic(&trash[0]);
+
/* Check for SMTP code 2xx (should be 250) */
- if ((len >= 3) && (trash[0] == '2'))
+ if (trash[0] == '2') {
s->result |= SRV_CHK_RUNNING;
- else
+ set_server_check_status(s, HCHK_STATUS_L57OKD);
+ } else {
s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s, HCHK_STATUS_L57RSPERR);
+ }
}
else {
/* other checks are valid if the connection succeeded anyway */
s->result |= SRV_CHK_RUNNING;
+ set_server_check_status(s, HCHK_STATUS_L14OK);
}
out_wakeup:
@@ -550,6 +684,7 @@ struct task *process_chk(struct task *t)
}
/* we'll initiate a new check */
+ s->check_start = now;
s->result = SRV_CHK_UNKNOWN; /* no result yet */
if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) != -1) {
if ((fd < global.maxsock) &&
@@ -626,6 +761,7 @@ struct task *process_chk(struct task *t)
if (ret) {
s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s,
HCHK_STATUS_SOCKERR);
switch (ret) {
case 1:
Alert("Cannot bind to
source address before connect() for server %s/%s. Aborting.\n",
@@ -657,6 +793,7 @@ struct task *process_chk(struct task *t)
ret = tcpv4_bind_socket(fd, flags,
&s->proxy->source_addr, remote);
if (ret) {
s->result |= SRV_CHK_ERROR;
+ set_server_check_status(s,
HCHK_STATUS_SOCKERR);
switch (ret) {
case 1:
Alert("Cannot bind to
source address before connect() for %s '%s'. Aborting.\n",
@@ -714,6 +851,17 @@ struct task *process_chk(struct task *t)
}
else if (errno != EALREADY && errno !=
EISCONN && errno != EAGAIN) {
s->result |= SRV_CHK_ERROR;
/* a real error */
+
+ switch (errno) {
+ /* FIXME: is it
possible to get ECONNREFUSED/ENETUNREACH with O_NONBLOCK? */
+ case ECONNREFUSED:
+ case ENETUNREACH:
+
set_server_check_status(s, HCHK_STATUS_L14UNR);
+ break;
+
+ default:
+
set_server_check_status(s, HCHK_STATUS_SOCKERR);
+ }
}
}
}
@@ -808,6 +956,9 @@ struct task *process_chk(struct task *t)
goto new_chk;
}
else if ((s->result & SRV_CHK_ERROR) ||
tick_is_expired(t->expire, now_ms)) {
+ if (!(s->result & SRV_CHK_ERROR))
+ set_server_check_status(s, EV_FD_ISSET(fd,
DIR_RD)?HCHK_STATUS_L57TMOUT:HCHK_STATUS_L14TMOUT);
+
//fprintf(stderr, "process_chk: 10\n");
/* failure or timeout detected */
if (s->health > s->rise) {
@@ -894,6 +1045,7 @@ int start_checks() {
t->expire = tick_add(now_ms,
MS_TO_TICKS(((mininter && mininter
>= srv_getinter(s)) ?
mininter :
srv_getinter(s)) * srvpos / nbchk));
+ s->check_start = now;
task_queue(t);
srvpos++;
diff --git a/src/dumpstats.c b/src/dumpstats.c
index 24aab05..0f20e32 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2,6 +2,7 @@
* Functions dedicated to statistics output
*
* Copyright 2000-2009 Willy Tarreau <[email protected]>
+ * Copyright 2007-2009 Krzysztof Piotr Oledzki <[email protected]>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -39,6 +40,7 @@
#include <proto/backend.h>
#include <proto/buffers.h>
+#include <proto/checks.h>
#include <proto/dumpstats.h>
#include <proto/fd.h>
#include <proto/freq_ctr.h>
@@ -222,6 +224,7 @@ int print_csv_header(struct chunk *msg, int size)
"chkfail,chkdown,lastchg,downtime,qlimit,"
"pid,iid,sid,throttle,lbtot,tracked,type,"
"rate,rate_lim,rate_max,"
+ "check_status,check_code,check_duration"
"\n");
}
@@ -860,7 +863,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
"<th colspan=3>Session rate</th><th
colspan=5>Sessions</th>"
"<th colspan=2>Bytes</th><th
colspan=2>Denied</th>"
"<th colspan=3>Errors</th><th
colspan=2>Warnings</th>"
- "<th colspan=8>Server</th>"
+ "<th colspan=9>Server</th>"
"</tr>\n"
"<tr align=\"center\" class=\"titre\">"
"<th>Cur</th><th>Max</th><th>Limit</th>"
@@ -868,7 +871,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
"<th>Limit</th><th>Total</th><th>LbTot</th><th>In</th><th>Out</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>Wght</th><th>Act</th>"
+ "<th>Status</th><th>Last
check</th><th>Wght</th><th>Act</th>"
"<th>Bck</th><th>Chk</th><th>Dwn</th><th>Dwntme</th>"
"<th>Thrtle</th>\n"
"</tr>",
@@ -912,7 +915,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
/* server status : reflect frontend status
*/
"<td align=center>%s</td>"
/* rest of server: nothing */
- "<td align=center colspan=7></td></tr>"
+ "<td align=center colspan=8></td></tr>"
"",
U2H0(px->denied_req),
U2H1(px->denied_resp),
U2H2(px->failed_req),
@@ -938,8 +941,10 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
",,,,,,,,"
/* pid, iid, sid, throttle, lbtot,
tracked, type */
"%d,%d,0,,,,%d,"
- /* rate, rate_lim, rate_max, */
+ /* rate, rate_lim, rate_max */
"%u,%u,%u,"
+ /* check_status, check_code,
check_duration */
+ ",,,"
"\n",
px->id,
px->feconn, px->feconn_max, px->maxconn,
px->cum_feconn,
@@ -1044,7 +1049,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
U2H3(sv->failed_conns),
U2H4(sv->failed_resp),
sv->retries, sv->redispatches);
- /* status */
+ /* status, lest check */
chunk_printf(&msg, sizeof(trash), "<td
nowrap>");
if (sv->state & SRV_CHECKED)
@@ -1056,6 +1061,14 @@ int stats_dump_proxy(struct session *s, struct proxy
*px, struct uri_auth *uri)
(svs->state & SRV_RUNNING) ? (svs->health
- svs->rise + 1) : (svs->health),
(svs->state & SRV_RUNNING) ? (svs->fall) :
(svs->rise));
+ chunk_printf(&msg, sizeof(trash), "</td><td
nowrap> %s%s",
+ tv_iszero(&sv->check_start)?"":"* ",
get_check_status_info(sv->check_status));
+
+ if (sv->check_status >= HCHK_STATUS_L57DATA)
+ chunk_printf(&msg, sizeof(trash),
"/%d", sv->check_code);
+
+ chunk_printf(&msg, sizeof(trash), " in %lums",
sv->check_duration);
+
chunk_printf(&msg, sizeof(trash),
/* weight */
"</td><td>%d</td>"
@@ -1180,6 +1193,18 @@ int stats_dump_proxy(struct session *s, struct proxy
*px, struct uri_auth *uri)
read_freq_ctr(&sv->sess_per_sec),
sv->sps_max);
+ /* check_status */
+ chunk_printf(&msg, sizeof(trash), "%s,",
get_check_status_info(sv->check_status));
+
+ /* check_code */
+ if (sv->check_status >= HCHK_STATUS_L57DATA)
+ chunk_printf(&msg, sizeof(trash),
"%u,", sv->check_code);
+ else
+ chunk_printf(&msg, sizeof(trash), ",");
+
+ /* check_duration */
+ chunk_printf(&msg, sizeof(trash), "%lu,",
sv->check_duration);
+
/* finish with EOL */
chunk_printf(&msg, sizeof(trash), "\n");
}
@@ -1228,7 +1253,7 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
* if the backend has known working
servers or if it has no server at
* all (eg: for stats). Then we display
the total weight, number of
* active and backups. */
- "<td align=center nowrap>%s %s</td><td
align=center>%d</td>"
+ "<td align=center nowrap>%s %s</td><td
align=center> </td><td align=center>%d</td>"
"<td align=center>%d</td><td
align=center>%d</td>"
"",
U2H0(px->denied_req),
U2H1(px->denied_resp),
@@ -1276,6 +1301,8 @@ int stats_dump_proxy(struct session *s, struct proxy *px,
struct uri_auth *uri)
"%d,%d,0,,%lld,,%d,"
/* rate, rate_lim, rate_max, */
"%u,,%u,"
+ /* check_status, check_code,
check_duration */
+ ",,,"
"\n",
px->id,
px->nbpend /* or px->totpend ? */,
px->nbpend_max,
--
1.6.4.2