]> git.kaiwu.me - haproxy.git/commitdiff
MINOR: promex: export "haproxy_sticktable_local_updates" metric
authorAurelien DARRAGON <adarragon@haproxy.com>
Wed, 18 Mar 2026 10:08:25 +0000 (11:08 +0100)
committerAurelien DARRAGON <adarragon@haproxy.com>
Wed, 18 Mar 2026 10:18:37 +0000 (11:18 +0100)
haproxy_sticktable_local_updates corresponds to the table->localupdate
counter, which is used internally by the peers protocol to identify
update messages in order to send and ack them among peers.

Here we decide to expose this information, as it is already the case in
"show peers" output, because it turns out that this value, which is
cumulative and grows in sync with the number of updates triggered on the
table due to changes initiated by the current process, can be used to
compute the update rate of the table. Computing the update rate of the
table (from the process point of view, ie: updates sent by the process and
not those received by the process), can be a great load indicator in order
to properly scale the infrastructure that is intended to handle the
table updates.

Note that there is a pitfall, which is that the value will eventually
wrap since it is stored using unsigned 32bits integer. Scripts or system
making use of this value must take wrapping into account between two
readings to properly compute the effective number of updates that were
performed between two readings. Also, they must ensure that the "polling"
rate between readings is small enough so that the value cannot wrap behind
their back.

addons/promex/README
src/stick_table.c

index 61d99de152328817e475dee93c6cd7b35dc6572f..4d52c1d1a4f07d2ae7f51e1bed331199e9901c08 100644 (file)
@@ -407,6 +407,7 @@ listed below. Metrics from extra counters are not listed.
 +----------------------------------------------------+
 | haproxy_sticktable_size                            |
 | haproxy_sticktable_used                            |
+| haproxy_sticktable_local_updates                   |
 +----------------------------------------------------+
 
 * Resolvers metrics
index ff3b552da3c2b55c349b7d73bd149842a67ce1bd..c36a91b9d23d0aa2bd7fd8ff5e356933402c9ee9 100644 (file)
@@ -53,6 +53,7 @@
 enum sticktable_field {
        STICKTABLE_SIZE = 0,
        STICKTABLE_USED,
+       STICKTABLE_LOCAL_UPDATES,
        /* must always be the last one */
        STICKTABLE_TOTAL_FIELDS
 };
@@ -6310,6 +6311,10 @@ static int stk_promex_metric_info(unsigned int id, struct promex_metric *metric,
                        *metric = (struct promex_metric){ .n = ist("used"), .type = PROMEX_MT_GAUGE, .flags = PROMEX_FL_MODULE_METRIC };
                        *desc = ist("Number of entries used in this stick table.");
                        break;
+               case STICKTABLE_LOCAL_UPDATES:
+                       *metric = (struct promex_metric){ .n = ist("local_updates"), .type = PROMEX_MT_GAUGE, .flags = PROMEX_FL_MODULE_METRIC };
+                       *desc = ist("Cumulative number of updates on the stick table initiated by the local process. Please note that this value will eventually wrap after 4294967295 since it is stored using unsigned int (uint32). As this metric is often used to compute the update rate of a given table between two queries, wrapping must be taken into account and the time between 2 queries must not exceed the theorical time needed for this value to wrap.");
+                       break;
                default:
                        return -1;
        }
@@ -6347,6 +6352,17 @@ static int stk_promex_fill_ts(void *unused, void *metric_ctx, unsigned int id, s
                case STICKTABLE_USED:
                        *field = mkf_u32(FN_GAUGE, t->current);
                        break;
+               case STICKTABLE_LOCAL_UPDATES:
+                       /* localupdate is meant to be guarded by updt_lock, but
+                        * here we don't care about the most up-to-date value, nor
+                        * need to read the value consistently with another table-related
+                        * one, all we really want is a rough reading of the current
+                        * number of local updates performed on the table, thus we hope
+                        * the value is read as an atomic operation (which should be
+                        * the case for uint32 on most platforms)
+                        */
+                       *field = mkf_u32(FN_GAUGE, t->localupdate);
+                       break;
                default:
                        return -1;
        }