Support in-flight request age metrics for router (#16341)
This commit is contained in:
@@ -26,7 +26,10 @@ use tracing::{debug, error, field::Empty, info, info_span, warn, Span};
|
||||
|
||||
pub use crate::core::token_bucket::TokenBucket;
|
||||
use crate::{
|
||||
observability::metrics::{method_to_static_str, metrics_labels, Metrics},
|
||||
observability::{
|
||||
inflight_tracker::InFlightRequestTracker,
|
||||
metrics::{method_to_static_str, metrics_labels, Metrics},
|
||||
},
|
||||
routers::error::extract_error_code_from_response,
|
||||
server::AppState,
|
||||
wasm::{
|
||||
@@ -607,12 +610,14 @@ pub async fn concurrency_limit_middleware(
|
||||
static ACTIVE_HTTP_CONNECTIONS: AtomicU64 = AtomicU64::new(0);
|
||||
|
||||
/// Tower Layer for HTTP metrics collection (SMG Layer 1 metrics)
|
||||
#[derive(Clone, Copy, Default)]
|
||||
pub struct HttpMetricsLayer;
|
||||
#[derive(Clone)]
|
||||
pub struct HttpMetricsLayer {
|
||||
tracker: Arc<InFlightRequestTracker>,
|
||||
}
|
||||
|
||||
impl HttpMetricsLayer {
|
||||
pub fn new() -> Self {
|
||||
Self
|
||||
pub fn new(tracker: Arc<InFlightRequestTracker>) -> Self {
|
||||
Self { tracker }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,7 +625,10 @@ impl<S> Layer<S> for HttpMetricsLayer {
|
||||
type Service = HttpMetricsMiddleware<S>;
|
||||
|
||||
fn layer(&self, inner: S) -> Self::Service {
|
||||
HttpMetricsMiddleware { inner }
|
||||
HttpMetricsMiddleware {
|
||||
inner,
|
||||
in_flight_request_tracker: self.tracker.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -628,6 +636,7 @@ impl<S> Layer<S> for HttpMetricsLayer {
|
||||
#[derive(Clone)]
|
||||
pub struct HttpMetricsMiddleware<S> {
|
||||
inner: S,
|
||||
in_flight_request_tracker: Arc<InFlightRequestTracker>,
|
||||
}
|
||||
|
||||
impl<S> Service<Request> for HttpMetricsMiddleware<S>
|
||||
@@ -651,15 +660,20 @@ where
|
||||
let start = Instant::now();
|
||||
|
||||
let mut inner = self.inner.clone();
|
||||
let in_flight_request_tracker = self.in_flight_request_tracker.clone();
|
||||
|
||||
Box::pin(async move {
|
||||
// Increment inside async block - ensures no leak if future is dropped before polling
|
||||
let active = ACTIVE_HTTP_CONNECTIONS.fetch_add(1, Ordering::Relaxed) + 1;
|
||||
Metrics::set_http_connections_active(active as usize);
|
||||
|
||||
let guard = in_flight_request_tracker.track();
|
||||
|
||||
// Capture result before decrementing to ensure decrement happens on error too
|
||||
let result = inner.call(req).await;
|
||||
|
||||
drop(guard);
|
||||
|
||||
// Always decrement, regardless of success or failure
|
||||
let active = ACTIVE_HTTP_CONNECTIONS.fetch_sub(1, Ordering::Relaxed) - 1;
|
||||
Metrics::set_http_connections_active(active as usize);
|
||||
|
||||
Reference in New Issue
Block a user