diff --git a/include/types/counters.h b/include/types/counters.h index 06ce61728..fd83ebbe7 100644 --- a/include/types/counters.h +++ b/include/types/counters.h @@ -44,6 +44,7 @@ struct fe_counters { long long failed_req; /* failed requests (eg: invalid or timeout) */ long long denied_conn; /* denied connection requests (tcp-req-conn rules) */ long long denied_sess; /* denied session requests (tcp-req-sess rules) */ + long long failed_rewrites; /* failed rewrites (warning) */ long long cli_aborts; /* aborted responses during DATA phase caused by the client */ long long srv_aborts; /* aborted responses during DATA phase caused by the server */ @@ -88,6 +89,7 @@ struct be_counters { long long srv_aborts; /* aborted responses during DATA phase caused by the server */ long long retries; /* retried and redispatched connections (BE only) */ long long redispatches; /* retried and redispatched connections (BE only) */ + long long failed_rewrites; /* failed rewrites (warning) */ long long failed_secu; /* blocked responses because of security concerns */ long long failed_checks, failed_hana; /* failed health checks and health analyses for servers */ diff --git a/include/types/stats.h b/include/types/stats.h index b4124334a..a22be365e 100644 --- a/include/types/stats.h +++ b/include/types/stats.h @@ -383,6 +383,7 @@ enum stat_field { ST_F_INTERCEPTED, ST_F_DCON, ST_F_DSES, + ST_F_WREW, /* must always be the last one */ ST_F_TOTAL_FIELDS diff --git a/src/proto_http.c b/src/proto_http.c index efa6d6a36..4fd5aeb15 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -2631,7 +2631,20 @@ resume_execution: } } - http_header_add_tail2(&txn->req, &txn->hdr_idx, replace->str, replace->len); + if (http_header_add_tail2(&txn->req, &txn->hdr_idx, replace->str, replace->len) < 0) { + static unsigned char rate_limit = 0; + + if ((rate_limit++ & 255) == 0) { + replace->str[rule->arg.hdr_add.name_len] = 0; + send_log(px, LOG_WARNING, "Proxy %s failed to add or set the request header '%s' for request #%u. You might need to increase tune.maxrewrite.", px->id, replace->str, s->uniq_id); + } + + HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1); + if (sess->fe != s->be) + HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1); + if (sess->listener->counters) + HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1); + } free_trash_chunk(replace); break; @@ -2931,7 +2944,23 @@ resume_execution: http_remove_header2(&txn->rsp, &txn->hdr_idx, &ctx); } } - http_header_add_tail2(&txn->rsp, &txn->hdr_idx, replace->str, replace->len); + + if (http_header_add_tail2(&txn->rsp, &txn->hdr_idx, replace->str, replace->len) < 0) { + static unsigned char rate_limit = 0; + + if ((rate_limit++ & 255) == 0) { + replace->str[rule->arg.hdr_add.name_len] = 0; + send_log(px, LOG_WARNING, "Proxy %s failed to add or set the response header '%s' for request #%u. You might need to increase tune.maxrewrite.", px->id, replace->str, s->uniq_id); + } + + HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1); + if (sess->fe != s->be) + HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1); + if (sess->listener->counters) + HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1); + if (objt_server(s->target)) + HA_ATOMIC_ADD(&objt_server(s->target)->counters.failed_rewrites, 1); + } free_trash_chunk(replace); break; diff --git a/src/stats.c b/src/stats.c index 7ad30a178..6255ce3d6 100644 --- a/src/stats.c +++ b/src/stats.c @@ -216,6 +216,7 @@ const char *stat_field_names[ST_F_TOTAL_FIELDS] = { [ST_F_INTERCEPTED] = "intercepted", [ST_F_DCON] = "dcon", [ST_F_DSES] = "dses", + [ST_F_WREW] = "wrew", }; /* one line of info */ @@ -1298,6 +1299,7 @@ int stats_fill_fe_stats(struct proxy *px, struct field *stats, int len) stats[ST_F_RATE] = mkf_u32(FN_RATE, read_freq_ctr(&px->fe_sess_per_sec)); stats[ST_F_RATE_LIM] = mkf_u32(FO_CONFIG|FN_LIMIT, px->fe_sps_lim); stats[ST_F_RATE_MAX] = mkf_u32(FN_MAX, px->fe_counters.sps_max); + stats[ST_F_WREW] = mkf_u64(FN_COUNTER, px->fe_counters.failed_rewrites); /* http response: 1xx, 2xx, 3xx, 4xx, 5xx, other */ if (px->mode == PR_MODE_HTTP) { @@ -1388,6 +1390,7 @@ int stats_fill_li_stats(struct proxy *px, struct listener *l, int flags, stats[ST_F_IID] = mkf_u32(FO_KEY|FS_SERVICE, px->uuid); stats[ST_F_SID] = mkf_u32(FO_KEY|FS_SERVICE, l->luid); stats[ST_F_TYPE] = mkf_u32(FO_CONFIG|FS_SERVICE, STATS_TYPE_SO); + stats[ST_F_WREW] = mkf_u64(FN_COUNTER, l->counters->failed_rewrites); if (flags & ST_SHLGNDS) { char str[INET6_ADDRSTRLEN]; @@ -1553,6 +1556,7 @@ int stats_fill_sv_stats(struct proxy *px, struct server *sv, int flags, stats[ST_F_ERESP] = mkf_u64(FN_COUNTER, sv->counters.failed_resp); stats[ST_F_WRETR] = mkf_u64(FN_COUNTER, sv->counters.retries); stats[ST_F_WREDIS] = mkf_u64(FN_COUNTER, sv->counters.redispatches); + stats[ST_F_WREW] = mkf_u64(FN_COUNTER, sv->counters.failed_rewrites); /* status */ fld_status = chunk_newstr(out); @@ -1745,6 +1749,7 @@ int stats_fill_be_stats(struct proxy *px, int flags, struct field *stats, int le stats[ST_F_ERESP] = mkf_u64(FN_COUNTER, px->be_counters.failed_resp); stats[ST_F_WRETR] = mkf_u64(FN_COUNTER, px->be_counters.retries); stats[ST_F_WREDIS] = mkf_u64(FN_COUNTER, px->be_counters.redispatches); + stats[ST_F_WREW] = mkf_u64(FN_COUNTER, px->be_counters.failed_rewrites); stats[ST_F_STATUS] = mkf_str(FO_STATUS, (px->lbprm.tot_weight > 0 || !px->srv) ? "UP" : "DOWN"); stats[ST_F_WEIGHT] = mkf_u32(FN_AVG, (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv); stats[ST_F_ACT] = mkf_u32(0, px->srv_act);