Skip to content

Commit f2e5da3

Browse files
authored
refactor(app/inbound): router metrics middleware are T-agnostic (#4181)
#4119 introduced a `Permitted<T>` structure, to provide a more formal notion of a `(HttpRoutePermit, T)` tuple. during review of #4180, we had a discussion about how the inbound proxy's http router had metrics layers which were tightly coupled to the notion of a `Permitted<T>`: > This isn't a hard blocker--but this is unfortunate that we're coupling > this impl to the Permitted target type -- target types are usually an > _internal implementation detail_ and not a public api that is depended > on elsewhere. > > ... > > and then have our Permitted impl `Param<MetricsVariant> for Permitted<T>`. > > then this module remains decoupled from the concrete target types. > > That is, the metrics module is decoupled from _where it's called_--as > long as the caller provides a target that can give us what we need to > build our extractors, we're good to go. this branch performs a series of changes to decouple our metric layers' extractors from `Permitted<T>`. importantly, this has the effect of leaving the inbound metrics layers' extractors agnostic to their target: they now provide implementations like `svc::ExtractParam<BodyDataMetrics, T>` rather than `svc::ExtractParam<BodyDataMetrics, Permitted<T>>`. see #4180. --- * refactor(app/inbound): `Permitted<T>` is a struct this restructures `Permitted<T>` so that it is no longer an enum. we instead define a "dumb" enum that represents the grpc/http dichotomy, and return to a model in which `Permitted<T>` is a `struct`. Signed-off-by: katelyn martin <[email protected]> * refactor(app/inbound): `Permitted<T>` is not `T: Param<P>` in order to carve out space to allow us to define other `Param<P>` implementations for `Permitted<T>`, we remove this blanket deference to the inner `T` target. Signed-off-by: katelyn martin <[email protected]> * refactor(app/inbound): `Permitted<T>` exposes `Param<P>` impls we cannot expose `T` or any of its own parameters, but we can expose the permit, its variant, and its labels. Signed-off-by: katelyn martin <[email protected]> * refactor(app/inbound): `family` lookups accept `PermitVariant` these now accept specifically the variant, rather than the permitted target. Signed-off-by: katelyn martin <[email protected]> * refactor(app/inbound): `ExtractRecordBodyDataMetrics` is `T`-agnostic this type now can extract metrics from arbitrary targets. Signed-off-by: katelyn martin <[email protected]> * refactor(app/inbound): `ExtractRequestCount` is `T`-agnostic this type now can extract metrics from arbitrary targets. Signed-off-by: katelyn martin <[email protected]> * refactor(app/inbound): `LogicalPerRequest::from` is `T`-agnostic Signed-off-by: katelyn martin <[email protected]> --------- Signed-off-by: katelyn martin <[email protected]>
1 parent 50ba196 commit f2e5da3

File tree

4 files changed

+107
-54
lines changed

4 files changed

+107
-54
lines changed

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
use crate::{policy, stack_labels, Inbound};
1+
use crate::{
2+
policy::{self, HttpRoutePermit},
3+
stack_labels, Inbound,
4+
};
25
use linkerd_app_core::{
36
classify, errors, http_tracing, profiles,
47
proxy::{http, tap},
@@ -259,14 +262,14 @@ impl<C> Inbound<C> {
259262

260263
// === impl LogicalPerRequest ===
261264

262-
impl<'a, T> From<&'a policy::Permitted<T>> for LogicalPerRequest
265+
impl<'a, T> From<&'a T> for LogicalPerRequest
263266
where
264267
T: Param<Remote<ServerAddr>>,
265268
T: Param<tls::ConditionalServerTls>,
269+
T: Param<HttpRoutePermit>,
266270
{
267-
fn from(permitted: &'a policy::Permitted<T>) -> Self {
268-
let target = permitted.target_ref();
269-
let permit = permitted.permit_ref();
271+
fn from(target: &'a T) -> Self {
272+
let permit: HttpRoutePermit = target.param();
270273

271274
let labels = [
272275
("srv", &permit.labels.route.server.0),
@@ -286,7 +289,7 @@ where
286289
Self {
287290
server: target.param(),
288291
tls: target.param(),
289-
permit: permit.clone(),
292+
permit,
290293
labels: labels.into(),
291294
}
292295
}

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

Lines changed: 29 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use crate::{policy::Permitted, InboundMetrics};
1+
use crate::{policy::PermitVariant, InboundMetrics};
22
use linkerd_app_core::{
33
metrics::{
44
prom::{
@@ -90,25 +90,30 @@ impl RequestCountFamilies {
9090
}
9191

9292
/// Fetches the proper request counting family, given a permitted target.
93-
fn family<T>(
93+
fn family(
9494
&self,
95-
permitted: &Permitted<T>,
95+
variant: PermitVariant,
9696
) -> &linkerd_http_prom::count_reqs::RequestCountFamilies<RequestCountLabels> {
9797
let Self { grpc, http } = self;
98-
match permitted {
99-
Permitted::Grpc { .. } => grpc,
100-
Permitted::Http { .. } => http,
98+
match variant {
99+
PermitVariant::Grpc => grpc,
100+
PermitVariant::Http => http,
101101
}
102102
}
103103
}
104104

105105
// === impl ExtractRequestCount ===
106106

107-
impl<T> svc::ExtractParam<RequestCount, Permitted<T>> for ExtractRequestCount {
108-
fn extract_param(&self, permitted: &Permitted<T>) -> RequestCount {
107+
impl<T> svc::ExtractParam<RequestCount, T> for ExtractRequestCount
108+
where
109+
T: svc::Param<PermitVariant> + svc::Param<RouteLabels>,
110+
{
111+
fn extract_param(&self, target: &T) -> RequestCount {
109112
let Self(families) = self;
110-
let family = families.family(permitted);
111-
let route = permitted.route_labels();
113+
let variant = target.param();
114+
let route = target.param();
115+
116+
let family = families.family(variant);
112117

113118
family.metrics(&RequestCountLabels { route })
114119
}
@@ -166,14 +171,14 @@ impl ResponseBodyFamilies {
166171
}
167172

168173
/// Fetches the proper body frame metrics family, given a permitted target.
169-
fn family<T>(
174+
fn family(
170175
&self,
171-
permitted: &Permitted<T>,
176+
variant: PermitVariant,
172177
) -> &linkerd_http_prom::body_data::response::ResponseBodyFamilies<ResponseBodyDataLabels> {
173178
let Self { grpc, http } = self;
174-
match permitted {
175-
Permitted::Grpc { .. } => grpc,
176-
Permitted::Http { .. } => http,
179+
match variant {
180+
PermitVariant::Grpc => grpc,
181+
PermitVariant::Http => http,
177182
}
178183
}
179184
}
@@ -213,11 +218,16 @@ impl EncodeLabelSet for ResponseBodyDataLabels {
213218

214219
// === impl ExtractRecordBodyDataMetrics ===
215220

216-
impl<T> svc::ExtractParam<BodyDataMetrics, Permitted<T>> for ExtractRecordBodyDataMetrics {
217-
fn extract_param(&self, permitted: &Permitted<T>) -> BodyDataMetrics {
221+
impl<T> svc::ExtractParam<BodyDataMetrics, T> for ExtractRecordBodyDataMetrics
222+
where
223+
T: svc::Param<PermitVariant> + svc::Param<RouteLabels>,
224+
{
225+
fn extract_param(&self, target: &T) -> BodyDataMetrics {
218226
let Self(families) = self;
219-
let family = families.family(permitted);
220-
let route = permitted.route_labels();
227+
let variant = target.param();
228+
let route = target.param();
229+
230+
let family = families.family(variant);
221231

222232
family.metrics(&ResponseBodyDataLabels { route })
223233
}

linkerd/app/inbound/src/policy.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ pub use self::{
1212
config::Config,
1313
http::{
1414
HttpInvalidPolicy, HttpRouteInvalidRedirect, HttpRouteNotFound, HttpRouteRedirect,
15-
HttpRouteUnauthorized, NewHttpPolicy, Permitted,
15+
HttpRouteUnauthorized, NewHttpPolicy, PermitVariant, Permitted,
1616
},
1717
tcp::NewTcpPolicy,
1818
};

linkerd/app/inbound/src/policy/http.rs

Lines changed: 68 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use futures::{future, TryFutureExt};
77
use linkerd_app_core::{
88
metrics::{RouteAuthzLabels, RouteLabels},
99
svc::{self, ServiceExt},
10-
tls,
11-
transport::{ClientAddr, OrigDstAddr, Remote},
10+
tls::{self, ConditionalServerTls},
11+
transport::{ClientAddr, OrigDstAddr, Remote, ServerAddr},
1212
Conditional, Error, Result,
1313
};
1414
use linkerd_proxy_server_policy::{grpc, http, route::RouteMatch};
@@ -48,9 +48,16 @@ struct ConnectionMeta {
4848

4949
/// A `T`-typed target with policy enforced by a [`NewHttpPolicy<N>`] layer.
5050
#[derive(Debug)]
51-
pub enum Permitted<T> {
52-
Grpc { permit: HttpRoutePermit, target: T },
53-
Http { permit: HttpRoutePermit, target: T },
51+
pub struct Permitted<T> {
52+
permit: HttpRoutePermit,
53+
protocol: PermitVariant,
54+
target: T,
55+
}
56+
57+
#[derive(Clone, Copy, Debug)]
58+
pub enum PermitVariant {
59+
Grpc,
60+
Http,
5461
}
5562

5663
#[derive(Debug, thiserror::Error)]
@@ -170,12 +177,20 @@ where
170177
Some(Routes::Http(routes)) => {
171178
let (permit, mtch, route) = try_fut!(self.authorize(&routes, &req));
172179
try_fut!(apply_http_filters(mtch, route, &mut req));
173-
Permitted::Http { permit, target }
180+
Permitted {
181+
permit,
182+
target,
183+
protocol: PermitVariant::Http,
184+
}
174185
}
175186
Some(Routes::Grpc(routes)) => {
176187
let (permit, _, route) = try_fut!(self.authorize(&routes, &req));
177188
try_fut!(apply_grpc_filters(route, &mut req));
178-
Permitted::Grpc { permit, target }
189+
Permitted {
190+
permit,
191+
target,
192+
protocol: PermitVariant::Grpc,
193+
}
179194
}
180195
};
181196

@@ -394,47 +409,72 @@ fn apply_grpc_filters<B>(route: &grpc::Policy, req: &mut ::http::Request<B>) ->
394409

395410
// === impl Permitted ===
396411

397-
/// An authorized `T`-typed target can produce `P`-typed parameters.
398-
impl<T, P> svc::Param<P> for Permitted<T>
412+
impl<T> svc::Param<Remote<ServerAddr>> for Permitted<T>
413+
where
414+
T: svc::Param<Remote<ServerAddr>>,
415+
{
416+
fn param(&self) -> Remote<ServerAddr> {
417+
self.target.param()
418+
}
419+
}
420+
421+
impl<T> svc::Param<ConditionalServerTls> for Permitted<T>
399422
where
400-
T: svc::Param<P>,
423+
T: svc::Param<ConditionalServerTls>,
401424
{
402-
fn param(&self) -> P {
403-
self.target_ref().param()
425+
fn param(&self) -> ConditionalServerTls {
426+
self.target.param()
427+
}
428+
}
429+
430+
impl<T> svc::Param<HttpRoutePermit> for Permitted<T> {
431+
fn param(&self) -> HttpRoutePermit {
432+
self.permit_ref().clone()
433+
}
434+
}
435+
436+
impl<T> svc::Param<PermitVariant> for Permitted<T> {
437+
fn param(&self) -> PermitVariant {
438+
self.variant()
439+
}
440+
}
441+
442+
impl<T> svc::Param<RouteLabels> for Permitted<T> {
443+
fn param(&self) -> RouteLabels {
444+
self.route_labels()
404445
}
405446
}
406447

407448
impl<T> Permitted<T> {
408449
/// Returns a reference to the [`HttpRoutePermit`] authorizing this `T`.
409450
pub fn permit_ref(&self) -> &HttpRoutePermit {
410-
match self {
411-
Self::Grpc { permit, .. } => permit,
412-
Self::Http { permit, .. } => permit,
413-
}
451+
&self.permit
452+
}
453+
454+
/// Returns the [`PermitVariant`] of the permitting policy.
455+
pub fn variant(&self) -> PermitVariant {
456+
self.protocol
414457
}
415458

416459
/// Returns a reference to the underlying `T`-typed target.
417460
pub fn target_ref(&self) -> &T {
418-
match self {
419-
Self::Grpc { target, .. } => target,
420-
Self::Http { target, .. } => target,
421-
}
461+
&self.target
422462
}
423463

424464
/// Consumes this permitted `T`, returning the inner `T`.
425465
pub fn into_target(self) -> T {
426-
match self {
427-
Self::Grpc { target, .. } => target,
428-
Self::Http { target, .. } => target,
429-
}
466+
self.target
430467
}
431468

432469
/// Consumes this permitted `T`, returning the `T` and its permit.
433470
pub fn into_parts(self) -> (T, HttpRoutePermit) {
434-
match self {
435-
Self::Grpc { target, permit } => (target, permit),
436-
Self::Http { target, permit } => (target, permit),
437-
}
471+
let Self {
472+
permit,
473+
protocol: _,
474+
target,
475+
} = self;
476+
477+
(target, permit)
438478
}
439479

440480
/// Returns the [`RouteLabels`] from the underlying permit.

0 commit comments

Comments
 (0)