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.
This commit is contained in:
Willy Tarreau 2024-10-22 16:57:03 +02:00
parent 37d5c6fe3a
commit 19e4ec43b9
3 changed files with 29 additions and 8 deletions

View File

@ -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 */

View File

@ -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;

View File

@ -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");
}