]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: filters: add per-filter call counters
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Oct 2024 14:57:03 +0000 (16:57 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 22 Oct 2024 18:13:00 +0000 (20:13 +0200)
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
src/filters.c
src/stream.c

index 2acacd076068e55c4365894c730df8f0fde79cee..6c1879fbed9a0b70743a87e4669982e3e220da47 100644 (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 */
index cc89469ca390af994267cc526275fb9365d9f51e..e650a08996806da626584d5e1f30077baee6e7d6 100644 (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;
index 1553b2ff8787d03b5c08a66a3d8fc823981afccb..7eea4ca93f2c351256a7b7c66fbb3d3fee1ac9c4 100644 (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");
        }