spring-projects / spring-boot

Spring Boot helps you to create Spring-powered, production-grade applications and services with absolute minimum fuss.
https://spring.io/projects/spring-boot
Apache License 2.0
75.14k stars 40.68k forks source link

Add list of effective PropertySources in EnvironmentEndpoint #19505

Open ttddyy opened 4 years ago

ttddyy commented 4 years ago

Currently, EnvironmentEndpoint shows where all of PropertySources are coming from including duplicated keys(overrides) if they are from different sources. (e.g.: one from application.yaml and same key from application-<profile>.yaml)

Usually, while troubleshooting or debugging, what people want to find out is the final value resolved by the Environment.(actual value resolved by @Value("x.y.z") etc.) Current /env can serve the purpose, but may need to go through several hoops to get the correct answer if there are overrides.

Having final property key-values as part of EnvironmentEndpoint would give clear answer what key-values are used in application.

Such property sources considering override can be obtained like this:

Map<String, Object> map = new HashMap<>();
for (PropertySource<?> propertySource : ((ConfigurableEnvironment) this.environment).getPropertySources()) {
    if (propertySource instanceof EnumerablePropertySource) {
        for (String key : ((EnumerablePropertySource<?>) propertySource).getPropertyNames()) {
            map.putIfAbsent(key, propertySource.getProperty(key));
        }
    }
}
// may sort the map with key...
snicoll commented 4 years ago

what people want to find out is the final value resolved by the Environment.(actual value resolved by @Value("x.y.z") etc.) Current /env can serve the purpose, but may need to go through several hoops to get the correct answer if there are overrides.

The purpose of /actuator/env is to provides an overview of property sources. If you need the actual value of a property (as well as the sources that contributed to it), /actuator/env/{id} is the endpoint you should use. What is wrong with that approach?

ttddyy commented 4 years ago

Hi @snicoll

let's say:

application.properties has defined:

my.prop= dev
foo.prop = FOO
bar.prop = BAR

application-prod.properties has defined:

my.prop = prod
foo.prop = FOO Override

In application,

Current /actuator/env contains detailed list of properties but it is too detailed when need to get a glance of effective properties.

For example, it contains my.prop with value dev indicating it is from application.properties and prod from application-prod.properties. Without knowing the relationship or ordering of application.properties and application-prod.properties, reader will not sure which value (dev vs prod) is the value ultimately used by the application.

/actuator/env/{id} requires to know what {id} (prop key) is the target to see. While troubleshooting, having list of all props with effective values is rather handy to start.

So, having effective list of properties key-value gives better understanding of what property values are used by the application.

Something like this:

"effectiveProperties": {
  "my.prop" : "prod",
  "foo.prop" : "FOO Override",
  "bar.prop" : "BAR"
}

May add source info:

"effectiveProperties": {
  "my.prop" : {
      "value": "prod",
      "origin": "class path resource [application-prod.properties]:1:1"
    },
  ...
}