Issue #113 - reformat, javadoc update and changes after review

Signed-off-by: Lachlan Roberts <lachlan@webtide.com>
This commit is contained in:
Lachlan Roberts 2018-11-27 14:04:37 +01:00
parent 2cd579353c
commit b35df419bb
10 changed files with 406 additions and 396 deletions

View File

@ -17,22 +17,22 @@
<New class="org.eclipse.jetty.server.AsyncRequestLogWriter"> <New class="org.eclipse.jetty.server.AsyncRequestLogWriter">
<Arg><Property name="jetty.base" default="." />/<Property> <Arg><Property name="jetty.base" default="." />/<Property>
<Name>jetty.customrequestlog.filePath</Name> <Name>jetty.customrequestlog.filePath</Name>
<Default><Property name="jetty.customrequestlog.dir" default="logs"/>/yyyy_mm_dd.request.log</Default> <Default><Property name="jetty.requestlog.dir" default="logs"/>/yyyy_mm_dd.request.log</Default>
</Property></Arg> </Property></Arg>
<Arg/> <Arg/>
<Set name="filenameDateFormat"><Property name="jetty.customrequestlog.filenameDateFormat" default="yyyy_MM_dd"/></Set> <Set name="filenameDateFormat"><Property name="jetty.requestlog.filenameDateFormat" default="yyyy_MM_dd"/></Set>
<Set name="retainDays"><Property name="jetty.customrequestlog.retainDays" default="90"/></Set> <Set name="retainDays"><Property name="jetty.requestlog.retainDays" default="90"/></Set>
<Set name="append"><Property name="jetty.customrequestlog.append" default="false"/></Set> <Set name="append"><Property name="jetty.requestlog.append" default="false"/></Set>
<Set name="timeZone"><Property name="jetty.customrequestlog.timezone" default="GMT"/></Set> <Set name="timeZone"><Property name="jetty.requestlog.timezone" default="GMT"/></Set>
</New> </New>
</Arg> </Arg>
<!-- Format String --> <!-- Format String -->
<Arg> <Arg>
<Property name="jetty.customrequestlog.formatString"> <Property name="jetty.requestlog.formatString">
<Default> <Default>
<Get class="org.eclipse.jetty.server.CustomRequestLog" name="NCSA_FORMAT"/> <Get class="org.eclipse.jetty.server.CustomRequestLog" name="EXTENDED_NCSA_FORMAT"/>
</Default> </Default>
</Property> </Property>
</Arg> </Arg>

View File

@ -7,7 +7,7 @@ Enables a format string style request log.
requestlog requestlog
[tags] [tags]
customrequestlog requestlog
[depend] [depend]
server server
@ -20,22 +20,22 @@ logs/
[ini-template] [ini-template]
## Logging directory (relative to $jetty.base) ## Logging directory (relative to $jetty.base)
# jetty.customrequestlog.dir=logs # jetty.requestlog.dir=logs
## File path ## File path
# jetty.customrequestlog.filePath=${jetty.customrequestlog.dir}/yyyy_mm_dd.request.log # jetty.requestlog.filePath=${jetty.requestlog.dir}/yyyy_mm_dd.request.log
## Date format for rollovered files (uses SimpleDateFormat syntax) ## Date format for rollovered files (uses SimpleDateFormat syntax)
# jetty.customrequestlog.filenameDateFormat=yyyy_MM_dd # jetty.requestlog.filenameDateFormat=yyyy_MM_dd
## How many days to retain old log files ## How many days to retain old log files
# jetty.customrequestlog.retainDays=90 # jetty.requestlog.retainDays=90
## Whether to append to existing file ## Whether to append to existing file
# jetty.customrequestlog.append=false # jetty.requestlog.append=false
## Timezone of the log entries ## Timezone of the log entries
# jetty.customrequestlog.timezone=GMT # jetty.requestlog.timezone=GMT
## Format string ## Format string
# jetty.customrequestlog.formatString=%a - %u %t "%r" %s %B "%{Referer}i" "%{User-Agent}i" "%C" # jetty.requestlog.formatString=%a - %u %t "%r" %s %B "%{Referer}i" "%{User-Agent}i" "%C"

View File

