]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: counters: add max-only reset helpers and use them for clear counters
authorAlexander Stephan <alexander.stephan@sap.com>
Thu, 16 Jul 2026 12:40:51 +0000 (12:40 +0000)
committerWilly Tarreau <w@1wt.eu>
Thu, 30 Jul 2026 17:00:47 +0000 (19:00 +0200)
The plain "clear counters" command (OPER level) resets only the max/peak
gauges of each object's counters, leaving cumulative counters intact,
while "clear counters all" (ADMIN) performs a full reset via the
counters_{fe,be}_reset() helpers introduced earlier in this series.

The max-only reset was open-coded inline in proxy_stats_clear_counters()
with a hand-maintained list of fields, duplicated across the backend,
server and listener branches. This is fragile: a new max gauge added to
struct {fe,be}_counters can silently be forgotten here.

Factor the max-only reset into counters_fe_reset_max() and
counters_be_reset_max(), living next to the existing reset helpers, and
call them from proxy_stats_clear_counters(). Unlike the full-reset
helpers these cannot use a blanket memset because the max fields are
interleaved with live cumulative fields, so the gauges are zeroed
individually.

While consolidating, the two open-coded lists turned out to disagree:
the backend branch cleared conn_max / cps_max / rps_max but not
cur_sess_max, while the server branch cleared cur_sess_max but none of
the former. Both used the same struct be_counters, so these were latent
gaps rather than intentional differences. counters_be_reset_max() now
clears the union of all peak gauges, so plain "clear counters"
consistently resets every max gauge for both backends and servers.

No functional change for the full-reset ("all") path.

include/haproxy/counters.h
src/counters.c
src/stats-proxy.c

index 1a8391bd01fdb0f996bf6b37baaade40a433a0f0..d1ad04b3ef3ed227e62aa41eb6260ac25571a0a0 100644 (file)
@@ -45,6 +45,15 @@ void counters_be_shared_drop(struct be_counters_shared *counters);
 void counters_fe_reset(struct fe_counters *counters);
 void counters_be_reset(struct be_counters *counters);
 
+/* Reset only the max/peak fields of <counters>, leaving cumulative counters
+ * intact. This is what the plain "clear counters" command does (as opposed to
+ * "clear counters all" which performs a full reset via counters_*_reset()).
+ * The max fields are interleaved with live cumulative fields, so they are
+ * cleared individually rather than with a blanket memset.
+ */
+void counters_fe_reset_max(struct fe_counters *counters);
+void counters_be_reset_max(struct be_counters *counters);
+
 /* time oriented helper: get last time (relative to current time) on a given
  * <scounter> array, for <elem> member (one member per thread group) which is
  * assumed to be unsigned long type.
index 5473c547112c530b19672db6051d29ea36c2da8a..591e07e4488aae83b91950e6cdbd83ef79929734 100644 (file)
@@ -214,3 +214,45 @@ void counters_be_reset(struct be_counters *counters)
        memset((char *)counters + sizeof(counters->shared), 0,
               sizeof(*counters) - sizeof(counters->shared));
 }
+
+/* Reset only the max/peak gauges of a frontend/listener <counters> struct,
+ * leaving cumulative counters intact. Used by the plain "clear counters"
+ * command (as opposed to "clear counters all" which resets everything via
+ * counters_fe_reset()).
+ */
+void counters_fe_reset_max(struct fe_counters *counters)
+{
+       if (!counters)
+               return;
+
+       counters->conn_max = 0;
+       counters->cps_max = 0;
+       counters->sps_max = 0;
+       counters->p.http.rps_max = 0;
+}
+
+/* Reset only the max/peak gauges of a backend/server <counters> struct,
+ * leaving cumulative counters intact. See counters_fe_reset_max().
+ *
+ * Note: this clears the union of all max gauges present in the struct. The
+ * previous inline code cleared slightly different subsets for backends and
+ * servers (backends left cur_sess_max untouched, servers left conn_max /
+ * cps_max / rps_max untouched); those were latent gaps, so plain "clear
+ * counters" now consistently resets every peak gauge for both.
+ */
+void counters_be_reset_max(struct be_counters *counters)
+{
+       if (!counters)
+               return;
+
+       counters->conn_max = 0;
+       counters->cps_max = 0;
+       counters->sps_max = 0;
+       counters->nbpend_max = 0;
+       counters->cur_sess_max = 0;
+       counters->qtime_max = 0;
+       counters->ctime_max = 0;
+       counters->dtime_max = 0;
+       counters->ttime_max = 0;
+       counters->p.http.rps_max = 0;
+}
index edc809885337077709c9095070d6a25dd94dafdb..f9aa3dcaa1931cadbe2493bbad5bdd86f49cc2f5 100644 (file)
@@ -1673,34 +1673,15 @@ void proxy_stats_clear_counters(int clrall, struct list *stat_modules)
                        counters_fe_reset(&px->fe_counters);
                }
                else {
-                       px->be_counters.conn_max = 0;
-                       px->be_counters.p.http.rps_max = 0;
-                       px->be_counters.sps_max = 0;
-                       px->be_counters.cps_max = 0;
-                       px->be_counters.nbpend_max = 0;
-                       px->be_counters.qtime_max = 0;
-                       px->be_counters.ctime_max = 0;
-                       px->be_counters.dtime_max = 0;
-                       px->be_counters.ttime_max = 0;
-
-                       px->fe_counters.conn_max = 0;
-                       px->fe_counters.p.http.rps_max = 0;
-                       px->fe_counters.sps_max = 0;
-                       px->fe_counters.cps_max = 0;
+                       counters_be_reset_max(&px->be_counters);
+                       counters_fe_reset_max(&px->fe_counters);
                }
 
                list_for_each_entry(sv, &px->servers, el_px) {
                        if (clrall)
                                counters_be_reset(&sv->counters);
-                       else {
-                               sv->counters.cur_sess_max = 0;
-                               sv->counters.nbpend_max = 0;
-                               sv->counters.sps_max = 0;
-                               sv->counters.qtime_max = 0;
-                               sv->counters.ctime_max = 0;
-                               sv->counters.dtime_max = 0;
-                               sv->counters.ttime_max = 0;
-                       }
+                       else
+                               counters_be_reset_max(&sv->counters);
                }
 
                list_for_each_entry(li, &px->conf.listeners, by_fe)
@@ -1708,7 +1689,7 @@ void proxy_stats_clear_counters(int clrall, struct list *stat_modules)
                                if (clrall)
                                        counters_fe_reset(li->counters);
                                else
-                                       li->counters->conn_max = 0;
+                                       counters_fe_reset_max(li->counters);
                        }
        }