summaryrefslogtreecommitdiffstats
path: root/container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java')
-rw-r--r--container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java106
1 files changed, 83 insertions, 23 deletions
diff --git a/container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java b/container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java
index 9bb9819cd1f..064b6cf6279 100644
--- a/container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java
+++ b/container-core/src/main/java/com/yahoo/container/jdisc/LoggingRequestHandler.java
@@ -3,6 +3,7 @@ package com.yahoo.container.jdisc;
import com.google.inject.Inject;
import com.yahoo.container.handler.Timing;
+import com.yahoo.container.http.AccessLogUtil;
import com.yahoo.container.logging.AccessLog;
import com.yahoo.container.logging.AccessLogEntry;
import com.yahoo.jdisc.Metric;
@@ -10,15 +11,16 @@ import com.yahoo.jdisc.Response;
import com.yahoo.jdisc.handler.CompletionHandler;
import com.yahoo.jdisc.handler.ContentChannel;
import com.yahoo.jdisc.http.server.jetty.AccessLoggingRequestHandler;
+import java.util.logging.Level;
import com.yahoo.yolean.Exceptions;
import java.io.IOException;
import java.io.OutputStream;
+import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.util.Optional;
import java.util.concurrent.Executor;
-import java.util.logging.Level;
/**
* A request handler base class extending the features of
@@ -26,43 +28,35 @@ import java.util.logging.Level;
*
* @author Steinar Knutsen
*/
-// TODO Vespa 8: Deprecate all constructors taking AccessLog as parameter
public abstract class LoggingRequestHandler extends ThreadedHttpRequestHandler {
- public LoggingRequestHandler(Executor executor, AccessLog ignored) {
- this(executor, ignored, null);
- }
+ private final AccessLog accessLog;
- public LoggingRequestHandler(Executor executor) {
- this(executor, null, null);
+ public LoggingRequestHandler(Executor executor, AccessLog accessLog) {
+ this(executor, accessLog, null);
}
public static class Context {
final Executor executor;
- final AccessLog ignored;
+ final AccessLog accessLog;
final Metric metric;
@Inject
- public Context(Executor executor, AccessLog ignored, Metric metric) {
+ public Context(Executor executor, AccessLog accessLog, Metric metric) {
this.executor = executor;
- this.ignored = ignored;
+ this.accessLog = accessLog;
this.metric = metric;
}
-
- public Context(Executor executor, Metric metric) {
- this(executor, null, metric);
- }
-
public Context(Context other) {
this.executor = other.executor;
- this.ignored = other.ignored;
+ this.accessLog = other.accessLog;
this.metric = other.metric;
}
public Executor getExecutor() { return executor; }
- public AccessLog getAccessLog() { return ignored; }
+ public AccessLog getAccessLog() { return accessLog; }
public Metric getMetric() { return metric; }
}
@@ -80,19 +74,20 @@ public abstract class LoggingRequestHandler extends ThreadedHttpRequestHandler {
@Inject
public LoggingRequestHandler(Context ctx) {
- this(ctx.executor, ctx.ignored, ctx.metric);
+ this(ctx.executor, ctx.accessLog, ctx.metric);
}
public LoggingRequestHandler(Context ctx, boolean allowAsyncResponse) {
- this(ctx.executor, ctx.ignored, ctx.metric, allowAsyncResponse);
+ this(ctx.executor, ctx.accessLog, ctx.metric, allowAsyncResponse);
}
- public LoggingRequestHandler(Executor executor, AccessLog ignored, Metric metric) {
- this(executor, ignored, metric, false);
+ public LoggingRequestHandler(Executor executor, AccessLog accessLog, Metric metric) {
+ this(executor, accessLog, metric, false);
}
- public LoggingRequestHandler(Executor executor, AccessLog ignored, Metric metric, boolean allowAsyncResponse) {
+ public LoggingRequestHandler(Executor executor, AccessLog accessLog, Metric metric, boolean allowAsyncResponse) {
super(executor, metric, allowAsyncResponse);
+ this.accessLog = accessLog;
}
@Override
@@ -111,6 +106,26 @@ public abstract class LoggingRequestHandler extends ThreadedHttpRequestHandler {
return clientAddress.toString();
}
+ private static long getEvalStart(Timing timing, long startTime) {
+ if (timing == null || timing.getQueryStartTime() == 0L) {
+ return startTime;
+ } else {
+ return timing.getQueryStartTime();
+ }
+ }
+
+ private static String remoteHostAddress(com.yahoo.jdisc.http.HttpRequest httpRequest) {
+ SocketAddress remoteAddress = httpRequest.getRemoteAddress();
+ if (remoteAddress == null) return "0.0.0.0";
+
+ if (remoteAddress instanceof InetSocketAddress) {
+ return ((InetSocketAddress) remoteAddress).getAddress().getHostAddress();
+ } else {
+ throw new RuntimeException("Expected remote address of type InetSocketAddress, got " +
+ remoteAddress.getClass().getName());
+ }
+ }
+
private void logTimes(long startTime, String sourceIP,
long renderStartTime, long commitStartTime, long endTime,
String req, String normalizedQuery, Timing t) {
@@ -242,8 +257,21 @@ public abstract class LoggingRequestHandler extends ThreadedHttpRequestHandler {
// The request is created by JDisc http layer (Jetty)
// Actual logging will be done by the Jetty integration; here, we just need to populate.
entry = jdiscRequestAccessLogEntry.get();
- httpResponse.populateAccessLogEntry(entry);
+ } else {
+ // Not running on JDisc http layer (Jetty), e.g unit tests
+ AccessLogEntry accessLogEntry = new AccessLogEntry();
+ populateAccessLogEntryNotCreatedByHttpServer(accessLogEntry,
+ jdiscRequest,
+ extendedResponse.getTiming(),
+ httpRequest.getUri().toString(),
+ commitStartTime,
+ startTime,
+ rendererWiring.written(),
+ httpResponse.getStatus());
+ accessLog.log(accessLogEntry);
+ entry = accessLogEntry;
}
+ httpResponse.populateAccessLogEntry(entry);
}
private String getUri(com.yahoo.jdisc.http.HttpRequest jdiscRequest) {
@@ -257,4 +285,36 @@ public abstract class LoggingRequestHandler extends ThreadedHttpRequestHandler {
}
}
+ private void populateAccessLogEntryNotCreatedByHttpServer(AccessLogEntry logEntry,
+ com.yahoo.jdisc.http.HttpRequest httpRequest,
+ Timing timing,
+ String fullRequest,
+ long commitStartTime,
+ long startTime,
+ long written,
+ int status) {
+ try {
+ InetSocketAddress remoteAddress = AccessLogUtil.getRemoteAddress(httpRequest);
+ long evalStartTime = getEvalStart(timing, startTime);
+ logEntry.setIpV4Address(remoteHostAddress(httpRequest));
+ logEntry.setTimeStamp(evalStartTime);
+ logEntry.setDurationBetweenRequestResponse(commitStartTime - evalStartTime);
+ logEntry.setReturnedContentSize(written);
+ logEntry.setStatusCode(status);
+ if (remoteAddress != null) {
+ logEntry.setRemoteAddress(remoteAddress);
+ logEntry.setRemotePort(remoteAddress.getPort());
+ }
+ URI uri = AccessLogUtil.getUri(httpRequest);
+ logEntry.setRawPath(uri.getRawPath());
+ logEntry.setRawQuery(uri.getRawQuery());
+ logEntry.setUserAgent(AccessLogUtil.getUserAgentHeader(httpRequest));
+ logEntry.setReferer(AccessLogUtil.getReferrerHeader(httpRequest));
+ logEntry.setHttpMethod(AccessLogUtil.getHttpMethod(httpRequest));
+ logEntry.setHttpVersion(AccessLogUtil.getHttpVersion(httpRequest));
+ } catch (Exception e) {
+ log.log(Level.WARNING, "Could not populate the access log [" + fullRequest + "]", e);
+ }
+ }
+
}