Skip to content

Commit

Permalink
Merge pull request #28136 from jonatan-ivanov
Browse files Browse the repository at this point in the history
* pr/28136:
  Polish "Add Java InfoContributor"
  Add Java InfoContributor

Closes gh-28136
  • Loading branch information
snicoll committed Oct 5, 2021
2 parents 0b58d48 + 5d17257 commit f1c1a4f
Show file tree
Hide file tree
Showing 7 changed files with 341 additions and 70 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -20,6 +20,7 @@
import org.springframework.boot.actuate.info.EnvironmentInfoContributor;
import org.springframework.boot.actuate.info.GitInfoContributor;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.boot.actuate.info.JavaInfoContributor;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
Expand All @@ -40,6 +41,7 @@
*
* @author Meang Akira Tanaka
* @author Stephane Nicoll
* @author Jonatan Ivanov
* @since 2.0.0
*/
@Configuration(proxyBeanMethods = false)
Expand Down Expand Up @@ -77,4 +79,11 @@ public InfoContributor buildInfoContributor(BuildProperties buildProperties) {
return new BuildInfoContributor(buildProperties);
}

@Bean
@ConditionalOnEnabledInfoContributor("java")
@Order(DEFAULT_ORDER)
public JavaInfoContributor javaInfoContributor() {
return new JavaInfoContributor();
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2019 the original author or authors.
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand All @@ -19,17 +19,19 @@
import java.util.Map;
import java.util.Properties;

import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;

import org.springframework.boot.actuate.info.BuildInfoContributor;
import org.springframework.boot.actuate.info.EnvironmentInfoContributor;
import org.springframework.boot.actuate.info.GitInfoContributor;
import org.springframework.boot.actuate.info.Info;
import org.springframework.boot.actuate.info.InfoContributor;
import org.springframework.boot.actuate.info.JavaInfoContributor;
import org.springframework.boot.autoconfigure.AutoConfigurations;
import org.springframework.boot.info.BuildProperties;
import org.springframework.boot.info.GitProperties;
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.boot.info.JavaInfo;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

Expand All @@ -39,94 +41,117 @@
* Tests for {@link InfoContributorAutoConfiguration}.
*
* @author Stephane Nicoll
* @author Jonatan Ivanov
*/
class InfoContributorAutoConfigurationTests {

private AnnotationConfigApplicationContext context;
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(InfoContributorAutoConfiguration.class));

@AfterEach
void close() {
if (this.context != null) {
this.context.close();
}
@Test
void disableEnvContributor() {
this.contextRunner.withPropertyValues("management.info.env.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(EnvironmentInfoContributor.class));
}

@Test
void disableEnvContributor() {
load("management.info.env.enabled:false");
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).hasSize(0);
void disableJavaContributor() {
this.contextRunner.withPropertyValues("management.info.java.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(JavaInfoContributor.class));
}

@Test
void defaultInfoContributorsEnabled() {
this.contextRunner.run((context) -> {
assertThat(context).hasSingleBean(EnvironmentInfoContributor.class)
.hasSingleBean(JavaInfoContributor.class);
assertThat(context.getBeansOfType(InfoContributor.class)).hasSize(2);
});
}

@Test
void defaultInfoContributorsDisabled() {
load("management.info.defaults.enabled:false");
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).hasSize(0);
this.contextRunner.withPropertyValues("management.info.defaults.enabled=false")
.run((context) -> assertThat(context).doesNotHaveBean(InfoContributor.class));
}

@Test
void defaultInfoContributorsDisabledWithCustomOne() {
load(CustomInfoContributorConfiguration.class, "management.info.defaults.enabled:false");
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).hasSize(1);
assertThat(this.context.getBean("customInfoContributor")).isSameAs(beans.values().iterator().next());
this.contextRunner.withPropertyValues("management.info.defaults.enabled=false")
.withUserConfiguration(CustomInfoContributorConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(InfoContributor.class);
assertThat(context.getBean(InfoContributor.class))
.isSameAs(context.getBean("customInfoContributor"));
});
}

@SuppressWarnings("unchecked")
@Test
void gitPropertiesDefaultMode() {
load(GitPropertiesConfiguration.class);
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).containsKeys("gitInfoContributor");
Map<String, Object> content = invokeContributor(
this.context.getBean("gitInfoContributor", InfoContributor.class));
Object git = content.get("git");
assertThat(git).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) git;
assertThat(gitInfo).containsOnlyKeys("branch", "commit");
this.contextRunner.withUserConfiguration(GitPropertiesConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(GitInfoContributor.class);
Map<String, Object> content = invokeContributor(context.getBean(GitInfoContributor.class));
Object git = content.get("git");
assertThat(git).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) git;
assertThat(gitInfo).containsOnlyKeys("branch", "commit");
});
}

@SuppressWarnings("unchecked")
@Test
void gitPropertiesFullMode() {
load(GitPropertiesConfiguration.class, "management.info.git.mode=full");
Map<String, Object> content = invokeContributor(
this.context.getBean("gitInfoContributor", InfoContributor.class));
Object git = content.get("git");
assertThat(git).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) git;
assertThat(gitInfo).containsOnlyKeys("branch", "commit", "foo");
assertThat(gitInfo.get("foo")).isEqualTo("bar");
this.contextRunner.withPropertyValues("management.info.git.mode=full")
.withUserConfiguration(GitPropertiesConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(GitInfoContributor.class);
Map<String, Object> content = invokeContributor(context.getBean(GitInfoContributor.class));
Object git = content.get("git");
assertThat(git).isInstanceOf(Map.class);
Map<String, Object> gitInfo = (Map<String, Object>) git;
assertThat(gitInfo).containsOnlyKeys("branch", "commit", "foo");
assertThat(gitInfo.get("foo")).isEqualTo("bar");
});
}

