Skip to content

Commit cb68324

Browse files
committed
feat(app/inbound): request body frame size metrics
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: * #4188 * #4187 * #4186 * #4174 * #4165 * #4166 * #4127 Signed-off-by: katelyn martin <[email protected]>
1 parent 447b182 commit cb68324

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)