Skip to content

15.3.1 Contributing information to the /info endpoint

As you saw in section 15.2.1, the /info endpoint starts off empty and uninformative. But you can easily add data to it by creating properties that are prefixed with info.

Although prefixing properties with info. is a very easy way to get custom data into the /info endpoint, it’s not the only way. Spring Boot offers an interface named InfoContributor that allows you to programmatically add any information you want to the /info endpoint response. Spring Boot even comes ready with a couple of useful implementations of InfoContributor that you’ll no doubt find useful.

Let’s see how you can write your own InfoContributor to add some custom info to the /info endpoint.

CREATING A CUSTOM INFOCONTRIBUTOR

Suppose you want to add some simple statistics regarding Taco Cloud to the /info endpoint. For example, let’s say you want to include information about how many tacos have been created. To do that, you can write a class that implements InfoContributor, inject it with TacoRepository, and then publish whatever count that TacoRepository gives you as information to the /info endpoint. The next listing shows how you might implement such a contributor.

Listing 15.3 A custom implementation of InfoContributor

java
package tacos.tacos;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.stereotype.Component;
import java.util.HashMap;
import java.util.Map;
import org.springframework.boot.actuate.info.Info.Builder;
@Component
public class TacoCountInfoContributor implements InfoContributor {
  private TacoRepository tacoRepo;
  public TacoCountInfoContributor(TacoRepository tacoRepo) {
    this.tacoRepo = tacoRepo;
  }
  @Override
  public void contribute(Builder builder) {
    long tacoCount = tacoRepo.count();
    Map<String, Object> tacoMap = new HashMap<String, Object>();
    tacoMap.put("count", tacoCount);
    builder.withDetail("taco-stats", tacoMap);
  }
}

By implementing InfoContributor, TacoCountInfoContributor is required to implement the contribute() method. This method is given a Builder object on which the contribute() method makes a call to withDetail() to add info details. In your implementation, you consult TacoRepository by calling its count() method to find out how many tacos have been created. In this particular case, you’re working with a reactive repository, so you need to call block() to get the count out of the returned Mono<Long>. Then you put that count into a Map, which you then give to the builder with the label taco-stats. The results of the /info endpoint will include that count, as shown here:

json
{
  "taco-stats": {
    "count": 44
  }
}

As you can see, an implementation of InfoContributor is able to use whatever means necessary to contribute information. This is in contrast to simply prefixing a property with info., which, although simple, is limited to static values.

INJECTING BUILD INFORMATION INTO THE /INFO ENDPOINT

Spring Boot comes with a few built-in implementations of InfoContributor that automatically add information to the results of the /info endpoint. Among them is BuildInfoContributor, which adds information from the project build file into the /info endpoint results. The basic information includes the project version, the timestamp of the build, and the host and user who performed the build.

To enable build information to be included in the results of the /info endpoint, add the build-info goal to the Spring Boot Maven Plugin executions, as follows:

xml
<build>
  <plugins>
    <plugin>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-maven-plugin</artifactId>
      <executions>
        <execution>
          <goals>
            <goal>build-info</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
  </plugins>
</build>

If you’re using Gradle to build your project, you can simply add the following lines to your build.gradle file:

yaml
springBoot {
  buildInfo()
}

In either event, the build will produce a file named build-info.properties in the distributable JAR or WAR file that BuildInfoContributor will consume and contribute to the /info endpoint. The following snippet from the /info endpoint response shows the build information that’s contributed:

json
{
"build": {
    "artifact": "tacocloud",
    "name": "taco-cloud",
    "time": "2021-08-08T23:55:16.379Z",
    "version": "0.0.15-SNAPSHOT",
    "group": "sia"
  },
}

This information is useful for understanding exactly which version of an application is running and when it was built. By performing a GET request to the /info endpoint, you’ll know whether you’re running the latest and greatest build of the project.

EXPOSING GIT COMMIT INFORMATION

Assuming that your project is kept in Git for source code control, you may want to include Git commit information in the /info endpoint. To do that, you’ll need to add the following plugin in the Maven project pom.xml:

