MINOR: backend: count the number of connect and reuse per server and per backend

Sadly we didn't have the cumulated number of connections established to
servers till now, so let's now update it per backend and per-server and
report it in the stats. On the stats page it appears in the tooltip
when hovering over the total sessions count field.
diff --git a/include/types/counters.h b/include/types/counters.h
index fd83ebb..79dd6d4 100644
--- a/include/types/counters.h
+++ b/include/types/counters.h
@@ -83,6 +83,8 @@
 	long long denied_req;                   /* blocked requests because of security concerns */
 	long long denied_resp;                  /* blocked responses because of security concerns */
 
+	long long connect;                      /* number of connection establishment attempts */
+	long long reuse;                        /* number of connection reuses */
 	long long failed_conns;                 /* failed connect() attempts (BE only) */
 	long long failed_resp;                  /* failed responses (BE only) */
 	long long cli_aborts;                   /* aborted responses during DATA phase caused by the client */
diff --git a/include/types/stats.h b/include/types/stats.h
index a188667..c3b9fc8 100644
--- a/include/types/stats.h
+++ b/include/types/stats.h
@@ -392,6 +392,8 @@
 	ST_F_DCON,
 	ST_F_DSES,
 	ST_F_WREW,
+	ST_F_CONNECT,
+	ST_F_REUSE,
 
 	/* must always be the last one */
 	ST_F_TOTAL_FIELDS
diff --git a/src/backend.c b/src/backend.c
index 34a04c3..bb9b4ea 100644
--- a/src/backend.c
+++ b/src/backend.c
@@ -1376,6 +1376,14 @@
 	if (s->be->options & PR_O_TCP_NOLING)
 		s->si[1].flags |= SI_FL_NOLINGER;
 
+	if (s->flags & SF_SRV_REUSED) {
+		HA_ATOMIC_ADD(&s->be->be_counters.reuse, 1);
+		HA_ATOMIC_ADD(&srv->counters.reuse, 1);
+	} else {
+		HA_ATOMIC_ADD(&s->be->be_counters.connect, 1);
+		HA_ATOMIC_ADD(&srv->counters.connect, 1);
+	}
+
 	err = si_connect(&s->si[1], srv_conn);
 
 #ifdef USE_OPENSSL
diff --git a/src/stats.c b/src/stats.c
index be70dde..76561ef 100644
--- a/src/stats.c
+++ b/src/stats.c
@@ -228,6 +228,8 @@
 	[ST_F_DCON]           = "dcon",
 	[ST_F_DSES]           = "dses",
 	[ST_F_WREW]           = "wrew",
+	[ST_F_CONNECT]        = "connect",
+	[ST_F_REUSE]          = "reuse",
 };
 
 /* one line of info */
@@ -960,6 +962,8 @@
 			tot += stats[ST_F_HRSP_5XX].u.u64;
 
 			chunk_appendf(out,
+			              "<tr><th>New connections:</th><td>%s</td></tr>"
+			              "<tr><th>Reused connections:</th><td>%s</td><td>(%d%%)</td></tr>"
 			              "<tr><th>Cum. HTTP responses:</th><td>%s</td></tr>"
 			              "<tr><th>- HTTP 1xx responses:</th><td>%s</td><td>(%d%%)</td></tr>"
 			              "<tr><th>- HTTP 2xx responses:</th><td>%s</td><td>(%d%%)</td></tr>"
@@ -969,6 +973,10 @@
 			              "<tr><th>- other responses:</th><td>%s</td><td>(%d%%)</td></tr>"
 			              "<tr><th>Failed hdr rewrites:</th><td>%s</td></tr>"
 			              "",
+			              U2H(stats[ST_F_CONNECT].u.u64),
+			              U2H(stats[ST_F_REUSE].u.u64),
+			              (stats[ST_F_CONNECT].u.u64 + stats[ST_F_REUSE].u.u64) ?
+			              (int)(100 * stats[ST_F_REUSE].u.u64 / (stats[ST_F_CONNECT].u.u64 + stats[ST_F_REUSE].u.u64)) : 0,
 			              U2H(tot),
 			              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,
@@ -1180,6 +1188,8 @@
 		/* http response (via hover): 1xx, 2xx, 3xx, 4xx, 5xx, other */
 		if (strcmp(field_str(stats, ST_F_MODE), "http") == 0) {
 			chunk_appendf(out,
+			              "<tr><th>New connections:</th><td>%s</td></tr>"
+			              "<tr><th>Reused connections:</th><td>%s</td><td>(%d%%)</td></tr>"
 			              "<tr><th>Cum. HTTP requests:</th><td>%s</td></tr>"
 			              "<tr><th>- HTTP 1xx responses:</th><td>%s</td></tr>"
 			              "<tr><th>- HTTP 2xx responses:</th><td>%s</td></tr>"
@@ -1191,6 +1201,10 @@
 			              "<tr><th>Failed hdr rewrites:</th><td>%s</td></tr>"
 				      "<tr><th colspan=3>Avg over last 1024 success. conn.</th></tr>"
 			              "",
+			              U2H(stats[ST_F_CONNECT].u.u64),
+			              U2H(stats[ST_F_REUSE].u.u64),
+			              (stats[ST_F_CONNECT].u.u64 + stats[ST_F_REUSE].u.u64) ?
+			              (int)(100 * stats[ST_F_REUSE].u.u64 / (stats[ST_F_CONNECT].u.u64 + stats[ST_F_REUSE].u.u64)) : 0,
 			              U2H(stats[ST_F_REQ_TOT].u.u64),
 			              U2H(stats[ST_F_HRSP_1XX].u.u64),
 			              U2H(stats[ST_F_HRSP_2XX].u.u64),
@@ -1596,6 +1610,8 @@
 	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_CONNECT]  = mkf_u64(FN_COUNTER, sv->counters.connect);
+	stats[ST_F_REUSE]    = mkf_u64(FN_COUNTER, sv->counters.reuse);
 
 	/* status */
 	fld_status = chunk_newstr(out);
@@ -1789,6 +1805,8 @@
 	stats[ST_F_WRETR]    = mkf_u64(FN_COUNTER, px->be_counters.retries);
 	stats[ST_F_WREDIS]   = mkf_u64(FN_COUNTER, px->be_counters.redispatches);
 	stats[ST_F_WREW]     = mkf_u64(FN_COUNTER, px->be_counters.failed_rewrites);
+	stats[ST_F_CONNECT]  = mkf_u64(FN_COUNTER, px->be_counters.connect);
+	stats[ST_F_REUSE]    = mkf_u64(FN_COUNTER, px->be_counters.reuse);
 	stats[ST_F_STATUS]   = mkf_str(FO_STATUS, (px->lbprm.tot_weight > 0 || !px->srv) ? "UP" : "DOWN");
 	stats[ST_F_WEIGHT]   = mkf_u32(FN_AVG, (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv);
 	stats[ST_F_ACT]      = mkf_u32(0, px->srv_act);