diff --git a/src/middleware/log_connection_pool_status.rs b/src/middleware/log_connection_pool_status.rs new file mode 100644 index 00000000000..1c6b85e05e8 --- /dev/null +++ b/src/middleware/log_connection_pool_status.rs @@ -0,0 +1,53 @@ +//! Log the current state of the database connection pool at most once per minute + +use super::prelude::*; +use crate::app::App; + +use conduit::Request; +use std::sync::{ + atomic::{AtomicUsize, Ordering}, + Arc, Mutex, +}; +use std::time::{Duration, Instant}; + +#[derive(Clone)] +pub(crate) struct LogConnectionPoolStatus { + app: Arc, + last_log_time: Arc>, + in_flight_requests: Arc, +} + +impl LogConnectionPoolStatus { + pub(crate) fn new(app: &Arc) -> Self { + Self { + app: app.clone(), + last_log_time: Arc::new(Mutex::new(Instant::now())), + in_flight_requests: Arc::new(AtomicUsize::new(0)), + } + } +} + +impl Middleware for LogConnectionPoolStatus { + fn before(&self, _: &mut dyn Request) -> Result<(), Box> { + let mut last_log_time = self.last_log_time.lock().unwrap_or_else(|e| e.into_inner()); + let in_flight_requests = self.in_flight_requests.fetch_add(1, Ordering::SeqCst); + if last_log_time.elapsed() >= Duration::from_secs(60) { + *last_log_time = Instant::now(); + println!( + "connection_pool_status=\"{:?}\" in_flight_requests={}", + self.app.diesel_database.state(), + in_flight_requests + ); + } + Ok(()) + } + + fn after( + &self, + _: &mut dyn Request, + res: Result>, + ) -> Result> { + self.in_flight_requests.fetch_sub(1, Ordering::SeqCst); + res + } +} diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 7fc05595e68..efa5e9f251b 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -9,6 +9,7 @@ pub use self::current_user::CurrentUser; pub use self::debug::*; pub use self::ember_index_rewrite::EmberIndexRewrite; pub use self::head::Head; +use self::log_connection_pool_status::LogConnectionPoolStatus; pub use self::security_headers::SecurityHeaders; pub use self::static_or_continue::StaticOrContinue; @@ -19,6 +20,7 @@ mod debug; mod ember_index_rewrite; mod ensure_well_formed_500; mod head; +mod log_connection_pool_status; mod log_request; mod require_user_agent; mod security_headers; @@ -53,6 +55,10 @@ pub fn build_middleware(app: Arc, endpoints: R404) -> MiddlewareBuilder { m.add(DebugRequest); } + if env::var_os("LOG_CONNECTION_POOL_STATUS").is_some() { + m.add(LogConnectionPoolStatus::new(&app)); + } + m.add(ConditionalGet); m.add(Cookie::new());