【问题标题】:How to turn off output from shutdown hooks in gradle boot tests?如何在 gradle 启动测试中关闭关闭挂钩的输出?
【发布时间】:2020-05-18 00:08:07
【问题描述】:

你可以从https://start.spring.io/starter.zip?type=gradle-project&language=java&bootVersion=2.2.5.RELEASE&baseDir=demo&groupId=com.example&artifactId=demo&name=demo&description=Demo%20project%20for%20Spring%20Boot&packageName=com.example.demo&packaging=jar&javaVersion=1.8&dependencies=h2,data-jpa,web这个issue从start.spring.io生成一个项目

我有一个用 gradle 构建的多模块 springBoot 应用程序,有一堆 SpringBoot 集成测试。当我进行构建时,我最终会得到一些从 SpringBoot 关闭到控制台的输出,如下所示。如何关闭此输出?

± |master ↑1 {1} S:3 U:10 ✗| → ./gradlew build

> Task :core:test
2020-02-01 11:20:33.529  INFO 24114 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-02-01 11:20:33.531  INFO 24114 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-02-01 11:20:33.538  INFO 24114 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

> Task :email:test
2020-02-01 11:20:43.820  INFO 24150 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-02-01 11:20:43.820  INFO 24150 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-02-01 11:20:43.822  INFO 24150 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Shutdown initiated...
2020-02-01 11:20:43.822  INFO 24150 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-02-01 11:20:43.830  INFO 24150 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.
2020-02-01 11:20:43.830  INFO 24150 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-2 - Shutdown completed.

> Task :security:test
2020-02-01 11:20:54.941  INFO 24188 --- [extShutdownHook] j.LocalContainerEntityManagerFactoryBean : Closing JPA EntityManagerFactory for persistence unit 'default'
2020-02-01 11:20:54.944  INFO 24188 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown initiated...
2020-02-01 11:20:54.952  INFO 24188 --- [extShutdownHook] com.zaxxer.hikari.HikariDataSource       : HikariPool-1 - Shutdown completed.

Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0.
Use '--warning-mode all' to show the individual deprecation warnings.
See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings

BUILD SUCCESSFUL in 46s
57 actionable tasks: 54 executed, 3 up-to-date

作为参考,使用 gradle 从 start.spring.io 创建的应用程序不会在屏幕上产生任何输出

./gradlew build

BUILD SUCCESSFUL in 779ms
5 actionable tasks: 5 up-to-date

而是将输出放在build/reports/

在我的情况下,我没有对引导附带的日志记录配置进行任何更改。没有 logback.xml,或对日志级别的 application.yml 进行更改。我期待 gradle 正在捕获系统输出和系统错误并将它们发送到build/reports/,但一些输出似乎正在逃逸到系统输出。

【问题讨论】:

  • 将这些包或类的日志级别调整为低于INFO(或完全删除)。
  • 这些是INFO 级别的日志行。如您所见,它们源自关闭挂钩,并且它们最终出现在配置日志记录的位置。我想从理论上讲,由于日志记录配置的更改以及随后异步执行的钩子,消息可能最终出现在与预期不同的位置。所以它会将这些行默认到控制台,因为之前的配置已被卸载。也许吧。
  • 你能添加你的测试类,以及你的主应用程序类吗?以及任何与数据源配置相关的 application.properties/yml?
  • 可能是关闭挂钩发生在 Gradle 测试工作进程在其输出重定向被拆除后被关闭时。这可能值得一个 gradle/gradle 问题来开启讨论。
  • 理想情况下,spring boot 在您的测试中是关闭的,而不必依赖 jvm 关闭挂钩,这将是一个 spring 问题。

标签: java spring-boot gradle


【解决方案1】:

@eskatos 是对的。在关闭工作进程之前执行测试用例后,日志管理器被拆除。当工作进程关闭并重定向回控制台时,将执行所有关闭挂钩。

由于这些消息是由 spring boot 生成的,最好的地方是使用 logback 测试配置 xml 过滤关闭消息。

src/test/resources 中类似于 logback-test.xml 的东西

