2014-06-27 9 views
10

Ich würde gerne YAML Config für Spring Boot verwenden, da ich es ziemlich lesbar und nützlich finde, eine einzige Datei zu haben, die zeigt, welche Eigenschaften in meinen verschiedenen Profilen aktiv sind. Leider finde ich, dass Einstellungseigenschaften in application.yml ziemlich zerbrechlich sein können.Wie protokolliere ich die aktive Konfiguration in einer Spring Boot-Anwendung?

Dinge wie die Verwendung einer Registerkarte anstelle von Leerzeichen führen dazu, dass Eigenschaften nicht existieren (ohne Warnungen, soweit ich sehen kann), und allzu oft finde ich, dass meine aktiven Profile aufgrund eines unbekannten Problems nicht gesetzt sind mein YAML.

Also habe ich mich gefragt, ob es irgendwelche Haken gibt, die es mir ermöglichen würden, die momentan aktiven Profile und Eigenschaften zu bekommen, so dass ich sie protokollieren könnte.

Gibt es auch eine Möglichkeit, den Start fehlschlagen zu lassen, wenn der application.yml Fehler enthält? Entweder das oder ein Mittel, um die YAML selbst zu validieren, damit ich den Startprozess beenden konnte.

Antwort

4

Ich hatte das gleiche Problem und wünschte, es gäbe ein Debug-Flag, das dem Profilverarbeitungssystem mitteilen würde, einige nützliche Protokollierungen auszuspucken. Eine Möglichkeit, dies zu tun, wäre, einen Ereignis-Listener für Ihren Anwendungskontext zu registrieren und die Profile aus der Umgebung auszudrucken. Ich habe es auf diese Weise nicht selbst versucht, daher kann Ihre Laufleistung variieren. Ich denke, vielleicht etwas wie das, was hier skizziert ist:

How to add a hook to the application context initialization event?

Dann sind Sie so etwas wie dies in Ihrem Zuhörer tun würde:

System.out.println("Active profiles: " + Arrays.toString(ctxt.getEnvironment().getActiveProfiles())); 

könnte einen Versuch wert sein. Eine andere Möglichkeit, die Sie wahrscheinlich tun könnten, wäre, die Umgebung so zu deklarieren, dass sie in den Code injiziert wird, in dem Sie die Profile drucken müssen. Beispiel:

+0

ich den Ansatz, die Ergebnisse von 'getEnvironment Protokollierung() getActiveProfiles()', als Teil der Start-up-Logging in meiner Anwendung 'Haupt' Methode. – Steve

2

Wenn application.yml Fehler enthält, führt dies beim Start zu einem Fehler. Ich denke, es kommt darauf an, was du mit "Fehler" meinst. Sicherlich wird es scheitern, wenn die YAML nicht gut ausgebildet ist. Wenn Sie beispielsweise @ConfigurationProperties setzen, die beispielsweise als ignoreInvalidFields=true markiert sind, oder wenn Sie einen Wert festlegen, der nicht konvertiert werden kann. Das sind ziemlich viele Fehler.

Die aktiven Profile werden wahrscheinlich durch die Environment Implementierung beim Start angemeldet werden (aber in jedem Fall ist es einfach für Sie, dass und melden Sie es in Ihrem Launcher Code greifen - die toString() von teh Environment werden die aktiven Profile Liste glaube ich) . Aktive Profile (und mehr) sind auch am Endpunkt/env verfügbar, wenn Sie den Aktuator hinzufügen.

5

Aktuator/env-Dienst zeigt Eigenschaften an, aber es zeigt nicht an, welcher Eigenschaftswert tatsächlich aktiv ist. Sehr oft können Sie Ihre Anwendungseigenschaften mit

  • profilspezifische Anwendungseigenschaften
  • Befehlszeilenargumente
  • OS Umgebungsvariablen

So außer Kraft setzen werden Sie die gleiche Eigenschaft und unterschiedliche Werte haben in mehreren Quellen.

Snippet unten druckt aktive Anwendung Eigenschaften Werte beim Start:

@Configuration 
public class PropertiesLogger { 
    private static final Logger log = LoggerFactory.getLogger(PropertiesLogger.class); 

    @Autowired 
    private AbstractEnvironment environment; 

    @PostConstruct 
    public void printProperties() { 

     log.info("**** APPLICATION PROPERTIES SOURCES ****"); 

     Set<String> properties = new TreeSet<>(); 
     for (PropertiesPropertySource p : findPropertiesPropertySources()) { 
      log.info(p.toString()); 
      properties.addAll(Arrays.asList(p.getPropertyNames())); 
     } 

     log.info("**** APPLICATION PROPERTIES VALUES ****"); 
     print(properties); 

    } 

    private List<PropertiesPropertySource> findPropertiesPropertySources() { 
     List<PropertiesPropertySource> propertiesPropertySources = new LinkedList<>(); 
     for (PropertySource<?> propertySource : environment.getPropertySources()) { 
      if (propertySource instanceof PropertiesPropertySource) { 
       propertiesPropertySources.add((PropertiesPropertySource) propertySource); 
      } 
     } 
     return propertiesPropertySources; 
    } 

    private void print(Set<String> properties) { 
     for (String propertyName : properties) { 
      log.info("{}={}", propertyName, environment.getProperty(propertyName)); 
     } 
    } 

} 
+0

Das hat nichts für mich gedruckt. – pacoverflow

+0

Nichts? Meinst du nicht auch "**** APPLICATION PROPERTIES SOURCES ****" ist auf @PostConstruct gedruckt? Zuerst würde ich sicherstellen, dass das PropertiesLogger-Objekt überhaupt in Ihrer Anwendung erstellt wird. Vielleicht kann etwas helfen @EnableAutoConfiguration. –

+1

Ich meine, es ausgedruckt "**** APPLIKATION EIGENSCHAFTEN QUELLEN ****" gefolgt von nichts gefolgt von "**** APPLIKATION EIGENSCHAFTEN WERTE ****", gefolgt von nichts. – pacoverflow

0

Falls Sie die aktiven Profile erhalten möchten, bevor Sie die Bohnen/Anwendung initialisiert, der einzige Weg, fand ich eine benutzerdefinierte Banner in SpringApplication Registrierung/Erbauer.

0

Zusätzlich zu anderen Antworten: aktive Eigenschaften für kontextaktualisiertes Ereignis protokollieren.

Java 8

package mypackage; 

import lombok.extern.slf4j.Slf4j; 
import org.springframework.context.event.ContextRefreshedEvent; 
import org.springframework.context.event.EventListener; 
import org.springframework.core.env.ConfigurableEnvironment; 
import org.springframework.core.env.MapPropertySource; 
import org.springframework.stereotype.Component; 

import java.util.ArrayList; 
import java.util.Collection; 
import java.util.List; 

@Slf4j 
@Component 
public class AppContextEventListener { 

    @EventListener 
    public void handleContextRefreshed(ContextRefreshedEvent event) { 
     printActiveProperties((ConfigurableEnvironment) event.getApplicationContext().getEnvironment()); 
    } 

    private void printActiveProperties(ConfigurableEnvironment env) { 

     System.out.println("************************* ACTIVE APP PROPERTIES ******************************"); 

     List<MapPropertySource> propertySources = new ArrayList<>(); 

     env.getPropertySources().forEach(it -> { 
      if (it instanceof MapPropertySource && it.getName().contains("applicationConfig")) { 
       propertySources.add((MapPropertySource) it); 
      } 
     }); 

     propertySources.stream() 
       .map(propertySource -> propertySource.getSource().keySet()) 
       .flatMap(Collection::stream) 
       .distinct() 
       .sorted() 
       .forEach(key -> { 
        try { 
         System.out.println(key + "=" + env.getProperty(key)); 
        } catch (Exception e) { 
         log.warn("{} -> {}", key, e.getMessage()); 
        } 
       }); 
     System.out.println("******************************************************************************"); 
    } 
} 

Kotlin

package mypackage 

import mu.KLogging 
import org.springframework.context.event.ContextRefreshedEvent 
import org.springframework.context.event.EventListener 
import org.springframework.core.env.ConfigurableEnvironment 
import org.springframework.core.env.MapPropertySource 
import org.springframework.stereotype.Component 

@Component 
class AppContextEventListener { 

    companion object : KLogging() 

    @EventListener 
    fun handleContextRefreshed(event: ContextRefreshedEvent) { 
     printActiveProperties(event.applicationContext.environment as ConfigurableEnvironment) 
    } 

    fun printActiveProperties(env: ConfigurableEnvironment) { 
     println("************************* ACTIVE APP PROPERTIES ******************************") 
     env.propertySources 
       .filter { it is MapPropertySource } 
       .map { it as MapPropertySource } 
       .filter { it.name.contains("applicationConfig") } 
       .map { it -> it.source.keys } 
       .flatMap { it } 
       .distinctBy { it } 
       .sortedBy { it } 
       .forEach { it -> 
        try { 
         println("$it=${env.getProperty(it)}") 
        } catch (e: Exception) { 
         logger.warn("$it -> ${e.message}") 
        } 
       } 
     println("******************************************************************************") 
    } 
} 

Ausgabe wie:.

************************* ACTIVE APP PROPERTIES ****************************** 
server.port=3000 
spring.application.name=my-app 
... 
2017-12-29 13:13:32.843 WARN 36252 --- [   main] m.AppContextEventListener  : spring.boot.admin.client.service-url -> Could not resolve placeholder 'management.address' in value "http://${management.address}:${server.port}" 
... 
spring.datasource.password= 
spring.datasource.url=jdbc:postgresql://localhost/my_db?currentSchema=public 
spring.datasource.username=db_user 
... 
****************************************************************************** 
Verwandte Themen