Skip to content

Commit ee3fa14

Browse files
authored
metrics: Support the Summary metric type (#756)
Prometheus supports two distribution types: histogram and summary. Histograms track values over a set of fixed buckets. Summaries, on the other hand, track fixed quantiles over a sliding time window. This change introduces a Summary metric type that is backed by a ring buffer of hdrhistograms. These histograms may either auto-resize or have a fixed upper bound. The histograms are "rotated" so that old values expire after a maximum lifetime.
1 parent c44027a commit ee3fa14

File tree

6 files changed

+505
-22
lines changed

6 files changed

+505
-22
lines changed

Cargo.lock

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ version = "0.4.7"
5454
source = "registry+https://github.com/rust-lang/crates.io-index"
5555
checksum = "4d25d88fd6b8041580a654f9d0c581a047baee2b3efee13275f2fc392fc75034"
5656

57+
[[package]]
58+
name = "arrayvec"
59+
version = "0.5.2"
60+
source = "registry+https://github.com/rust-lang/crates.io-index"
61+
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
62+
5763
[[package]]
5864
name = "async-stream"
5965
version = "0.2.1"
@@ -240,6 +246,16 @@ dependencies = [
240246
"build_const",
241247
]
242248

249+
[[package]]
250+
name = "crossbeam-channel"
251+
version = "0.4.4"
252+
source = "registry+https://github.com/rust-lang/crates.io-index"
253+
checksum = "b153fe7cbef478c567df0f972e02e6d736db11affe43dfc9c56a9374d1adfb87"
254+
dependencies = [
255+
"crossbeam-utils",
256+
"maybe-uninit",
257+
]
258+
243259
[[package]]
244260
name = "crossbeam-utils"
245261
version = "0.7.2"
@@ -308,6 +324,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
308324
checksum = "9fac2277e84e5e858483756647a9d0aa8d9a2b7cba517fd84325a0aaa69a0909"
309325
dependencies = [
310326
"libc",
327+
"miniz-sys",
311328
"miniz_oxide_c_api",
312329
]
313330

@@ -518,6 +535,20 @@ dependencies = [
518535
"tracing",
519536
]
520537

538+
[[package]]
539+
name = "hdrhistogram"
540+
version = "7.1.0"
541+
source = "registry+https://github.com/rust-lang/crates.io-index"
542+
checksum = "b3c22708574c44e924720c5b3a116326c688e6d532f438c77c007ec8768644f9"
543+
dependencies = [
544+
"base64 0.12.3",
545+
"byteorder",
546+
"crossbeam-channel",
547+
"flate2",
548+
"nom 5.1.2",
549+
"num-traits 0.2.6",
550+
]
551+
521552
[[package]]
522553
name = "heck"
523554
version = "0.3.0"
@@ -736,6 +767,19 @@ version = "1.4.0"
736767
source = "registry+https://github.com/rust-lang/crates.io-index"
737768
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
738769

770+
[[package]]
771+
name = "lexical-core"
772+
version = "0.7.4"
773+
source = "registry+https://github.com/rust-lang/crates.io-index"
774+
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
775+
dependencies = [
776+
"arrayvec",
777+
"bitflags",
778+
"cfg-if 0.1.10",
779+
"ryu",
780+
"static_assertions",
781+
]
782+
739783
[[package]]
740784
name = "libc"
741785
version = "0.2.76"
@@ -1160,10 +1204,13 @@ version = "0.1.0"
11601204
dependencies = [
11611205
"deflate",
11621206
"futures 0.3.5",
1207+
"hdrhistogram",
11631208
"http 0.2.1",
11641209
"hyper",
11651210
"indexmap",
1211+
"parking_lot",
11661212
"quickcheck",
1213+
"tokio",
11671214
"tracing",
11681215
]
11691216

@@ -1609,6 +1656,12 @@ version = "0.1.6"
16091656
source = "registry+https://github.com/rust-lang/crates.io-index"
16101657
checksum = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376"
16111658

1659+
[[package]]
1660+
name = "maybe-uninit"
1661+
version = "2.0.0"
1662+
source = "registry+https://github.com/rust-lang/crates.io-index"
1663+
checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00"
1664+
16121665
[[package]]
16131666
name = "memchr"
16141667
version = "0.1.11"
@@ -1633,6 +1686,16 @@ dependencies = [
16331686
"libmimalloc-sys",
16341687
]
16351688

1689+
[[package]]
1690+
name = "miniz-sys"
1691+
version = "0.1.12"
1692+
source = "registry+https://github.com/rust-lang/crates.io-index"
1693+
checksum = "1e9e3ae51cea1576ceba0dde3d484d30e6e5b86dee0b2d412fe3a16a15c98202"
1694+
dependencies = [
1695+
"cc",
1696+
"libc",
1697+
]
1698+
16361699
[[package]]
16371700
name = "miniz_oxide"
16381701
version = "0.1.2"
@@ -1742,6 +1805,17 @@ version = "2.2.1"
17421805
source = "registry+https://github.com/rust-lang/crates.io-index"
17431806
checksum = "cf51a729ecf40266a2368ad335a5fdde43471f545a967109cd62146ecf8b66ff"
17441807

1808+
[[package]]
1809+
name = "nom"
1810+
version = "5.1.2"
1811+
source = "registry+https://github.com/rust-lang/crates.io-index"
1812+
checksum = "ffb4262d26ed83a1c0a33a38fe2bb15797329c85770da05e6b828ddb782627af"
1813+
dependencies = [
1814+
"lexical-core",
1815+
"memchr 2.3.3",
1816+
"version_check",
1817+
]
1818+
17451819
[[package]]
17461820
name = "num-integer"
17471821
version = "0.1.39"
@@ -1908,7 +1982,7 @@ checksum = "6ab1427f3d2635891f842892dda177883dca0639e05fe66796a62c9d2f23b49c"
19081982
dependencies = [
19091983
"byteorder",
19101984
"libc",
1911-
"nom",
1985+
"nom 2.2.1",
19121986
"rustc_version",
19131987
]
19141988

@@ -2394,6 +2468,12 @@ version = "0.5.2"
23942468
source = "registry+https://github.com/rust-lang/crates.io-index"
23952469
checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d"
23962470

2471+
[[package]]
2472+
name = "static_assertions"
2473+
version = "1.1.0"
2474+
source = "registry+https://github.com/rust-lang/crates.io-index"
2475+
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
2476+
23972477
[[package]]
23982478
name = "string"
23992479
version = "0.2.0"
@@ -2913,6 +2993,12 @@ version = "0.1.3"
29132993
source = "registry+https://github.com/rust-lang/crates.io-index"
29142994
checksum = "6f2c54fe5e8d6907c60dc6fba532cc8529245d97ff4e26cb490cb462de114ba4"
29152995

2996+
[[package]]
2997+
name = "version_check"
2998+
version = "0.9.2"
2999+
source = "registry+https://github.com/rust-lang/crates.io-index"
3000+
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
3001+
29163002
[[package]]
29173003
name = "want"
29183004
version = "0.3.0"

linkerd/metrics/Cargo.toml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,20 @@ publish = false
77

88
[features]
99
default = []
10+
summary = ["hdrhistogram", "parking_lot", "tokio"]
1011
test_util = []
1112

1213
[dependencies]
1314
deflate = { version = "0.7.18", features = ["gzip"] }
1415
futures = "0.3"
16+
hdrhistogram = { version = "7.1", optional = true }
1517
http = "0.2"
1618
hyper = "0.13.7"
1719
indexmap = "1.0"
20+
parking_lot = { version = "0.11", optional = true }
21+
tokio = { version = "0.2", features = ["time"], optional = true }
1822
tracing = "0.1.2"
1923

2024
[dev-dependencies]
2125
quickcheck = { version = "0.9", default-features = false }
26+
tokio = { version = "0.2", features = ["macros", "test-util", "time"] }

linkerd/metrics/src/histogram.rs

Lines changed: 11 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ pub enum Bucket {
4545
#[derive(Debug)]
4646
pub struct Bounds(pub &'static [Bucket]);
4747

48-
/// Helper that lazily formats metric keys as {0}_{1}.
49-
struct Key<A: fmt::Display, B: fmt::Display>(A, B);
50-
5148
/// Helper that lazily formats an `{K}="{V}"`" label.
5249
struct Label<K: fmt::Display, V: fmt::Display>(K, V);
5350

@@ -189,11 +186,10 @@ impl<V: Into<u64>, F: Factor> FmtMetric for Histogram<V, F> {
189186
let total = Counter::<F>::new();
190187
for (le, count) in self {
191188
total.add(count.into());
192-
total.fmt_metric_labeled(f, Key(&name, "bucket"), Label("le", le))?;
189+
total.fmt_metric_labeled(f, format_args!("{}_bucket", &name), Label("le", le))?;
193190
}
194-
total.fmt_metric(f, Key(&name, "count"))?;
195-
self.sum.fmt_metric(f, Key(&name, "sum"))?;
196-
191+
total.fmt_metric(f, format_args!("{}_count", &name))?;
192+
self.sum.fmt_metric(f, format_args!("{}_sum", &name))?;
197193
Ok(())
198194
}
199195

@@ -210,23 +206,19 @@ impl<V: Into<u64>, F: Factor> FmtMetric for Histogram<V, F> {
210206
let total = Counter::<F>::new();
211207
for (le, count) in self {
212208
total.add(count.into());
213-
total.fmt_metric_labeled(f, Key(&name, "bucket"), (&labels, Label("le", le)))?;
209+
total.fmt_metric_labeled(
210+
f,
211+
format_args!("{}_bucket", &name),
212+
(&labels, Label("le", le)),
213+
)?;
214214
}
215-
total.fmt_metric_labeled(f, Key(&name, "count"), &labels)?;
216-
self.sum.fmt_metric_labeled(f, Key(&name, "sum"), &labels)?;
217-
215+
total.fmt_metric_labeled(f, format_args!("{}_count", &name), &labels)?;
216+
self.sum
217+
.fmt_metric_labeled(f, format_args!("{}_sum", &name), &labels)?;
218218
Ok(())
219219
}
220220
}
221221

222-
// ===== impl Key =====
223-
224-
impl<A: fmt::Display, B: fmt::Display> fmt::Display for Key<A, B> {
225-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
226-
write!(f, "{}_{}", self.0, self.1)
227-
}
228-
}
229-
230222
// ===== impl Label =====
231223

232224
impl<K: fmt::Display, V: fmt::Display> FmtLabels for Label<K, V> {

linkerd/metrics/src/lib.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,25 @@ pub mod latency;
99
mod prom;
1010
mod scopes;
1111
mod serve;
12+
#[cfg(feature = "summary")]
13+
mod summary;
1214

1315
pub use self::counter::Counter;
1416
pub use self::gauge::Gauge;
1517
pub use self::histogram::Histogram;
1618
pub use self::prom::{FmtLabels, FmtMetric, FmtMetrics, Metric};
1719
pub use self::scopes::Scopes;
1820
pub use self::serve::Serve;
21+
#[cfg(feature = "summary")]
22+
pub use self::summary::Summary;
1923

2024
#[macro_export]
2125
macro_rules! metrics {
2226
{ $( $name:ident : $kind:ty { $help:expr } ),+ } => {
2327
$(
2428
#[allow(non_upper_case_globals)]
25-
const $name: ::linkerd2_metrics::Metric<'static, &str, $kind> =
26-
::linkerd2_metrics::Metric {
29+
const $name: $crate::Metric<'static, &str, $kind> =
30+
$crate::Metric {
2731
name: stringify!($name),
2832
help: $help,
2933
_p: ::std::marker::PhantomData,

linkerd/metrics/src/prom.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,16 @@ impl<'a, N: fmt::Display, M: FmtMetric> Metric<'a, N, M> {
9494
metric.fmt_metric(f, &self.name)
9595
}
9696

97+
/// Formats a single metric with labels.
98+
pub fn fmt_metric_labeled<L: FmtLabels>(
99+
&self,
100+
f: &mut fmt::Formatter<'_>,
101+
metric: &M,
102+
labels: &L,
103+
) -> fmt::Result {
104+
metric.fmt_metric_labeled(f, &self.name, labels)
105+
}
106+
97107
/// Formats a single metric across labeled scopes.
98108
pub fn fmt_scopes<'s, L, S: 's, I, F>(
99109
&self,

0 commit comments

Comments
 (0)