diff --git a/docs/user_guide/phase.md b/docs/user_guide/phase.md index 5f3a891a..402de415 100644 --- a/docs/user_guide/phase.md +++ b/docs/user_guide/phase.md @@ -130,6 +130,13 @@ Every error that reaches `fail_to_proxy()` will be automatically logged in the e This callback returns a string which allows users to customize what info to dump in the error log to help track and debug the failures. +### `suppress_pre_request_error_log()` +This is also not a phase, but another callback. + +This callback is similar to `suppress_error_log()`, but it is invoked for downstream request read and parse failures before the per-request `CTX` is created. Because the request may not have been parsed successfully yet, it receives the downstream HTTP session directly instead of `Session` and `CTX`. + +Return `true` to suppress the error log. + ### `suppress_error_log()` This is also not a phase, but another callback. diff --git a/pingora-proxy/src/lib.rs b/pingora-proxy/src/lib.rs index 52a89cbd..f058ec51 100644 --- a/pingora-proxy/src/lib.rs +++ b/pingora-proxy/src/lib.rs @@ -67,7 +67,6 @@ use pingora_core::protocols::http::subrequest::server::SubrequestHandle; use pingora_core::protocols::http::v1::client::HttpSession as HttpSessionV1; use pingora_core::protocols::http::v2::server::H2Options; use pingora_core::protocols::http::HttpTask; -use pingora_core::protocols::http::ServerSession as HttpSession; use pingora_core::protocols::http::SERVER_NAME; use pingora_core::protocols::Stream; use pingora_core::protocols::{Digest, UniqueID}; @@ -89,6 +88,7 @@ pub mod subrequest; use subrequest::{BodyMode, Ctx as SubrequestCtx}; +pub use pingora_core::protocols::http::ServerSession as HttpSession; pub use proxy_cache::range_filter::{range_header_filter, MultiRangeInfo, RangeType}; pub use proxy_purge::PurgeStatus; pub use proxy_trait::{FailToProxy, ProxyHttp}; @@ -234,7 +234,12 @@ where } Err(mut e) => { e.as_down(); - error!("Fail to proxy: {e}"); + if !self + .inner + .suppress_pre_request_error_log(&downstream_session, &e) + { + error!("Fail to proxy: {e}"); + } if matches!(e.etype, InvalidHTTPHeader) { downstream_session .respond_error(400) diff --git a/pingora-proxy/src/proxy_trait.rs b/pingora-proxy/src/proxy_trait.rs index b81fbb9b..9e935a6a 100644 --- a/pingora-proxy/src/proxy_trait.rs +++ b/pingora-proxy/src/proxy_trait.rs @@ -505,6 +505,15 @@ pub trait ProxyHttp { ) { } + /// A value of true means that the log message will be suppressed. The default value is false. + /// + /// This callback is invoked for downstream request read or parse failures, before + /// [`Self::early_request_filter`] and before [`Self::CTX`] is created, so + /// implementations should not assume `session.req_header()` is available. + fn suppress_pre_request_error_log(&self, _session: &HttpSession, _error: &Error) -> bool { + false + } + /// A value of true means that the log message will be suppressed. The default value is false. fn suppress_error_log(&self, _session: &Session, _ctx: &Self::CTX, _error: &Error) -> bool { false