你如何告诉 Spring Boot 将嵌入式 Tomcat 的访问日志发送到标准输出?

Posted

技术标签:

【中文标题】你如何告诉 Spring Boot 将嵌入式 Tomcat 的访问日志发送到标准输出?【英文标题】:How do you tell Spring Boot to send the embedded Tomcat's access logs to stdout? 【发布时间】:2016-08-15 07:24:36 【问题描述】:

在独立的 Spring Boot Web 应用程序(可执行 jar)中,如何告诉 Spring Boot 我们希望将嵌入式 Tomcat 实例的 HTTP 访问日志发送到标准输出?

【问题讨论】:

我认为您只需将日志记录级别设置为调试,因为 spring 和 tomcat 日志默认设置为 info。日志将具有完全限定的类名,以便您知道日志的来源。 @RahulSharma 日志级别对 appender 输出位置(例如文件、标准输出、URL 等)完全没有影响。我们需要所有输出(包括 Tomcat 访问日志)到标准输出。一切异常 Tomcat 都很简单,难的是 Tomcat 日志。 抱歉,我以为您想查看 100% 的日志。从docs spring boot 默认将日志写入控制台,所以我不知道你为什么看不到它们。另外,您是否使用嵌入式tomcat?如果是,请查看嵌入式服务器属性here 【参考方案1】:

2019.02.11 更新:

这些墨水应该有助于映射您应该在application.properties 中设置的属性:

tomcat undertow

@acohen 的回答稍微正确。如果您提供空的双引号,它将不起作用。我将扩展他的答案,因为我认为这对于不想添加依赖项或修改代码的人来说很重要:

config/application.properties

# here we say that we want to enable accesslog
server.tomcat.accesslog.enabled=true

# it is important to understand what the options means:
# 'directory/prefix + suffix + file-date-format' will be
# the file that tomcat will try to open.
# /dev/stdout is standard output, so we want tomcat
# to write to that fd. Then, we need to play with
# directory, prefix, suffix and file-date-format to match our desired path.
server.tomcat.accesslog.directory=/dev
server.tomcat.accesslog.prefix=stdout
server.tomcat.accesslog.buffered=false

# Don't use empty double quotes, see below
server.tomcat.accesslog.suffix=
server.tomcat.accesslog.file-date-format=

注意事项

    如果将file-date-formatsuffix设置为双引号,就会出现这个错误:
