diff --git a/include/haproxy/listener.h b/include/haproxy/listener.h index 46d9ee27a..5b3dc189e 100644 --- a/include/haproxy/listener.h +++ b/include/haproxy/listener.h @@ -220,6 +220,9 @@ extern struct accept_queue_ring accept_queue_rings[MAX_THREADS] __attribute__((a extern const char* li_status_st[LI_STATE_COUNT]; enum li_status get_li_status(struct listener *l); +/* number of times an accepted connection resulted in maxconn being reached */ +extern ullong maxconn_reached; + static inline uint accept_queue_ring_len(const struct accept_queue_ring *ring) { uint idx, head, tail, len; diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index b15ca8604..d185d85ba 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -344,6 +344,7 @@ enum info_field { INF_START_TIME_SEC, INF_TAINTED, INF_WARNINGS, + INF_MAXCONN_REACHED, /* must always be the last one */ INF_TOTAL_FIELDS diff --git a/src/listener.c b/src/listener.c index 3da01df21..a1160da76 100644 --- a/src/listener.c +++ b/src/listener.c @@ -47,6 +47,8 @@ struct bind_kw_list bind_keywords = { /* list of the temporarily limited listeners because of lack of resource */ static struct mt_list global_listener_queue = MT_LIST_HEAD_INIT(global_listener_queue); static struct task *global_listener_queue_task; +/* number of times an accepted connection resulted in maxconn being reached */ +ullong maxconn_reached = 0; __decl_thread(static HA_RWLOCK_T global_listener_rwlock); /* listener status for stats */ @@ -1164,6 +1166,12 @@ void listener_accept(struct listener *l) _HA_ATOMIC_INC(&activity[tid].accepted); + /* count the number of times an accepted connection resulted in + * maxconn being reached. + */ + if (unlikely(_HA_ATOMIC_LOAD(&actconn) + 1 >= global.maxconn)) + _HA_ATOMIC_INC(&maxconn_reached); + /* past this point, l->bind_conf->accept() will automatically decrement * l->nbconn, feconn and actconn once done. Setting next_*conn=0 * allows the error path not to rollback on nbconn. It's more diff --git a/src/stats.c b/src/stats.c index eab75eef3..cc3668f55 100644 --- a/src/stats.c +++ b/src/stats.c @@ -157,6 +157,7 @@ const struct name_desc info_fields[INF_TOTAL_FIELDS] = { [INF_BUILD_INFO] = { .name = "Build info", .desc = "Build info" }, [INF_TAINTED] = { .name = "Tainted", .desc = "Experimental features used" }, [INF_WARNINGS] = { .name = "TotalWarnings", .desc = "Total warnings issued" }, + [INF_MAXCONN_REACHED] = { .name = "MaxconnReached", .desc = "Number of times an accepted connection resulted in Maxconn being reached" }, }; const struct name_desc stat_fields[ST_F_TOTAL_FIELDS] = { @@ -3603,7 +3604,7 @@ static void stats_dump_html_info(struct stconn *sc, struct uri_auth *uri) "
pid = %d (process #%d, nbproc = %d, nbthread = %d)
\n"
"uptime = %dd %dh%02dm%02ds; warnings = %u
\n"
"system limits: memmax = %s%s; ulimit-n = %d
\n"
- "maxsock = %d; maxconn = %d; maxpipes = %d
\n"
+ "maxsock = %d; maxconn = %d; reached = %llu; maxpipes = %d
\n"
"current conns = %d; current pipes = %d/%d; conn rate = %d/sec; bit rate = %.3f %cbps
\n"
"Running tasks: %d/%d; idle = %d %%
\n"
"