1

I have a spring boot application, which runs on AWS EC2 instances.

The deployable is just a jar that has tomcat embedded in it.

I am trying to get the application to send its access log to syslog so that I can use AWS CloudWatch to collect logs from different EC2 instances.

I have tried https://logback.qos.ch/access.html, but it does not work with syslog due to this issue: https://jira.qos.ch/browse/LOGBACK-317

Then I tried CommonsRequestLoggingFilter, this does not seem to send its logs to syslog.

I guess trying to send logs to syslog with Spring boot application is not a rare desire.

Is there any comprehensive way to do this?

Cui Pengfei 崔鹏飞
  • 8,017
  • 6
  • 46
  • 87
  • Possible duplicate of [Tomcat access logging through log4j?](https://stackoverflow.com/questions/18056682/tomcat-access-logging-through-log4j) – Strelok Jul 04 '18 at 14:12

1 Answers1

2

I just implemented this in my application. (For Spring boot 1.5.6)

  1. Make sure your tomcat access logging is on, below is the way access logging is enabled in application.yml -

    server: 
     tomcat:
      accesslog:
        enabled: true
        pattern: "<APPNAME> %h %l %u %t \"%r\" %s %b %D"
        prefix: "localhost_access_log"
        suffix: .txt
      basedir: /opt/tomcat 
    
  2. The above will output the access logs in your instances.

  3. Now have your logging defined. For example in application.yml file

    logging:
      level:
        org.springframework.web: INFO
        com.project.path : DEBUG
      config: <path to your config xxml>/logback-springboot.xml
    
  4. The above will get your logback config file from the desired location.
  5. Now, in your code, you need to define your own tomcat access config. For example -

    @Configuration
    public class AccessValveConfig extends WebMvcConfigurerAdapter implements
     EmbeddedServletContainerCustomizer {
    
     private static XLogger logger = XLoggerFactory
        .getXLogger(AccessValveConfig.class);
    
    
     @Override
      public void customize(ConfigurableEmbeddedServletContainer container) {
    
         if (container instanceof TomcatEmbeddedServletContainerFactory) {
    
            TomcatEmbeddedServletContainerFactory factory = 
                  (TomcatEmbeddedServletContainerFactory) container;
            AbstractAccessLogValve accessLogValve = new ApiAccessLogValve();
            accessLogValve.setPattern("common");
            factory.addContextValves(accessLogValve);
         } else {
         logger.error("WARNING! this customizer does not support your 
                 configured container");
        }
     }
    }
    
    public class ApiAccessLogValve extends AbstractAccessLogValve {
    
      private static XLogger logger = XLoggerFactory
        .getXLogger(ApiAccessLogValve.class);
    
      public ApiAccessLogValve(){
       super();
      }
    
     @Override
     protected void log(CharArrayWriter message) {
       synchronized (this) {
        logger.info(message.toString());
       }
     }
    }
    
  6. Now make the necessary configs in your logback xml.

    <!--This will print app logs in user facility-->
    <appender name="SYSLOG" class="ch.qos.logback.classic.net.SyslogAppender">
     <syslogHost><<your host name>></syslogHost>
     <port>514</port>
     <facility>USER</facility>
     <suffixPattern><<your pattern>></suffixPattern>
    </appender>
    <!-- This will print your access logs in local0 facility-->
    <appender name="LOCAL0" class="ch.qos.logback.classic.net.SyslogAppender">
      <syslogHost><<your host name>></syslogHost>
      <port>514</port>
      <facility>LOCAL0</facility>
      <suffixPattern><<pattern>></suffixPattern>
    </appender>
    
    <Logger name="package path to ApiAccessLogValve" level="INFO" 
        additivity="false">
       <appender-ref ref="LOCAL0" />
    </Logger>
    

Now you are all set.

KRV
  • 66
  • 4