From: Willy Tarreau Date: Fri, 4 Jul 2025 22:07:25 +0000 (+0200) Subject: MINOR: pattern: add a counter of added/freed patterns X-Git-Tag: v3.3-dev3~39 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=573143e0c8792a073433830159bc869e2934d7ba;p=thirdparty%2Fhaproxy.git MINOR: pattern: add a counter of added/freed patterns 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. --- diff --git a/include/haproxy/pattern.h b/include/haproxy/pattern.h index 570ff282b..1f3fdf164 100644 --- a/include/haproxy/pattern.h +++ b/include/haproxy/pattern.h @@ -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 *); diff --git a/include/haproxy/stats-t.h b/include/haproxy/stats-t.h index 465bbe068..f05ec08eb 100644 --- a/include/haproxy/stats-t.h +++ b/include/haproxy/stats-t.h @@ -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 diff --git a/src/pattern.c b/src/pattern.c index 715c64a63..3e25b88e7 100644 --- a/src/pattern.c +++ b/src/pattern.c @@ -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 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) diff --git a/src/stats.c b/src/stats.c index b7e6e1805..f710a4aab 100644 --- a/src/stats.c +++ b/src/stats.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include #include #include #include @@ -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; }