@ -20,6 +20,7 @@ package org.eclipse.jetty.server;
import java.io.IOException; import java.io.IOException;
import java.util.Locale; import java.util.Locale;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpHeader; import org.eclipse.jetty.http.HttpHeader;
@ -36,7 +37,8 @@ import org.eclipse.jetty.util.log.Logger;
* Configuration options allow a choice between the standard Common Log Format (as used in the 3 log format) and the * Configuration options allow a choice between the standard Common Log Format (as used in the 3 log format) and the
* Combined Log Format (single log format). This log format can be output by most web servers, and almost all web log * Combined Log Format (single log format). This log format can be output by most web servers, and almost all web log
* analysis software can understand these formats. * analysis software can understand these formats.
* @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#NCSA_FORMAT} with a {@link RequestLog.Writer} *
* @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#EXTENDED_NCSA_FORMAT} with a {@link RequestLog.Writer}
*/ */
@Deprecated @Deprecated
public class AbstractNCSARequestLog extends ContainerLifeCycle implements RequestLog public class AbstractNCSARequestLog extends ContainerLifeCycle implements RequestLog
@ -67,6 +69,7 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
/** /**
* Is logging enabled * Is logging enabled
*
* @return true if logging is enabled * @return true if logging is enabled
*/ */
protected boolean isEnabled() protected boolean isEnabled()
@ -76,6 +79,7 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
/** /**
* Write requestEntry out. (to disk or slf4j log) * Write requestEntry out. (to disk or slf4j log)
*
* @param requestEntry the request entry * @param requestEntry the request entry
* @throws IOException if unable to write the entry * @throws IOException if unable to write the entry
*/ */
@ -84,9 +88,9 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
_requestLogWriter.write(requestEntry); _requestLogWriter.write(requestEntry);
} }
private void append(StringBuilder buf,String s) private void append(StringBuilder buf, String s)
{ {
if (s==null || s.length()==0) if (s == null || s.length() == 0)
buf.append('-'); buf.append('-');
else else
buf.append(s); buf.append(s);
@ -113,7 +117,7 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
if (_logServer) if (_logServer)
{ {
append(buf,request.getServerName()); append(buf, request.getServerName());
buf.append(' '); buf.append(' ');
} }
@ -128,9 +132,9 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
buf.append(addr); buf.append(addr);
buf.append(" - "); buf.append(" - ");
String auth = getAuthentication(request); String auth = getAuthentication(request);
append(buf,auth==null?"-":auth); append(buf, auth == null ? "-" : auth);
buf.append(" ["); buf.append(" [");
if (_logDateCache != null) if (_logDateCache != null)
@ -139,15 +143,15 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
buf.append(request.getTimeStamp()); buf.append(request.getTimeStamp());
buf.append("] \""); buf.append("] \"");
append(buf,request.getMethod()); append(buf, request.getMethod());
buf.append(' '); buf.append(' ');
append(buf,request.getOriginalURI()); append(buf, request.getOriginalURI());
buf.append(' '); buf.append(' ');
append(buf,request.getProtocol()); append(buf, request.getProtocol());
buf.append("\" "); buf.append("\" ");
int status = response.getCommittedMetaData().getStatus(); int status = response.getCommittedMetaData().getStatus();
if (status >=0) if (status >= 0)
{ {
buf.append((char)('0' + ((status / 100) % 10))); buf.append((char)('0' + ((status / 100) % 10)));
buf.append((char)('0' + ((status / 10) % 10))); buf.append((char)('0' + ((status / 10) % 10)));
@ -222,21 +226,22 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
LOG.warn(e); LOG.warn(e);
} }
} }
/** /**
* Extract the user authentication * Extract the user authentication
*
* @param request The request to extract from * @param request The request to extract from
* @return The string to log for authenticated user. * @return The string to log for authenticated user.
*/ */
protected String getAuthentication(Request request) protected String getAuthentication(Request request)
{ {
Authentication authentication = request.getAuthentication(); Authentication authentication = request.getAuthentication();
if (authentication instanceof Authentication.User) if (authentication instanceof Authentication.User)
return ((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName(); return ((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName();
// TODO extract the user name if it is Authentication.Deferred and return as '?username' // TODO extract the user name if it is Authentication.Deferred and return as '?username'
return null; return null;
} }
@ -425,7 +430,7 @@ public class AbstractNCSARequestLog extends ContainerLifeCycle implements Reques
{ {
if (_logDateFormat != null) if (_logDateFormat != null)
{ {
_logDateCache = new DateCache(_logDateFormat, _logLocale ,_logTimeZone); _logDateCache = new DateCache(_logDateFormat, _logLocale, _logTimeZone);
} }
if (_ignorePaths != null && _ignorePaths.length > 0) if (_ignorePaths != null && _ignorePaths.length > 0)

View File

@ -22,7 +22,7 @@ import java.util.concurrent.BlockingQueue;
/** /**
* An asynchronously writing NCSA Request Log * An asynchronously writing NCSA Request Log
* @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#NCSA_FORMAT} with an {@link AsyncRequestLogWriter} * @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#EXTENDED_NCSA_FORMAT} with an {@link AsyncRequestLogWriter}
*/ */
@Deprecated @Deprecated
public class AsyncNCSARequestLog extends NCSARequestLog public class AsyncNCSARequestLog extends NCSARequestLog

View File

@ -26,6 +26,10 @@ import org.eclipse.jetty.util.BlockingArrayQueue;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
/**
* An asynchronously writing RequestLogWriter
*/
public class AsyncRequestLogWriter extends RequestLogWriter public class AsyncRequestLogWriter extends RequestLogWriter
{ {
private static final Logger LOG = Log.getLogger(AsyncRequestLogWriter.class); private static final Logger LOG = Log.getLogger(AsyncRequestLogWriter.class);
@ -38,19 +42,19 @@ public class AsyncRequestLogWriter extends RequestLogWriter
this(null, null); this(null, null);
} }
public AsyncRequestLogWriter(String filename,BlockingQueue<String> queue) public AsyncRequestLogWriter(String filename, BlockingQueue<String> queue)
{ {
super(filename); super(filename);
if (queue==null) if (queue == null)
queue=new BlockingArrayQueue<>(1024); queue = new BlockingArrayQueue<>(1024);
_queue=queue; _queue = queue;
} }
private class WriterThread extends Thread private class WriterThread extends Thread
{ {
WriterThread() WriterThread()
{ {
setName("AsyncRequestLogWriter@"+Integer.toString(AsyncRequestLogWriter.this.hashCode(),16)); setName("AsyncRequestLogWriter@" + Integer.toString(AsyncRequestLogWriter.this.hashCode(), 16));
} }
@Override @Override
@ -61,13 +65,13 @@ public class AsyncRequestLogWriter extends RequestLogWriter
try try
{ {
String log = _queue.poll(10, TimeUnit.SECONDS); String log = _queue.poll(10, TimeUnit.SECONDS);
if (log!=null) if (log != null)
AsyncRequestLogWriter.super.write(log); AsyncRequestLogWriter.super.write(log);
while(!_queue.isEmpty()) while (!_queue.isEmpty())
{ {
log=_queue.poll(); log = _queue.poll();
if (log!=null) if (log != null)
AsyncRequestLogWriter.super.write(log); AsyncRequestLogWriter.super.write(log);
} }
} }
@ -97,7 +101,7 @@ public class AsyncRequestLogWriter extends RequestLogWriter
_thread.interrupt(); _thread.interrupt();
_thread.join(); _thread.join();
super.doStop(); super.doStop();
_thread=null; _thread = null;
} }
@Override @Override
@ -107,7 +111,7 @@ public class AsyncRequestLogWriter extends RequestLogWriter
{ {
if (_warnedFull) if (_warnedFull)
LOG.warn("Log Queue overflow"); LOG.warn("Log Queue overflow");
_warnedFull=true; _warnedFull = true;
} }
} }
} }

View File

@ -29,6 +29,7 @@ import java.util.concurrent.TimeUnit;
import java.util.function.Supplier; import java.util.function.Supplier;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import org.eclipse.jetty.http.HttpFields; import org.eclipse.jetty.http.HttpFields;
@ -37,6 +38,7 @@ import org.eclipse.jetty.http.pathmap.PathMappings;
import org.eclipse.jetty.server.handler.ContextHandler; import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.util.DateCache; import org.eclipse.jetty.util.DateCache;
import org.eclipse.jetty.util.annotation.ManagedAttribute; import org.eclipse.jetty.util.annotation.ManagedAttribute;
import org.eclipse.jetty.util.annotation.ManagedObject;
import org.eclipse.jetty.util.component.ContainerLifeCycle; import org.eclipse.jetty.util.component.ContainerLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
@ -46,237 +48,223 @@ import static java.lang.invoke.MethodHandles.foldArguments;
import static java.lang.invoke.MethodType.methodType; import static java.lang.invoke.MethodType.methodType;
/** /**
<table> * A flexible RequestLog, which produces log strings in a customizable format.
<caption>CustomRequestLog Format Codes</caption> * The Logger takes a format string where request characteristics can be added using "%" format codes which are
<tr> * replaced by the corresponding value in the log output.
<td><b>Format String</b></td> * <p>
<td><b>Description</b></td> * The terms server, client, local and remote are used to refer to the different addresses and ports
</tr> * which can be logged. Server and client refer to the logical addresses which can be modified in the request
* headers. Where local and remote refer to the physical addresses which may be a proxy between the
<tr> * end-user and the server.
<td>%%</td> *
<td>The percent sign.</td> *
</tr> * <br><br>Percent codes are specified in the format %MODIFIERS{PARAM}CODE
*<pre>
* MODIFIERS:
* Optional list of comma separated HTTP status codes which may be preceded by a single "!" to indicate
* negation. If the status code is not in the list the literal string "-" will be logged instead of
<tr> * the resulting value from the percent code.
<td valign="top">%{format}a</td> * {PARAM}:
<td> * Parameter string which may be optional depending on the percent code used.
Client IP address of the request. * CODE:
Valid formats are {server, client, local, remote} * A one or two character code specified by the {@link CustomRequestLog} table of format codes.
* </pre>
where server and client are the logical addresses *
where local and remote are the physical addresses * <table>
</td> * <caption>Format Codes</caption>
</tr> * <tr>
* <td><b>Format String</b></td>
* <td><b>Description</b></td>
* </tr>
<tr> *
<td valign="top">%a</td> * <tr>
<td>Client IP address of the request.</td> * <td>%%</td>
</tr> * <td>The percent sign.</td>
* </tr>
<tr> *
<td valign="top">%{c}a</td> * <tr>
<td>Underlying peer IP address of the connection.</td> * <td valign="top">%{format}a</td>
</tr> * <td>
* Address or Hostname. Valid formats are {server, client, local, remote}
<tr> * Optional format parameter which will be server by default.
<td valign="top">%A</td> * <br>
<td>Local IP-address.</td> * Where server and client are the logical addresses which can be modified in the request headers, while local and
</tr> * remote are the physical addresses so may be a proxy between the end-user and the server.
* </td>
<tr> * </tr>
<td valign="top">%h</td> *
<td>Remote hostname. Will log a dotted-string form of the IP if the Hostname cannot be resolved.</td> * <tr>
</tr> * <td valign="top">%{format}p</td>
* <td>
<tr> * Port. Valid formats are {server, client, local, remote}
<td valign="top">%v</td> * Optional format parameter which will be server by default.
<td> * <br>
todo this is now %{server}a * Where server and client are the logical ports which can be modified in the request headers, while local and
The canonical ServerName of the server serving the request.</td> * remote are the physical ports so may be to a proxy between the end-user and the server.
</tr> * </td>
* </tr>
*
<tr> * <tr>
<td valign="top">%B</td> * <td valign="top">%{clf}I</td>
<td>Size of response in bytes, excluding HTTP headers.</td> * <td>
</tr> * Size of request in bytes, excluding HTTP headers.
* Optional parameter with value of clf to use CLF format, i.e. a '-' rather than a 0 when no bytes are sent.
<tr> * </td>
<td valign="top">%b</td> * </tr>
<td>Size of response in bytes, excluding HTTP headers. In CLF format, i.e. a '-' rather than a 0 when no bytes are sent.</td> *
</tr> * <tr>
* <td valign="top">%{clf}O</td>
<tr> * <td>
<td valign="top">%{VARNAME}C</td> * Size of response in bytes, excluding HTTP headers.
<td> * Optional parameter with value of clf to use CLF format, i.e. a '-' rather than a 0 when no bytes are sent.
The contents of cookie VARNAME in the request sent to the server. Only version 0 cookies are fully supported. * </td>
Optional VARNAME parameter, without this parameter %C will log all cookies from the request. * </tr>
</td> *
</tr> * <tr>
* <td valign="top">%{clf}S</td>
<tr> * <td>
<td valign="top">%D</td> * Bytes transferred (received and sent). This is the combination of %I and %O.
<td>The time taken to serve the request, in microseconds.</td> * Optional parameter with value of clf to use CLF format, i.e. a '-' rather than a 0 when no bytes are sent.
</tr> * </td>
* </tr>
<tr> *
<td valign="top">%{VARNAME}e</td> * <tr>
<td>The contents of the environment variable VARNAME.</td> * <td valign="top">%{VARNAME}C</td>
</tr> * <td>
* The contents of cookie VARNAME in the request sent to the server. Only version 0 cookies are fully supported.
<tr> * Optional VARNAME parameter, without this parameter %C will log all cookies from the request.
<td valign="top">%f</td> * </td>
<td>Filename.</td> * </tr>
</tr> *
* <tr>
<tr> * <td valign="top">%D</td>
<td valign="top">%H</td> * <td>The time taken to serve the request, in microseconds.</td>
<td>The request protocol.</td> * </tr>
</tr> *
* <tr>
<tr> * <td valign="top">%{VARNAME}e</td>
<td valign="top">%{VARNAME}i</td> * <td>The contents of the environment variable VARNAME.</td>
<td>The contents of VARNAME: header line(s) in the request sent to the server.</td> * </tr>
</tr> *
* <tr>
<tr> * <td valign="top">%f</td>
<td valign="top">%k</td> * <td>Filename.</td>
<td>Number of keepalive requests handled on this connection. * </tr>
Interesting if KeepAlive is being used, so that, for example, a '1' means the first keepalive request *
after the initial one, '2' the second, etc...; otherwise this is always 0 (indicating the initial request).</td> * <tr>
</tr> * <td valign="top">%H</td>
* <td>The request protocol.</td>
<tr> * </tr>
<td valign="top">%m</td> *
<td>The request method.</td> * <tr>
</tr> * <td valign="top">%{VARNAME}i</td>
* <td>The contents of VARNAME: header line(s) in the request sent to the server.</td>
<tr> * </tr>
<td valign="top">%{VARNAME}o</td> *
<td>The contents of VARNAME: header line(s) in the response.</td> * <tr>
</tr> * <td valign="top">%k</td>
* <td>Number of keepalive requests handled on this connection.
<tr> * Interesting if KeepAlive is being used, so that, for example, a '1' means the first keepalive request
<td valign="top">%p</td> * after the initial one, '2' the second, etc...; otherwise this is always 0 (indicating the initial request).</td>
<td>The canonical port of the server serving the request. * </tr>
todo merge this with below *
</td> * <tr>
</tr> * <td valign="top">%m</td>
<tr> * <td>The request method.</td>
<td valign="top">%{format}p</td> * </tr>
<td>The canonical port of the server serving the request, or the server's actual port, or the client's actual port. *
Valid formats are canonical, local, or remote. * <tr>
todo update this documenatation * <td valign="top">%{VARNAME}o</td>
server, client logical * <td>The contents of VARNAME: header line(s) in the response.</td>
local, remote physical * </tr>
</td> *
</tr> * <tr>
* <td valign="top">%q</td>
<tr> * <td>The query string (prepended with a ? if a query string exists, otherwise an empty string).</td>
<td valign="top">%q</td> * </tr>
<td>The query string (prepended with a ? if a query string exists, otherwise an empty string).</td> *
</tr> * <tr>
* <td valign="top">%r</td>
<tr> * <td>First line of request.</td>
<td valign="top">%r</td> * </tr>
<td>First line of request.</td> *
</tr> * <tr>
* <td valign="top">%R</td>
<tr> * <td>The handler generating the response (if any).</td>
<td valign="top">%R</td> * </tr>
<td>The handler generating the response (if any).</td> *
</tr> * <tr>
* <td valign="top">%s</td>
<tr> * <td>Response status.</td>
<td valign="top">%s</td> * </tr>
<td>Response status.</td> *
</tr> * <tr>
* <td valign="top">%{format}t</td>
<tr> * <td>
<td valign="top">%{format}t</td> * The time, in the form given by an optional format, parameter (default format [18/Sep/2011:19:18:28 -0400] where
<td> * the last number indicates the timezone offset from GMT.)
The time, in the form given by an optional format, parameter (default format [18/Sep/2011:19:18:28 -0400] where * <br>
the last number indicates the timezone offset from GMT.) * The format parameter should be in a format supported by {@link DateCache}
<br> * </td>
The format parameter should be in a format supported by {@link DateCache} * </tr>
</td> *
</tr> * <tr>
* <td valign="top">%T</td>
<tr> * <td>The time taken to serve the request, in seconds.</td>
<td valign="top">%T</td> * </tr>
<td>The time taken to serve the request, in seconds.</td> *
</tr> * <tr>
* <td valign="top">%{UNIT}T</td>
<tr> * <td>The time taken to serve the request, in a time unit given by UNIT.
<td valign="top">%{UNIT}T</td> * Valid units are ms for milliseconds, us for microseconds, and s for seconds.
<td>The time taken to serve the request, in a time unit given by UNIT. * Using s gives the same result as %T without any format; using us gives the same result as %D.</td>
Valid units are ms for milliseconds, us for microseconds, and s for seconds. * </tr>
Using s gives the same result as %T without any format; using us gives the same result as %D.</td> *
</tr> * <tr>
* <td valign="top">%{d}u</td>
<tr> * <td>
<td valign="top">%{d}u</td> * Remote user if the request was authenticated. May be bogus if return status (%s) is 401 (unauthorized).
<td> * Optional parameter d, with this parameter deferred authentication will also be checked.
Remote user if the request was authenticated. May be bogus if return status (%s) is 401 (unauthorized). * </td>
Optional parameter d, with this parameter deferred authentication will also be checked. * </tr>
</td> *
</tr> * <tr>
* <td valign="top">%U</td>
<tr> * <td>The URL path requested, not including any query string.</td>
<td valign="top">%U</td> * </tr>
<td>The URL path requested, not including any query string.</td> *
</tr> * <tr>
* <td valign="top">%X</td>
<tr> * <td>
<td valign="top">%X</td> * Connection status when response is completed:
<td> * <pre>
Connection status when response is completed: * X = Connection aborted before the response completed.
<pre> * + = Connection may be kept alive after the response is sent.
X = Connection aborted before the response completed. * - = Connection will be closed after the response is sent.</pre>
+ = Connection may be kept alive after the response is sent. * </td>
- = Connection will be closed after the response is sent.</pre> * </tr>
</td> *
</tr> * <tr>
* <td valign="top">%{VARNAME}^ti</td>
<tr> * <td>The contents of VARNAME: trailer line(s) in the request sent to the server.</td>
<td valign="top">%I</td> * </tr>
<td>Bytes received.</td> *
</tr> * <tr>
* <td>%{VARNAME}^to</td>
<tr> * <td>The contents of VARNAME: trailer line(s) in the response sent from the server.</td>
<td valign="top">%O</td> * </tr>
<td>Bytes sent.</td> * </table>
</tr>
<tr>
<td valign="top">%S</td>
<td>Bytes transferred (received and sent). This is the combination of %I and %O.</td>
</tr>
<tr>
<td valign="top">%{VARNAME}^ti</td>
<td>The contents of VARNAME: trailer line(s) in the request sent to the server.</td>
</tr>
<tr>
<td>%{VARNAME}^to</td>
<td>The contents of VARNAME: trailer line(s) in the response sent from the server.</td>
</tr>
</table>
*/ */
@ManagedObject("Custom format request log")
public class CustomRequestLog extends ContainerLifeCycle implements RequestLog public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
{ {
protected static final Logger LOG = Log.getLogger(CustomRequestLog.class); protected static final Logger LOG = Log.getLogger(CustomRequestLog.class);
public static final String NCSA_FORMAT = "%a - %u %t \"%r\" %s %B \"%{Referer}i\" \"%{User-Agent}i\" \"%C\"";
public static final String DEFAULT_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZ"; public static final String DEFAULT_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZ";
public static final String NCSA_FORMAT = "%{client}a - %u %t \"%r\" %s %O";
public static final String EXTENDED_NCSA_FORMAT = "%{client}a - %u %t \"%r\" %s %O \"%{Referer}i\" \"%{User-Agent}i\"";
private static ThreadLocal<StringBuilder> _buffers = ThreadLocal.withInitial(() -> new StringBuilder(256)); private static ThreadLocal<StringBuilder> _buffers = ThreadLocal.withInitial(() -> new StringBuilder(256));
private String[] _ignorePaths; private String[] _ignorePaths;
@ -286,9 +274,11 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private RequestLog.Writer _requestLogWriter; private RequestLog.Writer _requestLogWriter;
private final MethodHandle _logHandle; private final MethodHandle _logHandle;
private final String _formatString;
public CustomRequestLog(RequestLog.Writer writer, String formatString) public CustomRequestLog(RequestLog.Writer writer, String formatString)
{ {
_formatString = formatString;
_requestLogWriter = writer; _requestLogWriter = writer;
addBean(_requestLogWriter); addBean(_requestLogWriter);
@ -335,7 +325,8 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
/** /**
* Extract the user authentication * Extract the user authentication
* @param request The request to extract from *
* @param request The request to extract from
* @param checkDeferred Whether to check for deferred authentication * @param checkDeferred Whether to check for deferred authentication
* @return The string to log for authenticated user. * @return The string to log for authenticated user.
*/ */
@ -346,7 +337,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
String name = null; String name = null;
boolean deferred = false; boolean deferred = false;
if (checkDeferred && authentication instanceof Authentication.Deferred) if (checkDeferred && authentication instanceof Authentication.Deferred)
{ {
authentication = ((Authentication.Deferred)authentication).authenticate(request); authentication = ((Authentication.Deferred)authentication).authenticate(request);
deferred = true; deferred = true;
@ -355,7 +346,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
if (authentication instanceof Authentication.User) if (authentication instanceof Authentication.User)
name = ((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName(); name = ((Authentication.User)authentication).getUserIdentity().getUserPrincipal().getName();
return (name==null) ? null : (deferred ? ("?"+name):name); return (name == null) ? null : (deferred ? ("?" + name) : name);
} }
/** /**
@ -378,6 +369,18 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
return _ignorePaths; return _ignorePaths;
} }
/**
* Retrieve the format string.
*
* @return the format string
*/
@ManagedAttribute("format string")
public String getFormatString()
{
return _formatString;
}
/** /**
* Set up request logging and open log file. * Set up request logging and open log file.
* *
@ -442,7 +445,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private static void append(StringBuilder buf, String s) private static void append(StringBuilder buf, String s)
{ {
if (s==null || s.length()==0) if (s == null || s.length() == 0)
buf.append('-'); buf.append('-');
else else
buf.append(s); buf.append(s);
@ -474,11 +477,21 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private static List<Token> getTokens(String formatString) private static List<Token> getTokens(String formatString)
{ {
/*
Extracts literal strings and percent codes out of the format string.
We will either match a percent code of the format %MODIFIERS{PARAM}CODE, or a literal string
until the next percent code or the end of the formatString is reached.
where
MODIFIERS is an optional comma separated list of numbers.
{PARAM} is an optional string parameter to the percent code.
CODE is a 1 to 2 character string corresponding to a format code.
*/
final Pattern PATTERN = Pattern.compile("^(?:%(?<MOD>!?[0-9,]+)?(?:\\{(?<ARG>[^}]+)})?(?<CODE>(?:(?:ti)|(?:to)|[a-zA-Z%]))|(?<LITERAL>[^%]+))(?<REMAINING>.*)"); final Pattern PATTERN = Pattern.compile("^(?:%(?<MOD>!?[0-9,]+)?(?:\\{(?<ARG>[^}]+)})?(?<CODE>(?:(?:ti)|(?:to)|[a-zA-Z%]))|(?<LITERAL>[^%]+))(?<REMAINING>.*)");
List<Token> tokens = new ArrayList<>(); List<Token> tokens = new ArrayList<>();
String remaining = formatString; String remaining = formatString;
while(remaining.length()>0) while (remaining.length() > 0)
{ {
Matcher m = PATTERN.matcher(remaining); Matcher m = PATTERN.matcher(remaining);
if (m.matches()) if (m.matches())
@ -542,6 +555,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
this.literal = null; this.literal = null;
} }
public Token(String literal) public Token(String literal)
{ {
this.code = null; this.code = null;
@ -554,17 +568,16 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
public boolean isLiteralString() public boolean isLiteralString()
{ {
return(literal != null); return (literal != null);
} }
public boolean isPercentCode() public boolean isPercentCode()
{ {
return(code != null); return (code != null);
} }
} }
private MethodHandle updateLogHandle(MethodHandle logHandle, MethodHandle append, String literal) private MethodHandle updateLogHandle(MethodHandle logHandle, MethodHandle append, String literal)
{ {
return foldArguments(logHandle, dropArguments(dropArguments(append.bindTo(literal), 1, Request.class), 2, Response.class)); return foldArguments(logHandle, dropArguments(dropArguments(append.bindTo(literal), 1, Request.class), 2, Response.class));
@ -577,11 +590,11 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
String responseCode = Integer.toString(response.getStatus()); String responseCode = Integer.toString(response.getStatus());
if (negated) if (negated)
{ {
return(!modifiers.contains(responseCode)); return (!modifiers.contains(responseCode));
} }
else else
{ {
return(modifiers.contains(responseCode)); return (modifiers.contains(responseCode));
} }
} }
@ -602,6 +615,9 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
case "a": case "a":
{ {
if (arg == null || arg.isEmpty())
arg = "server";
String method; String method;
switch (arg) switch (arg)
{ {
@ -629,23 +645,35 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
break; break;
} }
case "h": case "p":
{ {
String method = "logRemoteHostName"; if (arg == null || arg.isEmpty())
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType); arg = "server";
break;
}
case "B": String method;
{ switch (arg)
String method = "logResponseSize"; {
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType);
break; case "server":
} method = "logServerPort";
break;
case "client":
method = "logClientPort";
break;
case "local":
method = "logLocalPort";
break;
case "remote":
method = "logRemotePort";
break;
default:
throw new IllegalArgumentException("Invalid arg for %p");
}
case "b":
{
String method = "logResponseSizeCLF";
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType); specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType);
break; break;
} }
@ -656,9 +684,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
if (arg == null || arg.isEmpty()) if (arg == null || arg.isEmpty())
method = "logBytesReceived"; method = "logBytesReceived";
else if (arg.equals("CLF")) else if (arg.equals("CLF"))
{
method = "logBytesReceivedCLF"; method = "logBytesReceivedCLF";
}
else else
throw new IllegalArgumentException("Invalid argument for %I"); throw new IllegalArgumentException("Invalid argument for %I");
@ -672,11 +698,23 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
if (arg == null || arg.isEmpty()) if (arg == null || arg.isEmpty())
method = "logBytesSent"; method = "logBytesSent";
else if (arg.equals("CLF")) else if (arg.equals("CLF"))
{
method = "logBytesSentCLF"; method = "logBytesSentCLF";
}
else else
throw new IllegalArgumentException("Invalid argument for %I"); throw new IllegalArgumentException("Invalid argument for %O");
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType);
break;
}
case "S":
{
String method;
if (arg == null || arg.isEmpty())
method = "logBytesTransferred";
else if (arg.equals("CLF"))
method = "logBytesTransferredCLF";
else
throw new IllegalArgumentException("Invalid argument for %S");
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType); specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType);
break; break;
@ -767,36 +805,6 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
break; break;
} }
case "p":
{
String method;
switch (arg)
{
case "server":
method = "logServerPort";
break;
case "client":
method = "logClientPort";
break;
case "local":
method = "logLocalPort";
break;
case "remote":
method = "logRemotePort";
break;
default:
throw new IllegalArgumentException("Invalid arg for %p");
}
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType);
break;
}
case "q": case "q":
{ {
String method = "logQueryString"; String method = "logQueryString";
@ -829,9 +837,9 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
{ {
DateCache logDateCache; DateCache logDateCache;
if (arg == null || arg.isEmpty()) if (arg == null || arg.isEmpty())
logDateCache = new DateCache(DEFAULT_DATE_FORMAT, _logLocale , _logTimeZone); logDateCache = new DateCache(DEFAULT_DATE_FORMAT, _logLocale, _logTimeZone);
else else
logDateCache = new DateCache(arg, _logLocale , _logTimeZone); logDateCache = new DateCache(arg, _logLocale, _logTimeZone);
String method = "logRequestTime"; String method = "logRequestTime";
MethodType logTypeDateCache = methodType(Void.TYPE, DateCache.class, StringBuilder.class, Request.class, Response.class); MethodType logTypeDateCache = methodType(Void.TYPE, DateCache.class, StringBuilder.class, Request.class, Response.class);
@ -891,14 +899,6 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
break; break;
} }
case "S":
{
String method = "logBytesTransferred";
specificHandle = MethodHandles.lookup().findStatic(CustomRequestLog.class, method, logType);
break;
}
case "ti": case "ti":
{ {
if (arg == null || arg.isEmpty()) if (arg == null || arg.isEmpty())
@ -940,7 +940,6 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
} }
//-----------------------------------------------------------------------------------// //-----------------------------------------------------------------------------------//
private static void logNothing(StringBuilder b, Request request, Response response) private static void logNothing(StringBuilder b, Request request, Response response)
@ -996,7 +995,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private static void logResponseSizeCLF(StringBuilder b, Request request, Response response) private static void logResponseSizeCLF(StringBuilder b, Request request, Response response)
{ {
long written = response.getHttpChannel().getBytesWritten(); long written = response.getHttpChannel().getBytesWritten();
if (written==0) if (written == 0)
b.append('-'); b.append('-');
else else
b.append(written); b.append(written);
@ -1007,17 +1006,47 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
b.append(response.getHttpChannel().getBytesWritten()); b.append(response.getHttpChannel().getBytesWritten());
} }
private static void logBytesSentCLF(StringBuilder b, Request request, Response response)
{
long sent = response.getHttpChannel().getBytesWritten();
if (sent == 0)
b.append('-');
else
b.append(sent);
}
private static void logBytesReceived(StringBuilder b, Request request, Response response) private static void logBytesReceived(StringBuilder b, Request request, Response response)
{ {
//todo this be content received rather than consumed //todo this be content received rather than consumed
b.append(request.getHttpInput().getContentConsumed()); b.append(request.getHttpInput().getContentConsumed());
} }
private static void logBytesReceivedCLF(StringBuilder b, Request request, Response response)
{
//todo this be content received rather than consumed
long received = request.getHttpInput().getContentConsumed();
if (received == 0)
b.append('-');
else
b.append(received);
}
private static void logBytesTransferred(StringBuilder b, Request request, Response response) private static void logBytesTransferred(StringBuilder b, Request request, Response response)
{ {
//todo this be content received rather than consumed
b.append(request.getHttpInput().getContentConsumed() + response.getHttpOutput().getWritten()); b.append(request.getHttpInput().getContentConsumed() + response.getHttpOutput().getWritten());
} }
private static void logBytesTransferredCLF(StringBuilder b, Request request, Response response)
{
//todo this be content received rather than consumed
long transferred = request.getHttpInput().getContentConsumed() + response.getHttpOutput().getWritten();
if (transferred == 0)
b.append('-');
else
b.append(transferred);
}
private static void logRequestCookie(String arg, StringBuilder b, Request request, Response response) private static void logRequestCookie(String arg, StringBuilder b, Request request, Response response)
{ {
@ -1059,12 +1088,12 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private static void logFilename(StringBuilder b, Request request, Response response) private static void logFilename(StringBuilder b, Request request, Response response)
{ {
UserIdentity.Scope scope = request.getUserIdentityScope(); UserIdentity.Scope scope = request.getUserIdentityScope();
if (scope==null || scope.getContextHandler()==null) if (scope == null || scope.getContextHandler() == null)
b.append('-'); b.append('-');
else else
{ {
ContextHandler context = scope.getContextHandler(); ContextHandler context = scope.getContextHandler();
int lengthToStrip = scope.getContextPath().length()>1 ? scope.getContextPath().length() : 0; int lengthToStrip = scope.getContextPath().length() > 1 ? scope.getContextPath().length() : 0;
String filename = context.getServletContext().getRealPath(request.getPathInfo().substring(lengthToStrip)); String filename = context.getServletContext().getRealPath(request.getPathInfo().substring(lengthToStrip));
append(b, filename); append(b, filename);
} }
@ -1101,7 +1130,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private static void logQueryString(StringBuilder b, Request request, Response response) private static void logQueryString(StringBuilder b, Request request, Response response)
{ {
append(b, "?"+request.getQueryString()); append(b, "?" + request.getQueryString());
} }
private static void logRequestFirstLine(StringBuilder b, Request request, Response response) private static void logRequestFirstLine(StringBuilder b, Request request, Response response)
@ -1166,7 +1195,7 @@ public class CustomRequestLog extends ContainerLifeCycle implements RequestLog
private static void logConnectionStatus(StringBuilder b, Request request, Response response) private static void logConnectionStatus(StringBuilder b, Request request, Response response)
{ {
b.append(request.getHttpChannel().isResponseCompleted() ? (request.getHttpChannel().isPersistent() ? '+' : '-') : 'X'); b.append(request.getHttpChannel().isResponseCompleted() ? (request.getHttpChannel().isPersistent() ? '+' : '-') : 'X');
} }

View File

@ -32,7 +32,8 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
* Format (single log format). This log format can be output by most web * Format (single log format). This log format can be output by most web
* servers, and almost all web log analysis software can understand these * servers, and almost all web log analysis software can understand these
* formats. * formats.
* @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#NCSA_FORMAT} with a {@link RequestLogWriter} *
* @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#EXTENDED_NCSA_FORMAT} with a {@link RequestLogWriter}
*/ */
@Deprecated @Deprecated
@ManagedObject("NCSA standard format request log") @ManagedObject("NCSA standard format request log")
@ -40,7 +41,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
{ {
private final RequestLogWriter _requestLogWriter; private final RequestLogWriter _requestLogWriter;
/* ------------------------------------------------------------ */
/** /**
* Create request log object with default settings. * Create request log object with default settings.
*/ */
@ -49,7 +49,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
this((String)null); this((String)null);
} }
/* ------------------------------------------------------------ */
/** /**
* Create request log object with specified output file name. * Create request log object with specified output file name.
* *
@ -62,7 +61,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
this(new RequestLogWriter(filename)); this(new RequestLogWriter(filename));
} }
/* ------------------------------------------------------------ */
/** /**
* Create request log object given a RequestLogWriter file name. * Create request log object given a RequestLogWriter file name.
* *
@ -76,21 +74,18 @@ public class NCSARequestLog extends AbstractNCSARequestLog
setExtended(true); setExtended(true);
} }
/* ------------------------------------------------------------ */
/** /**
* Set the output file name of the request log. * Set the output file name of the request log.
* The file name may be in the format expected by * The file name may be in the format expected by
* {@link RolloverFileOutputStream}. * {@link RolloverFileOutputStream}.
* *
* @param filename file name of the request log * @param filename file name of the request log
*
*/ */
public void setFilename(String filename) public void setFilename(String filename)
{ {
_requestLogWriter.setFilename(filename); _requestLogWriter.setFilename(filename);
} }
/* ------------------------------------------------------------ */
@Override @Override
public void setLogTimeZone(String tz) public void setLogTimeZone(String tz)
{ {
@ -98,7 +93,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
_requestLogWriter.setTimeZone(tz); _requestLogWriter.setTimeZone(tz);
} }
/* ------------------------------------------------------------ */
/** /**
* Retrieve the output file name of the request log. * Retrieve the output file name of the request log.
* *
@ -109,8 +103,7 @@ public class NCSARequestLog extends AbstractNCSARequestLog
{ {
return _requestLogWriter.getFileName(); return _requestLogWriter.getFileName();
} }
/* ------------------------------------------------------------ */
/** /**
* Retrieve the file name of the request log with the expanded * Retrieve the file name of the request log with the expanded
* date wildcard if the output is written to the disk using * date wildcard if the output is written to the disk using
@ -123,14 +116,12 @@ public class NCSARequestLog extends AbstractNCSARequestLog
return _requestLogWriter.getDatedFilename(); return _requestLogWriter.getDatedFilename();
} }
/* ------------------------------------------------------------ */
@Override @Override
protected boolean isEnabled() protected boolean isEnabled()
{ {
return _requestLogWriter.isEnabled(); return _requestLogWriter.isEnabled();
} }
/* ------------------------------------------------------------ */
/** /**
* Set the number of days before rotated log files are deleted. * Set the number of days before rotated log files are deleted.
* *
@ -141,7 +132,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
_requestLogWriter.setRetainDays(retainDays); _requestLogWriter.setRetainDays(retainDays);
} }
/* ------------------------------------------------------------ */
/** /**
* Retrieve the number of days before rotated log files are deleted. * Retrieve the number of days before rotated log files are deleted.
* *
@ -153,7 +143,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
return _requestLogWriter.getRetainDays(); return _requestLogWriter.getRetainDays();
} }
/* ------------------------------------------------------------ */
/** /**
* Set append to log flag. * Set append to log flag.
* *
@ -165,7 +154,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
_requestLogWriter.setAppend(append); _requestLogWriter.setAppend(append);
} }
/* ------------------------------------------------------------ */
/** /**
* Retrieve append to log flag. * Retrieve append to log flag.
* *
@ -177,19 +165,17 @@ public class NCSARequestLog extends AbstractNCSARequestLog
return _requestLogWriter.isAppend(); return _requestLogWriter.isAppend();
} }
/* ------------------------------------------------------------ */
/** /**
* Set the log file name date format. * Set the log file name date format.
* @see RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
* *
* @param logFileDateFormat format string that is passed to {@link RolloverFileOutputStream} * @param logFileDateFormat format string that is passed to {@link RolloverFileOutputStream}
* @see RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
*/ */
public void setFilenameDateFormat(String logFileDateFormat) public void setFilenameDateFormat(String logFileDateFormat)
{ {
_requestLogWriter.setFilenameDateFormat(logFileDateFormat); _requestLogWriter.setFilenameDateFormat(logFileDateFormat);
} }
/* ------------------------------------------------------------ */
/** /**
* Retrieve the file name date format string. * Retrieve the file name date format string.
* *
@ -200,14 +186,12 @@ public class NCSARequestLog extends AbstractNCSARequestLog
return _requestLogWriter.getFilenameDateFormat(); return _requestLogWriter.getFilenameDateFormat();
} }
/* ------------------------------------------------------------ */
@Override @Override
public void write(String requestEntry) throws IOException public void write(String requestEntry) throws IOException
{ {
_requestLogWriter.write(requestEntry); _requestLogWriter.write(requestEntry);
} }
/* ------------------------------------------------------------ */
/** /**
* Set up request logging and open log file. * Set up request logging and open log file.
* *
@ -219,7 +203,6 @@ public class NCSARequestLog extends AbstractNCSARequestLog
super.doStart(); super.doStart();
} }
/* ------------------------------------------------------------ */
/** /**
* Close the log file and perform cleanup. * Close the log file and perform cleanup.
* *

View File

@ -16,30 +16,34 @@
// ======================================================================== // ========================================================================
// //
package org.eclipse.jetty.server; package org.eclipse.jetty.server;
import java.io.IOException; import java.io.IOException;
import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.server.handler.RequestLogHandler;
/** /**
* A <code>RequestLog</code> can be attached to a {@link org.eclipse.jetty.server.handler.RequestLogHandler} to enable * A <code>RequestLog</code> can be attached to a {@link org.eclipse.jetty.server.handler.RequestLogHandler} to enable
* logging of requests/responses. * logging of requests/responses.
*
* @see RequestLogHandler#setRequestLog(RequestLog) * @see RequestLogHandler#setRequestLog(RequestLog)
* @see Server#setRequestLog(RequestLog) * @see Server#setRequestLog(RequestLog)
*/ */
public interface RequestLog public interface RequestLog
{ {
/** /**
* @param request The request to log. * @param request The request to log.
* @param response The response to log. Note that for some requests * @param response The response to log. Note that for some requests
* the response instance may not have been fully populated (Eg 400 bad request * the response instance may not have been fully populated (Eg 400 bad request
* responses are sent without a servlet response object). Thus for basic * responses are sent without a servlet response object). Thus for basic
* log information it is best to consult {@link Response#getCommittedMetaData()} * log information it is best to consult {@link Response#getCommittedMetaData()}
* and {@link Response#getHttpChannel()} directly. * and {@link Response#getHttpChannel()} directly.
*/ */
void log(Request request, Response response); void log(Request request, Response response);
/**
* Writes the generated log string to a log sink
*/
interface Writer interface Writer
{ {
void write(String requestEntry) throws IOException; void write(String requestEntry) throws IOException;

View File

@ -29,6 +29,9 @@ import org.eclipse.jetty.util.component.AbstractLifeCycle;
import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger; import org.eclipse.jetty.util.log.Logger;
/**
* Writer which outputs pre-formatted request log strings to a file using {@link RolloverFileOutputStream}.
*/
public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Writer public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Writer
{ {
private static final Logger LOG = Log.getLogger(RequestLogWriter.class); private static final Logger LOG = Log.getLogger(RequestLogWriter.class);
@ -53,7 +56,7 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
setAppend(true); setAppend(true);
setRetainDays(31); setRetainDays(31);
if(filename != null) if (filename != null)
setFilename(filename); setFilename(filename);
} }
@ -63,7 +66,6 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
* {@link RolloverFileOutputStream}. * {@link RolloverFileOutputStream}.
* *
* @param filename file name of the request log * @param filename file name of the request log
*
*/ */
public void setFilename(String filename) public void setFilename(String filename)
{ {
@ -86,7 +88,6 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
return _filename; return _filename;
} }
/** /**
* Retrieve the file name of the request log with the expanded * Retrieve the file name of the request log with the expanded
* date wildcard if the output is written to the disk using * date wildcard if the output is written to the disk using
@ -126,7 +127,6 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
return _retainDays; return _retainDays;
} }
/** /**
* Set append to log flag. * Set append to log flag.
* *
@ -148,19 +148,17 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
return _append; return _append;
} }
/** /**
* Set the log file name date format. * Set the log file name date format.
* @see RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
* *
* @param logFileDateFormat format string that is passed to {@link RolloverFileOutputStream} * @param logFileDateFormat format string that is passed to {@link RolloverFileOutputStream}
* @see RolloverFileOutputStream#RolloverFileOutputStream(String, boolean, int, TimeZone, String, String)
*/ */
public void setFilenameDateFormat(String logFileDateFormat) public void setFilenameDateFormat(String logFileDateFormat)
{ {
_filenameDateFormat = logFileDateFormat; _filenameDateFormat = logFileDateFormat;
} }
/* ------------------------------------------------------------ */
/** /**
* Retrieve the file name date format string. * Retrieve the file name date format string.
* *
@ -171,13 +169,12 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
return _filenameDateFormat; return _filenameDateFormat;
} }
/* ------------------------------------------------------------ */
@Override @Override
public void write(String requestEntry) throws IOException public void write(String requestEntry) throws IOException
{ {
synchronized(this) synchronized (this)
{ {
if (_writer==null) if (_writer == null)
return; return;
_writer.write(requestEntry); _writer.write(requestEntry);
_writer.write(System.lineSeparator()); _writer.write(System.lineSeparator());
@ -185,18 +182,12 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
} }
} }
/* ------------------------------------------------------------ */
/**
* Set up request logging and open log file.
*
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
*/
@Override @Override
protected synchronized void doStart() throws Exception protected synchronized void doStart() throws Exception
{ {
if (_filename != null) if (_filename != null)
{ {
_fileOut = new RolloverFileOutputStream(_filename,_append,_retainDays,TimeZone.getTimeZone(getTimeZone()),_filenameDateFormat,null); _fileOut = new RolloverFileOutputStream(_filename, _append, _retainDays, TimeZone.getTimeZone(getTimeZone()), _filenameDateFormat, null);
_closeOut = true; _closeOut = true;
LOG.info("Opened " + getDatedFilename()); LOG.info("Opened " + getDatedFilename());
} }
@ -205,7 +196,7 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
_out = _fileOut; _out = _fileOut;
synchronized(this) synchronized (this)
{ {
_writer = new OutputStreamWriter(_out); _writer = new OutputStreamWriter(_out);
} }
@ -222,12 +213,6 @@ public class RequestLogWriter extends AbstractLifeCycle implements RequestLog.Wr
return _timeZone; return _timeZone;
} }
/* ------------------------------------------------------------ */
/**
* Close the log file and perform cleanup.
*
* @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStop()
*/
@Override @Override
protected void doStop() throws Exception protected void doStop() throws Exception
{ {

View File

@ -24,7 +24,7 @@ import org.eclipse.jetty.util.annotation.ManagedObject;
/** /**
* Implementation of NCSARequestLog where output is sent as a SLF4J INFO Log message on the named logger "org.eclipse.jetty.server.RequestLog" * Implementation of NCSARequestLog where output is sent as a SLF4J INFO Log message on the named logger "org.eclipse.jetty.server.RequestLog"
* @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#NCSA_FORMAT} with an {@link Slf4jRequestLogWriter} * @deprecated use {@link CustomRequestLog} given format string {@link CustomRequestLog#EXTENDED_NCSA_FORMAT} with an {@link Slf4jRequestLogWriter}
*/ */
@Deprecated @Deprecated
@ManagedObject("NCSA standard format request log to slf4j bridge") @ManagedObject("NCSA standard format request log to slf4j bridge")