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.
This commit is contained in:
Willy Tarreau 2025-07-05 00:07:25 +02:00
parent a075d6928a
commit 573143e0c8
4 changed files with 16 additions and 1 deletions

View 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 *);

View 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

View 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)

View 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;
}