From 19e4ec43b91113fc89e1695665e9afa7a4dd4bbd Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Tue, 22 Oct 2024 16:57:03 +0200 Subject: [PATCH] MINOR: filters: add per-filter call counters The idea here is to record how many times a filter is being called on a stream. We're incrementing the same counter all along, regardless of the type of event, since the purpose is essentially to detect one that might be misbehaving. The number of calls is reported in "show sess all" next to the filter name. It may also help detect suboptimal processing. For example compressing 1GB shows 138k calls to the compression filter, which is roughly two calls per buffer. Maybe we wake up with incomplete buffers and compress less. That's left for a future analysis. --- include/haproxy/filters-t.h | 1 + src/filters.c | 34 +++++++++++++++++++++++++++------- src/stream.c | 2 +- 3 files changed, 29 insertions(+), 8 deletions(-) diff --git a/include/haproxy/filters-t.h b/include/haproxy/filters-t.h index 2acacd076068..6c1879fbed9a 100644 --- a/include/haproxy/filters-t.h +++ b/include/haproxy/filters-t.h @@ -227,6 +227,7 @@ struct filter { struct flt_conf *config; /* the filter's configuration */ void *ctx; /* The filter context (opaque) */ unsigned short flags; /* FLT_FL_* */ + unsigned int calls; /* number of calls */ unsigned long long offset[2]; /* Offset of input data already filtered for a specific channel * 0: request channel, 1: response channel */ unsigned int pre_analyzers; /* bit field indicating analyzers to pre-process */ diff --git a/src/filters.c b/src/filters.c index cc89469ca390..e650a0899680 100644 --- a/src/filters.c +++ b/src/filters.c @@ -464,6 +464,7 @@ flt_stream_release(struct stream *s, int only_backend) list_for_each_entry_safe(filter, back, &strm_flt(s)->filters, list) { if (!only_backend || (filter->flags & FLT_FL_IS_BACKEND_FILTER)) { + filter->calls++; if (FLT_OPS(filter)->detach) FLT_OPS(filter)->detach(s, filter); LIST_DELETE(&filter->list); @@ -485,8 +486,11 @@ flt_stream_start(struct stream *s) struct filter *filter; list_for_each_entry(filter, &strm_flt(s)->filters, list) { - if (FLT_OPS(filter)->stream_start && FLT_OPS(filter)->stream_start(s, filter) < 0) - return -1; + if (FLT_OPS(filter)->stream_start) { + filter->calls++; + if (FLT_OPS(filter)->stream_start(s, filter) < 0) + return -1; + } } if (strm_li(s) && (strm_li(s)->bind_conf->analysers & AN_REQ_FLT_START_FE)) { s->req.flags |= CF_FLT_ANALYZE; @@ -505,8 +509,10 @@ flt_stream_stop(struct stream *s) struct filter *filter; list_for_each_entry(filter, &strm_flt(s)->filters, list) { - if (FLT_OPS(filter)->stream_stop) + if (FLT_OPS(filter)->stream_stop) { + filter->calls++; FLT_OPS(filter)->stream_stop(s, filter); + } } } @@ -520,8 +526,10 @@ flt_stream_check_timeouts(struct stream *s) struct filter *filter; list_for_each_entry(filter, &strm_flt(s)->filters, list) { - if (FLT_OPS(filter)->check_timeouts) + if (FLT_OPS(filter)->check_timeouts) { + filter->calls++; FLT_OPS(filter)->check_timeouts(s, filter); + } } } @@ -546,9 +554,11 @@ flt_set_stream_backend(struct stream *s, struct proxy *be) end: list_for_each_entry(filter, &strm_flt(s)->filters, list) { - if (FLT_OPS(filter)->stream_set_backend && - FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0) - return -1; + if (FLT_OPS(filter)->stream_set_backend) { + filter->calls++; + if (FLT_OPS(filter)->stream_set_backend(s, filter, be) < 0) + return -1; + } } if (be->be_req_ana & AN_REQ_FLT_START_BE) { s->req.flags |= CF_FLT_ANALYZE; @@ -590,6 +600,7 @@ flt_http_end(struct stream *s, struct http_msg *msg) if (FLT_OPS(filter)->http_end) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->http_end(s, filter, msg); if (ret <= 0) BREAK_EXECUTION(s, msg->chn, end); @@ -617,6 +628,7 @@ flt_http_reset(struct stream *s, struct http_msg *msg) list_for_each_entry(filter, &strm_flt(s)->filters, list) { if (FLT_OPS(filter)->http_reset) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); + filter->calls++; FLT_OPS(filter)->http_reset(s, filter, msg); } } @@ -636,6 +648,7 @@ flt_http_reply(struct stream *s, short status, const struct buffer *msg) list_for_each_entry(filter, &strm_flt(s)->filters, list) { if (FLT_OPS(filter)->http_reply) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); + filter->calls++; FLT_OPS(filter)->http_reply(s, filter, status, msg); } } @@ -678,6 +691,7 @@ flt_http_payload(struct stream *s, struct http_msg *msg, unsigned int len) if (FLT_OPS(filter)->http_payload) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->http_payload(s, filter, msg, out + offset, data - offset); if (ret < 0) goto end; @@ -749,6 +763,7 @@ flt_start_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) FLT_OFF(filter, chn) = 0; if (FLT_OPS(filter)->channel_start_analyze) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->channel_start_analyze(s, filter, chn); if (ret <= 0) BREAK_EXECUTION(s, chn, end); @@ -781,6 +796,7 @@ flt_pre_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) RESUME_FILTER_LOOP(s, chn) { if (FLT_OPS(filter)->channel_pre_analyze && (filter->pre_analyzers & an_bit)) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->channel_pre_analyze(s, filter, chn, an_bit); if (ret <= 0) BREAK_EXECUTION(s, chn, check_result); @@ -814,6 +830,7 @@ flt_post_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) list_for_each_entry(filter, &strm_flt(s)->filters, list) { if (FLT_OPS(filter)->channel_post_analyze && (filter->post_analyzers & an_bit)) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->channel_post_analyze(s, filter, chn, an_bit); if (ret < 0) break; @@ -842,6 +859,7 @@ flt_analyze_http_headers(struct stream *s, struct channel *chn, unsigned int an_ RESUME_FILTER_LOOP(s, chn) { if (FLT_OPS(filter)->http_headers) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_HTTP_ANA|STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->http_headers(s, filter, msg); if (ret <= 0) BREAK_EXECUTION(s, chn, check_result); @@ -887,6 +905,7 @@ flt_end_analyze(struct stream *s, struct channel *chn, unsigned int an_bit) if (FLT_OPS(filter)->channel_end_analyze) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->channel_end_analyze(s, filter, chn); if (ret <= 0) BREAK_EXECUTION(s, chn, end); @@ -965,6 +984,7 @@ flt_tcp_payload(struct stream *s, struct channel *chn, unsigned int len) if (FLT_OPS(filter)->tcp_payload) { DBG_TRACE_DEVEL(FLT_ID(filter), STRM_EV_TCP_ANA|STRM_EV_FLT_ANA, s); + filter->calls++; ret = FLT_OPS(filter)->tcp_payload(s, filter, chn, out + offset, data - offset); if (ret < 0) goto end; diff --git a/src/stream.c b/src/stream.c index 1553b2ff8787..7eea4ca93f2c 100644 --- a/src/stream.c +++ b/src/stream.c @@ -3537,7 +3537,7 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch list_for_each_entry(flt, &strm->strm_flt.filters, list) { if (flt->list.p != &strm->strm_flt.filters) chunk_appendf(buf, ", "); - chunk_appendf(buf, "%p=\"%s\"", flt, FLT_ID(flt)); + chunk_appendf(buf, "%p=\"%s\" [%u]", flt, FLT_ID(flt), flt->calls); } chunk_appendf(buf, "}\n"); }