]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: pattern: add a counter of added/freed patterns
authorWilly Tarreau <w@1wt.eu>
Fri, 4 Jul 2025 22:07:25 +0000 (00:07 +0200)
committerWilly Tarreau <w@1wt.eu>
Fri, 4 Jul 2025 22:12:45 +0000 (00:12 +0200)
Patterns are allocated when loading maps/acls from a file or dynamically
via the CLI, and are released only from the CLI (e.g. "clear map xxx").
These ones do not use pools and are much harder to monitor, e.g. in case
a script adds many and forgets to clear them, etc.

Let's add a new pair of metrics "PatternsAdded" and "PatternsFreed" that
will report the number of added and freed patterns respectively. This
can allow to simply graph both. The difference between the two normally
represents the number of allocated patterns. If Added grows without
Freed following, it can indicate a faulty script that doesn't perform
the needed cleanup. The metrics are also made available to Prometheus
as patterns_added_total and patterns_freed_total respectively.

include/haproxy/pattern.h
include/haproxy/stats-t.h
src/pattern.c
src/stats.c

index 570ff282b14a80555ee69b22486740302db009d5..1f3fdf164fb581b8d7d306c858e33f91cfef867a 100644 (file)
@@ -33,6 +33,9 @@
 extern const char *const pat_match_names[PAT_MATCH_NUM];
 extern int const pat_match_types[PAT_MATCH_NUM];
 
+extern unsigned long long patterns_added;
+extern unsigned long long patterns_freed;
+
 extern int (*const pat_parse_fcts[PAT_MATCH_NUM])(const char *, struct pattern *, int, char **);
 extern int (*const pat_index_fcts[PAT_MATCH_NUM])(struct pattern_expr *, struct pattern *, char **);
 extern void (*const pat_prune_fcts[PAT_MATCH_NUM])(struct pattern_expr *);
index 465bbe06816de22383ee0d1c896a219e062c28f1..f05ec08ebec9149fe4b0cc5bbfb02484d2e88fd0 100644 (file)
@@ -337,6 +337,8 @@ enum stat_idx_info {
        ST_I_INF_CURR_STRM,
        ST_I_INF_CUM_STRM,
        ST_I_INF_WARN_BLOCKED,
+       ST_I_INF_PATTERNS_ADDED,
+       ST_I_INF_PATTERNS_FREED,
 
        /* must always be the last one */
        ST_I_INF_MAX
index 715c64a63cd57f99f98b049d55086b5e2482f068..3e25b88e79e96a5b610d4aa26ea129f46555d69f 100644 (file)
@@ -143,6 +143,9 @@ struct list pattern_reference = LIST_HEAD_INIT(pattern_reference);
 static THREAD_LOCAL struct lru64_head *pat_lru_tree;
 static unsigned long long pat_lru_seed __read_mostly;
 
+unsigned long long patterns_added = 0;
+unsigned long long patterns_freed = 0;
+
 /*
  *
  * The following functions are not exported and are used by internals process
@@ -1590,6 +1593,7 @@ void pat_ref_delete_by_ptr(struct pat_ref *ref, struct pat_ref_elt *elt)
        ebmb_delete(&elt->node);
        free(elt->sample);
        free(elt);
+       HA_ATOMIC_INC(&patterns_freed);
 }
 
 /* This function removes the pattern matching the pointer <refelt> from
@@ -2001,6 +2005,7 @@ struct pat_ref_elt *pat_ref_append(struct pat_ref *ref, const char *pattern, con
        /* Even if calloc()'ed, ensure this node is not linked to a tree. */
        elt->node.node.leaf_p = NULL;
        ebst_insert(&ref->ebmb_root, &elt->node);
+       HA_ATOMIC_INC(&patterns_added);
        return elt;
  fail:
        free(elt);
@@ -2176,6 +2181,7 @@ int pat_ref_purge_range(struct pat_ref *ref, uint from, uint to, int budget)
                ebmb_delete(&elt->node);
                free(elt->sample);
                free(elt);
+               HA_ATOMIC_INC(&patterns_freed);
        }
 
        list_for_each_entry(expr, &ref->pat, list)
index b7e6e18051a73df7d1931301409ce94a9fb5aad8..f710a4aab96f9e8f30a65900ebfc17375206a1ad 100644 (file)
@@ -45,7 +45,7 @@
 #include <haproxy/listener.h>
 #include <haproxy/log.h>
 #include <haproxy/map-t.h>
-#include <haproxy/pattern-t.h>
+#include <haproxy/pattern.h>
 #include <haproxy/pipe.h>
 #include <haproxy/pool.h>
 #include <haproxy/proxy.h>
@@ -172,6 +172,8 @@ const struct stat_col stat_cols_info[ST_I_INF_MAX] = {
        [ST_I_INF_CURR_STRM]                      = { .name = "CurrStreams",                 .alt_name = NULL,                            .desc = "Current number of streams on this worker process" },
        [ST_I_INF_CUM_STRM]                       = { .name = "CumStreams",                  .alt_name = NULL,                            .desc = "Total number of streams created on this worker process since started" },
        [ST_I_INF_WARN_BLOCKED]                   = { .name = "BlockedTrafficWarnings",      .alt_name = NULL,                            .desc = "Total number of warnings issued about traffic being blocked by too slow a task" },
+       [ST_I_INF_PATTERNS_ADDED]                 = { .name = "PatternsAdded",               .alt_name = "patterns_added_total",          .desc = "Total number of patterns added (acl/map entries)" },
+       [ST_I_INF_PATTERNS_FREED]                 = { .name = "PatternsFreed",               .alt_name = "patterns_freed_total",          .desc = "Total number of patterns freed (acl/map entries)" },
 };
 
 /* one line of info */
@@ -836,6 +838,8 @@ int stats_fill_info(struct field *line, int len, uint flags)
        line[ST_I_INF_CURR_STRM]                      = mkf_u64(0, glob_curr_strms);
        line[ST_I_INF_CUM_STRM]                       = mkf_u64(0, glob_cum_strms);
        line[ST_I_INF_WARN_BLOCKED]                   = mkf_u32(0, warn_blocked_issued);
+       line[ST_I_INF_PATTERNS_ADDED]                 = mkf_u64(0, patterns_added);
+       line[ST_I_INF_PATTERNS_FREED]                 = mkf_u64(0, patterns_freed);
 
        return 1;
 }