From: Christopher Faulet Date: Tue, 22 Oct 2024 14:46:34 +0000 (+0200) Subject: DEBUG: stream: Add debug counters to track some client/server aborts X-Git-Tag: v3.1-dev11~81 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c8aecc393bd125e476469d2b6159a1af542c78ae;p=thirdparty%2Fhaproxy.git DEBUG: stream: Add debug counters to track some client/server aborts Not all aborts are tracked for now but only those a bit ambiguous. Mainly, aborts during the data forwarding are concerned. Those triggered during the request or the response analysis are easier to analyze with the stream termination state. --- diff --git a/src/http_ana.c b/src/http_ana.c index a30100ffd6..d94ca18f4b 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -515,8 +515,9 @@ int http_process_req_common(struct stream *s, struct channel *req, int an_bit, s if (!ret) continue; } - if (!http_apply_redirect_rule(rule, s, txn)) + if (!http_apply_redirect_rule(rule, s, txn)) { goto return_int_err; + } goto done; } @@ -1007,8 +1008,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) * response. Otherwise, let a change to forward the response * first. */ - if (htx_is_empty(htxbuf(&s->res.buf))) + if (htx_is_empty(htxbuf(&s->res.buf))) { + COUNT_IF(1, "Server abort during request forwarding"); goto return_srv_abort; + } } http_end_request(s); @@ -1040,8 +1043,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) missing_data_or_waiting: /* stop waiting for data if the input is closed before the end */ - if (msg->msg_state < HTTP_MSG_ENDING && (s->scf->flags & (SC_FL_ABRT_DONE|SC_FL_EOS))) + if (msg->msg_state < HTTP_MSG_ENDING && (s->scf->flags & (SC_FL_ABRT_DONE|SC_FL_EOS))) { + COUNT_IF(1, "Client abort during request forwarding"); goto return_cli_abort; + } waiting: /* waiting for the last bits to leave the buffer */ @@ -1049,8 +1054,10 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) /* Handle server aborts only if there is no response. Otherwise, * let a change to forward the response first. */ - if (htx_is_empty(htxbuf(&s->res.buf))) + if (htx_is_empty(htxbuf(&s->res.buf))) { + COUNT_IF(1, "Server abort during request forwarding"); goto return_srv_abort; + } } /* When TE: chunked is used, we need to get there again to parse remaining @@ -1113,6 +1120,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) if (objt_server(s->target)) _HA_ATOMIC_INC(&__objt_server(s->target)->counters.internal_errors); status = 500; + COUNT_IF(1, "Internal error during request forwarding"); goto return_prx_cond; return_bad_req: @@ -1120,6 +1128,7 @@ int http_request_forward_body(struct stream *s, struct channel *req, int an_bit) if (sess->listener && sess->listener->counters) _HA_ATOMIC_INC(&sess->listener->counters->failed_req); status = 400; + COUNT_IF(1, "Request parsing error during request forwarding"); /* fall through */ return_prx_cond: @@ -2151,6 +2160,7 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit if ((s->scf->flags & SC_FL_SHUT_DONE) && co_data(res)) { /* response errors are most likely due to the client aborting * the transfer. */ + COUNT_IF(1, "Client abort during response forwarding"); goto return_cli_abort; } @@ -2164,8 +2174,10 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit return 0; missing_data_or_waiting: - if (s->scf->flags & SC_FL_SHUT_DONE) + if (s->scf->flags & SC_FL_SHUT_DONE) { + COUNT_IF(1, "Client abort during response forwarding"); goto return_cli_abort; + } /* stop waiting for data if the input is closed before the end. If the * client side was already closed, it means that the client has aborted, @@ -2174,11 +2186,15 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit */ if (msg->msg_state < HTTP_MSG_ENDING && (s->scb->flags & (SC_FL_EOS|SC_FL_ABRT_DONE))) { if ((s->scf->flags & (SC_FL_EOS|SC_FL_ABRT_DONE)) && - (s->scb->flags & SC_FL_SHUT_DONE)) + (s->scb->flags & SC_FL_SHUT_DONE)) { + COUNT_IF(1, "Client abort during response forwarding"); goto return_cli_abort; + } /* If we have some pending data, we continue the processing */ - if (htx_is_empty(htx)) + if (htx_is_empty(htx)) { + COUNT_IF(1, "Server abort during response forwarding"); goto return_srv_abort; + } } /* When TE: chunked is used, we need to get there again to parse @@ -2238,6 +2254,7 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit _HA_ATOMIC_INC(&__objt_server(s->target)->counters.internal_errors); if (!(s->flags & SF_ERR_MASK)) s->flags |= SF_ERR_INTERNAL; + COUNT_IF(1, "Internal error during response forwarding"); goto return_error; return_bad_res: @@ -2247,6 +2264,7 @@ int http_response_forward_body(struct stream *s, struct channel *res, int an_bit health_adjust(__objt_server(s->target), HANA_STATUS_HTTP_RSP); } stream_inc_http_fail_ctr(s); + COUNT_IF(1, "Response parsing error during response forwarding"); /* fall through */ return_error: diff --git a/src/stream.c b/src/stream.c index bc037d8c5a..0fa942944c 100644 --- a/src/stream.c +++ b/src/stream.c @@ -1846,6 +1846,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) sc_abort(scf); sc_shutdown(scf); if (!(req->analysers) && !(res->analysers)) { + COUNT_IF(1, "Report a client abort (no analysers)"); _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.cli_aborts); if (sess->listener && sess->listener->counters) @@ -1868,6 +1869,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.failed_resp); if (!(req->analysers) && !(res->analysers)) { + COUNT_IF(1, "Report a client abort (no analysers)"); _HA_ATOMIC_INC(&s->be->be_counters.srv_aborts); _HA_ATOMIC_INC(&sess->fe->fe_counters.srv_aborts); if (sess->listener && sess->listener->counters) @@ -2173,6 +2175,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.cli_aborts); s->flags |= SF_ERR_CLICL; + COUNT_IF(1, "Report unhandled client error"); } else if (req->flags & CF_READ_TIMEOUT) { _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts); @@ -2182,6 +2185,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.cli_aborts); s->flags |= SF_ERR_CLITO; + COUNT_IF(1, "Report unhandled client timeout (RD)"); } else { _HA_ATOMIC_INC(&s->be->be_counters.srv_aborts); @@ -2191,6 +2195,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.srv_aborts); s->flags |= SF_ERR_SRVTO; + COUNT_IF(1, "Report unhandled server timeout (WR)"); } sess_set_term_flags(s); @@ -2219,6 +2224,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.srv_aborts); s->flags |= SF_ERR_SRVCL; + COUNT_IF(1, "Report unhandled server error"); } else if (res->flags & CF_READ_TIMEOUT) { _HA_ATOMIC_INC(&s->be->be_counters.srv_aborts); @@ -2228,6 +2234,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.srv_aborts); s->flags |= SF_ERR_SRVTO; + COUNT_IF(1, "Report unhandled server timeout (RD)"); } else { _HA_ATOMIC_INC(&s->be->be_counters.cli_aborts); @@ -2237,6 +2244,7 @@ struct task *process_stream(struct task *t, void *context, unsigned int state) if (srv) _HA_ATOMIC_INC(&srv->counters.cli_aborts); s->flags |= SF_ERR_CLITO; + COUNT_IF(1, "Report unhandled client timeout (WR)"); } sess_set_term_flags(s); }