使用Root-Logger显示Spring-Boot横幅WARN

时间:2017-03-23 13:52:28

标签: java spring spring-mvc spring-boot logback

在开发和测试环境下,ROOT记录器级别为DEBUG或INFO。应用程序启动时会显示spring-boot标题:

2017-03-23 14:31:00,322 [INFO ]                 - 
 :: Spring Boot ::         (v1.5.2.RELEASE)
 :: Application ::         AcMe (v1.0-SNAPSHOT)
 :: Build ::               2017-03-23 09:53

但是在生产环境中运行时,我的ROOT记录器级别通常是WARN。这会导致横幅打印不出来。

如何配置回溯以便横幅广告也会在制作中显示?

我的猜测是添加另一个记录器,但以下(和相似的配置)不起作用:

<logger name="org.springframework.web" level="INFO" additivity="false">
    <appender-ref ref="FILE"/>
</logger>

这是我的配置

application.properties:

  spring.main.banner-mode=log

application-devel.properties:

  logging.config=classpath:logging-spring-devel.xml

application-production.properties:

  logging.config=classpath:logging-spring-production.xml

logging-devel.xml(显示横幅)

        LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}application.log}"/>
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_FILE}</file>
            ...
        </appender>
        <root level="INFO">
            <appender-ref ref="FILE"/>
        </root>
    </configuration>

logging-production.xml(横幅未显示)

        LOG_PATH:-${LOG_TEMP:-${java.io.tmpdir:-/tmp}}/}application.log}"/>
        <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_FILE}</file>
            ...
        </appender>
        <root level="WARN">
            <appender-ref ref="FILE"/>
        </root>
    </configuration>

4 个答案:

答案 0 :(得分:6)

在打印横幅时,Spring Boot使用org.springframework.boot.SpringApplication等级为INFO的记录器。

简单的解决方案是为此特定类启用INFO级别:

<logger name="org.springframework.boot.SpringApplication"
        level="INFO" additivity="false">
    <appender-ref ref="FILE"/>
</logger>

答案 1 :(得分:1)

我遇到了同样的问题,只是在application.properties中设置了此属性:

spring.main.banner-mode=LOG

现在,它以日志级别INFO打印到控制台和文件。只要您已将根日志级别和附加程序设置为接受INFO,就可以看到它。

<root level="info">
    <appender-ref ref="RollingFile" />
    <appender-ref ref="Console" />
</root>

答案 2 :(得分:0)

这就是我想出的。它包含了在常规实现中更换记录器的想法。

使用默认日志实现的问题是通过slf4j bridge调整commons-logging的方式。

这可能是最活跃的代码之一,所以希望我们会在即将发布的spring-boot发行版中看到修复...

步骤1:注册新的应用程序监听器

/META-INF/spring.factory

 org.springframework.context.ApplicationListener=ac.me.appevents.BannerDisplay

第2步:实施应用程序监听器

package ac.me.appevents;

import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.Marker;
import org.slf4j.MarkerFactory;
import org.springframework.boot.ResourceBanner;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.env.Environment;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.ClassUtils;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.io.UnsupportedEncodingException;

public class BannerDisplay implements ApplicationListener<ApplicationEnvironmentPreparedEvent> {
    /**
     * Banner location property key.
     */
    private static final String BANNER_LOCATION_PROPERTY = "banner.location";

    /**
     * Default banner location.
     */
    private static final String BANNER_LOCATION_PROPERTY_VALUE = "banner.txt";

    private static final Logger LOG = LoggerFactory.getLogger(BannerDisplay.class);

    private static final Marker MRK = MarkerFactory.getMarker("Banner");

    private ResourceLoader resourceLoader;

    private Class<?> deduceMainApplicationClass() {
        try {
            StackTraceElement[] stackTrace = new RuntimeException().getStackTrace();
            for (StackTraceElement stackTraceElement : stackTrace) {
                if ("main".equals(stackTraceElement.getMethodName())) {
                    return Class.forName(stackTraceElement.getClassName());
                }
            }
        }
        catch (ClassNotFoundException ex) {
            // Swallow and continue
        }
        return null;
    }

    @Override
    public void onApplicationEvent(ApplicationEnvironmentPreparedEvent event) {
        Environment environment = event.getEnvironment();

        String location = environment.getProperty(BANNER_LOCATION_PROPERTY, BANNER_LOCATION_PROPERTY_VALUE);
        ResourceLoader resLoader = getResourceLoader();
        Resource resource = resLoader.getResource(location);
        if (resource.exists()) {
            ResourceBanner banner = new ResourceBanner(resource);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            banner.printBanner(environment, deduceMainApplicationClass(), new PrintStream(baos));
            String charset = environment.getProperty("banner.charset", "UTF-8");
            try {

                LOG.info(MRK, baos.toString(charset));
            }
            catch (UnsupportedEncodingException e) {
                LOG.warn(MRK, "Unsupported banner charset encoding.", e);
            }

        }
    }

    @NotNull
    private ResourceLoader getResourceLoader() {
        if (resourceLoader == null) {
            this.resourceLoader = new DefaultResourceLoader(ClassUtils.getDefaultClassLoader());
        }
        return resourceLoader;
    }

    public void setResourceLoader(final ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }
}

答案 3 :(得分:0)

首先,我必须承认我没有对此进行测试,但至少它可能会给你一些想法。

您可以删除var results = Regex.Matches(s, @"(?<!{){{{([^{}]*)}}}(?!})") .Cast<Match>() .Select(m => m.Groups[1].Value) .ToList(); 并提供自己的包装器实现,该实现将使用记录器而不是提供的输出流。代码看起来像这样:

spring.main.banner-mode=log

您可以在此课程中将public class BannerLoggerWrapper implements Banner { private static final Log logger = LogFactory.getLog(BannerLoggerWrapper.class); private Banner actual; public BannerLoggerWrapper(Banner actual) { this.actual = actual; } @Override public void printBanner(Environment environment, Class<?> sourceClass, PrintStream out) { try { logger.info(createStringFromBanner(environment, sourceClass)); } catch (UnsupportedEncodingException ex) { logger.warn("Failed to create String for banner", ex); } } private String createStringFromBanner(Environment environment, Class<?> sourceClass) throws UnsupportedEncodingException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); actual.printBanner(environment, sourceClass, new PrintStream(baos)); String charset = environment.getProperty("banner.charset", "UTF-8"); return baos.toString(charset); } } 替换为logger.info,或者您可以为此记录器创建特定的其他配置:

logger.warn

根据documentation,您可以使用<logger name="your.package.name.BannerLoggerWrapper" level="INFO" additivity="false"> <appender-ref ref="FILE"/> </logger> 配置Spring Boot以使用Banner实施。