feat(metrics): add real-time throughput sampling and byte-counting metrics
This commit is contained in:
@@ -21,6 +21,7 @@ use tracing::{debug, error, info, warn};
|
||||
use rustproxy_routing::RouteManager;
|
||||
use rustproxy_metrics::MetricsCollector;
|
||||
|
||||
use crate::counting_body::{CountingBody, Direction};
|
||||
use crate::request_filter::RequestFilter;
|
||||
use crate::response_filter::ResponseFilter;
|
||||
use crate::upstream_selector::UpstreamSelector;
|
||||
@@ -345,8 +346,16 @@ impl HttpProxyService {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap the request body in CountingBody to track bytes_in
|
||||
let counting_req_body = CountingBody::new(
|
||||
body,
|
||||
Arc::clone(&self.metrics),
|
||||
route_id.map(|s| s.to_string()),
|
||||
Direction::In,
|
||||
);
|
||||
|
||||
// Stream the request body through to upstream
|
||||
let upstream_req = upstream_req.body(body).unwrap();
|
||||
let upstream_req = upstream_req.body(counting_req_body).unwrap();
|
||||
|
||||
let upstream_response = match sender.send_request(upstream_req).await {
|
||||
Ok(resp) => resp,
|
||||
@@ -401,8 +410,16 @@ impl HttpProxyService {
|
||||
}
|
||||
}
|
||||
|
||||
// Wrap the request body in CountingBody to track bytes_in
|
||||
let counting_req_body = CountingBody::new(
|
||||
body,
|
||||
Arc::clone(&self.metrics),
|
||||
route_id.map(|s| s.to_string()),
|
||||
Direction::In,
|
||||
);
|
||||
|
||||
// Stream the request body through to upstream
|
||||
let upstream_req = upstream_req.body(body).unwrap();
|
||||
let upstream_req = upstream_req.body(counting_req_body).unwrap();
|
||||
|
||||
let upstream_response = match sender.send_request(upstream_req).await {
|
||||
Ok(resp) => resp,
|
||||
@@ -417,6 +434,10 @@ impl HttpProxyService {
|
||||
}
|
||||
|
||||
/// Build the client-facing response from an upstream response, streaming the body.
|
||||
///
|
||||
/// The response body is wrapped in a `CountingBody` that counts bytes as they
|
||||
/// stream from upstream to client. When the body is fully consumed (or dropped),
|
||||
/// it reports byte counts to the metrics collector and calls `connection_closed`.
|
||||
async fn build_streaming_response(
|
||||
&self,
|
||||
upstream_response: Response<Incoming>,
|
||||
@@ -433,10 +454,22 @@ impl HttpProxyService {
|
||||
ResponseFilter::apply_headers(route, headers, None);
|
||||
}
|
||||
|
||||
// Wrap the response body in CountingBody to track bytes_out.
|
||||
// CountingBody will report bytes and we close the connection metric
|
||||
// after the body stream completes (not before it even starts).
|
||||
let counting_body = CountingBody::new(
|
||||
resp_body,
|
||||
Arc::clone(&self.metrics),
|
||||
route_id.map(|s| s.to_string()),
|
||||
Direction::Out,
|
||||
);
|
||||
|
||||
// Close the connection metric now — the HTTP request/response cycle is done
|
||||
// from the proxy's perspective once we hand the streaming body to hyper.
|
||||
// Bytes will still be counted as they flow.
|
||||
self.metrics.connection_closed(route_id);
|
||||
|
||||
// Stream the response body directly from upstream to client
|
||||
let body: BoxBody<Bytes, hyper::Error> = BoxBody::new(resp_body);
|
||||
let body: BoxBody<Bytes, hyper::Error> = BoxBody::new(counting_body);
|
||||
|
||||
Ok(response.body(body).unwrap())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user