]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stream: maintain per-stream counters of the number of passes on code
authorWilly Tarreau <w@1wt.eu>
Tue, 22 Oct 2024 14:35:04 +0000 (16:35 +0200)
committerWilly Tarreau <w@1wt.eu>
Tue, 22 Oct 2024 18:13:00 +0000 (20:13 +0200)
Process_stream() is a complex function and a few times some lopos were
either witnessed or suspected. Each time this happens it's extremely
difficult to figure why because it involves combinations of analysers,
filters, errors etc.

Let's at least maintain a set of 4 counters per stream that report the
number of times we've been through each of the 4 most important blocks
(stconn changes, request analysers, response analysers, and propagation
of changes down). These ones are stored in the stream and reported in
"show sess all", just like they will be reported in panic dumps.

include/haproxy/stream-t.h
src/stream.c

index ad79f5decee16f0d53537b2468c2cd875c276998..363b7eb7550c2e9ffcda50decf8acb8cd2475eab 100644 (file)
@@ -246,6 +246,10 @@ struct stream {
        uint64_t lat_time;              /* total latency time experienced */
        uint64_t cpu_time;              /* total CPU time consumed */
        struct freq_ctr call_rate;      /* stream task call rate without making progress */
+       uint32_t passes_stconn;         /* number of passes on the stconn evaluation code */
+       uint32_t passes_reqana;         /* number of passes on the req analysers block */
+       uint32_t passes_resana;         /* number of passes on the res analysers block */
+       uint32_t passes_propag;         /* number of passes on the shut/err propag code */
 
        unsigned short max_retries;     /* Maximum number of connection retried (=0 is backend is not set) */
        short store_count;
index 0fa942944c0639456827120c9ecc6890d78378e5..1553b2ff8787d03b5c08a66a3d8fc823981afccb 100644 (file)
@@ -421,6 +421,7 @@ struct stream *stream_new(struct session *sess, struct stconn *sc, struct buffer
 
        s->lat_time = s->cpu_time = 0;
        s->call_rate.curr_tick = s->call_rate.curr_ctr = s->call_rate.prev_ctr = 0;
+       s->passes_stconn = s->passes_reqana = s->passes_resana = s->passes_propag = 0;
        s->pcli_next_pid = 0;
        s->pcli_flags = 0;
        s->unique_id = IST_NULL;
@@ -1840,6 +1841,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
         * the client cannot have connect (hence retryable) errors. Also, the
         * connection setup code must be able to deal with any type of abort.
         */
+       s->passes_stconn++;
        srv = objt_server(s->target);
        if (unlikely(scf->flags & SC_FL_ERROR)) {
                if (sc_state_in(scf->state, SC_SB_EST|SC_SB_DIS)) {
@@ -1969,6 +1971,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
         */
 
  resync_request:
+       s->passes_reqana++;
        /* Analyse request */
        if (((req->flags & ~rqf_last) & CF_MASK_ANALYSER) ||
            ((scf->flags ^ scf_flags) & (SC_FL_EOS|SC_FL_ABRT_DONE|SC_FL_ABRT_WANTED)) ||
@@ -2073,6 +2076,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
        req_ana_back = req->analysers;
 
  resync_response:
+       s->passes_resana++;
        /* Analyse response */
 
        if (((res->flags & ~rpf_last) & CF_MASK_ANALYSER) ||
@@ -2155,7 +2159,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state)
         * both buffers.
         */
 
-
+       s->passes_propag++;
        /*
         * Now we propagate unhandled errors to the stream. Normally
         * we're just in a data phase here since it means we have not
@@ -3308,6 +3312,9 @@ void strm_dump_to_buffer(struct buffer *buf, const struct stream *strm, const ch
                     strm->conn_err_type, strm->srv_conn, strm->pend_pos,
                     LIST_INLIST(&strm->buffer_wait.list), strm->stream_epoch);
 
+       chunk_appendf(buf, "%s  p_stc=%u p_req=%u p_res=%u p_prp=%u\n", pfx,
+                     strm->passes_stconn, strm->passes_reqana, strm->passes_resana, strm->passes_propag);
+
        chunk_appendf(buf,
                     "%s  frontend=%s (id=%u mode=%s), listener=%s (id=%u)", pfx,
                     HA_ANON_STR(anon_key, strm_fe(strm)->id), strm_fe(strm)->uuid, proxy_mode_str(strm_fe(strm)->mode),