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?
I just implemented this in my application. (For Spring boot 1.5.6)
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
The above will output the access logs in your instances.
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
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());
}
}
}
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.