Spring 启动嵌入式 tomcat 日志

Spring boot embedded tomcat logs

我正在使用 spring boot embedded tomcat with spring boot 1.5.9, 我也在使用 Log4j2。

最近我在加载过程中遇到问题,所以我想更好地理解 tomcat 日志 [不是访问日志],我试过(在 application.properties 中):

logging.level.org.apache.tomcat: INFO
logging.level.org.apache.catalina: INFO

但是上面的 none 有效。还有其他方法可以实现吗?

为 Java Util Logging、Log4J、Log4J2 和 Logback 提供默认配置。在每种情况下,记录器都预先配置为使用控制台输出,也可以使用可选的文件输出

参考这个 link :

spring 中的嵌入式 tomcat 引导在内部将日志回显到控制台。 默认日志配置将在写入时将消息回显到控制台。因此,除非您按照您的描述明确指定文件,否则它会保留在控制台中。

来自spring boot logging doc.

您可以根据需要自定义日志记录。

我费了好大劲,没找到我的 help.Utlimately 我已经从我的 spring 启动 application.Deploy 构建了“WAR”到 tomcat实例和 遵循以下步骤,将所有内部 tomcat 日志(JULI)日志重定向到我的应用程序日志文件。

  1. 删除现有的 JULI 库(CATALINA_HOME/bin/tomcat-juli.jar 文件)和现有的 Tomcat Java 日志配置文件(CATALINA_HOME/conf/logging.properties)。

  2. 从 Tomcat 下载的附加部分 (http://tomcat.apache.org/download-70.cgi) 下载 JULI Log4j Tomcat 库 (tomcat-juli.jar) .将下载的文件放到 CATALINA_HOME/bin 目录。

  3. 从 Tomcat 下载的附加部分下载 Tomcat JULI 适配器库 (tomcat-juli-adapters.jar)。将此文件放在 CATALINA_HOME/lib 目录中。

  4. 下载Log4j(1.2以上版本),将下载的库文件放到CATALINA_HOME/lib目录下

  5. 在以下位置创建 Log4j 配置文件:CATALINA_HOME/lib/log4j.properties。检查下面匹配默认 Java 日志记录配置的 log4j 配置。

  6. 重新启动Tomcat。

匹配默认值的 Log4j 配置文件 Tomcat 日志记录设置:

log4j.rootLogger=INFO, CATALINA
//Define all the appenders log4j.appender.CATALINA=org.apache.log4j.DailyRollingFileAppender
log4j.appender.CATALINA.File=${catalina.base}/logs/catalina.
log4j.appender.CATALINA.Append=true log4j.appender.CATALINA.Encoding=UTF-8

//Roll-over the log once per day
log4j.appender.CATALINA.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout

log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.LOCALHOST=org.apache.log4j.DailyRollingFileAppender
log4j.appender.LOCALHOST.File=${catalina.base}/logs/localhost.
log4j.appender.LOCALHOST.Append=true log4j.appender.LOCALHOST.Encoding=UTF-8
log4j.appender.LOCALHOST.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.LOCALHOST.layout = org.apache.log4j.PatternLayout
log4j.appender.LOCALHOST.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.MANAGER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.MANAGER.File=${catalina.base}/logs/manager.
log4j.appender.MANAGER.Append=true log4j.appender.MANAGER.Encoding=UTF-8
log4j.appender.MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.HOST-MANAGER=org.apache.log4j.DailyRollingFileAppender
log4j.appender.HOST-MANAGER.File=${catalina.base}/logs/host-manager.
log4j.appender.HOST-MANAGER.Append=true log4j.appender.HOST-MANAGER.Encoding=UTF-8
log4j.appender.HOST-MANAGER.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.HOST-MANAGER.layout = org.apache.log4j.PatternLayout
log4j.appender.HOST-MANAGER.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Encoding=UTF-8
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern = %d [%t] %-5p %c- %m%n

//Configure which loggers log to which appenders
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].
[localhost]=INFO,
 LOCALHOST
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].
[localhost].[/manager]=INFO,MANAGER
log4j.logger.org.apache.catalina.core.ContainerBase.[Catalina].
[localhost].[/host-manager]=
INFO, HOST-
MANAGER

您还可以在 GIT @ link

上查看可用的适配器

在您的 spring 引导应用程序中,您可以进行更改,例如从嵌入式 Tomcat 服务器添加和删除 jars、文件夹,甚至使用 [= 添加自定义配置文件62=] ,spring 开机.

找到了!!您现在可以通过 3 个简单的步骤在应用程序的 Log4j 日志文件中查看嵌入式 Tomcat 的内部日志:

1] 添加到您的 pom:

 <dependency>
      <groupId>org.apache.logging.log4j</groupId>
      <artifactId>log4j-jul</artifactId>
     </dependency>

2] 向您的 运行 arg 添加一个新的 JVM 参数,例如:

java -Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager -jar target/demo-0.0.1-SNAPSHOT.jar

3] 添加到您的 application.properties:

logging.level.org.apache=DEBUG

享受生活! :)

解释: 问题是因为 Log4j 日志级别没有传播到 JUL(这是嵌入式 tomcat 使用的实际日志记录方式)所以上面实现了与 JUL 和 Log4j 日志级别的连接。

参考: 阅读 Spring boot 1.5.10 发行说明(解决方案不需要)后,我看到了新文档,阐明了如何实现它并对其进行了解释:

https://github.com/spring-projects/spring-boot/issues/2923#issuecomment-358451260

对于 slf4j 和 Spring Boot 2 隐藏来自 Tomcat 的异常并自行处理:

  • 添加到 pom:

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jul-to-slf4j</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    
  • 添加到配置:

    @PostConstruct
    void postConstruct() {
        SLF4JBridgeHandler.install();
    }
    
  • 添加到application.yaml

    logging:
        level:
          org.apache.catalina: off
    
  • 处理 ErrorController

    中的异常
    @Controller
    @Slf4j
    public class ErrorController implements 
                  org.springframework.boot.web.servlet.error.ErrorController {
        private static final String ERROR_PATH = "/error";
    
       @Autowired
       private ErrorAttributes errorAttributes;
    
       @Override
       public String getErrorPath() {
          return ERROR_PATH;
       }
    
       @RequestMapping(ERROR_PATH)
       public ModelAndView error(HttpServletRequest request) {
           return processException(errorAttributes.getError(new ServletWebRequest(request)));
       }
    }
    

org.apache.catalina.valves.AccessLogValve 生成的日志文件,通常命名为 localhost_access_log 可以这样配置:

@Configuration
public class EmbeddedTomcatConfig {
    @Bean
    public TomcatEmbeddedServletContainerFactory containerFactory() {
        TomcatEmbeddedServletContainerFactory tomcatEmbeddedServletContainerFactory = new TomcatEmbeddedServletContainerFactory();
        AccessLogValve accessLogValve = new AccessLogValve();
        // set desired properties like
        accessLogValve.setDirectory(...);
        tomcatEmbeddedServletContainerFactory.addEngineValves(accessLogValve);
        return tomcatEmbeddedServletContainerFactory;
    }
}

或者,使用 Spring 启动 2 会更好:

   @Bean
   public WebServerFactoryCustomizer<TomcatServletWebServerFactory> customizer() {
        return container -> {
            AccessLogValve accessLogValve = new AccessLogValve();
            // set desired properties like
            accessLogValve.setDirectory("...");
            container.addEngineValves(accessLogValve);
        };
    }