Skip to content

Commit e48c8d3

Browse files
authored
Add proxy_build_info metric (#600)
## Why Closes linkerd/linkerd2#3424 ## What A new `proxy_build_info` metric is introduced that contains the following fields: - `git_branch`: The branch that the proxy was built on - `git_version`: The version of the proxy. This is the output of `git describe` and finds the most recent tag that is reachable from the commit. - `rust_version`: The rust version used to build the proxy This metric is a gauge that always has a value of `1`. The reasoning is described [here](https://www.robustperception.io/exposing-the-software-version-to-prometheus). The fields reflect those of the `prometheus_build_info` discussed in the link above. ```bash ❯ linkerd metrics -n linkerd pods/linkerd-tap-5f6565cfc5-56q9r .. # HELP proxy_build_info Proxy build info # TYPE proxy_build_info gauge proxy_build_info{git_branch="kleimkuhler/build-info",git_version="release/v2.104.1-11-gea34a589",rust_version="rustc 1.44.1 (c7087fe00 2020-06-17)",} 1 ``` ## How The `.git/` directory is now copied into the docker container when building so that the `build.rs` file being introduced can reference the git history to find the most recent tag and populate the `GIT_BRANCH` and `GIT_VERSION` environment variables at compile time. ### Labels I considered a `git_release` and `git_revision` tag instead of the single `git_version`. `git_release` would be the most recent tag reachable from the commit, and `git_revision` would be the full commit SHA. I chose the output of `git describe` instead because it includes both the tag and short SHA as well as how many additional commits have occurred on top of the tag. I think this makes it a little easier as a user to see that the proxy build version is the `kleimkuhler/build-info` branch, which is `1` commit from `release/v2.104.1` with the SHA starting with `1ee7452f`: ```bash ❯ git describe release/v2.104.1-1-g1ee7452f ``` Signed-off-by: Kevin Leimkuhler <[email protected]>
1 parent f37e3ff commit e48c8d3

File tree

5 files changed

+103
-2
lines changed

5 files changed

+103
-2
lines changed

.dockerignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
.travis.yml
2-
.git
32
**/.idea
43
**/cmake-*
54
**/CMakeLists.txt

linkerd/app/core/build.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use std::process::Command;
2+
use std::string::String;
3+
4+
const UNAVAILABLE: &str = "unavailable";
5+
6+
fn set_env(name: &str, cmd: &mut Command) {
7+
let value = match cmd.output() {
8+
Ok(output) => String::from_utf8(output.stdout).unwrap(),
9+
Err(err) => {
10+
println!("cargo:warning={}", err);
11+
UNAVAILABLE.to_string()
12+
}
13+
};
14+
println!("cargo:rustc-env={}={}", name, value);
15+
}
16+
17+
fn main() {
18+
set_env(
19+
"GIT_BRANCH",
20+
Command::new("git").args(&["rev-parse", "--abbrev-ref", "HEAD"]),
21+
);
22+
set_env(
23+
"GIT_VERSION",
24+
Command::new("git").args(&["describe", "--always", "HEAD"]),
25+
);
26+
set_env("RUST_VERSION", Command::new("rustc").arg("--version"));
27+
28+
let profile = std::env::var("PROFILE").unwrap();
29+
println!("cargo:rustc-env=PROFILE={}", profile);
30+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
use linkerd2_metrics::{metrics, FmtLabels, FmtMetric, FmtMetrics, Gauge};
2+
use std::env;
3+
use std::fmt;
4+
use std::string::String;
5+
use std::sync::Arc;
6+
7+
const GIT_BRANCH: &'static str = env!("GIT_BRANCH");
8+
const GIT_VERSION: &'static str = env!("GIT_VERSION");
9+
const PROFILE: &'static str = env!("PROFILE");
10+
const RUST_VERSION: &'static str = env!("RUST_VERSION");
11+
12+
metrics! {
13+
proxy_build_info: Gauge {
14+
"Proxy build info"
15+
}
16+
}
17+
18+
#[derive(Clone, Debug, Default)]
19+
pub struct Report {
20+
name: String,
21+
// `value` remains constant over the lifetime of the proxy so that
22+
// build information in `labels` remains accurate
23+
value: Arc<Gauge>,
24+
labels: Arc<BuildInfoLabels>,
25+
}
26+
27+
#[derive(Clone, Debug, Default)]
28+
struct BuildInfoLabels {
29+
git_branch: String,
30+
git_version: String,
31+
profile: String,
32+
rust_version: String,
33+
}
34+
35+
impl Report {
36+
pub fn new() -> Self {
37+
let labels = Arc::new(BuildInfoLabels {
38+
git_branch: GIT_BRANCH.to_string(),
39+
git_version: GIT_VERSION.to_string(),
40+
profile: PROFILE.to_string(),
41+
rust_version: RUST_VERSION.to_string(),
42+
});
43+
Self {
44+
name: "proxy_build_info".to_string(),
45+
value: Arc::new(1.into()),
46+
labels,
47+
}
48+
}
49+
}
50+
51+
impl FmtMetrics for Report {
52+
fn fmt_metrics(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
53+
proxy_build_info.fmt_help(f)?;
54+
self.value
55+
.fmt_metric_labeled(f, self.name.as_str(), self.labels.as_ref())?;
56+
Ok(())
57+
}
58+
}
59+
60+
impl FmtLabels for BuildInfoLabels {
61+
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
62+
write!(f, "git_branch=\"{}\",", self.git_branch)?;
63+
write!(f, "git_version=\"{}\",", self.git_version)?;
64+
write!(f, "profile=\"{}\",", self.profile)?;
65+
write!(f, "rust_version=\"{}\",", self.rust_version)?;
66+
Ok(())
67+
}
68+
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
pub mod build_info;
12
pub mod process;

linkerd/app/src/metrics.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ impl Metrics {
1818
pub fn new(retain_idle: Duration) -> (Self, impl FmtMetrics + Clone + Send + 'static) {
1919
let process = telemetry::process::Report::new(SystemTime::now());
2020

21+
let build_info = telemetry::build_info::Report::new();
22+
2123
let (control, control_report) = {
2224
let m = metrics::Requests::<ControlLabels, Class>::default();
2325
let r = m.clone().into_report(retain_idle).with_prefix("control");
@@ -98,7 +100,8 @@ impl Metrics {
98100
.and_then(transport_report)
99101
.and_then(opencensus_report)
100102
.and_then(stack)
101-
.and_then(process);
103+
.and_then(process)
104+
.and_then(build_info);
102105

103106
(metrics, report)
104107
}

0 commit comments

Comments
 (0)