Chromium Code Reviews| Index: components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java |
| diff --git a/components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java b/components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java |
| index 6f1c9ab457d0dc222d0a9b3ba33c6153c9ae122d..53eabac0c51acd73d0b04fb27b81f0528c6f0934 100644 |
| --- a/components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java |
| +++ b/components/cronet/android/api/src/org/chromium/net/RequestFinishedInfo.java |
| @@ -4,21 +4,25 @@ |
| package org.chromium.net; |
| +import android.support.annotation.IntDef; |
| import android.support.annotation.Nullable; |
| +import java.lang.annotation.Retention; |
| +import java.lang.annotation.RetentionPolicy; |
| import java.util.Collection; |
| +import java.util.Date; |
| import java.util.concurrent.Executor; |
| /** |
| * Information about a finished request. Passed to {@link RequestFinishedInfo.Listener}. |
| * |
| - * {@hide} as it's a prototype. |
| + * {hide} as it's a prototype. |
| */ |
| public final class RequestFinishedInfo { |
| /** |
| * Listens for finished requests for the purpose of collecting metrics. |
| * |
| - * {@hide} as it's a prototype. |
| + * {hide} as it's a prototype. |
| */ |
| public abstract static class Listener { |
| private final Executor mExecutor; |
| @@ -47,78 +51,235 @@ public final class RequestFinishedInfo { |
| } |
| /** |
| - * Metrics collected for a single request. |
| + * Metrics collected for a single request. Most of these metrics are timestamps for events |
| + * during the lifetime of the request, which can be used to build a detailed timeline for |
| + * investigating performance. |
| * |
| - * {@hide} as it's a prototype. |
| + * Events happen in this order: |
| + * <ol> |
| + * <li>{@link #getRequestStart request start}</li> |
| + * <li>{@link #getDnsStart DNS start}</li> |
| + * <li>{@link #getDnsEnd DNS end}</li> |
| + * <li>{@link #getConnectStart connect start}</li> |
| + * <li>{@link #getSslStart SSL start}</li> |
| + * <li>{@link #getSslEnd SSL end}</li> |
| + * <li>{@link #getConnectEnd connect end}</li> |
| + * <li>{@link #getSendingStart sending start}</li> |
| + * <li>{@link #getSendingEnd sending end}</li> |
| + * <li>{@link #getResponseStart response start}</li> |
| + * <li>{@link #getResponseEnd response end}</li> |
| + * </ol> |
| + * |
| + * Start times are reported as the time when a request started blocking on event, not when the |
| + * event actually occurred, with the exception of push start and end. If a metric is not |
| + * meaningful or not available, including cases when a request finished before reaching that |
| + * stage, start and end times will be {@code null}. If no time was spent blocking on an event, |
| + * start and end will be the same time. |
| + * |
| + * If the system clock is adjusted during the request, some of the {@link java.util.Date} values |
| + * might not match it. Timestamps are recorded using a clock that is guaranteed not to run |
| + * backwards. All timestamps are correct relative to the system clock at the time of request |
| + * start, and taking the difference between two timestamps will give the correct difference |
| + * between the events. In order to preserve this property, timestamps for events other than |
| + * request start are not guaranteed to match the system clock at the times they represent. |
| + * |
| + * Most timing metrics are taken from |
| + * <a |
| + * href="https://cs.chromium.org/chromium/src/net/base/load_timing_info.h">LoadTimingInfo</a>, |
| + * which holds the information for <a href="http://w3c.github.io/navigation-timing/"></a> and |
| + * <a href="https://www.w3.org/TR/resource-timing/"></a>. |
| + * |
| + * {hide} as it's a prototype. |
|
pauljensen
2016/09/12 11:50:09
hide->@hide
mgersh
2016/09/12 20:55:13
Oops. I was testing and forgot to change it back.
|
| */ |
| - public static class Metrics { |
| + public abstract static class Metrics { |
| + /** |
| + * Returns time when the request started. |
| + * @return {@link java.util.Date} representing when the native request actually started. |
| + * This timestamp will match the system clock at the time it represents. |
| + */ |
| + @Nullable |
| + public abstract Date getRequestStart(); |
| + |
| + /** |
| + * Returns time when DNS lookup started. |
| + * @return {@link java.util.Date} representing when DNS lookup started. {@code null} if the |
| + * socket was reused (see {@link #getSocketReused}). |
| + */ |
| @Nullable |
| - private final Long mTtfbMs; |
| + public abstract Date getDnsStart(); |
| + |
| + /** |
| + * Returns time when DNS lookup finished. |
|
pauljensen
2016/09/12 11:50:09
We should address what happens if Cronet internall
mgersh
2016/09/12 20:55:13
Done.
|
| + * @return {@link java.util.Date} representing when DNS lookup finished. {@code null} if the |
| + * socket was reused (see {@link #getSocketReused}). |
| + */ |
| @Nullable |
| - private final Long mTotalTimeMs; |
| + public abstract Date getDnsEnd(); |
| + |
| + /** |
| + * Returns time when connection establishmentn started. |
|
pauljensen
2016/09/12 11:50:09
extra n on the end of establishment
mgersh
2016/09/12 20:55:13
Done.
|
| + * @return {@link java.util.Date} representing when connection establishment started, |
| + * typically when DNS resolution finishes. {@code null} if the socket was reused (see |
| + * {@link #getSocketReused}). |
| + */ |
| @Nullable |
| - private final Long mSentBytesCount; |
| + public abstract Date getConnectStart(); |
| + |
| + /** |
| + * Returns time when connection establishment finished. |
| + * @return {@link java.util.Date} representing when connection establishment finished, |
| + * after TCP connection is established and, if using HTTPS, SSL handshake is completed. |
| + * {@code null} if the socket was reused (see {@link #getSocketReused}). |
| + */ |
| @Nullable |
| - private final Long mReceivedBytesCount; |
| + public abstract Date getConnectEnd(); |
| - public Metrics(@Nullable Long ttfbMs, @Nullable Long totalTimeMs, |
| - @Nullable Long sentBytesCount, @Nullable Long receivedBytesCount) { |
| - mTtfbMs = ttfbMs; |
| - mTotalTimeMs = totalTimeMs; |
| - mSentBytesCount = sentBytesCount; |
| - mReceivedBytesCount = receivedBytesCount; |
| - } |
| + /** |
| + * Returns time when SSL handshake started. |
| + * @return {@link java.util.Date} representing when SSL handshake started. {@code null} if |
| + * SSL is not used or if the socket was reused (see {@link #getSocketReused}). |
| + */ |
| + @Nullable |
| + public abstract Date getSslStart(); |
| + |
| + /** |
| + * Returns time when SSL handshake finished. |
|
pauljensen
2016/09/12 11:50:09
What are the SSL timestamps for QUIC 0-RTT?
mgersh
2016/09/12 20:55:13
Done.
|
| + * @return {@link java.util.Date} representing when SSL handshake finished. {@code null} if |
| + * SSL is not used or if the socket was reused (see {@link #getSocketReused}). |
| + */ |
| + @Nullable |
| + public abstract Date getSslEnd(); |
| + |
| + /** |
| + * Returns time when sending the request started. |
| + * @return {@link java.util.Date} representing when sending HTTP request headers started. |
| + */ |
| + @Nullable |
| + public abstract Date getSendingStart(); |
| + |
| + /** |
| + * Returns time when sending the request finished. |
| + * @return {@link java.util.Date} representing when sending HTTP request body finished. |
| + * (Sending request body happens after sending request headers.) |
| + */ |
| + @Nullable |
| + public abstract Date getSendingEnd(); |
| + |
| + /** |
| + * Returns time when first byte of HTTP/2 server push was received. |
| + * @return {@link java.util.Date} representing when the first byte of an HTTP/2 server push |
| + * was received. {@code null} if server push is not used. |
| + */ |
| + @Nullable |
| + public abstract Date getPushStart(); |
| + |
| + /** |
| + * Returns time when last byte of HTTP/2 server push was received. |
| + * @return {@link java.util.Date} representing when the last byte of an HTTP/2 server push |
| + * was received. {@code null} if server push is not used. |
| + */ |
| + @Nullable |
| + public abstract Date getPushEnd(); |
| + |
| + /** |
| + * Returns time when first byte of response was received. |
|
pauljensen
2016/09/12 11:50:09
Does this include the headers and/or the body?
mgersh
2016/09/12 20:55:13
Took another look at what this is and rewrote it.
|
| + * @return {@link java.util.Date} representing when the first byte of the response was |
| + * received. |
| + */ |
| + @Nullable |
| + public abstract Date getResponseStart(); |
| + |
| + /** |
| + * Returns time when last byte of response was received. |
| + * @return {@link java.util.Date} representing when the last byte of the response was |
| + * received. |
| + */ |
| + @Nullable |
| + public abstract Date getResponseEnd(); |
| + |
| + /** |
| + * Returns whether the socket was reused from a previous request. |
| + * @return whether this request reused a socket from a previous request. When {@code true}, |
| + * DNS, connection, and SSL times will be {@code null}. |
|
pauljensen
2016/09/12 11:50:09
What happens for multiplexed streams (i.e. HTTP/2
mgersh
2016/09/12 20:55:13
Done.
|
| + */ |
| + @Nullable |
| + public abstract boolean getSocketReused(); |
| /** |
| * Returns milliseconds between request initiation and first byte of response headers, |
| - * or null if not collected. |
| + * or {@code null} if not collected. |
| + * TODO(mgersh): Remove once new API works http://crbug.com/629194 |
|
pauljensen
2016/09/12 11:50:09
add a @hide here and on line 220; that way if some
mgersh
2016/09/12 20:55:13
Done.
|
| */ |
| @Nullable |
| - public Long getTtfbMs() { |
| - return mTtfbMs; |
| - } |
| + public abstract Long getTtfbMs(); |
| /** |
| * Returns milliseconds between request initiation and finish, |
| - * including a failure or cancellation, or null if not collected. |
| + * including a failure or cancellation, or {@code null} if not collected. |
| + * TODO(mgersh): Remove once new API works http://crbug.com/629194 |
| */ |
| @Nullable |
| - public Long getTotalTimeMs() { |
| - return mTotalTimeMs; |
| - } |
| + public abstract Long getTotalTimeMs(); |
| /** |
| - * Returns total bytes sent over the network transport layer, or null if not collected. |
| + * Returns total bytes sent over the network transport layer, or {@code null} if not |
| + * collected. |
| */ |
| @Nullable |
| - public Long getSentBytesCount() { |
| - return mSentBytesCount; |
| - } |
| + public abstract Long getSentBytesCount(); |
| /** |
| - * Returns total bytes received over the network transport layer, or null if not collected. |
| + * Returns total bytes received over the network transport layer, or {@code null} if not |
| + * collected. |
| */ |
| @Nullable |
| - public Long getReceivedBytesCount() { |
| - return mReceivedBytesCount; |
| - } |
| + public abstract Long getReceivedBytesCount(); |
| } |
| private final String mUrl; |
| private final Collection<Object> mAnnotations; |
| private final Metrics mMetrics; |
| + |
| + /** @hide */ |
| + @IntDef({SUCCEEDED, FAILED, CANCELED}) |
| + @Retention(RetentionPolicy.SOURCE) |
| + public @interface FinishedReason {} |
| + |
| + /** |
| + * Reason value indicating that the request succeeded. Returned from {@link #getFinishedReason}. |
| + */ |
| + public static final int SUCCEEDED = 0; |
| + /** |
| + * Reason value indicating that the request failed or errored. Returned from |
| + * {@link #getFinishedReason}. |
| + */ |
| + public static final int FAILED = 1; |
| + /** |
| + * Reason value indicating that the request was canceled. Returned from |
| + * {@link #getFinishedReason}. |
| + */ |
| + public static final int CANCELED = 2; |
| + |
| + @FinishedReason |
| + private final int mFinishedReason; |
| + |
| @Nullable |
| private final UrlResponseInfo mResponseInfo; |
| + @Nullable |
| + private final UrlRequestException mException; |
| /** |
| * @hide only used by internal implementation. |
| */ |
| public RequestFinishedInfo(String url, Collection<Object> annotations, Metrics metrics, |
| - @Nullable UrlResponseInfo responseInfo) { |
| + @FinishedReason int finishedReason, @Nullable UrlResponseInfo responseInfo, |
| + @Nullable UrlRequestException exception) { |
| mUrl = url; |
| mAnnotations = annotations; |
| mMetrics = metrics; |
| + mFinishedReason = finishedReason; |
| mResponseInfo = responseInfo; |
| + mException = exception; |
| } |
| /** Returns the request's original URL. */ |
| @@ -132,6 +293,7 @@ public final class RequestFinishedInfo { |
| } |
| // TODO(klm): Collect and return a chain of Metrics objects for redirect responses. |
| + // TODO(mgersh): Update this javadoc when new metrics are fully implemented |
| /** |
| * Returns metrics collected for this request. |
| * |
| @@ -149,6 +311,15 @@ public final class RequestFinishedInfo { |
| } |
| /** |
| + * Returns the reason why the request finished. |
| + * @return one of {@link #SUCCEEDED}, {@link #FAILED}, or {@link #CANCELED} |
| + */ |
| + @FinishedReason |
| + public int getFinishedReason() { |
| + return mFinishedReason; |
| + } |
| + |
| + /** |
| * Returns a {@link UrlResponseInfo} for the request, if its response had started. |
| * @return {@link UrlResponseInfo} for the request, if its response had started. |
| */ |
| @@ -156,4 +327,15 @@ public final class RequestFinishedInfo { |
| public UrlResponseInfo getResponseInfo() { |
| return mResponseInfo; |
| } |
| + |
| + /** |
| + * If the request failed, returns the same {@link UrlRequestException} provided to |
| + * {@link UrlRequest.Callback#onFailed}. |
| + * |
| + * @return the request's {@link UrlRequestException}, if the request failed |
| + */ |
| + @Nullable |
| + public UrlRequestException getException() { |
| + return mException; |
| + } |
| } |