我配置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
有没有办法配置访问日志?
答案 0 :(得分:8)
对于嵌入式Jetty,您也可以将其作为Spring Boot配置的一部分来编写:
@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;
}
答案 1 :(得分:6)
您必须在服务器容器中包含相关功能。例如。对于Tomcat,在LogbackValve
bean中添加EmbeddedServletContainerCustomizer
。 TomcatEmbeddedServletContainerFactory
为此目的使用addContextValves
方法。
答案 2 :(得分:6)
在尝试使用SpringBoot 1.4 + Jetty + Logback-access获得解决方案数小时后,我终于找到了解决我的问题的答案。
Jetty的API接口在v9.3中已更改,Logback-access不再有效。
Logback项目中有一个pull请求可以让它再次运行。
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-access提供的自定义PatternLayout中的所有访问日志特定参数。您可能需要滚动自己的模式类。
认为这可能有用,但它没有(或者我没有正确地做到)。
<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
上面的pull请求中还提到了一个问题的修复,可以在它被排序之前使用。
创建一个添加缺少接口的类,并使用它而不是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 {
}
Jetty Configuration @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,所以我可以将所有日志配置保存在同一个文件中。
祝你好运。答案 3 :(得分:1)
这个版本的编程adding a Tomcat valve for logback-access改进了作者的原始解决方案。
感谢wacai。这是我的版本
:
${logback.access.config.path:}
src/main/resources/logback-access.xml
logback-access.xml
注意:您需要使用logback-access 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);
}
});
}
}
};
}
}
答案 4 :(得分:0)
替代方法是注册Servlet过滤器并写入常规日志。
要防止将访问事件与其他事件混合,请禁用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
是常规的Servlet过滤器,可以通过@ServletComponentScan
@Configuration
上的@WebFilter
+ implements javax.servlet.Filter
或{bean}上的@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;
}
轻松在Spring Boot应用中注册配置:
GenericFilterBean
我建议至少使用OncePerRequestFilter
或更好org.springframework.web.filter
。 Spring Web已在AbstractRequestLoggingFilter
包中提供了一些日志记录过滤器:
CommonsRequestLoggingFilter
ServletContextRequestLoggingFilter
OncePerRequestFilter
我基于 var stats;
var camera, controls, scene, renderer;
init();
render();
function init() {
scene = new THREE.Scene();
var ambient = new THREE.AmbientLight( 0xFFFFFF );
scene.add( ambient );
var container = document.getElementById('container');
renderer = new THREE.WebGLRenderer({antialias: 1 });
renderer.shadowMap.enabled = true;
renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( window.innerWidth, window.innerHeight);
renderer.setClearColor(0x013A65);
container.appendChild( renderer.domElement );
camera = new THREE.PerspectiveCamera( 50, window.innerWidth / window.innerHeight, 1, 5000 );
camera.position.set(0,0,0);
controls = new THREE.OrbitControls( camera, renderer.domElement );
controls.addEventListener( 'change', render );
controls.enableKeys = false;
controls.enableZoom = true;
controls.minDistance = 2000;
controls.maxDistance = 3500;
controls.maxPolarAngle = Math.PI/2;
// world
var onError = function ( xhr ) { };
THREE.Loader.Handlers.add( /\.dds$/i, new THREE.DDSLoader() );
var mtlLoader = new THREE.MTLLoader();
mtlLoader.setPath( './assets/3d/' );
mtlLoader.load( 'A.mtl', function( materials ) {
materials.preload();
var objLoader = new THREE.OBJLoader();
objLoader.setMaterials( materials );
mtlLoader.setPath( './assets/3d/' );
objLoader.load( './assets/3d/A.obj', function ( object ) {
object.position.x = 0;
object.position.y = 0;
object.position.z = 0;
scene.add( object );
}, onError );
});
//Text
var loader = new THREE.FontLoader();
loader.load( './fonts/Open_Sans_Regular.json', function ( font ) {
var textGeometry = new THREE.TextGeometry( "Test", {font: font, size: 22, height: 3, curveSegments: 1});var textMaterial = new THREE.MeshPhongMaterial({ color: 0xFFFFFF, specular: 0xFFFFFF });var mesh1 = new THREE.Mesh( textGeometry, textMaterial );mesh1.position.x = -200;mesh1.position.y = 250;mesh1.position.z = 725;scene.add( mesh1);});
// lights
light = new THREE.DirectionalLight( 0xFFFFFF );
light.position.set( 1, 1, 1 );
scene.add( light );
window.addEventListener( 'resize', onWindowResize, true );
}
function onWindowResize() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize( window.innerWidth, window.innerHeight );
}
function animate() {
requestAnimationFrame( animate );
stats.update();
render();
}
function render() {
renderer.render( scene, camera );
}
定义自己的实现,用IP地址和其他信息填充Slf4j MDC上下文......
答案 5 :(得分:0)
currently accepted answer的实施,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);
}
}
};
}
}
并在maven logback-access
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>
答案 6 :(得分:0)
在我们的案例中,我们将Jetty v9.x +随附的项目从SpringBoot 1.3.0更新为1.5.16.RELEASE,该项目打破了该线程先前所报告的logback访问日志的生成。要解决此问题,我们按照以下步骤进行了操作-
@Bean
RequestLog makeRequestLog() {
RequestLog requestLog = new Jetty93RequestLogImpl()
requestLog.resource = '/logback-access.xml'
requestLog
}
// Jetty 9.x
private static class Jetty93RequestLogImpl extends RequestLogImpl implements LifeCycle {
}
答案 7 :(得分:0)
使用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>