Spring Конфигурация журнала встроенного доступа Bootty/tomcat
Я logback.xml
он отлично работает, но logback-access.xml
не работает.
в maven pom.xml
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
</dependency>
в src/main/resource
logback.xml
logback-access.xml
Есть ли способ настроить доступ журнала?
Ответы
Ответ 1
Вам нужно будет включить соответствующую функцию в контейнер сервера. Например. для Tomcat добавьте LogbackValve
в EmbeddedServletContainerCustomizer
bean. Для этой цели TomcatEmbeddedServletContainerFactory
имеет метод addContextValves
.
Ответ 2
Для встроенного Jetty вы также можете записать это как часть вашей конфигурации загрузки Spring:
@Bean
public EmbeddedServletContainerFactory jettyConfigBean() {
JettyEmbeddedServletContainerFactory jef = new JettyEmbeddedServletContainerFactory();
jef.addServerCustomizers(new JettyServerCustomizer() {
public void customize(Server server) {
HandlerCollection handlers = new HandlerCollection();
for (Handler handler : server.getHandlers()) {
handlers.addHandler(handler);
}
RequestLogHandler reqLogs = new RequestLogHandler();
NCSARequestLog reqLogImpl = new NCSARequestLog("./logs/access-yyyy_mm_dd.log");
reqLogImpl.setRetainDays(30);
reqLogImpl.setAppend(true);
reqLogImpl.setExtended(false);
reqLogImpl.setLogTimeZone("GMT");
reqLogs.setRequestLog(reqLogImpl);
handlers.addHandler(reqLogs);
server.setHandler(handlers);
// For Jetty 9.3+, use the following
//RequestLogHandler reqLogs = new RequestLogHandler();
//reqLogs.setServer(server);
//RequestLogImpl rli = new RequestLogImpl();
//rli.setResource("/logback-access.xml");
//rli.setQuiet(false);
//rli.start();
//reqLogs.setRequestLog(rli);
//handlers.addHandler(reqLogs);
//server.setHandler(handlers);
}
});
return jef;
}
Ответ 3
После многих часов попыток найти решение для работы с SpringBoot 1.4 + Jetty + Logback-access я наконец нашел ответ на свои проблемы.
Интерфейс Jetty API изменен в v9.3 и Logback-доступ больше не работает.
http://shibboleth.1660669.n2.nabble.com/Jetty-9-3-access-logging-recommended-configuration-td7620755.html
В проекте Logback был выдвинут запрос на запуск, чтобы он снова заработал.
https://github.com/qos-ch/logback/pull/269
Есть пара решений, которые упомянуты в приведенном выше запросе на получение.
Вариант 1
Используйте реализацию org.eclipse.jetty.server.Slf4jRequestLog, чтобы перенаправить конфигурацию ведения журнала обратно в классический Logback.
JettyConfiguration @Bean
RequestLogHandler requestLogsHandler = new RequestLogHandler();
requestLogsHandler.setServer(server);
Slf4jRequestLog log = new Slf4jRequestLog();
log.setLoggerName("com.example.accesslog");
requestLogsHandler.setRequestLog(log);
handlers.addHandler(requestLogsHandler);
server.setHandler(handlers);
logback.xml
<appender name="FILE-ACCESS" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>${LOG_PATH}/main.log</file>
<encoder>
<!-- You'll have to work this out -->
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/main.%d{yyyy-MM-dd}-%i.log
</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy
class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>20MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>14</maxHistory>
</rollingPolicy>
</appender>
<logger name="com.example.accesslog">
<appender-ref ref="FILE-ACCESS" />
</logger>
Это работает, но вы теряете все специфические параметры журнала доступа в пользовательском шаблоне, доступном при Logback-доступе. Вам, вероятно, нужно свернуть свои собственные шаблоны классов.
Думал, что это может сработать, но это не сработало (или я не сделал это должным образом).
<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
<layout class="ch.qos.logback.access.PatternLayout">
<pattern>%h %l %u [%t] "%r" %s %b "%i{Referer}" "%i{User-Agent}"</pattern>
</layout>
</encoder>
Вариант 2
В приведенном выше запросе на удаление также упоминается исправление проблемы, которую можно использовать до ее сортировки.
Создайте класс, который добавляет отсутствующий интерфейс, и используйте его вместо RequestLogImpl.
Новый класс
package com.example.ch.qos.logback.access.jetty;
import ch.qos.logback.access.jetty.RequestLogImpl;
import org.eclipse.jetty.util.component.LifeCycle;
public class LogbackAccessRequestLogImplFix1052 extends RequestLogImpl implements LifeCycle {
}
Конфигурация причала @Bean
RequestLogHandler requestLogs = new RequestLogHandler();
requestLogs.setServer(server);
LogbackAccessRequestLogImplFix1052 rli = new LogbackAccessRequestLogImplFix1052();
rli.setResource("/logback-access.xml");
rli.setQuiet(false);
requestLogs.setRequestLog(rli);
handlers.addHandler(requestLogs);
server.setHandler(handlers);
Я попробовал оба варианта, и в итоге я выбрал вариант 2, так как уже потратил слишком много времени на это. Я предпочел бы вариант 1, хотя, чтобы я мог сохранить все мои настройки регистрации в одном и том же файле.
Удачи.
Ответ 4
Эта версия программно добавление клапана Tomcat для доступа к журналу немного улучшает исходное решение автора.
Благодаря wacai для этого. Вот моя версия, которая
- удаляет конечный
:
из ${logback.access.config.path:}
- предполагает
src/main/resources/logback-access.xml
- удаляет параметр конфигурации, чтобы изменить имя
logback-access.xml
- работает в Spring Boot 1.3.3
ПРИМЕЧАНИЕ. Для загрузки конфигурации из ресурсов необходим обратный доступ 1.1.6 - автоматически ищет ресурсы для logback-access.xml
.
import ch.qos.logback.access.tomcat.LogbackValve;
import org.apache.catalina.Context;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class LogbackAccessEventConfiguration {
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer() {
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addContextCustomizers(new TomcatContextCustomizer() {
@Override
public void customize(Context context) {
LogbackValve logbackValve = new LogbackValve();
logbackValve.setFilename("logback-access.xml");
context.getPipeline().addValve(logbackValve);
}
});
}
}
};
}
}
Ответ 5
Альтернативным способом является регистрация фильтра сервлета и запись в обычный журнал.
Чтобы запретить события микширования с другими событиями отключить additivity
:
<appender name="ACCESS-LOG"
class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>./log/evilAccess.log</file>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>
%d{yyyy-MM-dd HH:mm:ss} %msg ip=%mdc{ip} session=%mdc{session} user=%mdc{user}%n
</Pattern>
</encoder>
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
<fileNamePattern>./log/evilAccess-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<maxFileSize>5MB</maxFileSize>
<maxHistory>30</maxHistory>
</rollingPolicy>
</appender>
<logger name="com.evil.web.log.MyAccessLogFilter" level="debug" additivity="false">
<appender-ref ref="ACCESS-LOG" />
</logger>
<logger name="com.evil.web.log.MyAccessLogFilter" level="debug" additivity="false">
<appender-ref ref="ACCESS-LOG" />
</logger>
LoggingFilter
- обычный сервлет-фильтр, который можно легко зарегистрировать в Spring приложении для загрузки через @ServletComponentScan
на @Configuration
class + @WebFilter
на implements javax.servlet.Filter
или через bean config:
@Bean
myAccessLogFilter myAccessLogFilter() {
SaAccessLogFilter filter = new MyAccessLogFilter();
// filter.setMaxPayloadLength(100);
return filter;
}
@Bean
FilterRegistrationBean registration() {
FilterRegistrationBean registration = new FilterRegistrationBean(myAccessLogFilter());
registration.setOrder(1);
registration.setEnabled(true);
return registration;
}
Я рекомендую использовать как минимум GenericFilterBean
или лучше OncePerRequestFilter
. Некоторые фильтры регистрации уже предоставлены пакетом Spring Web внутри org.springframework.web.filter
:
-
AbstractRequestLoggingFilter
-
CommonsRequestLoggingFilter
-
ServletContextRequestLoggingFilter
Я определяю собственную реализацию на основе OncePerRequestFilter
для заполнения контекста MDF Slf4j с IP-адресом и другой информацией...
Ответ 6
Реализация принятого в настоящее время ответа, любезность Ego Slayer, размещена в вики сообщества:
Я начинаю с http://spring.io/guides/gs/rest-service/
просто создайте файл здесь src/main/java/hello/MyConfig.java
package hello;
import org.apache.catalina.valves.AccessLogValve;
import org.springframework.boot.context.embedded.ConfigurableEmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import ch.qos.logback.access.tomcat.LogbackValve;
@Configuration
public class MyConfig {
@Bean
public EmbeddedServletContainerCustomizer containerCustomizer(){
return new EmbeddedServletContainerCustomizer() {
@Override
public void customize(ConfigurableEmbeddedServletContainerFactory factory) {
if(factory instanceof TomcatEmbeddedServletContainerFactory){
TomcatEmbeddedServletContainerFactory containerFactory = (TomcatEmbeddedServletContainerFactory) factory;
LogbackValve logbackValve = new LogbackValve();
logbackValve.setFilename("src/main/resources/logback-access.xml");
containerFactory.addContextValves(logbackValve);
}
}
};
}
}
и добавьте logback-access
в maven pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-rest-service</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>0.5.0.M6</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-access</artifactId>
<version>1.0.13</version>
</dependency>
</dependencies>
<properties>
<start-class>hello.Application</start-class>
</properties>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<url>http://repo.spring.io/libs-snapshot</url>
<snapshots><enabled>true</enabled></snapshots>
</pluginRepository>
</pluginRepositories>
</project>
Ответ 7
В нашем случае мы обновили проект с SpringBoot 1.3.0 до 1.5.16.RELEASE, который поставляется с Jetty v9. x+, который прервал генерацию журнала доступа для обратного входа, как сообщалось ранее в этом потоке. Чтобы решить эту проблему, мы сделали следующие шаги -
- Добавлены logback-access-spring-boot-starter в зависимости, наряду с logback-classic и logback-core.
- Добавлен следующий код в моем JettyConfig
@Bean
RequestLog makeRequestLog() {
RequestLog requestLog = new Jetty93RequestLogImpl()
requestLog.resource = '/logback-access.xml'
requestLog
}
// Jetty 9.x
private static class Jetty93RequestLogImpl extends RequestLogImpl implements LifeCycle {
}
Ответ 8
Пример использования Spring boot 2 (2.1.4.RELEASE). Хорошо работает для меня.
@Component
public class JettyCustomizationConfig implements WebServerFactoryCustomizer<ConfigurableJettyWebServerFactory> {
@Override
public void customize(ConfigurableJettyWebServerFactory server) {
server.addServerCustomizers(customJettyServer());
}
private JettyServerCustomizer customJettyServer() {
return server -> {
HandlerCollection handlers = new HandlerCollection();
RequestLogHandler requestLogHandler = new RequestLogHandler();
requestLogHandler.setServer(server);
RequestLogImpl requestLog = new RequestLogImpl();
requestLog.setResource("/logback-access.xml");
requestLog.setQuiet(false);
requestLog.start();
requestLogHandler.setRequestLog(requestLog);
handlers.addHandler(server.getHandler());
handlers.addHandler(requestLogHandler);
server.setHandler(handlers);
};
}
}
Logback-access.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" />
<property name="log.path" value="logs" />
<appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${log.path}/requests/seastar_request_%d{yyyy-MM-dd}.log</fileNamePattern>
</rollingPolicy>
</appender>
<appender-ref ref="FILE"/>
</configuration>