@Test
void customGitInfoContributor() {
load(CustomGitInfoContributorConfiguration.class);
assertThat(this.context.getBean(GitInfoContributor.class))
.isSameAs(this.context.getBean("customGitInfoContributor"));
this.contextRunner.withUserConfiguration(CustomGitInfoContributorConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(GitInfoContributor.class);
assertThat(context.getBean(GitInfoContributor.class)).isSameAs(context.getBean("customGitInfoContributor"));
});
}

@SuppressWarnings("unchecked")
@Test
void buildProperties() {
load(BuildPropertiesConfiguration.class);
Map<String, InfoContributor> beans = this.context.getBeansOfType(InfoContributor.class);
assertThat(beans).containsKeys("buildInfoContributor");
Map<String, Object> content = invokeContributor(
this.context.getBean("buildInfoContributor", InfoContributor.class));
Object build = content.get("build");
assertThat(build).isInstanceOf(Map.class);
Map<String, Object> buildInfo = (Map<String, Object>) build;
assertThat(buildInfo).containsOnlyKeys("group", "artifact", "foo");
assertThat(buildInfo.get("foo")).isEqualTo("bar");
this.contextRunner.withUserConfiguration(BuildPropertiesConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(BuildInfoContributor.class);
Map<String, Object> content = invokeContributor(context.getBean(BuildInfoContributor.class));
Object build = content.get("build");
assertThat(build).isInstanceOf(Map.class);
Map<String, Object> buildInfo = (Map<String, Object>) build;
assertThat(buildInfo).containsOnlyKeys("group", "artifact", "foo");
assertThat(buildInfo.get("foo")).isEqualTo("bar");
});
}

@Test
void customBuildInfoContributor() {
load(CustomBuildInfoContributorConfiguration.class);
assertThat(this.context.getBean(BuildInfoContributor.class))
.isSameAs(this.context.getBean("customBuildInfoContributor"));
this.contextRunner.withUserConfiguration(CustomBuildInfoContributorConfiguration.class).run((context) -> {
assertThat(context).hasSingleBean(BuildInfoContributor.class);
assertThat(context.getBean(BuildInfoContributor.class))
.isSameAs(context.getBean("customBuildInfoContributor"));
});
}

@Test
void javaInfoContributor() {
this.contextRunner.run((context) -> {
assertThat(context).hasSingleBean(JavaInfoContributor.class);
Map<String, Object> content = invokeContributor(context.getBean(JavaInfoContributor.class));
assertThat(content).containsKey("java");
assertThat(content.get("java")).isInstanceOf(JavaInfo.class);
});
}

private Map<String, Object> invokeContributor(InfoContributor contributor) {
Expand All @@ -135,21 +160,6 @@ private Map<String, Object> invokeContributor(InfoContributor contributor) {
return builder.build().getDetails();
}

private void load(String... environment) {
load(null, environment);
}

private void load(Class<?> config, String... environment) {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
if (config != null) {
context.register(config);
}
context.register(InfoContributorAutoConfiguration.class);
TestPropertyValues.of(environment).applyTo(context);
context.refresh();
this.context = context;
}

@Configuration(proxyBeanMethods = false)
static class GitPropertiesConfiguration {

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.actuate.info;

import org.springframework.boot.actuate.info.Info.Builder;
import org.springframework.boot.info.JavaInfo;

/**
* An {@link InfoContributor} that exposes {@link JavaInfo}.
*
* @author Jonatan Ivanov
* @since 2.6.0
*/
public class JavaInfoContributor implements InfoContributor {

private final JavaInfo javaInfo;

public JavaInfoContributor() {
this.javaInfo = new JavaInfo();
}

@Override
public void contribute(Builder builder) {
builder.withDetail("java", this.javaInfo);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* Copyright 2012-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package org.springframework.boot.actuate.info;

import org.junit.jupiter.api.Test;

import org.springframework.boot.info.JavaInfo;

import static org.assertj.core.api.Assertions.assertThat;

/**
* Tests for {@link JavaInfoContributor}
*
* @author Jonatan Ivanov
*/
class JavaInfoContributorTests {

@Test
void javaInfoShouldBeAdded() {
JavaInfoContributor javaInfoContributor = new JavaInfoContributor();
Info.Builder builder = new Info.Builder();
javaInfoContributor.contribute(builder);
Info info = builder.build();
assertThat(info.getDetails().get("java")).isInstanceOf(JavaInfo.class);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -1157,6 +1157,9 @@ When appropriate, Spring auto-configures the following `InfoContributor` beans:

| {spring-boot-actuator-module-code}/info/BuildInfoContributor.java[`BuildInfoContributor`]
| Exposes build information if a `META-INF/build-info.properties` file is available.

| {spring-boot-actuator-module-code}/info/JavaInfoContributor.java[`JavaInfoContributor`]
| Exposes Java runtime information under the `java` key.
|===

TIP: You can disable them all by setting the configprop:management.info.defaults.enabled[] property.
Expand Down Expand Up @@ -1240,6 +1243,12 @@ See "<<howto#howto.build.generate-info,how to generate build information>>" for



[[actuator.endpoints.info.java-information]]
==== Java Information
The `info` endpoint publishes information about your Java runtime environment, see {spring-boot-module-api}/info/JavaInfo.html[`JavaInfo`] for more details.



[[actuator.endpoints.info.writing-custom-info-contributors]]
==== Writing Custom InfoContributors
To provide custom application information, you can register Spring beans that implement the {spring-boot-actuator-module-code}/info/InfoContributor.java[`InfoContributor`] interface.
Expand Down
Loading

0 comments on commit f1c1a4f

Please sign in to comment.