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

Closes gh-8819
pull/8971/merge
Stephane Nicoll 8 years ago
parent ce892a06e4
commit f5db75792e

@ -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,67 +936,70 @@ 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 boolean logCookies;
private TimeZone timeZone = TimeZone.getTimeZone("GMT");
/**
* Controls logging of the request hostname.
* Enable logging of the request cookies.
*/
private boolean logServer;
private boolean logCookies;
/**
* Controls logging of request processing time.
* Enable logging of the request hostname.
*/
private boolean logLatency;
private boolean logServer;
/**
* Set the timestamp format for request log entries in the file. If this is not set, the pre-formated request
* timestamp is used.
* Enable logging of request processing time.
*/
private String logDateFormat;
private boolean logLatency;
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 setFileDateFormat(String fileDateFormat) {
this.fileDateFormat = fileDateFormat;
}
public void setRetainDays(int retainDays) {
this.retainDays = retainDays;
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 setExtendedFormat(boolean extendedFormat) {
this.extendedFormat = extendedFormat;
}
public String getDateFormat() {
return this.dateFormat;
}
public void setFilenameDateFormat(String filenameDateFormat) {
this.filenameDateFormat = filenameDateFormat;
public void setDateFormat(String dateFormat) {
this.dateFormat = dateFormat;
}
public boolean isExtended() {
return this.extended;
public Locale getLocale() {
return this.locale;
}
public void setExtended(boolean extended) {
this.extended = extended;
public void setLocale(Locale locale) {
this.locale = locale;
}
public String getLogTimeZone() {
return this.logTimeZone;
public TimeZone getTimeZone() {
return this.timeZone;
}
public void setLogTimeZone(String logTimeZone) {
this.logTimeZone = logTimeZone;
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;
}
}
}

@ -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);
});
}

@ -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) {

@ -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(

@ -157,22 +157,20 @@ content into your application; rather pick only the properties that you need.
server.error.path=/error # Path of the error controller.
server.error.whitelabel.enabled=true # Enable the default error page displayed in browsers in case of a server error.
server.jetty.acceptors= # Number of acceptor threads to use.
server.jetty.accesslog.append=false # Append to log.
server.jetty.accesslog.date-format=dd/MMM/yyyy:HH:mm:ss Z # Timestamp format of the request log.
server.jetty.accesslog.enabled=false # Enable access log.
server.jetty.accesslog.extended-format=false # Enable extended NCSA format.
server.jetty.accesslog.file-date-format= # Date format to place in log file name.
server.jetty.accesslog.filename= # Log filename. If not specified, logs will be redirected to "System.err".
server.jetty.accesslog.locale= # Locale of the request log.
server.jetty.accesslog.log-cookies=false # Enable logging of the request cookies.
server.jetty.accesslog.log-latency=false # Enable logging of request processing time.
server.jetty.accesslog.log-server=false # Enable logging of the request hostname.
server.jetty.accesslog.retention-period=31 # Number of days before rotated log files are deleted.
server.jetty.accesslog.time-zone=GMT # Timezone of the request log.
server.jetty.max-http-post-size=0 # Maximum size in bytes of the HTTP post or put content.
server.jetty.selectors= # Number of selector threads to use.
server.jetty.accesslog.enabled=false # Enable access log.
server.jetty.accesslog.filename= # Filename of Jetty access logs.
server.jetty.accesslog.retainDays=31 # number of days before rotated log files are deleted.
server.jetty.accesslog.append=true # append to log flag.
server.jetty.accesslog.filenameDateFormat=yyyy_MM_dd # log file name date format.
server.jetty.accesslog.extended= true # extended request log format flag.
server.jetty.accesslog.logTimeZone= GMT # the timezone of the request log
server.jetty.accesslog.logCookies=false # Controls logging of the request cookies.
server.jetty.accesslog.logServer=false # Controls logging of the request hostname.
server.jetty.accesslog.logLatency=false # Controls logging of request processing time.
server.jetty.accesslog.logDateFormat= # Set the timestamp format for request log entries in the file. If this is not set, the pre-formated request timestamp is used.
server.jsp-servlet.class-name=org.apache.jasper.servlet.JspServlet # The class name of the JSP servlet.
server.jsp-servlet.init-parameters.*= # Init parameters used to configure the JSP servlet
server.jsp-servlet.registered=true # Whether or not the JSP servlet is registered
server.port=8080 # Server HTTP port.
server.server-header= # Value to use for the Server response header (no header is sent if empty)
server.use-forward-headers= # If X-Forwarded-* headers should be applied to the HttpRequest.

@ -636,7 +636,8 @@ sample project for an example.
[[howto-configure-accesslogs]]
=== Configure Access Logging
Access logs can be configured for Tomcat, Undertow and Jetty via their respective namespaces.
Access logs can be configured for Tomcat, Undertow and Jetty via their respective
namespaces.
For instance, the following logs access on Tomcat with a
https://tomcat.apache.org/tomcat-8.0-doc/config/valve.html#Access_Logging[custom pattern].
@ -664,16 +665,17 @@ Access logging for undertow can be configured in a similar fashion
Logs are stored in a `logs` directory relative to the working directory of the
application. This can be customized via `server.undertow.accesslog.directory`.
Access logging for jetty can be configured in a similar fashion
Finally, access logging for jetty can also be configured that way:
[source,properties,indent=0,subs="verbatim,quotes,attributes"]
----
server.jetty.accesslog.enabled=true
server.jetty.accesslog.filename=
server.jetty.accesslog.filename=access-log
----
If no filename logs will go to System.err.
For more details please refer to https://www.eclipse.org/jetty/documentation/9.3.x/configuring-jetty-request-logs.html.
By default, logs will be redirected to `System.err`. For more details, please refer to
https://www.eclipse.org/jetty/documentation/9.3.x/configuring-jetty-request-logs.html[the documentation].
[[howto-use-behind-a-proxy-server]]

Loading…
Cancel
Save