Skip to content

Commit 65db3dd

Browse files
authored
feat(policy): Allow outbound hostname metrics (#3770)
Outbound hostname metrics were recently disabled. This conditionally re-enables those through a `LINKERD2_PROXY_OUTBOUND_METRICS_HOSTNAME_LABELS` env var, wired through the policy/routing config with the option of individual policies and routes to set this separately from the global config. Signed-off-by: Scott Fleener <scott@buoyant.io>
1 parent 123d7a3 commit 65db3dd

File tree

8 files changed

+100
-62
lines changed

8 files changed

+100
-62
lines changed

linkerd/app/outbound/src/lib.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66
#![allow(opaque_hidden_inferred_bound)]
77
#![forbid(unsafe_code)]
88

9-
use linkerd_app_core::http_tracing::SpanSink;
109
use linkerd_app_core::{
1110
config::{ProxyConfig, QueueConfig},
1211
drain,
1312
exp_backoff::ExponentialBackoff,
13+
http_tracing::SpanSink,
1414
identity, io,
1515
metrics::prom,
1616
profiles,
@@ -143,6 +143,7 @@ impl Outbound<()> {
143143
client: C,
144144
backoff: ExponentialBackoff,
145145
limits: ReceiveLimits,
146+
export_hostname_labels: bool,
146147
) -> impl policy::GetPolicy
147148
where
148149
C: tonic::client::GrpcService<tonic::body::BoxBody, Error = Error>,
@@ -151,12 +152,18 @@ impl Outbound<()> {
151152
C::ResponseBody: Send + 'static,
152153
C::Future: Send,
153154
{
154-
policy::Api::new(workload, limits, Duration::from_secs(10), client)
155-
.into_watch(backoff)
156-
.map_result(|response| match response {
157-
Err(e) => Err(e.into()),
158-
Ok(rsp) => Ok(rsp.into_inner()),
159-
})
155+
policy::Api::new(
156+
workload,
157+
limits,
158+
Duration::from_secs(10),
159+
export_hostname_labels,
160+
client,
161+
)
162+
.into_watch(backoff)
163+
.map_result(|res| match res {
164+
Err(e) => Err(e.into()),
165+
Ok(rsp) => Ok(rsp.into_inner()),
166+
})
160167
}
161168

162169
#[cfg(any(test, feature = "test-util"))]

linkerd/app/outbound/src/policy/api.rs

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use linkerd_app_core::{
88
svc::Service,
99
Addr, Error, Recover, Result,
1010
};
11-
use linkerd_proxy_client_policy::ClientPolicy;
11+
use linkerd_proxy_client_policy::{ClientPolicy, ClientPolicyOverrides};
1212
use linkerd_tonic_stream::{LimitReceiveFuture, ReceiveLimits};
1313
use linkerd_tonic_watch::StreamWatch;
1414
use std::sync::Arc;
@@ -19,6 +19,7 @@ pub(crate) struct Api<S> {
1919
workload: Arc<str>,
2020
limits: ReceiveLimits,
2121
default_detect_timeout: time::Duration,
22+
export_hostname_labels: bool,
2223
client: Client<S>,
2324
}
2425

@@ -39,12 +40,14 @@ where
3940
workload: Arc<str>,
4041
limits: ReceiveLimits,
4142
default_detect_timeout: time::Duration,
43+
export_hostname_labels: bool,
4244
client: S,
4345
) -> Self {
4446
Self {
4547
workload,
4648
limits,
4749
default_detect_timeout,
50+
export_hostname_labels,
4851
client: Client::new(client),
4952
}
5053
}
@@ -86,6 +89,9 @@ where
8689
};
8790

8891
let detect_timeout = self.default_detect_timeout;
92+
let overrides = ClientPolicyOverrides {
93+
export_hostname_labels: self.export_hostname_labels,
94+
};
8995
let limits = self.limits;
9096
let mut client = self.client.clone();
9197
Box::pin(async move {
@@ -96,7 +102,7 @@ where
96102
// If the server returned an invalid client policy, we
97103
// default to using an invalid policy that causes all
98104
// requests to report an internal error.
99-
let policy = ClientPolicy::try_from(up).unwrap_or_else(|error| {
105+
let policy = ClientPolicy::try_from(overrides, up).unwrap_or_else(|error| {
100106
tracing::warn!(%error, "Client policy misconfigured");
101107
INVALID_POLICY
102108
.get_or_init(|| ClientPolicy::invalid(detect_timeout))

linkerd/app/src/env.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,9 @@ pub const ENV_OUTBOUND_MAX_IN_FLIGHT: &str = "LINKERD2_PROXY_OUTBOUND_MAX_IN_FLI
146146
const ENV_OUTBOUND_DISABLE_INFORMATIONAL_HEADERS: &str =
147147
"LINKERD2_PROXY_OUTBOUND_DISABLE_INFORMATIONAL_HEADERS";
148148

149+
const ENV_OUTBOUND_METRICS_HOSTNAME_LABELS: &str =
150+
"LINKERD2_PROXY_OUTBOUND_METRICS_HOSTNAME_LABELS";
151+
149152
const ENV_TRACE_ATTRIBUTES_PATH: &str = "LINKERD2_PROXY_TRACE_ATTRIBUTES_PATH";
150153
const ENV_TRACE_PROTOCOL: &str = "LINKERD2_PROXY_TRACE_PROTOCOL";
151154
const ENV_TRACE_SERVICE_NAME: &str = "LINKERD2_PROXY_TRACE_SERVICE_NAME";
@@ -791,11 +794,14 @@ pub fn parse_config<S: Strings>(strings: &S) -> Result<super::Config, EnvError>
791794
},
792795
}
793796
};
797+
let export_hostname_labels =
798+
parse(strings, ENV_OUTBOUND_METRICS_HOSTNAME_LABELS, parse_bool)?.unwrap_or(false);
794799

795800
policy::Config {
796801
control,
797802
workload,
798803
limits,
804+
export_hostname_labels,
799805
}
800806
};
801807

linkerd/app/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ impl Config {
174174
}?;
175175

176176
debug!("Building Policy client");
177+
let export_hostname_labels = policy.export_hostname_labels;
177178
let policies = {
178179
let control_metrics =
179180
ControlMetrics::register(registry.sub_registry_with_prefix("control_policy"));
@@ -243,6 +244,7 @@ impl Config {
243244
policies.client.clone(),
244245
policies.backoff,
245246
policies.limits,
247+
export_hostname_labels,
246248
);
247249

248250
let dst_addr = dst.addr.clone();

linkerd/app/src/policy.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ pub struct Config {
1515
pub control: control::Config,
1616
pub workload: String,
1717
pub limits: ReceiveLimits,
18+
pub export_hostname_labels: bool,
1819
}
1920

2021
/// Handles to policy service clients.

linkerd/proxy/client-policy/src/grpc.rs

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ pub mod proto {
105105
proto::{
106106
BackendSet, InvalidBackend, InvalidDistribution, InvalidFailureAccrual, InvalidMeta,
107107
},
108-
Meta, RouteBackend, RouteDistribution,
108+
ClientPolicyOverrides, Meta, RouteBackend, RouteDistribution,
109109
};
110110
use linkerd2_proxy_api::outbound::{self, grpc_route};
111111
use linkerd_http_route::{
@@ -184,22 +184,22 @@ pub mod proto {
184184
Redirect(#[from] InvalidRequestRedirect),
185185
}
186186

187-
impl TryFrom<outbound::proxy_protocol::Grpc> for Grpc {
188-
type Error = InvalidGrpcRoute;
189-
fn try_from(proto: outbound::proxy_protocol::Grpc) -> Result<Self, Self::Error> {
187+
impl Grpc {
188+
pub fn try_from(
189+
overrides: ClientPolicyOverrides,
190+
proto: outbound::proxy_protocol::Grpc,
191+
) -> Result<Self, InvalidGrpcRoute> {
190192
let routes = proto
191193
.routes
192194
.into_iter()
193-
.map(try_route)
195+
.map(|p| try_route(overrides, p))
194196
.collect::<Result<Arc<[_]>, _>>()?;
195197
Ok(Self {
196198
routes,
197199
failure_accrual: proto.failure_accrual.try_into()?,
198200
})
199201
}
200-
}
201202

202-
impl Grpc {
203203
pub fn fill_backends(&self, set: &mut BackendSet) {
204204
for Route { ref rules, .. } in &*self.routes {
205205
for Rule { ref policy, .. } in rules {
@@ -209,7 +209,10 @@ pub mod proto {
209209
}
210210
}
211211

212-
fn try_route(proto: outbound::GrpcRoute) -> Result<Route, InvalidGrpcRoute> {
212+
fn try_route(
213+
overrides: ClientPolicyOverrides,
214+
proto: outbound::GrpcRoute,
215+
) -> Result<Route, InvalidGrpcRoute> {
213216
let outbound::GrpcRoute {
214217
hosts,
215218
rules,
@@ -227,14 +230,15 @@ pub mod proto {
227230

228231
let rules = rules
229232
.into_iter()
230-
.map(|rule| try_rule(&meta, rule))
233+
.map(|rule| try_rule(&meta, overrides, rule))
231234
.collect::<Result<Vec<_>, _>>()?;
232235

233236
Ok(Route { hosts, rules })
234237
}
235238

236239
fn try_rule(
237240
meta: &Arc<Meta>,
241+
overrides: ClientPolicyOverrides,
238242
proto: outbound::grpc_route::Rule,
239243
) -> Result<Rule, InvalidGrpcRoute> {
240244
#[allow(deprecated)]
@@ -262,13 +266,8 @@ pub mod proto {
262266
.ok_or(InvalidGrpcRoute::Missing("distribution"))?
263267
.try_into()?;
264268

265-
let export_hostname_labels = false;
266-
let mut params = RouteParams::try_from_proto(
267-
timeouts,
268-
retry,
269-
allow_l5d_request_headers,
270-
export_hostname_labels,
271-
)?;
269+
let mut params =
270+
RouteParams::try_from_proto(timeouts, retry, allow_l5d_request_headers, overrides)?;
272271
let legacy = request_timeout.map(TryInto::try_into).transpose()?;
273272
params.timeouts.request = params.timeouts.request.or(legacy);
274273

@@ -288,7 +287,7 @@ pub mod proto {
288287
timeouts: Option<linkerd2_proxy_api::http_route::Timeouts>,
289288
retry: Option<grpc_route::Retry>,
290289
allow_l5d_request_headers: bool,
291-
export_hostname_labels: bool,
290+
overrides: ClientPolicyOverrides,
292291
) -> Result<Self, InvalidGrpcRoute> {
293292
Ok(Self {
294293
retry: retry.map(Retry::try_from).transpose()?,
@@ -297,7 +296,7 @@ pub mod proto {
297296
.transpose()?
298297
.unwrap_or_default(),
299298
allow_l5d_request_headers,
300-
export_hostname_labels,
299+
export_hostname_labels: overrides.export_hostname_labels,
301300
})
302301
}
303302
}

linkerd/proxy/client-policy/src/http.rs

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub mod proto {
125125
proto::{
126126
BackendSet, InvalidBackend, InvalidDistribution, InvalidFailureAccrual, InvalidMeta,
127127
},
128-
Meta, RouteBackend, RouteDistribution,
128+
ClientPolicyOverrides, Meta, RouteBackend, RouteDistribution,
129129
};
130130
use linkerd2_proxy_api::outbound::{self, http_route};
131131
use linkerd_http_route::http::{
@@ -217,13 +217,15 @@ pub mod proto {
217217
}
218218
}
219219

220-
impl TryFrom<outbound::proxy_protocol::Http1> for Http1 {
221-
type Error = InvalidHttpRoute;
222-
fn try_from(proto: outbound::proxy_protocol::Http1) -> Result<Self, Self::Error> {
220+
impl Http1 {
221+
pub fn try_from(
222+
overrides: ClientPolicyOverrides,
223+
proto: outbound::proxy_protocol::Http1,
224+
) -> Result<Self, InvalidHttpRoute> {
223225
let routes = proto
224226
.routes
225227
.into_iter()
226-
.map(try_route)
228+
.map(|p| try_route(overrides, p))
227229
.collect::<Result<Arc<[_]>, _>>()?;
228230
Ok(Self {
229231
routes,
@@ -232,13 +234,15 @@ pub mod proto {
232234
}
233235
}
234236

235-
impl TryFrom<outbound::proxy_protocol::Http2> for Http2 {
236-
type Error = InvalidHttpRoute;
237-
fn try_from(proto: outbound::proxy_protocol::Http2) -> Result<Self, Self::Error> {
237+
impl Http2 {
238+
pub fn try_from(
239+
overrides: ClientPolicyOverrides,
240+
proto: outbound::proxy_protocol::Http2,
241+
) -> Result<Self, InvalidHttpRoute> {
238242
let routes = proto
239243
.routes
240244
.into_iter()
241-
.map(try_route)
245+
.map(|p| try_route(overrides, p))
242246
.collect::<Result<Arc<[_]>, _>>()?;
243247
Ok(Self {
244248
routes,
@@ -247,7 +251,10 @@ pub mod proto {
247251
}
248252
}
249253

250-
fn try_route(proto: outbound::HttpRoute) -> Result<Route, InvalidHttpRoute> {
254+
fn try_route(
255+
overrides: ClientPolicyOverrides,
256+
proto: outbound::HttpRoute,
257+
) -> Result<Route, InvalidHttpRoute> {
251258
let outbound::HttpRoute {
252259
hosts,
253260
rules,
@@ -265,14 +272,15 @@ pub mod proto {
265272

266273
let rules = rules
267274
.into_iter()
268-
.map(|rule| try_rule(&meta, rule))
275+
.map(|rule| try_rule(&meta, overrides, rule))
269276
.collect::<Result<Vec<_>, _>>()?;
270277

271278
Ok(Route { hosts, rules })
272279
}
273280

274281
fn try_rule(
275282
meta: &Arc<Meta>,
283+
overrides: ClientPolicyOverrides,
276284
proto: outbound::http_route::Rule,
277285
) -> Result<Rule, InvalidHttpRoute> {
278286
#[allow(deprecated)]
@@ -300,13 +308,8 @@ pub mod proto {
300308
.ok_or(InvalidHttpRoute::Missing("distribution"))?
301309
.try_into()?;
302310

303-
let export_hostname_labels = false;
304-
let mut params = RouteParams::try_from_proto(
305-
timeouts,
306-
retry,
307-
allow_l5d_request_headers,
308-
export_hostname_labels,
309-
)?;
311+
let mut params =
312+
RouteParams::try_from_proto(timeouts, retry, allow_l5d_request_headers, overrides)?;
310313
let legacy = request_timeout.map(TryInto::try_into).transpose()?;
311314
params.timeouts.request = params.timeouts.request.or(legacy);
312315

@@ -326,7 +329,7 @@ pub mod proto {
326329
timeouts: Option<linkerd2_proxy_api::http_route::Timeouts>,
327330
retry: Option<http_route::Retry>,
328331
allow_l5d_request_headers: bool,
329-
export_hostname_labels: bool,
332+
overrides: ClientPolicyOverrides,
330333
) -> Result<Self, InvalidHttpRoute> {
331334
Ok(Self {
332335
retry: retry.map(Retry::try_from).transpose()?,
@@ -335,7 +338,7 @@ pub mod proto {
335338
.transpose()?
336339
.unwrap_or_default(),
337340
allow_l5d_request_headers,
338-
export_hostname_labels,
341+
export_hostname_labels: overrides.export_hostname_labels,
339342
})
340343
}
341344
}

0 commit comments

Comments
 (0)