1 // Copyright 2016 The Chromium Authors 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package android.net.http; 6 7 import androidx.annotation.Nullable; 8 9 import java.time.Instant; 10 import java.util.Collection; 11 import java.util.concurrent.Executor; 12 13 /** 14 * Information about a finished request. Passed to {@link RequestFinishedInfo.Listener}. 15 * 16 * <p>To associate the data with the original request, use {@link 17 * UrlRequest.Builder#addRequestAnnotation} to add a unique identifier when creating the 18 * request, and call {@link #getAnnotations} when the {@link RequestFinishedInfo} is received to 19 * retrieve the identifier. 20 * 21 * {@hide} 22 */ 23 public abstract class RequestFinishedInfo { 24 /** 25 * Listens for finished requests for the purpose of collecting metrics. 26 * 27 * {@hide} 28 */ 29 public abstract static class Listener { 30 private final Executor mExecutor; 31 Listener(Executor executor)32 public Listener(Executor executor) { 33 if (executor == null) { 34 throw new IllegalStateException("Executor must not be null"); 35 } 36 mExecutor = executor; 37 } 38 39 /** 40 * Invoked with request info. Will be called in a task submitted to the {@link 41 * java.util.concurrent.Executor} returned by {@link #getExecutor}. 42 * 43 * @param requestInfo {@link RequestFinishedInfo} for finished request. 44 */ onRequestFinished(RequestFinishedInfo requestInfo)45 public abstract void onRequestFinished(RequestFinishedInfo requestInfo); 46 47 /** 48 * Returns this listener's executor. Can be called on any thread. 49 * 50 * @return this listener's {@link java.util.concurrent.Executor} 51 */ getExecutor()52 public Executor getExecutor() { 53 return mExecutor; 54 } 55 } 56 57 /** 58 * Metrics collected for a single request. Most of these metrics are timestamps for events 59 * during the lifetime of the request, which can be used to build a detailed timeline for 60 * investigating performance. 61 * 62 * <p>Events happen in this order: 63 * 64 * <ol> 65 * <li>{@link #getRequestStart request start} 66 * <li>{@link #getDnsStart DNS start} 67 * <li>{@link #getDnsEnd DNS end} 68 * <li>{@link #getConnectStart connect start} 69 * <li>{@link #getSslStart SSL start} 70 * <li>{@link #getSslEnd SSL end} 71 * <li>{@link #getConnectEnd connect end} 72 * <li>{@link #getSendingStart sending start} 73 * <li>{@link #getSendingEnd sending end} 74 * <li>{@link #getResponseStart response start} 75 * <li>{@link #getRequestEnd request end} 76 * </ol> 77 * 78 * Start times are reported as the time when a request started blocking on event, not when the 79 * event actually occurred, with the exception of push start and end. If a metric is not 80 * meaningful or not available, including cases when a request finished before reaching that 81 * stage, start and end times will be {@code null}. If no time was spent blocking on an event, 82 * start and end will be the same time. 83 * 84 * <p>If the system clock is adjusted during the request, some of the {@link java.util.Date} 85 * values might not match it. Timestamps are recorded using a clock that is guaranteed not to 86 * run backwards. All timestamps are correct relative to the system clock at the time of request 87 * start, and taking the difference between two timestamps will give the correct difference 88 * between the events. In order to preserve this property, timestamps for events other than 89 * request start are not guaranteed to match the system clock at the times they represent. 90 * 91 * <p>Most timing metrics are taken from <a 92 * href="https://cs.chromium.org/chromium/src/net/base/load_timing_info.h">LoadTimingInfo</a>, 93 * which holds the information for <a href="http://w3c.github.io/navigation-timing/"></a> and <a 94 * href="https://www.w3.org/TR/resource-timing/"></a>. 95 * 96 * <p>{@hide} as it's a prototype. 97 */ 98 public abstract static class Metrics { 99 /** 100 * Returns time when the request started. 101 * 102 * @return {@link java.util.Date} representing when the native request actually started. 103 * This 104 * timestamp will match the system clock at the time it represents. 105 */ 106 @Nullable getRequestStart()107 public abstract Instant getRequestStart(); 108 109 /** 110 * Returns time when DNS lookup started. This and {@link #getDnsEnd} will return non-null 111 * values regardless of whether the result came from a DNS server or the local cache. 112 * 113 * @return {@link java.util.Date} representing when DNS lookup started. {@code null} if the 114 * socket was reused (see {@link #getSocketReused}). 115 */ 116 @Nullable getDnsStart()117 public abstract Instant getDnsStart(); 118 119 /** 120 * Returns time when DNS lookup finished. This and {@link #getDnsStart} will return non-null 121 * values regardless of whether the result came from a DNS server or the local cache. 122 * 123 * @return {@link java.util.Date} representing when DNS lookup finished. {@code null} if the 124 * socket was reused (see {@link #getSocketReused}). 125 */ 126 @Nullable getDnsEnd()127 public abstract Instant getDnsEnd(); 128 129 /** 130 * Returns time when connection establishment started. 131 * 132 * @return {@link java.util.Date} representing when connection establishment started, 133 * typically 134 * when DNS resolution finishes. {@code null} if the socket was reused (see {@link 135 * #getSocketReused}). 136 */ 137 @Nullable getConnectStart()138 public abstract Instant getConnectStart(); 139 140 /** 141 * Returns time when connection establishment finished. 142 * 143 * @return {@link java.util.Date} representing when connection establishment finished, after 144 * TCP 145 * connection is established and, if using HTTPS, SSL handshake is completed. For QUIC 146 * 0-RTT, this represents the time of handshake confirmation and might happen later than 147 * {@link #getSendingStart}. {@code null} if the socket was reused (see {@link 148 * #getSocketReused}). 149 */ 150 @Nullable getConnectEnd()151 public abstract Instant getConnectEnd(); 152 153 /** 154 * Returns time when SSL handshake started. For QUIC, this will be the same time as {@link 155 * #getConnectStart}. 156 * 157 * @return {@link java.util.Date} representing when SSL handshake started. {@code null} if 158 * SSL 159 * is not used or if the socket was reused (see {@link #getSocketReused}). 160 */ 161 @Nullable getSslStart()162 public abstract Instant getSslStart(); 163 164 /** 165 * Returns time when SSL handshake finished. For QUIC, this will be the same time as {@link 166 * #getConnectEnd}. 167 * 168 * @return {@link java.util.Date} representing when SSL handshake finished. {@code null} if 169 * SSL 170 * is not used or if the socket was reused (see {@link #getSocketReused}). 171 */ 172 @Nullable getSslEnd()173 public abstract Instant getSslEnd(); 174 175 /** 176 * Returns time when sending the request started. 177 * 178 * @return {@link java.util.Date} representing when sending HTTP request headers started. 179 */ 180 @Nullable getSendingStart()181 public abstract Instant getSendingStart(); 182 183 /** 184 * Returns time when sending the request finished. 185 * 186 * @return {@link java.util.Date} representing when sending HTTP request body finished. 187 * (Sending 188 * request body happens after sending request headers.) 189 */ 190 @Nullable getSendingEnd()191 public abstract Instant getSendingEnd(); 192 193 /** 194 * Returns time when first byte of HTTP/2 server push was received. 195 * 196 * @return {@link java.util.Date} representing when the first byte of an HTTP/2 server push 197 * was 198 * received. {@code null} if server push is not used. 199 */ 200 @Nullable getPushStart()201 public abstract Instant getPushStart(); 202 203 /** 204 * Returns time when last byte of HTTP/2 server push was received. 205 * 206 * @return {@link java.util.Date} representing when the last byte of an HTTP/2 server push 207 * was 208 * received. {@code null} if server push is not used. 209 */ 210 @Nullable getPushEnd()211 public abstract Instant getPushEnd(); 212 213 /** 214 * Returns time when the end of the response headers was received. 215 * 216 * @return {@link java.util.Date} representing when the end of the response headers was 217 * received. 218 */ 219 @Nullable getResponseStart()220 public abstract Instant getResponseStart(); 221 222 /** 223 * Returns time when the request finished. 224 * 225 * @return {@link java.util.Date} representing when the request finished. 226 */ 227 @Nullable getRequestEnd()228 public abstract Instant getRequestEnd(); 229 230 /** 231 * Returns whether the socket was reused from a previous request. In HTTP/2 or QUIC, if 232 * streams are multiplexed in a single connection, returns {@code true} for all streams 233 * after the first. 234 * 235 * @return whether this request reused a socket from a previous request. When {@code true}, 236 * DNS, 237 * connection, and SSL times will be {@code null}. 238 */ getSocketReused()239 public abstract boolean getSocketReused(); 240 241 /** 242 * Returns total bytes sent over the network transport layer, or {@code null} if not 243 * collected. 244 */ 245 @Nullable getSentByteCount()246 public abstract Long getSentByteCount(); 247 248 /** 249 * Returns total bytes received over the network transport layer, or {@code null} if not 250 * collected. Number of bytes does not include any previous redirects. 251 */ 252 @Nullable getReceivedByteCount()253 public abstract Long getReceivedByteCount(); 254 } 255 256 /** 257 * Reason value indicating that the request succeeded. Returned from {@link #getFinishedReason}. 258 */ 259 public static final int SUCCEEDED = 0; 260 /** 261 * Reason value indicating that the request failed or returned an error. Returned from {@link 262 * #getFinishedReason}. 263 */ 264 public static final int FAILED = 1; 265 /** 266 * Reason value indicating that the request was canceled. Returned from {@link 267 * #getFinishedReason}. 268 */ 269 public static final int CANCELED = 2; 270 271 /** 272 * Returns the request's original URL. 273 * 274 * @return the request's original URL 275 */ getUrl()276 public abstract String getUrl(); 277 278 /** 279 * Returns the objects that the caller has supplied when initiating the request, using {@link 280 * UrlRequest.Builder#addRequestAnnotation}. Annotations can be used to associate a 281 * {@link RequestFinishedInfo} with the original request or type of request. 282 * 283 * @return annotations supplied when creating the request 284 */ getAnnotations()285 public abstract Collection<Object> getAnnotations(); 286 287 // TODO(klm): Collect and return a chain of Metrics objects for redirect responses. 288 // TODO(mgersh): Update this javadoc when new metrics are fully implemented 289 290 /** 291 * Returns metrics collected for this request. 292 * 293 * <p>The reported times and bytes account for all redirects, i.e. 294 * the TTFB is from the start of the original request to the ultimate response headers, the TTLB 295 * is from the start of the original request to the end of the ultimate response, the received 296 * byte count is for all redirects and the ultimate response combined. These cumulative metric 297 * definitions are debatable, but are chosen to make sense for user-facing latency analysis. 298 * 299 * @return metrics collected for this request. 300 * 301 * <p>{@hide} as the Metrics class is hidden 302 */ getMetrics()303 public abstract Metrics getMetrics(); 304 305 /** 306 * Returns the reason why the request finished. 307 * 308 * @return one of {@link #SUCCEEDED}, {@link #FAILED}, or {@link #CANCELED} 309 */ getFinishedReason()310 public abstract int getFinishedReason(); 311 312 /** 313 * Returns a {@link UrlResponseInfo} for the request, if its response had started. 314 * 315 * @return {@link UrlResponseInfo} for the request, if its response had started. 316 */ 317 @Nullable getResponseInfo()318 public abstract UrlResponseInfo getResponseInfo(); 319 320 /** 321 * If the request failed, returns the same {@link HttpException} provided to 322 * {@link UrlRequest.Callback#onFailed}. 323 * 324 * @return the request's {@link HttpException}, if the request failed 325 */ 326 @Nullable getException()327 public abstract HttpException getException(); 328 } 329