Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expose Git and build information as metrics #30628

Closed
wants to merge 1 commit into from
Closed

Expose Git and build information as metrics #30628

wants to merge 1 commit into from

Conversation

mafr
Copy link
Contributor

@mafr mafr commented Apr 10, 2022

Introduce new metrics git.info and build.info that expose some information from GitProperties and BuildProperties respectively, if available. This is the same info that /actuator/info provides, but represented as metrics, which allows for convenient integration in Grafana dashboards.

Using tags on a pseudo gauge seems to be the standard way of doing this; see for example Prometheus' go_info metric or Micrometer's own jvm.info metric (not yet included in Spring Boot).

Build runs locally, auto formatter has been applied, Checkstyle has no objections.

Introduce new metrics git.info and build.info that expose some
information from GitProperties and BuildProperties respectively.
@mafr mafr marked this pull request as ready for review April 10, 2022 16:18
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Apr 10, 2022
@wilkinsona
Copy link
Member

wilkinsona commented Apr 11, 2022

See #12348 for some history on this topic and micrometer-metrics/micrometer#2221 for the addition of jvm.info to Micrometer.

@jonatan-ivanov
Copy link
Member

jonatan-ivanov commented Apr 26, 2022

I think this makes as much sense (if not more) as micrometer-metrics/micrometer#2221. Also, what everyone thinks (/cc @shakuzen) about adding a GitInfoMetrics and a BuildInfoMetrics class or maybe just BuildInfoMetrics (that does both) to Micrometer?
The users need to supply the data (e.g.: through ctor) but it would give a simple contract about what needs to be provided and what will be produced. The advantage of doing it is having the same naming convention across Micrometer users also for non spring boot apps.

@wilkinsona
Copy link
Member

wilkinsona commented Apr 26, 2022

Thanks for taking a look, @jonatan-ivanov.

The advantage of doing it is having the same naming convention across Micrometer users also for non spring boot apps

That's quite a compelling advantage. +1 from me, FWIW.


addTag(builder, "branch", props.getBranch());
addTag(builder, "id", props.getShortCommitId());
addTag(builder, "time", props.getCommitTime());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you use this?
I'm not sure this is very usable with other metrics but it might be useful for setting up an alert to detect apps that were build against a commit before a certain date (e.g.: we made a company wide change that everyone needs to adopt and if your last change is before this date you did not).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We found this very handy on Grafana dashboards in development systems. Product owners often asked us whether a specific branch (or yesterday's fix) has already been deployed. I haven't used the commit time it in any type of reporting query yet.

As for why these tags and not others: For consistency reasons I decided to expose the exact information that Actuator's Info endpoint provides.

Gauge.Builder<Supplier<Number>> builder = Gauge.builder("git.info", () -> 1L)
.description("Project Git information").strongReference(true);

addTag(builder, "branch", props.getBranch());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How would you use this?
I'm not sure this is very usable with other metrics but it might be useful for setting up an alert to detect apps that were build (or not) against certain branches (e.g.: everyone needs to build against main/release all the time).

addTag(builder, "artifact", props.getArtifact());
addTag(builder, "group", props.getGroup());
addTag(builder, "version", props.getVersion());
addTag(builder, "time", props.getTime());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have the same thoughts as above for commit time.

}

private static void addTag(Gauge.Builder<Supplier<Number>> builder, String name, Object value) {
if (value != null) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can be a little dangerous. Let's say one app has the all the git info, the other does not. If that happens you will end-up with the same metric name but different set of tags. This can lead to all sorts of issues and some backends does not or does not like to support this (e.g.: prometheus). I would return a default value like unknown or N/A if the value is missing but I would always want to have the same set of keys.

Here's is an example (ServiceA has all the details, ServiceB only has the commit id)

git_info{service="serviceA",branch="main",id="cafecafe",time="2022-04-26T18:39:18"} 1.0
git_info{service="serviceB",id="deadbeef"} 1.0

This can be problematic (see above), my proposal instead is:

git_info{service="serviceA",branch="main",id="cafecafe",time="2022-04-26T18:39:18"} 1.0
git_info{service="serviceB",branch="unknown",id="deadbeef",time="unknown"} 1.0

I have a sad but real-life example for this. If you use heroku in a way that it will build your app when you deploy, heroku removes the .git folder so the git plugin will fail. You can generate git.properties on your own but heroku will only tell you the commit id so the git info will be incomplete (this page might take some time to load).

Copy link
Member

@jonatan-ivanov jonatan-ivanov Apr 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you do this, you can also simplify things above.

Gauge.builder("git.info", () -> 1L)
        .description("Project Git information").strongReference(true);
        .tag("branch", getOrDefault(props.getBranch()));
	.tag("id", getOrDefault(props.getShortCommitId()));
	.tag("time", getOrDefault(props.getCommitTime()));
	.register(registry);

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me!

}

@Test
void gitPropertiesPresent() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add a test for the case when one of the properties are not present.

@mafr
Copy link
Contributor Author

mafr commented Apr 27, 2022

Thanks for your feedback, everyone! If there's consensus on this, I'm happy to make a PR against Micrometer to add GitInfoMetrics and BuildInfoMetrics (with the suggested changes) and later adjust this PR to use them (maybe add JvmMetrics while I'm at it).

@shakuzen
Copy link
Member

If this is worth doing, I agree something in Micrometer standardizing it irrespective of framework would be a worthwhile goal. I'm not sure exactly what it would look like, since there isn't a generic git/build info class like Boot has.

which allows for convenient integration in Grafana dashboards.

I'd like to better understand the use cases we're trying to enable to make sure we're doing it in the best way for most users. I talked to @jonatan-ivanov today a bit about my concern over how well these kinds of info metrics can be used across different metrics backends. Prometheus consistently seems to be the backend people requesting it are using, and I want to make sure it is useful in other backends as well. We can discuss that more in the Micrometer repo or Slack.

@wilkinsona
Copy link
Member

Thanks, @shakuzen. I'll place this PR on hold until the discussion in the Micrometer repo or Slack has reached a conclusion. Could you please link to the discussion once it's begun as I'd like to follow along if I can.

@snicoll
Copy link
Member

snicoll commented Aug 10, 2023

The observability team has been discussing this and we need some work on Micrometer first. Let's follow-up on the issue you've created there and we can revisit this once that completes. Thanks for the PR, in any case!

@snicoll snicoll closed this Aug 10, 2023
@snicoll snicoll added for: external-project For an external project and not something we can fix and removed status: on-hold We can't start working on this issue yet status: waiting-for-triage An issue we've not yet triaged labels Aug 10, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
for: external-project For an external project and not something we can fix
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants