programing

Spring Boot 어플리케이션에서 액티브 설정을 기록하려면 어떻게 해야 합니까?

magicmemo 2023. 3. 17. 20:32
반응형

Spring Boot 어플리케이션에서 액티브 설정을 기록하려면 어떻게 해야 합니까?

Spring Boot에 YAML 설정을 사용하고 싶습니다.다른 프로파일로 액티브한 속성을 나타내는 파일이 1개 있으면 읽기 쉽고 편리하기 때문입니다.불행히도, 저는 그 설정 속성을 찾고 있습니다.application.yml깨지기 쉬워요.

공백 대신 탭을 사용하면 속성이 존재하지 않고(경고 없이) YAML에서 알 수 없는 문제가 발생하여 활성 프로파일이 설정되지 않는 경우가 많습니다.

그래서 현재 액티브한 프로파일과 속성을 입수하여 로그에 기록할 수 있는 후크가 있는지 궁금했습니다.

마찬가지로 기동이 실패하는 원인이 되는 것은application.yml에러가 포함되어 있습니까?혹은 제가 직접 YAML을 검증하고 스타트업 프로세스를 종료할 수 있도록 하기 위한 수단입니다.

다른 답변과 함께 컨텍스트 새로 고침 이벤트에서 활성 속성을 로깅합니다.

자바 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("******************************************************************************");
    }
}

코틀린

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.name.contains("applicationConfig") }
                .map { it as EnumerablePropertySource<*> }
                .map { it -> it.propertyNames.toList() }
                .flatMap { it }
                .distinctBy { it }
                .sortedBy { it }
                .forEach { it ->
                    try {
                        println("$it=${env.getProperty(it)}")
                    } catch (e: Exception) {
                        logger.warn("$it -> ${e.message}")
                    }
                }
        println("******************************************************************************")
    }
}

출력:

************************* 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
...
******************************************************************************

저도 같은 문제가 있었습니다.프로파일 처리 시스템에 유용한 로깅을 출력하도록 지시하는 디버깅플래그가 있으면 좋겠습니다.응용 프로그램 컨텍스트의 이벤트청취자를 등록하고 환경에서 프로파일을 인쇄하는 방법이 있습니다.저도 이런 식으로 해 본 적이 없기 때문에 주행거리가 다를 수 있습니다.아마 여기에 나와 있는 것과 같은 것이 있을 겁니다.

애플리케이션 컨텍스트 초기화 이벤트에 후크를 추가하려면 어떻게 해야 합니까?

그런 다음 청취자에게 다음과 같은 동작을 할 수 있습니다.

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

시도해 볼 가치가 있을 거야.프로파일을 인쇄할 필요가 있는 코드에 환경 투입을 선언하는 방법도 있습니다.예:

@Component
public class SomeClass {
  @Autowired
  private Environment env;
  ...
  private void dumpProfiles() {
    // Print whatever needed from env here
  }
}

액추에이터 /env 서비스는 속성을 표시하지만 실제로 활성 상태인 속성 값은 표시하지 않습니다.응용 프로그램 속성을 덮어쓰는 경우가 많습니다.

  • 프로필별 응용 프로그램 속성
  • 명령줄 인수
  • OS 환경 변수

따라서 여러 소스에서 동일한 속성과 다른 값을 갖게 됩니다.

아래는 시작 시 활성 응용 프로그램 속성 값을 인쇄합니다.

@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));
        }
    }

}

ifapplication.yml에러가 포함되어 있어 기동시에 에러가 발생합니다.하지만 '오류'가 무슨 뜻인지에 따라 다르겠죠.YAML을 사용하다, 「 」, 「 」를 설정하고 는,@ConfigurationProperties라고 표시되어 있다ignoreInvalidFields=true예를 들어 변환할 수 없는 값을 설정한 경우 등입니다.그것은 꽤 광범위한 오류입니다.

에, 「」, 「」에 됩니다.Environment코드에 할 수 toString()teh Environment(미국의액튜에이터를 추가하면 /env 엔드포인트에서도 활성 프로파일(및 기타)을 사용할 수 있습니다.

콩/어플리케이션을 초기화하기 전에 액티브프로파일을 가져오려면 Spring Boot Servlet에 커스텀배너를 등록하는 방법밖에 없었습니다.Initializer/Spring Application(JHipster 응용 프로그램의 ApplicationWebXml).

예.

@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder)
{
    // set a default to use when no profile is configured.
    DefaultProfileUtil.addDefaultProfile(builder.application());
    return builder.sources(MyApp.class).banner(this::printBanner);
}

/** Custom 'banner' to obtain early access to the Spring configuration to validate and debug it. */
private void printBanner(Environment env, Class<?> sourceClass, PrintStream out)
{
    if (env.getProperty("spring.datasource.url") == null)
    {
        throw new RuntimeException(
            "'spring.datasource.url' is not configured! Check your configuration files and the value of 'spring.profiles.active' in your launcher.");
    }
    ...
}

언급URL : https://stackoverflow.com/questions/24448947/how-to-log-the-active-configuration-in-a-spring-boot-application

반응형