Skip to content

Commit

Permalink
metrics: Use prometheus-client for proxy_build_info (#2551)
Browse files Browse the repository at this point in the history
In preparation to add metrics that report float values, and ultimately in
service of replacing Linkerd's custom metrics implementation with an
upstream library, this change adds an integration with the
prometheus-client crate.

This is accomplished by leaving the existing types and traits in place
and adding a FmtMetrics implementation for the prometheus-client
Registry type, minimizing the change needed to support this new library.

New metrics can use the upstream registry and metric types. The
proxy_build_info metric has been ported to use the new API to validate
the new library. Now, the metrics dump ends with:

    # HELP proxy_build_info Proxy build info.
    # TYPE proxy_build_info gauge
    proxy_build_info{date="2023-12-05T19:52:40Z",git_sha="215c32d3f",profile="release",vendor="code@ver-sea",version="0.0.0-dev.215c32d3f"} 1
    # EOF
  • Loading branch information
olix0r authored Dec 5, 2023
1 parent b12ff1d commit f920e6c
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 60 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -465,6 +465,12 @@ dependencies = [
"tower",
]

[[package]]
name = "dtoa"
version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653"

[[package]]
name = "either"
version = "1.8.1"
Expand Down Expand Up @@ -1143,6 +1149,7 @@ dependencies = [
"linkerd-transport-metrics",
"parking_lot",
"pin-project",
"prometheus-client",
"quickcheck",
"regex",
"semver",
Expand Down Expand Up @@ -1623,6 +1630,7 @@ dependencies = [
"hyper",
"linkerd-stack",
"parking_lot",
"prometheus-client",
"quickcheck",
"tokio",
"tracing",
Expand Down Expand Up @@ -2550,6 +2558,29 @@ dependencies = [
"rustix 0.36.16",
]

[[package]]
name = "prometheus-client"
version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "510c4f1c9d81d556458f94c98f857748130ea9737bbd6053da497503b26ea63c"
dependencies = [
"dtoa",
"itoa",
"parking_lot",
"prometheus-client-derive-encode",
]

[[package]]
name = "prometheus-client-derive-encode"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8"
dependencies = [
"proc-macro2",
"quote",
"syn 2.0.39",
]

[[package]]
name = "prost"
version = "0.12.1"
Expand Down
1 change: 1 addition & 0 deletions linkerd/app/core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ linkerd-transport-header = { path = "../../transport-header" }
linkerd-transport-metrics = { path = "../../transport-metrics" }
linkerd-tls = { path = "../../tls" }
linkerd-trace-context = { path = "../../trace-context" }
prometheus-client = "0.22"
regex = "1"
serde_json = "1"
thiserror = "1"
Expand Down
28 changes: 28 additions & 0 deletions linkerd/app/core/src/build_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
use linkerd_metrics::prom::{self, encoding::EncodeLabelSet};

pub const BUILD_INFO: BuildInfo = BuildInfo {
date: env!("LINKERD2_PROXY_BUILD_DATE"),
git_sha: env!("GIT_SHA"),
profile: env!("PROFILE"),
vendor: env!("LINKERD2_PROXY_VENDOR"),
version: env!("LINKERD2_PROXY_VERSION"),
};

#[derive(Copy, Clone, Debug, Default, Hash, PartialEq, Eq, EncodeLabelSet)]
pub struct BuildInfo {
pub date: &'static str,
pub git_sha: &'static str,
pub profile: &'static str,
pub vendor: &'static str,
pub version: &'static str,
}

impl BuildInfo {
pub fn metric(&self) -> prom::Family<BuildInfo, prom::ConstGauge> {
let fam = prom::Family::<Self, prom::ConstGauge>::new_with_constructor(|| {
prom::ConstGauge::new(1)
});
let _ = fam.get_or_create(self);
fam
}
}
2 changes: 2 additions & 0 deletions linkerd/app/core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@

use thiserror::Error;

mod build_info;
pub mod classify;
pub mod config;
pub mod control;
Expand All @@ -27,6 +28,7 @@ pub mod svc;
pub mod telemetry;
pub mod transport;

pub use self::build_info::{BuildInfo, BUILD_INFO};
pub use drain;
pub use ipnet::{IpNet, Ipv4Net, Ipv6Net};
pub use linkerd_addr::{self as addr, Addr, AddrMatch, IpMatch, NameAddr, NameMatch};
Expand Down
28 changes: 20 additions & 8 deletions linkerd/app/core/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
pub use crate::transport::labels::{TargetAddr, TlsAccept};
use crate::{
classify::Class,
control, http_metrics, http_metrics as metrics, opencensus, profiles, stack_metrics,
control, http_metrics, opencensus, profiles, stack_metrics,
svc::Param,
telemetry, tls,
transport::{self, labels::TlsConnect},
Expand Down Expand Up @@ -39,6 +39,9 @@ pub struct Metrics {
pub proxy: Proxy,
pub control: ControlHttp,
pub opencensus: opencensus::metrics::Registry,

// Global prometheus registry for new metrics.
pub registry: prom::Registry,
}

#[derive(Clone, Debug)]
Expand Down Expand Up @@ -147,36 +150,42 @@ impl Metrics {
retain_idle: Duration,
start_time: telemetry::StartTime,
) -> (Self, impl FmtMetrics + Clone + Send + 'static) {
let registry = prom::Registry::default();

let process = telemetry::process::Report::new(start_time);

let build_info = telemetry::build_info::Report::default();
registry.write().register(
"proxy_build_info",
"Proxy build info",
crate::BUILD_INFO.metric(),
);

let (control, control_report) = {
let m = metrics::Requests::<ControlLabels, Class>::default();
let m = http_metrics::Requests::<ControlLabels, Class>::default();
let r = m.clone().into_report(retain_idle).with_prefix("control");
(m, r)
};

let (http_endpoint, endpoint_report) = {
let m = metrics::Requests::<EndpointLabels, Class>::default();
let m = http_metrics::Requests::<EndpointLabels, Class>::default();
let r = m.clone().into_report(retain_idle);
(m, r)
};

let (http_profile_route, profile_route_report) = {
let m = metrics::Requests::<ProfileRouteLabels, Class>::default();
let m = http_metrics::Requests::<ProfileRouteLabels, Class>::default();
let r = m.clone().into_report(retain_idle).with_prefix("route");
(m, r)
};

let (http_profile_route_retry, retry_report) = {
let m = metrics::Retries::<ProfileRouteLabels>::default();
let m = http_metrics::Retries::<ProfileRouteLabels>::default();
let r = m.clone().into_report(retain_idle).with_prefix("route");
(m, r)
};

let (http_profile_route_actual, actual_report) = {
let m = metrics::Requests::<ProfileRouteLabels, Class>::default();
let m = http_metrics::Requests::<ProfileRouteLabels, Class>::default();
let r = m
.clone()
.into_report(retain_idle)
Expand All @@ -203,6 +212,7 @@ impl Metrics {
proxy,
control,
opencensus,
registry: registry.clone(),
};

let report = endpoint_report
Expand All @@ -214,7 +224,9 @@ impl Metrics {
.and_report(opencensus_report)
.and_report(stack)
.and_report(process)
.and_report(build_info);
// The prom registry reports an "# EOF" at the end of its export, so
// it should be emitted last.
.and_report(registry);

(metrics, report)
}
Expand Down
2 changes: 1 addition & 1 deletion linkerd/app/core/src/telemetry.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
pub mod build_info;
pub mod process;

pub use self::process::StartTime;
38 changes: 0 additions & 38 deletions linkerd/app/core/src/telemetry/build_info.rs

This file was deleted.

1 change: 1 addition & 0 deletions linkerd/metrics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ http = "0.2"
hyper = { version = "0.14", features = ["http1", "http2"] }
linkerd-stack = { path = "../stack", optional = true }
parking_lot = "0.12"
prometheus-client = "0.22"
tokio = { version = "1", features = ["time"] }
tracing = "0.1"

Expand Down
2 changes: 1 addition & 1 deletion linkerd/metrics/src/counter.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::{
prom::{FmtLabels, FmtMetric},
fmt::{FmtLabels, FmtMetric},
Factor,
};
use std::fmt::{self, Display};
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion linkerd/metrics/src/gauge.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use super::prom::{FmtLabels, FmtMetric};
use super::fmt::{FmtLabels, FmtMetric};
use std::fmt::{self, Display};
use std::sync::atomic::{AtomicU64, Ordering};

Expand Down
33 changes: 31 additions & 2 deletions linkerd/metrics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,26 +4,55 @@
//! Utilities for exposing metrics to Prometheus.
mod counter;
mod fmt;
mod gauge;
mod histogram;
pub mod latency;
#[cfg(feature = "linkerd-stack")]
mod new_metrics;
mod prom;
mod serve;
mod store;

#[cfg(feature = "linkerd-stack")]
pub use self::new_metrics::NewMetrics;
pub use self::{
counter::Counter,
fmt::{FmtLabels, FmtMetric, FmtMetrics, Metric},
gauge::Gauge,
histogram::Histogram,
prom::{FmtLabels, FmtMetric, FmtMetrics, Metric},
serve::Serve,
store::{LastUpdate, SharedStore, Store},
};

/// Integration with the [`prometheus_client`]` crate.
///
/// This should be used for all new metrics.
pub mod prom {
use parking_lot::RwLock;
use std::sync::Arc;

pub use prometheus_client::{
metrics::{
counter::{ConstCounter, Counter},
family::Family,
gauge::{ConstGauge, Gauge},
histogram::Histogram,
info::Info,
},
*,
};

/// New metrics should use the prometheus-client Registry.
pub type Registry = Arc<RwLock<registry::Registry>>;

impl crate::FmtMetrics for Registry {
#[inline]
fn fmt_metrics(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
encoding::text::encode(f, &self.read())
}
}
}

#[macro_export]
macro_rules! metrics {
{ $( $name:ident : $kind:ty { $help:expr } ),+ } => {
Expand Down
15 changes: 6 additions & 9 deletions linkerd2-proxy/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,7 @@ compile_error!(
);

use linkerd_app::{
core::{
telemetry::{build_info, StartTime},
transport::BindTcp,
},
core::{telemetry::StartTime, transport::BindTcp, BUILD_INFO},
trace, Config,
};
use linkerd_signal as signal;
Expand All @@ -42,11 +39,11 @@ fn main() {

info!(
"{profile} {version} ({sha}) by {vendor} on {date}",
date = build_info::DATE,
sha = build_info::GIT_SHA,
version = build_info::VERSION,
profile = build_info::PROFILE,
vendor = build_info::VENDOR,
date = BUILD_INFO.date,
sha = BUILD_INFO.git_sha,
version = BUILD_INFO.version,
profile = BUILD_INFO.profile,
vendor = BUILD_INFO.vendor,
);

// Load configuration from the environment without binding ports.
Expand Down

0 comments on commit f920e6c

Please sign in to comment.