feat(metrics): add frontend and backend protocol distribution metrics
This commit is contained in:
@@ -110,6 +110,36 @@ impl Drop for ActiveRequestGuard {
|
||||
}
|
||||
}
|
||||
|
||||
/// RAII guard that calls frontend_protocol_closed or backend_protocol_closed on drop.
|
||||
/// Ensures active protocol counters are decremented on all exit paths.
|
||||
pub(crate) struct ProtocolGuard {
|
||||
metrics: Arc<MetricsCollector>,
|
||||
version: &'static str,
|
||||
is_frontend: bool,
|
||||
}
|
||||
|
||||
impl ProtocolGuard {
|
||||
pub fn frontend(metrics: Arc<MetricsCollector>, version: &'static str) -> Self {
|
||||
metrics.frontend_protocol_opened(version);
|
||||
Self { metrics, version, is_frontend: true }
|
||||
}
|
||||
|
||||
pub fn backend(metrics: Arc<MetricsCollector>, version: &'static str) -> Self {
|
||||
metrics.backend_protocol_opened(version);
|
||||
Self { metrics, version, is_frontend: false }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for ProtocolGuard {
|
||||
fn drop(&mut self) {
|
||||
if self.is_frontend {
|
||||
self.metrics.frontend_protocol_closed(self.version);
|
||||
} else {
|
||||
self.metrics.backend_protocol_closed(self.version);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Backend stream that can be either plain TCP or TLS-wrapped.
|
||||
/// Used for `terminate-and-reencrypt` mode where the backend requires TLS.
|
||||
pub(crate) enum BackendStream {
|
||||
@@ -625,6 +655,18 @@ impl HttpProxyService {
|
||||
.map(|p| p.as_str().eq_ignore_ascii_case("websocket"))
|
||||
.unwrap_or(false);
|
||||
|
||||
// Track frontend protocol for distribution metrics (h1/h2/h3/ws)
|
||||
let frontend_proto: &'static str = if is_h1_websocket || is_h2_websocket {
|
||||
"ws"
|
||||
} else {
|
||||
match req.version() {
|
||||
hyper::Version::HTTP_2 => "h2",
|
||||
hyper::Version::HTTP_3 => "h3",
|
||||
_ => "h1", // HTTP/1.0, HTTP/1.1
|
||||
}
|
||||
};
|
||||
let _frontend_proto_guard = ProtocolGuard::frontend(Arc::clone(&self.metrics), frontend_proto);
|
||||
|
||||
if is_h1_websocket || is_h2_websocket {
|
||||
let result = self.handle_websocket_upgrade(
|
||||
req, peer_addr, &upstream, route_match.route, route_id, &upstream_key, cancel, &ip_str, is_h2_websocket,
|
||||
@@ -2383,6 +2425,8 @@ impl HttpProxyService {
|
||||
selector: upstream_selector,
|
||||
key: upstream_key_owned.clone(),
|
||||
};
|
||||
// Track backend WebSocket connection — guard decrements on tunnel close
|
||||
let _backend_ws_guard = ProtocolGuard::backend(Arc::clone(&metrics), "ws");
|
||||
|
||||
let client_upgraded = match on_client_upgrade.await {
|
||||
Ok(upgraded) => upgraded,
|
||||
|
||||
Reference in New Issue
Block a user