java.io.FileNotFoundException: /dev/stdout"""" (Permission denied)

    如果您不将它们包含在配置文件中,那么您将使用默认值并出现此错误:
java.io.FileNotFoundException: /dev/stdout.2019-02-07.log (Permission denied)
    如果您将它们留空,那么它会起作用。

【讨论】:

我试过 undertow,它仍然说 Failed to create access log directory 'logs'。我使用 server.undertow.accesslog.directory=/dev @ravthiru 我不熟悉undertow,可能猜到这个doc undertow 的选项是dir(因为方法是getDir())而不是directory。这只是一个猜测,告诉我这是怎么回事:) 我在 docker 容器中运行应用程序,所以我写入目录 /proc/1/fd 前缀为“1”,但由于某种原因,它在它之前添加了“management_”。无法打开访问日志文件 [/proc/1/fd/management_1] @AFP_555 我也在 docker 中运行它。不知道为什么 management_ 被加上前缀。听起来像记录器配置。你有一个可行的例子吗? @Sebastian 它显示了该错误,但之后一切都按预期工作。虽然很高兴没有看到那个错误。我认为原因是我们正在使用嵌入式服务器的“管理。*”配置。【参考方案2】:

如果你使用 Logback,你可以使用logback-access。

添加依赖ch.qos.logback:logback-access

添加 TeeFilter 的可选 Javaconfig(请求和响应日志记录):

@Bean(name = "TeeFilter")
public Filter teeFilter() 
    return new ch.qos.logback.access.servlet.TeeFilter();

嵌入式 tomcat 的 Javaconfig:

@Bean
public EmbeddedServletContainerFactory servletContainer() 
    TomcatEmbeddedServletContainerFactory tomcat = new TomcatEmbeddedServletContainerFactory();

    // put logback-access.xml in src/main/resources/conf
    tomcat.addContextValves(new LogbackValve());

    return tomcat;

logback-access.xml 的内容(保存在src/main/resources/conf

<configuration>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <Pattern>combined</Pattern>
      <Pattern>%fullRequest%n%n%fullResponse</Pattern>
    </encoder>
  </appender>

  <appender-ref ref="STDOUT" />

</configuration>

【讨论】:

我们确实使用了 Logback 并且已经使用了控制台附加程序 :) 缺少的部分是 TomcatEmbeddedServletContainerFactory bean 配置。很好的答案! 在 Spring Boot 中,它会尝试将 Valve 文件名作为类路径资源查找 - 如果“src/main/resources”在您的文件名文字中,它将无法找到。 更好的方法是将logback-access.xml 文件放在src/main/resources/conf 下。来自文档:默认情况下,LogbackValve 在 server.xml 所在的同一文件夹中查找名为 logback-access.xml 的配置文件,即 $TOMCAT_HOME/conf/。【参考方案3】:

这是在 Spring Boot 2.x 上为我完成的:

server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.directory=/dev
server.tomcat.accesslog.prefix=stdout
server.tomcat.accesslog.buffered=false
server.tomcat.accesslog.suffix=""
server.tomcat.accesslog.file-date-format=""

【讨论】:

你是在pivot/cf上运行这个吗? 带有application.yml的完整示例:***.com/a/62002598/8718377【参考方案4】:

以下是 JohanB 针对 Spring Boot 2.0.0+ 的出色回答的后续行动。

在 Spring Boot 2.0.0 中,EmbeddedServletContainerFactory 被替换为 TomcatServletWebServerFactory。 JohanB 的答案的所有其他方面仍然可以正常工作,只需要修改工厂 bean 创建:

@Bean
public TomcatServletWebServerFactory servletContainer() 
    TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
    // put logback-access.xml in src/main/resources/conf
    tomcat.addContextValves(new LogbackValve());
    return tomcat;

【讨论】:

这个怎么用?即,我把它放在哪里? 你必须把它放在一个 Java 类中,并在类上注解 @Configuration 以便 Spring 加载其中定义的 bean【参考方案5】:

JohanB 的解决方案有效,但如果您不想编写代码,有人会做得更好并包装 Server access logs in a nice Spring Boot starter。它涵盖了 Tomcat、Jetty 和 Undertow。

只需添加依赖即可:

<dependency>
    <groupId>net.rakugakibox.spring.boot</groupId>
    <artifactId>logback-access-spring-boot-starter</artifactId>
    <version>2.7.1</version>
</dependency>

还有一个位于类路径根目录的 logback-access.xml 文件:

<configuration>
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>common</pattern>
        </encoder>
    </appender>
    <appender-ref ref="CONSOLE" />
</configuration>

并将访问日志打印到标准输出:

127.0.0.1 - - [08/févr./2019:11:23:30 +0100] "GET /password HTTP/1.1" 200 32

此时,如果您想打印完整的 HTTP 请求和响应以进行调试,则需要 create the TeeFilter Bean on your own。

【讨论】:

以上是关于你如何告诉 Spring Boot 将嵌入式 Tomcat 的访问日志发送到标准输出?的主要内容,如果未能解决你的问题,请参考以下文章

如何在嵌入式 tomcat 服务器上部署 Spring Boot Web 应用程序,来自 Spring Boot 本身

当两个应用程序都使用嵌入式activemq时,如何将Jms消息从一个spring-boot应用程序发送到另一个应用程序

Spring Boot文档阅读笔记-how-to-implement-2-way-ssl-using-spring-boot

如何关闭spring boot嵌入式服务器

如何将JDBI添加到Spring Boot应用程序中?

将spring boot应用程序用作unix服务时如何调整jvm