<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.core.filter.EvaluatorFilter">
            <evaluator> <!-- defaults to type ch.qos.logback.classic.boolex.JaninoEventEvaluator -->
                <expression>return event.getThreadName().contains("ShutdownHook");</expression>
            </evaluator>
            <OnMismatch>NEUTRAL</OnMismatch>
            <OnMatch>DENY</OnMatch>
        </filter>
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="INFO">
        <appender-ref ref="STDOUT" />
    </root>
</configuration>

build.gradle

testCompile 'org.codehaus.janino:janino'

【讨论】:

    【解决方案2】:

    可以使用TestLoggingContainer testLogging.showStandardStreams = false 禁用输出 决定在Test 任务中记录onOutput 的内容,以控制测试JVM 的stdout/stderr:

    apply plugin: 'java'
    
    test {
    
        // show standard out and standard error of the test JVM on the console
        // can be used to disable the console output:
        testLogging.showStandardStreams = true
    
        // listen to standard out and standard error of the test JVM
        // can be used to make the logging optional:
        onOutput { descriptor, event ->
            logger.lifecycle("Test: " + descriptor + " produced standard out/err: " + event.message)
        }
    }
    

    这些流是来自 JVM 的 TestLogEvent STANDARD_OUTSTANDARD_ERROR。当可以确定包含extShutdownHookevent.message 时,可以跳过日志记录。

    【讨论】:

    • start.spring.io/…可以从start.spring.io生成一个项目到这个issue来重现这个issue
    • 这可能不是问题,因为INFO 是 Spring 的默认日志记录级别;可以设置其他日志级别,例如。 logging.level.org.springframework=TRACE 作为环境变量。
    • 我相信关闭挂钩日志是在测试任务之外生成的。您能否更新您的答案以显示如何过滤关闭挂钩消息?我认为过滤这些消息的最佳位置是它们在 Spring Boot 中的生成位置。
    【解决方案3】:

    我可以隐藏 spring-data 特定的测试记录(基于this spring-starter) 通过将以下application.properties 添加到 src/test/resources:

    logging.level.root=ERROR
    

    logging.level.org.springframework 不会影响例如com.zaxxer.hikari 记录器,但你在这里有 flexible options

    root=ERROR 就像“大锤方法”)。

    src/main/resources 也是可能的,但不仅在测试时有效,而且在应用程序运行时也有效) (application.properties 只是此属性的 many possible "locations" 之一...另请参阅:https://docs.spring.io/spring-boot/docs/current/reference/html/appendix-application-properties.html

    有了这个,我得到一个“静默”的 gradle 输出,也在 clean build:

    $ ./gradlew clean build
    
    BUILD SUCCESSFUL in 10s
    7 actionable tasks: 7 executed
    

    【讨论】:

      【解决方案4】:

      Gradle 有一个安静模式。

      ./gradlew build -q

      但您仍然需要有关测试的信息。你可以使用 jacoco 和 sonarqube。它对我有用 herehere

      【讨论】:

        【解决方案5】:

        Spring Boot 2.5 更新

        此解决方案不再有效。 有关详细信息,请参阅此 GitHub 问题:https://github.com/spring-projects/spring-boot/issues/28108


        在最近的版本中,Spring Boot 具有在退出之前关闭日志系统的属性。将以下行添加到您的配置中:

        src/test/resources/application.yaml

        logging:
          register-shutdown-hook: true
        

        src/test/resources/application.properties

        logging.register-shutdown-hook=true
        

        属性定义和文档可以在 GitHub 上的 Spring Boot 存储库中找到:https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot/src/main/resources/META-INF/additional-spring-configuration-metadata.json

        {
          "name": "logging.register-shutdown-hook",
          "type": "java.lang.Boolean",
          "description": "Register a shutdown hook for the logging system when it is initialized. Disabled automatically when deployed as a war file.",
          "sourceType": "org.springframework.boot.context.logging.LoggingApplicationListener",
          "defaultValue": true
        }
        

        运行测试时似乎默认未注册关闭挂钩。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2015-12-27
          • 2011-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2010-10-07
          相关资源
          最近更新 更多