2017-03-23 31 views
7

在开发和测试环境下,ROOT记录器级别为DEBUG或INFO。弹簧启动横幅显示在应用程序启动:显示带Root Logger的Spring-Boot Banner WARN

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 

但在生产环境中运行时,我的根记录水平通常是WARN。这导致横幅不被打印出来。

如何配置logback,以便在生产中显示横幅?

我的猜测是,添加另一个记录仪,但以下(和相似配置)没有工作:

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

这里我的配置

application.properties:

spring.main.banner-mode=log 

应用-devel.properties:

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

application-production.properties:

测井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> 

测井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

在打印过程中,Spring Boot使用类org.springframework.boot.SpringApplicationINFO级别的记录器。

的simples的解决办法是让这个特殊类INFO级别:

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

更改日志记录级别为一类是去照你说的最好的方式。 Spring Boot的另一种方法是通过Environment属性,我将其作为JVM参数传入, -Dlogging.level.org.springframework.boot.SpringApplication = INFO – PaulNUK

+0

工作:)非常感谢。 – Hannes

0

这是,我想出了什么。它包含了在常规实施中更换记录器的想法。

使用默认日志实现的问题是通过slf4j桥改编commons-logging的方式。

这可能是最丑陋的代码活着之一,所以希望我们将看到在即将到来的春季启动版本修复...

第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; 
    } 
} 
0

首先,我必须承认,我没有测试过这个,但至少它可能会给你一些想法。

您可以删除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.warn取代logger.info也可以此logger specificaly创建额外的配置:

<logger name="your.package.name.BannerLoggerWrapper" level="INFO" additivity="false"> 
    <appender-ref ref="FILE"/> 
</logger> 

根据documentation你可以配置Spring引导到使用SpringApplication.setBanner(…​)使用Banner实现。