Skip to content

Commit 0d0c5e7

Browse files
authored
metrics: factor out NewService for target-scoped metrics (#1117)
While working on adding a target port label to the TLS detection failure metrics added in #1114, I realized that there was some boilerplate code for scoping metrics based on a label from a target that was basically repeated between `linkerd-http-metrics` and `linkerd-transport`'s `metrics` module, and that this boilerplate code would have to be rewritten a third time for adding target port labels to the TLS detection metrics. Instead of rewriting this code a third time, I factored it out into a `NewMetrics` type in the `linkerd-metrics` crate, which given a registry of scopes, a `NewService`, and a metrics service type that can be constructed from the `NewService`'s service and the registry's metrics, implements `NewService` by wrapping the inner service with a metrics service scoped for the target's labels. The `linkerd-http-metrics` crate's `NewHttpMetrics` and the `linkerd-transport` crate's `metrics::MakeAccept` can both be replaced with the new `NewMetrics` type. Signed-off-by: Eliza Weisman <[email protected]>
1 parent eb38172 commit 0d0c5e7

File tree

18 files changed

+164
-153
lines changed

18 files changed

+164
-153
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,6 +1035,7 @@ dependencies = [
10351035
"hdrhistogram",
10361036
"http",
10371037
"hyper",
1038+
"linkerd-stack",
10381039
"parking_lot",
10391040
"quickcheck",
10401041
"tokio",

linkerd/app/admin/src/stack.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ impl Config {
6262
let (ready, latch) = crate::server::Readiness::new();
6363
let admin = crate::server::Admin::new(report, ready, shutdown, trace);
6464
let admin = svc::stack(admin)
65-
.push(metrics.http_endpoint.to_layer::<classify::Response, _>())
65+
.push(metrics.http_endpoint.to_layer::<classify::Response, _, Target>())
6666
.push_on_response(
6767
svc::layers()
6868
.push(metrics.http_errors.clone())

linkerd/app/core/src/control.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl Config {
9393
.push(self::resolve::layer(dns, resolve_backoff))
9494
.push_on_response(self::control::balance::layer())
9595
.into_new_service()
96-
.push(metrics.to_layer::<classify::Response, _>())
96+
.push(metrics.to_layer::<classify::Response, _, _>())
9797
.push(self::add_origin::layer())
9898
.push_on_response(svc::layers().push_spawn_buffer(self.buffer_capacity))
9999
.push_map_target(move |()| addr.clone())

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

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -149,7 +149,11 @@ where
149149
// Registers the stack to be tapped.
150150
.push(tap::NewTapHttp::layer(rt.tap.clone()))
151151
// Records metrics for each `Target`.
152-
.push(rt.metrics.http_endpoint.to_layer::<classify::Response, _>())
152+
.push(
153+
rt.metrics
154+
.http_endpoint
155+
.to_layer::<classify::Response, _, _>(),
156+
)
153157
.push_on_response(http_tracing::client(rt.span_sink.clone(), trace_labels()))
154158
.push_on_response(http::BoxResponse::layer())
155159
.check_new_service::<Target, http::Request<_>>();
@@ -174,7 +178,11 @@ where
174178
// by tap.
175179
.push_http_insert_target::<dst::Route>()
176180
// Records per-route metrics.
177-
.push(rt.metrics.http_route.to_layer::<classify::Response, _>())
181+
.push(
182+
rt.metrics
183+
.http_route
184+
.to_layer::<classify::Response, _, dst::Route>(),
185+
)
178186
// Sets the per-route response classifier as a request
179187
// extension.
180188
.push(classify::NewClassify::layer())

linkerd/app/outbound/src/http/endpoint.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,11 @@ impl<C> Outbound<C> {
4545
.into_new_service()
4646
.push_new_reconnect(backoff)
4747
.push(tap::NewTapHttp::layer(rt.tap.clone()))
48-
.push(rt.metrics.http_endpoint.to_layer::<classify::Response, _>())
48+
.push(
49+
rt.metrics
50+
.http_endpoint
51+
.to_layer::<classify::Response, _, _>(),
52+
)
4953
.push_on_response(http_tracing::client(
5054
rt.span_sink.clone(),
5155
crate::trace_labels(),

linkerd/app/outbound/src/http/logical.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::{CanonicalDstHeader, Concrete, Endpoint, Logical};
22
use crate::{endpoint, resolve, stack_labels, Outbound};
33
use linkerd_app_core::{
4-
classify, config, profiles,
4+
classify, config, dst, profiles,
55
proxy::{
66
api_resolve::{ConcreteAddr, Metadata},
77
core::Resolve,
@@ -118,7 +118,7 @@ impl<E> Outbound<E> {
118118
.push(
119119
rt.metrics
120120
.http_route_actual
121-
.to_layer::<classify::Response, _>(),
121+
.to_layer::<classify::Response, _, dst::Route>(),
122122
)
123123
// Depending on whether or not the request can be retried,
124124
// it may have one of two `Body` types. This layer unifies
@@ -131,7 +131,7 @@ impl<E> Outbound<E> {
131131
// Sets an optional request timeout.
132132
.push(http::MakeTimeoutLayer::default())
133133
// Records per-route metrics.
134-
.push(rt.metrics.http_route.to_layer::<classify::Response, _>())
134+
.push(rt.metrics.http_route.to_layer::<classify::Response, _, _>())
135135
// Sets the per-route response classifier as a request
136136
// extension.
137137
.push(classify::NewClassify::layer())

linkerd/http-metrics/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ http-body = "0.4"
1414
hyper = { version = "0.14.10", features = ["http1", "http2"] }
1515
linkerd-error = { path = "../error" }
1616
linkerd-http-classify = { path = "../http-classify" }
17-
linkerd-metrics = { path = "../metrics" }
17+
linkerd-metrics = { path = "../metrics", features = ["linkerd-stack"] }
1818
linkerd-stack = { path = "../stack" }
1919
parking_lot = "0.11"
2020
pin-project = "1"

linkerd/http-metrics/src/lib.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@
33
#![allow(clippy::inconsistent_struct_constructor)]
44

55
pub use self::{requests::Requests, retries::Retries};
6-
use linkerd_metrics::{LastUpdate, Store};
6+
use linkerd_metrics::SharedStore;
77
use parking_lot::Mutex;
8-
use std::{fmt, hash::Hash, sync::Arc, time::Duration};
8+
use std::{fmt, hash::Hash, time::Duration};
99

1010
pub mod requests;
1111
pub mod retries;
1212

13-
type Registry<T, M> = Store<T, Mutex<M>>;
13+
type Registry<T, M> = SharedStore<T, Mutex<M>>;
1414

1515
/// Reports metrics for prometheus.
1616
#[derive(Debug)]
@@ -19,7 +19,7 @@ where
1919
T: Hash + Eq,
2020
{
2121
prefix: &'static str,
22-
registry: Arc<Mutex<Registry<T, M>>>,
22+
registry: Registry<T, M>,
2323
/// The amount of time metrics with no updates should be retained for reports
2424
retain_idle: Duration,
2525
/// Whether latencies should be reported.
@@ -46,7 +46,7 @@ impl<T, M> Report<T, M>
4646
where
4747
T: Hash + Eq,
4848
{
49-
fn new(retain_idle: Duration, registry: Arc<Mutex<Registry<T, M>>>) -> Self {
49+
fn new(retain_idle: Duration, registry: Registry<T, M>) -> Self {
5050
Self {
5151
prefix: "",
5252
registry,

linkerd/http-metrics/src/requests/mod.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,22 @@
11
mod report;
22
mod service;
33

4-
use super::{LastUpdate, Registry, Report};
4+
pub use self::service::{NewHttpMetrics, ResponseBody};
5+
use super::Report;
56
use linkerd_http_classify::ClassifyResponse;
6-
use linkerd_metrics::{latency, Counter, FmtMetrics, Histogram};
7-
use linkerd_stack::layer;
8-
use parking_lot::Mutex;
7+
use linkerd_metrics::{latency, Counter, FmtMetrics, Histogram, LastUpdate, NewMetrics};
8+
use linkerd_stack::{self as svc, layer};
99
use std::{
1010
collections::HashMap,
1111
fmt::Debug,
1212
hash::Hash,
13-
sync::Arc,
1413
time::{Duration, Instant},
1514
};
1615

17-
pub use self::service::{NewHttpMetrics, ResponseBody};
18-
19-
type SharedRegistry<T, C> = Arc<Mutex<Registry<T, Metrics<C>>>>;
16+
type Registry<T, C> = super::Registry<T, Metrics<C>>;
2017

2118
#[derive(Debug)]
22-
pub struct Requests<T, C>(SharedRegistry<T, C>)
19+
pub struct Requests<T, C>(Registry<T, C>)
2320
where
2421
T: Hash + Eq,
2522
C: Hash + Eq;
@@ -52,7 +49,7 @@ pub struct ClassMetrics {
5249

5350
impl<T: Hash + Eq, C: Hash + Eq> Default for Requests<T, C> {
5451
fn default() -> Self {
55-
Requests(Arc::new(Mutex::new(Registry::default())))
52+
Requests(Registry::default())
5653
}
5754
}
5855

@@ -64,12 +61,15 @@ impl<T: Hash + Eq, C: Hash + Eq> Requests<T, C> {
6461
Report::new(retain_idle, self.0)
6562
}
6663

67-
pub fn to_layer<L, N>(&self) -> impl layer::Layer<N, Service = NewHttpMetrics<N, T, L>> + Clone
64+
pub fn to_layer<L, N, Tgt>(
65+
&self,
66+
) -> impl layer::Layer<N, Service = NewHttpMetrics<N, T, L, C, N::Service>> + Clone
6867
where
6968
L: ClassifyResponse<Class = C> + Send + Sync + 'static,
69+
N: svc::NewService<Tgt>,
7070
{
7171
let reg = self.0.clone();
72-
layer::mk(move |inner| NewHttpMetrics::new(reg.clone(), inner))
72+
NewMetrics::layer(reg)
7373
}
7474
}
7575

linkerd/http-metrics/src/requests/report.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
use super::{ClassMetrics, Metrics, StatusMetrics};
2-
use crate::{Prefixed, Registry, Report};
3-
use linkerd_metrics::{latency, Counter, FmtLabels, FmtMetric, FmtMetrics, Histogram, Metric};
2+
use crate::{Prefixed, Report};
3+
use linkerd_metrics::{
4+
latency, Counter, FmtLabels, FmtMetric, FmtMetrics, Histogram, Metric, Store,
5+
};
6+
use parking_lot::Mutex;
47
use std::{fmt, hash::Hash, time::Instant};
58
use tracing::trace;
69

@@ -43,7 +46,7 @@ where
4346
C: FmtLabels + Hash + Eq,
4447
{
4548
fn fmt_by_target<N, M>(
46-
registry: &Registry<T, Metrics<C>>,
49+
registry: &Store<T, Mutex<Metrics<C>>>,
4750
f: &mut fmt::Formatter<'_>,
4851
metric: Metric<'_, N, M>,
4952
get_metric: impl Fn(&Metrics<C>) -> &M,
@@ -56,7 +59,7 @@ where
5659
}
5760

5861
fn fmt_by_status<N, M>(
59-
registry: &Registry<T, Metrics<C>>,
62+
registry: &Store<T, Mutex<Metrics<C>>>,
6063
f: &mut fmt::Formatter<'_>,
6164
metric: Metric<'_, N, M>,
6265
get_metric: impl Fn(&StatusMetrics<C>) -> &M,
@@ -78,7 +81,7 @@ where
7881
}
7982

8083
fn fmt_by_class<N, M>(
81-
registry: &Registry<T, Metrics<C>>,
84+
registry: &Store<T, Mutex<Metrics<C>>>,
8285
f: &mut fmt::Formatter<'_>,
8386
metric: Metric<'_, N, M>,
8487
get_metric: impl Fn(&ClassMetrics) -> &M,

0 commit comments

Comments
 (0)