Commit 95f31b0d authored by Andy Wilkinson's avatar Andy Wilkinson

Polish Undertow access logs contribution

 - Apply project’s code formatting and conventions
 - Don’t use the IO and worker thread configuration when creating the
   worker for the AccessLogReceiver. The IO and worker thread
   configuration is for HTTP request processing and a worker in its
   default configuration should be sufficient for the access log
   receiver.
 - Don’t use a temporary directory as the default for the access log
   directory. A temporary directory makes (some) sense for Tomcat as it
   requires a directory for its basedir. Undertow has no such
   requirement and using a temporary directory makes it hard to locate
   the logs. The default has been updated to a directory named logs,
   created in the current working directory.
 - Document the new properties in the application properties appendix

Closes gh-3014
parent 90e43737
...@@ -582,7 +582,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord ...@@ -582,7 +582,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
/** /**
* Format pattern for access logs. * Format pattern for access logs.
*/ */
private String accessLogPattern; private String accessLogPattern = "common";
/** /**
* Enable access log. * Enable access log.
...@@ -590,9 +590,9 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord ...@@ -590,9 +590,9 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
private boolean accessLogEnabled = false; private boolean accessLogEnabled = false;
/** /**
* Undertow access log directory. If not specified a temporary directory will be used. * Undertow access log directory.
*/ */
private File accessLogDir; private File accessLogDir = new File("logs");
public Integer getBufferSize() { public Integer getBufferSize() {
return this.bufferSize; return this.bufferSize;
...@@ -635,7 +635,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord ...@@ -635,7 +635,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
} }
public String getAccessLogPattern() { public String getAccessLogPattern() {
return accessLogPattern; return this.accessLogPattern;
} }
public void setAccessLogPattern(String accessLogPattern) { public void setAccessLogPattern(String accessLogPattern) {
...@@ -643,7 +643,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord ...@@ -643,7 +643,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
} }
public boolean isAccessLogEnabled() { public boolean isAccessLogEnabled() {
return accessLogEnabled; return this.accessLogEnabled;
} }
public void setAccessLogEnabled(boolean accessLogEnabled) { public void setAccessLogEnabled(boolean accessLogEnabled) {
...@@ -651,7 +651,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord ...@@ -651,7 +651,7 @@ public class ServerProperties implements EmbeddedServletContainerCustomizer, Ord
} }
public File getAccessLogDir() { public File getAccessLogDir() {
return accessLogDir; return this.accessLogDir;
} }
public void setAccessLogDir(File accessLogDir) { public void setAccessLogDir(File accessLogDir) {
......
...@@ -95,6 +95,9 @@ content into your application; rather pick only the properties that you need. ...@@ -95,6 +95,9 @@ content into your application; rather pick only the properties that you need.
server.tomcat.max-http-header-size= # maximum size in bytes of the HTTP message header server.tomcat.max-http-header-size= # maximum size in bytes of the HTTP message header
server.tomcat.max-threads = 0 # number of threads in protocol handler server.tomcat.max-threads = 0 # number of threads in protocol handler
server.tomcat.uri-encoding = UTF-8 # character encoding to use for URL decoding server.tomcat.uri-encoding = UTF-8 # character encoding to use for URL decoding
server.undertow.access-log-enabled=false # if access logging is enabled
server.undertow.access-log-pattern=common # log pattern of the access log
server.undertow.access-log-dir=logs # access logs directory
# SPRING MVC ({sc-spring-boot-autoconfigure}/web/WebMvcProperties.{sc-ext}[WebMvcProperties]) # SPRING MVC ({sc-spring-boot-autoconfigure}/web/WebMvcProperties.{sc-ext}[WebMvcProperties])
spring.mvc.locale= # set fixed locale, e.g. en_UK spring.mvc.locale= # set fixed locale, e.g. en_UK
......
server.undertow.access-log-enabled=true server.undertow.access-log-enabled=true
server.undertow.access-log-dir=target/logs
server.undertow.access-log-pattern=combined server.undertow.access-log-pattern=combined
\ No newline at end of file
...@@ -32,7 +32,6 @@ import org.apache.commons.logging.LogFactory; ...@@ -32,7 +32,6 @@ import org.apache.commons.logging.LogFactory;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Marcos Barbero
*/ */
public abstract class AbstractEmbeddedServletContainerFactory extends public abstract class AbstractEmbeddedServletContainerFactory extends
AbstractConfigurableEmbeddedServletContainer implements AbstractConfigurableEmbeddedServletContainer implements
...@@ -79,25 +78,6 @@ public abstract class AbstractEmbeddedServletContainerFactory extends ...@@ -79,25 +78,6 @@ public abstract class AbstractEmbeddedServletContainerFactory extends
return file; return file;
} }
/**
* Returns the absolute temp dir for given web server.
* @param prefix webserver name
* @return The temp dir for given web server.
*/
protected File createTempDir(String prefix) {
try {
File tempFolder = File.createTempFile(prefix + ".", "." + getPort());
tempFolder.delete();
tempFolder.mkdir();
tempFolder.deleteOnExit();
return tempFolder;
}
catch (IOException ex) {
throw new EmbeddedServletContainerException(
String.format("Unable to create %s tempdir", prefix), ex);
}
}
private File getExplodedWarFileDocumentRoot() { private File getExplodedWarFileDocumentRoot() {
File file = getCodeSourceArchive(); File file = getCodeSourceArchive();
if (this.logger.isDebugEnabled()) { if (this.logger.isDebugEnabled()) {
......
...@@ -79,7 +79,6 @@ import org.springframework.util.StringUtils; ...@@ -79,7 +79,6 @@ import org.springframework.util.StringUtils;
* @author Brock Mills * @author Brock Mills
* @author Stephane Nicoll * @author Stephane Nicoll
* @author Andy Wilkinson * @author Andy Wilkinson
* @author Marcos Barbero
* @see #setPort(int) * @see #setPort(int)
* @see #setContextLifecycleListeners(Collection) * @see #setContextLifecycleListeners(Collection)
* @see TomcatEmbeddedServletContainer * @see TomcatEmbeddedServletContainer
...@@ -388,6 +387,25 @@ public class TomcatEmbeddedServletContainerFactory extends ...@@ -388,6 +387,25 @@ public class TomcatEmbeddedServletContainerFactory extends
this.resourceLoader = resourceLoader; this.resourceLoader = resourceLoader;
} }
/**
* Returns the absolute temp dir for given web server.
* @param prefix webserver name
* @return The temp dir for given web server.
*/
protected File createTempDir(String prefix) {
try {
File tempFolder = File.createTempFile(prefix + ".", "." + getPort());
tempFolder.delete();
tempFolder.mkdir();
tempFolder.deleteOnExit();
return tempFolder;
}
catch (IOException ex) {
throw new EmbeddedServletContainerException(
"Unable to create Tomcat tempdir", ex);
}
}
/** /**
* Set the Tomcat base directory. If not specified a temporary directory will be used. * Set the Tomcat base directory. If not specified a temporary directory will be used.
* @param baseDirectory the tomcat base directory * @param baseDirectory the tomcat base directory
......
...@@ -22,6 +22,7 @@ import io.undertow.UndertowMessages; ...@@ -22,6 +22,7 @@ import io.undertow.UndertowMessages;
import io.undertow.server.HandlerWrapper; import io.undertow.server.HandlerWrapper;
import io.undertow.server.HttpHandler; import io.undertow.server.HttpHandler;
import io.undertow.server.handlers.accesslog.AccessLogHandler; import io.undertow.server.handlers.accesslog.AccessLogHandler;
import io.undertow.server.handlers.accesslog.AccessLogReceiver;
import io.undertow.server.handlers.accesslog.DefaultAccessLogReceiver; import io.undertow.server.handlers.accesslog.DefaultAccessLogReceiver;
import io.undertow.server.handlers.resource.ClassPathResourceManager; import io.undertow.server.handlers.resource.ClassPathResourceManager;
import io.undertow.server.handlers.resource.FileResourceManager; import io.undertow.server.handlers.resource.FileResourceManager;
...@@ -76,8 +77,8 @@ import org.springframework.util.ResourceUtils; ...@@ -76,8 +77,8 @@ import org.springframework.util.ResourceUtils;
import org.xnio.OptionMap; import org.xnio.OptionMap;
import org.xnio.Options; import org.xnio.Options;
import org.xnio.SslClientAuthMode; import org.xnio.SslClientAuthMode;
import org.xnio.XnioWorker;
import org.xnio.Xnio; import org.xnio.Xnio;
import org.xnio.XnioWorker;
/** /**
* {@link EmbeddedServletContainerFactory} that can be used to create * {@link EmbeddedServletContainerFactory} that can be used to create
...@@ -366,45 +367,38 @@ public class UndertowEmbeddedServletContainerFactory extends ...@@ -366,45 +367,38 @@ public class UndertowEmbeddedServletContainerFactory extends
deploymentInfo.addInitialHandlerChainWrapper(new HandlerWrapper() { deploymentInfo.addInitialHandlerChainWrapper(new HandlerWrapper() {
@Override @Override
public HttpHandler wrap(HttpHandler handler) { public HttpHandler wrap(HttpHandler handler) {
try { return createAccessLogHandler(handler);
String formatString = (accessLogPattern != null) ? accessLogPattern
: "common";
DefaultAccessLogReceiver accessLogReceiver = new DefaultAccessLogReceiver(
createWorker(), getLogsDir(), "access_log");
return new AccessLogHandler(handler, accessLogReceiver, formatString,
Undertow.class.getClassLoader());
}
catch (IOException ex) {
throw new IllegalStateException(ex);
}
} }
}); });
} }
private XnioWorker createWorker() throws IOException { private AccessLogHandler createAccessLogHandler(HttpHandler handler) {
Xnio xnio = Xnio.getInstance(Undertow.class.getClassLoader()); try {
OptionMap.Builder builder = OptionMap.builder(); createAccessLogDirectoryIfNecessary();
if(this.ioThreads != null && this.ioThreads > 0) { AccessLogReceiver accessLogReceiver = new DefaultAccessLogReceiver(
builder.set(Options.WORKER_IO_THREADS, ioThreads); createWorker(), this.accessLogDirectory, "access_log");
String formatString = (this.accessLogPattern != null) ? this.accessLogPattern
: "common";
return new AccessLogHandler(handler, accessLogReceiver, formatString,
Undertow.class.getClassLoader());
} }
if(this.workerThreads != null && this.workerThreads > 0) { catch (IOException ex) {
builder.set(Options.WORKER_TASK_CORE_THREADS, workerThreads); throw new IllegalStateException("Failed to create AccessLogHandler", ex);
builder.set(Options.WORKER_TASK_MAX_THREADS, workerThreads);
} }
return xnio.createWorker(builder.getMap());
} }
private File getLogsDir() { private void createAccessLogDirectoryIfNecessary() {
File logsDir; Assert.notNull(this.accessLogDirectory, "accesslogDirectory must not be null");
if (accessLogDirectory != null) { if (!this.accessLogDirectory.isDirectory() && !this.accessLogDirectory.mkdirs()) {
logsDir = accessLogDirectory; throw new IllegalStateException("Failed to create access log directory '"
if (!logsDir.isDirectory() && !logsDir.mkdirs()) { + this.accessLogDirectory + "'");
throw new IllegalStateException("Failed to create logs dir '" + logsDir + "'");
}
} else {
logsDir = createTempDir("undertow");
} }
return logsDir; }
private XnioWorker createWorker() throws IOException {
Xnio xnio = Xnio.getInstance(Undertow.class.getClassLoader());
OptionMap.Builder builder = OptionMap.builder();
return xnio.createWorker(builder.getMap());
} }
private void registerServletContainerInitializerToDriveServletContextInitializers( private void registerServletContainerInitializerToDriveServletContextInitializers(
...@@ -517,7 +511,7 @@ public class UndertowEmbeddedServletContainerFactory extends ...@@ -517,7 +511,7 @@ public class UndertowEmbeddedServletContainerFactory extends
} }
public boolean isAccessLogEnabled() { public boolean isAccessLogEnabled() {
return accessLogEnabled; return this.accessLogEnabled;
} }
/** /**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment