Skip to content

Commit

Permalink
Add proxy_build_info metric (linkerd#600)
Browse files Browse the repository at this point in the history
## 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 <kevin@kleimkuhler.com>
  • Loading branch information
kleimkuhler authored Jul 24, 2020
1 parent f37e3ff commit e48c8d3
Show file tree
Hide file tree
Showing 5 changed files with 103 additions and 2 deletions.
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
.travis.yml
.git
**/.idea
**/cmake-*
**/CMakeLists.txt
Expand Down
30 changes: 30 additions & 0 deletions linkerd/app/core/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
use std::process::Command;
use std::string::String;

const UNAVAILABLE: &str = "unavailable";

fn set_env(name: &str, cmd: &mut Command) {
let value = match cmd.output() {
Ok(output) => String::from_utf8(output.stdout).unwrap(),
Err(err) => {
println!("cargo:warning={}", err);
UNAVAILABLE.to_string()
}
};
println!("cargo:rustc-env={}={}", name, value);
}

fn main() {
set_env(
"GIT_BRANCH",
Command::new("git").args(&["rev-parse", "--abbrev-ref", "HEAD"]),
);
set_env(
"GIT_VERSION",
Command::new("git").args(&["describe", "--always", "HEAD"]),
);
set_env("RUST_VERSION", Command::new("rustc").arg("--version"));

let profile = std::env::var("PROFILE").unwrap();
println!("cargo:rustc-env=PROFILE={}", profile);
}
68 changes: 68 additions & 0 deletions linkerd/app/core/src/telemetry/build_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use linkerd2_metrics::{metrics, FmtLabels, FmtMetric, FmtMetrics, Gauge};
use std::env;
use std::fmt;
use std::string::String;
use std::sync::Arc;

const GIT_BRANCH: &'static str = env!("GIT_BRANCH");
const GIT_VERSION: &'static str = env!("GIT_VERSION");
const PROFILE: &'static str = env!("PROFILE");
const RUST_VERSION: &'static str = env!("RUST_VERSION");

metrics! {
proxy_build_info: Gauge {
"Proxy build info"
}
}

#[derive(Clone, Debug, Default)]
pub struct Report {
name: String,
// `value` remains constant over the lifetime of the proxy so that
// build information in `labels` remains accurate
value: Arc<Gauge>,
labels: Arc<BuildInfoLabels>,
}

#[derive(Clone, Debug, Default)]
struct BuildInfoLabels {
git_branch: String,
git_version: String,
profile: String,
rust_version: String,
}

impl Report {
pub fn new() -> Self {
let labels = Arc::new(BuildInfoLabels {
git_branch: GIT_BRANCH.to_string(),
git_version: GIT_VERSION.to_string(),
profile: PROFILE.to_string(),
rust_version: RUST_VERSION.to_string(),
});
Self {
name: "proxy_build_info".to_string(),
value: Arc::new(1.into()),
labels,
}
}
}

impl FmtMetrics for Report {
fn fmt_metrics(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
proxy_build_info.fmt_help(f)?;
self.value
.fmt_metric_labeled(f, self.name.as_str(), self.labels.as_ref())?;
Ok(())
}
}

impl FmtLabels for BuildInfoLabels {
fn fmt_labels(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "git_branch=\"{}\",", self.git_branch)?;
write!(f, "git_version=\"{}\",", self.git_version)?;
write!(f, "profile=\"{}\",", self.profile)?;
write!(f, "rust_version=\"{}\",", self.rust_version)?;
Ok(())
}
}
1 change: 1 addition & 0 deletions linkerd/app/core/src/telemetry/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
pub mod build_info;
pub mod process;
5 changes: 4 additions & 1 deletion linkerd/app/src/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ impl Metrics {
pub fn new(retain_idle: Duration) -> (Self, impl FmtMetrics + Clone + Send + 'static) {
let process = telemetry::process::Report::new(SystemTime::now());

let build_info = telemetry::build_info::Report::new();

let (control, control_report) = {
let m = metrics::Requests::<ControlLabels, Class>::default();
let r = m.clone().into_report(retain_idle).with_prefix("control");
Expand Down Expand Up @@ -98,7 +100,8 @@ impl Metrics {
.and_then(transport_report)
.and_then(opencensus_report)
.and_then(stack)
.and_then(process);
.and_then(process)
.and_then(build_info);

(metrics, report)
}
Expand Down

0 comments on commit e48c8d3

Please sign in to comment.