Add support for configuring Jetty's request log via the environment

Closes gh-8819
This commit is contained in:
Stephane Nicoll
2017-04-27 10:41:39 +02:00
parent ce892a06e4
commit f5db75792e
6 changed files with 186 additions and 101 deletions

View File

@@ -23,18 +23,10 @@ import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.eclipse.jetty.server.AbstractConnector;
import org.eclipse.jetty.server.ConnectionFactory;
import org.eclipse.jetty.server.Handler;
import org.eclipse.jetty.server.HttpConfiguration;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.server.handler.HandlerWrapper;
import java.util.TimeZone;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.DeprecatedConfigurationProperty;
@@ -58,6 +50,7 @@ import org.springframework.util.StringUtils;
* @author Venil Noronha
* @author Aurélien Leboulanger
* @author Brian Clozel
* @author Olivier Lamy
*/
@ConfigurationProperties(prefix = "server", ignoreUnknownFields = true)
public class ServerProperties {
@@ -895,6 +888,11 @@ public class ServerProperties {
*/
public static class Jetty {
/**
* Access log configuration.
*/
private final Accesslog accesslog = new Accesslog();
/**
* Maximum size in bytes of the HTTP post or put content.
*/
@@ -910,7 +908,9 @@ public class ServerProperties {
*/
private Integer selectors;
private final Accesslog accesslog = new Accesslog();
public Accesslog getAccesslog() {
return this.accesslog;
}
public int getMaxHttpPostSize() {
return this.maxHttpPostSize;
@@ -936,68 +936,71 @@ public class ServerProperties {
this.selectors = selectors;
}
public Accesslog getAccesslog() {
return this.accesslog;
}
/**
* Jetty access log properties.
*/
public static class Accesslog {
/**
* Enable access log.
*/
private boolean enabled;
private boolean enabled = false;
/**
* accesslog filename. If no filename, logs will be redirected to System.err
* Log filename. If not specified, logs will be redirected to "System.err".
*/
private String filename;
/**
* number of days before rotated log files are deleted. Default 31
* Date format to place in log file name.
*/
private int retainDays = 31;
private String fileDateFormat;
/**
* append to log.
* Number of days before rotated log files are deleted.
*/
private int retentionPeriod = 31; // no days
/**
* Append to log.
*/
private boolean append;
/**
* the log file name date format.
* Enable extended NCSA format.
*/
private String filenameDateFormat;
private boolean extendedFormat;
/**
* extended NCSA format.
* Timestamp format of the request log.
*/
private boolean extended;
private String dateFormat = "dd/MMM/yyyy:HH:mm:ss Z";
/**
* Set the timezone of the request log.
* Locale of the request log.
*/
private String logTimeZone;
private Locale locale;
/**
* Controls logging of the request cookies.
* Timezone of the request log.
*/
private TimeZone timeZone = TimeZone.getTimeZone("GMT");
/**
* Enable logging of the request cookies.
*/
private boolean logCookies;
/**
* Controls logging of the request hostname.
* Enable logging of the request hostname.
*/
private boolean logServer;
/**
* Controls logging of request processing time.
* Enable logging of request processing time.
*/
private boolean logLatency;
/**
* Set the timestamp format for request log entries in the file. If this is not set, the pre-formated request
* timestamp is used.
*/
private String logDateFormat;
public boolean isEnabled() {
return this.enabled;
}
@@ -1014,12 +1017,20 @@ public class ServerProperties {
this.filename = filename;
}
public int getRetainDays() {
return this.retainDays;
public String getFileDateFormat() {
return this.fileDateFormat;
}
public void setRetainDays(int retainDays) {
this.retainDays = retainDays;
public void setFileDateFormat(String fileDateFormat) {
this.fileDateFormat = fileDateFormat;
}
public int getRetentionPeriod() {
return this.retentionPeriod;
}
public void setRetentionPeriod(int retentionPeriod) {
this.retentionPeriod = retentionPeriod;
}
public boolean isAppend() {
@@ -1030,28 +1041,36 @@ public class ServerProperties {
this.append = append;
}
public String getFilenameDateFormat() {
return this.filenameDateFormat;
public boolean isExtendedFormat() {
return this.extendedFormat;
}
public void setFilenameDateFormat(String filenameDateFormat) {
this.filenameDateFormat = filenameDateFormat;
public void setExtendedFormat(boolean extendedFormat) {
this.extendedFormat = extendedFormat;
}
public boolean isExtended() {
return this.extended;
public String getDateFormat() {
return this.dateFormat;
}
public void setExtended(boolean extended) {
this.extended = extended;
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
public String getLogTimeZone() {
return this.logTimeZone;
public Locale getLocale() {
return this.locale;
}
public void setLogTimeZone(String logTimeZone) {
this.logTimeZone = logTimeZone;
public void setLocale(Locale locale) {
this.locale = locale;
}
public TimeZone getTimeZone() {
return this.timeZone;
}
public void setTimeZone(TimeZone timeZone) {
this.timeZone = timeZone;
}
public boolean isLogCookies() {
@@ -1063,28 +1082,20 @@ public class ServerProperties {
}
public boolean isLogServer() {
return logServer;
return this.logServer;
}
public void setLogServer( boolean logServer ) {
public void setLogServer(boolean logServer) {
this.logServer = logServer;
}
public boolean isLogLatency() {
return logLatency;
return this.logLatency;
}
public void setLogLatency( boolean logLatency ) {
public void setLogLatency(boolean logLatency) {
this.logLatency = logLatency;
}
public String getLogDateFormat() {
return logDateFormat;
}
public void setLogDateFormat( String logDateFormat ) {
this.logDateFormat = logDateFormat;
}
}
}

View File

@@ -67,6 +67,7 @@ import org.springframework.util.StringUtils;
*
* @author Brian Clozel
* @author Stephane Nicoll
* @author Olivier Lamy
* @since 2.0.0
*/
public class DefaultServletWebServerFactoryCustomizer
@@ -643,27 +644,30 @@ public class DefaultServletWebServerFactoryCustomizer
}
private static void customizeAccesslog(JettyServletWebServerFactory factory,
final ServerProperties.Jetty.Accesslog accesslog) {
factory.addServerCustomizers( server -> {
final ServerProperties.Jetty.Accesslog accesslog) {
factory.addServerCustomizers(server -> {
NCSARequestLog requestLog = new NCSARequestLog();
if (accesslog.getFilename() != null) {
requestLog.setFilename(accesslog.getFilename());
}
if (accesslog.getFilenameDateFormat() != null) {
requestLog.setFilenameDateFormat(accesslog.getFilenameDateFormat());
if (accesslog.getFileDateFormat() != null) {
requestLog.setFilenameDateFormat(accesslog.getFileDateFormat());
}
if (accesslog.getRetainDays() > 0) {
requestLog.setRetainDays(accesslog.getRetainDays());
}
requestLog.setLogTimeZone(accesslog.getLogTimeZone());
requestLog.setExtended(accesslog.isExtended());
requestLog.setRetainDays(accesslog.getRetentionPeriod());
requestLog.setAppend(accesslog.isAppend());
requestLog.setLogCookies(accesslog.isLogCookies());
requestLog.setLogServer( accesslog.isLogServer() );
requestLog.setLogLatency( accesslog.isLogLatency() );
if (!StringUtils.isEmpty( accesslog.getLogDateFormat() )) {
requestLog.setLogDateFormat( accesslog.getLogDateFormat() );
requestLog.setExtended(accesslog.isExtendedFormat());
if (accesslog.getDateFormat() != null) {
requestLog.setLogDateFormat(accesslog.getDateFormat());
}
if (accesslog.getLocale() != null) {
requestLog.setLogLocale(accesslog.getLocale());
}
if (accesslog.getTimeZone() != null) {
requestLog.setLogTimeZone(accesslog.getTimeZone().getID());
}
requestLog.setLogCookies(accesslog.isLogCookies());
requestLog.setLogServer(accesslog.isLogServer());
requestLog.setLogLatency(accesslog.isLogLatency());
server.setRequestLog(requestLog);
});
}

View File

@@ -185,20 +185,20 @@ public class ServerPropertiesTests {
}
@Test
public void testJettyBinding() throws Exception {
public void testCustomizeJettyAccessLog() throws Exception {
Map<String, String> map = new HashMap<String, String>();
map.put("server.jetty.accesslog.enabled", "true");
map.put("server.jetty.accesslog.filename", "foo.txt");
map.put("server.jetty.accesslog.retainDays", "4");
map.put("server.jetty.accesslog.file-date-format", "yyyymmdd");
map.put("server.jetty.accesslog.retention-period", "4");
map.put("server.jetty.accesslog.append", "true");
map.put("server.jetty.accesslog.filenameDateFormat", "yyyymmdd");
bindProperties(map);
ServerProperties.Jetty jetty = this.properties.getJetty();
assertThat(jetty.getAccesslog().isEnabled()).isEqualTo(true);
assertThat(jetty.getAccesslog().getFilename()).isEqualTo("foo.txt");
assertThat(jetty.getAccesslog().getRetainDays()).isEqualTo(4);
assertThat(jetty.getAccesslog().getFileDateFormat()).isEqualTo("yyyymmdd");
assertThat(jetty.getAccesslog().getRetentionPeriod()).isEqualTo(4);
assertThat(jetty.getAccesslog().isAppend()).isEqualTo(true);
assertThat(jetty.getAccesslog().getFilenameDateFormat()).isEqualTo("yyyymmdd");
}
private void bindProperties(Map<String, String> map) {

View File

@@ -20,6 +20,7 @@ import java.io.File;
import java.net.URL;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Locale;
import java.util.Map;
import javax.servlet.ServletContext;
@@ -33,6 +34,8 @@ import org.apache.catalina.valves.AccessLogValve;
import org.apache.catalina.valves.RemoteIpValve;
import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
import org.apache.coyote.AbstractProtocol;
import org.eclipse.jetty.server.NCSARequestLog;
import org.eclipse.jetty.server.RequestLog;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
@@ -45,6 +48,7 @@ import org.springframework.beans.MutablePropertyValues;
import org.springframework.boot.autoconfigure.web.ServerProperties;
import org.springframework.boot.bind.RelaxedDataBinder;
import org.springframework.boot.web.embedded.jetty.JettyServletWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.boot.web.embedded.tomcat.TomcatContextCustomizer;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.boot.web.embedded.tomcat.TomcatWebServer;
@@ -527,6 +531,72 @@ public class DefaultServletWebServerFactoryCustomizerTests {
verify(factory).setSessionStoreDir(new File("myfolder"));
}
@Test
public void jettyAccessLogCanBeEnabled() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory(0);
Map<String, String> map = new HashMap<>();
map.put("server.jetty.accesslog.enabled", "true");
bindProperties(map);
this.customizer.customize(factory);
JettyWebServer webServer = (JettyWebServer) factory.getWebServer();
try {
NCSARequestLog requestLog = getNCSARequestLog(webServer);
assertThat(requestLog.getFilename()).isNull();
assertThat(requestLog.isAppend()).isFalse();
assertThat(requestLog.isExtended()).isFalse();
assertThat(requestLog.getLogCookies()).isFalse();
assertThat(requestLog.getLogServer()).isFalse();
assertThat(requestLog.getLogLatency()).isFalse();
}
finally {
webServer.stop();
}
}
@Test
public void jettyAccessLogCanBeCustomized() {
JettyServletWebServerFactory factory = new JettyServletWebServerFactory(0);
Map<String, String> map = new HashMap<>();
map.put("server.jetty.accesslog.enabled", "true");
map.put("server.jetty.accesslog.filename", "foo");
map.put("server.jetty.accesslog.file-date-format", "yyyy-MM-dd");
map.put("server.jetty.accesslog.retention-period", "42");
map.put("server.jetty.accesslog.append", "true");
map.put("server.jetty.accesslog.extended-format", "true");
map.put("server.jetty.accesslog.date-format", "HH:mm:ss");
map.put("server.jetty.accesslog.locale", "en_BE");
map.put("server.jetty.accesslog.time-zone", "UTC");
map.put("server.jetty.accesslog.log-cookies", "true");
map.put("server.jetty.accesslog.log-server", "true");
map.put("server.jetty.accesslog.log-latency", "true");
bindProperties(map);
this.customizer.customize(factory);
JettyWebServer webServer = (JettyWebServer) factory.getWebServer();
NCSARequestLog requestLog = getNCSARequestLog(webServer);
try {
assertThat(requestLog.getFilename()).isEqualTo("foo");
assertThat(requestLog.getFilenameDateFormat()).isEqualTo("yyyy-MM-dd");
assertThat(requestLog.getRetainDays()).isEqualTo(42);
assertThat(requestLog.isAppend()).isTrue();
assertThat(requestLog.isExtended()).isTrue();
assertThat(requestLog.getLogDateFormat()).isEqualTo("HH:mm:ss");
assertThat(requestLog.getLogLocale()).isEqualTo(new Locale("en", "BE"));
assertThat(requestLog.getLogTimeZone()).isEqualTo("UTC");
assertThat(requestLog.getLogCookies()).isTrue();
assertThat(requestLog.getLogServer()).isTrue();
assertThat(requestLog.getLogLatency()).isTrue();
}
finally {
webServer.stop();
}
}
private NCSARequestLog getNCSARequestLog(JettyWebServer webServer) {
RequestLog requestLog = webServer.getServer().getRequestLog();
assertThat(requestLog).isInstanceOf(NCSARequestLog.class);
return (NCSARequestLog) requestLog;
}
@Test
public void skipNullElementsForUndertow() throws Exception {
UndertowServletWebServerFactory factory = mock(