Skip to content

Commit c91ecee

Browse files
authored
feat(app/inbound): request body frame size metrics (#4180)
this commit introduces an additional layer of telemetry to the inbound proxy's http router. either http and grpc metrics are used, depending upon the policy that authorized a given request. this is based upon #4174, which refactored the request body telemetry middleware to be metrics agnostic. see: * #4189 * #4188 * #4187 * #4186 * #4174 * #4165 * #4166 * #4127 Signed-off-by: katelyn martin <[email protected]>
1 parent d127592 commit c91ecee

File tree

2 files changed

+128
-3
lines changed

2 files changed

+128
-3
lines changed

linkerd/app/inbound/src/http/router/metrics.rs

Lines changed: 124 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use linkerd_http_prom::{
1818
pub(super) fn layer<N>(
1919
InboundMetrics {
2020
request_count,
21+
request_body_data,
2122
response_body_data,
2223
..
2324
}: &InboundMetrics,
@@ -34,11 +35,16 @@ pub(super) fn layer<N>(
3435
NewRecordResponseBodyData::layer_via(extract)
3536
};
3637

37-
svc::layer::mk(move |inner| count.layer(body.layer(inner)))
38+
let request = {
39+
let extract = ExtractRequestBodyDataParams(request_body_data.clone());
40+
NewRecordRequestBodyData::new(extract)
41+
};
42+
43+
svc::layer::mk(move |inner| count.layer(body.layer(request.layer(inner))))
3844
}
3945

4046
/// An `N`-typed service instrumented with metrics middleware.
41-
type Instrumented<N> = NewCountRequests<NewRecordResponseBodyData<N>>;
47+
type Instrumented<N> = NewCountRequests<NewRecordResponseBodyData<NewRecordRequestBodyData<N>>>;
4248

4349
/// An `N`-typed `NewService<T>` instrumented with request counting metrics.
4450
type NewCountRequests<N> = count_reqs::NewCountRequests<ExtractRequestCount, N>;
@@ -75,6 +81,30 @@ pub struct ResponseBodyDataLabels {
7581
#[derive(Clone, Debug)]
7682
pub struct ExtractResponseBodyDataMetrics(ResponseBodyFamilies);
7783

84+
/// An `N`-typed `NewService<T>` instrumented with request body metrics.
85+
type NewRecordRequestBodyData<N> = body_data::request::NewRecordBodyData<
86+
N,
87+
ExtractRequestBodyDataParams,
88+
ExtractRequestBodyDataMetrics,
89+
>;
90+
91+
#[derive(Clone, Debug)]
92+
pub struct RequestBodyFamilies {
93+
grpc: body_data::request::RequestBodyFamilies<RequestBodyDataLabels>,
94+
http: body_data::request::RequestBodyFamilies<RequestBodyDataLabels>,
95+
}
96+
97+
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
98+
pub struct RequestBodyDataLabels {
99+
route: RouteLabels,
100+
}
101+
102+
#[derive(Clone, Debug)]
103+
pub struct ExtractRequestBodyDataParams(RequestBodyFamilies);
104+
105+
#[derive(Clone, Debug)]
106+
pub struct ExtractRequestBodyDataMetrics(BodyDataMetrics);
107+
78108
// === impl RequestCountFamilies ===
79109

80110
impl RequestCountFamilies {
@@ -236,3 +266,95 @@ where
236266
family.metrics(&ResponseBodyDataLabels { route })
237267
}
238268
}
269+
270+
// === impl RequestBodyFamilies ===
271+
272+
impl RequestBodyFamilies {
273+
/// Registers a new [`RequestBodyDataFamilies`] with the given registry.
274+
pub fn register(reg: &mut prom::Registry) -> Self {
275+
let grpc = {
276+
let reg = reg.sub_registry_with_prefix("grpc");
277+
body_data::request::RequestBodyFamilies::register(reg)
278+
};
279+
280+
let http = {
281+
let reg = reg.sub_registry_with_prefix("http");
282+
body_data::request::RequestBodyFamilies::register(reg)
283+
};
284+
285+
Self { grpc, http }
286+
}
287+
288+
/// Fetches the proper body frame metrics family, given a permitted target.
289+
fn family(
290+
&self,
291+
variant: PermitVariant,
292+
) -> &body_data::request::RequestBodyFamilies<RequestBodyDataLabels> {
293+
let Self { grpc, http } = self;
294+
match variant {
295+
PermitVariant::Grpc => grpc,
296+
PermitVariant::Http => http,
297+
}
298+
}
299+
}
300+
301+
// === impl RequestBodyDataLabels ===
302+
303+
impl EncodeLabelSetMut for RequestBodyDataLabels {
304+
fn encode_label_set(&self, enc: &mut LabelSetEncoder<'_>) -> std::fmt::Result {
305+
use encoding::EncodeLabel as _;
306+
307+
let Self {
308+
route:
309+
RouteLabels {
310+
server: ServerLabel(parent, port),
311+
route,
312+
},
313+
} = self;
314+
315+
("parent_group", parent.group()).encode(enc.encode_label())?;
316+
("parent_kind", parent.kind()).encode(enc.encode_label())?;
317+
("parent_name", parent.name()).encode(enc.encode_label())?;
318+
("parent_port", *port).encode(enc.encode_label())?;
319+
320+
("route_group", route.group()).encode(enc.encode_label())?;
321+
("route_kind", route.kind()).encode(enc.encode_label())?;
322+
("route_name", route.name()).encode(enc.encode_label())?;
323+
324+
Ok(())
325+
}
326+
}
327+
328+
impl EncodeLabelSet for RequestBodyDataLabels {
329+
fn encode(&self, mut enc: LabelSetEncoder<'_>) -> std::fmt::Result {
330+
self.encode_label_set(&mut enc)
331+
}
332+
}
333+
334+
// === impl ExtractRequestBodyDataParams ===
335+
336+
impl<T> svc::ExtractParam<ExtractRequestBodyDataMetrics, T> for ExtractRequestBodyDataParams
337+
where
338+
T: svc::Param<PermitVariant> + svc::Param<RouteLabels>,
339+
{
340+
fn extract_param(&self, target: &T) -> ExtractRequestBodyDataMetrics {
341+
let Self(families) = self;
342+
let variant = target.param();
343+
let route = target.param();
344+
345+
let family = families.family(variant);
346+
let metrics = family.metrics(&RequestBodyDataLabels { route });
347+
348+
ExtractRequestBodyDataMetrics(metrics)
349+
}
350+
}
351+
352+
// === impl ExtractRequestBodyDataMetrics ===
353+
354+
impl<T> svc::ExtractParam<BodyDataMetrics, T> for ExtractRequestBodyDataMetrics {
355+
fn extract_param(&self, _: &T) -> BodyDataMetrics {
356+
let Self(metrics) = self;
357+
358+
metrics.clone()
359+
}
360+
}

linkerd/app/inbound/src/metrics.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
pub(crate) mod authz;
1212
pub(crate) mod error;
1313

14-
use crate::http::router::{RequestCountFamilies, ResponseBodyFamilies};
14+
use crate::http::router::{RequestBodyFamilies, RequestCountFamilies, ResponseBodyFamilies};
1515
pub use linkerd_app_core::metrics::*;
1616

1717
/// Holds LEGACY inbound proxy metrics.
@@ -30,6 +30,7 @@ pub struct InboundMetrics {
3030
pub detect: crate::detect::MetricsFamilies,
3131
pub direct: crate::direct::MetricsFamilies,
3232
pub request_count: RequestCountFamilies,
33+
pub request_body_data: RequestBodyFamilies,
3334
pub response_body_data: ResponseBodyFamilies,
3435
}
3536

@@ -41,6 +42,7 @@ impl InboundMetrics {
4142
reg.sub_registry_with_prefix("tcp_transport_header"),
4243
);
4344
let request_count = RequestCountFamilies::register(reg);
45+
let request_body_data = RequestBodyFamilies::register(reg);
4446
let response_body_data = ResponseBodyFamilies::register(reg);
4547

4648
Self {
@@ -52,6 +54,7 @@ impl InboundMetrics {
5254
detect,
5355
direct,
5456
request_count,
57+
request_body_data,
5558
response_body_data,
5659
}
5760
}

0 commit comments

Comments
 (0)