html
<build>
  <plugins>
  ...
    <plugin>
      <groupId>pl.project13.maven</groupId>
      <artifactId>git-commit-id-plugin</artifactId>
    </plugin>
  </plugins>
</build>

If you’re a Gradle user, don’t worry. There’s an equivalent plugin for you to add to your build.gradle file, shown here:

yaml
plugins {
  id "com.gorylenko.gradle-git-properties" version "2.3.1"
}

Both of these plugins do essentially the same thing: they generate a build-time artifact named git.properties that contains all of the Git metadata for the project. A special InfoContributor implementation discovers that file at runtime and exposes its contents as part of the /info endpoint.

Of course, to generate the git.properties file, the project needs to have Git commit metadata. That is, it must be a clone of a Git repository or be a newly initialized local Git repository with at least one commit. If not, then either of these plugins will fail. You can, however, configure them to ignore the missing Git metadata. For the Maven plugin, set the failOnNoGitDirectory property to false like this:

html
<build>
  <plugins>
  ...
    <plugin>
      <groupId>pl.project13.maven</groupId>
      <artifactId>git-commit-id-plugin</artifactId>
        <configuration>
          <failOnNoGitDirectory>false</failOnNoGitDirectory>
        </configuration>
    </plugin>
  </plugins>
</build>

Similarly, you can set the failOnNoGitDirectory property in Gradle by specifying it under gitProperties like this:

yaml
gitProperties {
  failOnNoGitDirectory = false
}

In its simplest form, the Git information presented in the /info endpoint includes the Git branch, commit hash, and timestamp that the application was built against, as shown here:

json
{
  "git": {
    "branch": "main",
    "commit": {
      "id": "df45505",
      "time": "2021-08-08T21:51:12Z"
    }
  },
...
}

This information is quite definitive in describing the state of the code when the project was built. But by setting the management.info.git.mode property to full, you can get extremely detailed information about the Git commit that was in play when the project was built, as shown in the next code sample:

yaml
management:
  info:
    git:
      mode: full

The following listing shows a sample of what the full Git info might look like.

Listing 15.4 Full Git commit info exposed through the /info endpoint

json

"git":{
    "local":{
        "branch":{
            "ahead":"8",
            "behind":"0"
        }
    },
    "commit":{
        "id":{
            "describe-short":"df45505-dirty",
            "abbrev":"df45505",
            "full":"df455055daaf3b1347b0ad1d9dca4ebbc6067810",
            "describe":"df45505-dirty"
        },
        "message":{
            "short":"Apply chapter 18 edits",
            "full":"Apply chapter 18 edits"
        },
        "user":{
            "name":"Craig Walls",
            "email":"craig@habuma.com"
        },
        "author":{
            "time":"2021-08-08T15:51:12-0600"
        },
        "committer":{
            "time":"2021-08-08T15:51:12-0600"
        },
        "time":"2021-08-08T21:51:12Z"
    },
    "branch":"master",
    "build":{
        "time":"2021-08-09T00:13:37Z",
        "version":"0.0.15-SNAPSHOT",
        "host":"Craigs-MacBook-Pro.local",
        "user":{
            "name":"Craig Walls",
            "email":"craig@habuma.com"
        }
    },
    "tags":"",
    "total":{
        "commit":{
            "count":"196"
        }
    },
    "closest":{
        "tag":{
            "commit":{
                "count":""
            },
            "name":""
        }
    },
    "remote":{
        "origin":{
            "url":"git@github.com:habuma/spring-in-action-6-samples.git"
        }
    },
    "dirty":"true"
},

In addition to the timestamp and abbreviated Git commit hash, the full version includes the name and email of the user who committed the code as well as the commit message and other information, allowing you to pinpoint exactly what code was used to build the project. In fact, notice that the dirty field in listing 15.4 is true, indicating that some uncommitted changes existed in the build directory when the project was built. It doesn’t get much more definitive than that!

Released under the MIT License.