Les Hazlewood
Les Hazlewood

Reputation: 19497

How do you tell Spring Boot to send the embedded Tomcat's access logs to stdout?

In a standalone Spring Boot web application (executable jar), how do you tell Spring Boot that we want the embedded Tomcat instance's HTTP access logs to be sent to stdout?

Upvotes: 30

Views: 35200

Answers (5)

JohanB's solution works, but if you don't want to write code, someone did it better and wrapped Server access logs in a nice Spring Boot starter. It covers Tomcat, Jetty and Undertow.

Just add the dependency:

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

And a logback-access.xml file at the classpath root:

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

and the access logs are printed to stdout:

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

At this point you will need to create the TeeFilter Bean on your own if you want to print the full HTTP request & response for debugging.

Upvotes: 4

Sebastian
Sebastian

Reputation: 5865

Update 2019.02.11:

These inks should be useful to map which properties you should set in application.properties:


@acohen answer is slightly correct. If you provide the empty double quotes it won't work. I will extend his answer because I think it's important for people who don't want to mess with adding dependencies or modifying code:

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=

Notes

  1. If you set file-date-format and suffix to be double quotes, you will have this error:
java.io.FileNotFoundException: /dev/stdout"""" (Permission denied)

  1. If you don't include them in the config file, you will then be using defaults values and this error:
java.io.FileNotFoundException: /dev/stdout.2019-02-07.log (Permission denied)
  1. If you leave them empty, then it will work.

Upvotes: 43

okrunner
okrunner

Reputation: 3193

This did it for me on 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=""

Upvotes: 9

Chris Paika
Chris Paika

Reputation: 97

Here's the followup up on the great answer from JohanB, for Spring Boot 2.0.0+.

In Spring Boot 2.0.0, the EmbeddedServletContainerFactory was replaced with TomcatServletWebServerFactory. All other aspects of JohanB's answer still works correctly the factory bean creation just needs to be modified:

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

Upvotes: 5

JohanB
JohanB

Reputation: 2148

If you use Logback, you can use logback-access for this.

Add dependency ch.qos.logback:logback-access

Optional Javaconfig to add TeeFilter (request & response logging):

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

Javaconfig for embedded tomcat:

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

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

    return tomcat;
}

Contents for logback-access.xml (save in 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>

Upvotes: 20

Related Questions