1 /*
2 * Copyright (C) 2017 Square, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package okhttp3;
17
18 import java.io.IOException;
19 import java.net.InetAddress;
20 import java.net.InetSocketAddress;
21 import java.net.Proxy;
22 import java.util.List;
23 import javax.annotation.Nullable;
24
25 /**
26 * Listener for metrics events. Extend this class to monitor the quantity, size, and duration of
27 * your application's HTTP calls.
28 *
29 * <p>All start/connect/acquire events will eventually receive a matching end/release event,
30 * either successful (non-null parameters), or failed (non-null throwable). The first common
31 * parameters of each event pair are used to link the event in case of concurrent or repeated
32 * events e.g. dnsStart(call, domainName) -> dnsEnd(call, domainName, inetAddressList).
33 *
34 * <p>Nesting is as follows
35 * <ul>
36 * <li>call -> (dns -> connect -> secure connect)* -> request events</li>
37 * <li>call -> (connection acquire/release)*</li>
38 * </ul>
39 *
40 * <p>Request events are ordered:
41 * requestHeaders -> requestBody -> responseHeaders -> responseBody
42 *
43 * <p>Since connections may be reused, the dns and connect events may not be present for a call,
44 * or may be repeated in case of failure retries, even concurrently in case of happy eyeballs type
45 * scenarios. A redirect cross domain, or to use https may cause additional connection and request
46 * events.
47 *
48 * <p>All event methods must execute fast, without external locking, cannot throw exceptions,
49 * attempt to mutate the event parameters, or be re-entrant back into the client.
50 * Any IO - writing to files or network should be done asynchronously.
51 */
52 public abstract class EventListener {
53 public static final EventListener NONE = new EventListener() {
54 };
55
56 static EventListener.Factory factory(EventListener listener) {
57 return call -> listener;
58 }
59
60 /**
61 * Invoked as soon as a call is enqueued or executed by a client. In case of thread or stream
62 * limits, this call may be executed well before processing the request is able to begin.
63 *
64 * <p>This will be invoked only once for a single {@link Call}. Retries of different routes
65 * or redirects will be handled within the boundaries of a single callStart and {@link
66 * #callEnd}/{@link #callFailed} pair.
67 */
68 public void callStart(Call call) {
69 }
70
71 /**
72 * Invoked just prior to a DNS lookup. See {@link Dns#lookup(String)}.
73 *
74 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
75 * to the {@link Call#request()} is a redirect to a different host.
76 *
77 * <p>If the {@link Call} is able to reuse an existing pooled connection, this method will not be
78 * invoked. See {@link ConnectionPool}.
79 */
80 public void dnsStart(Call call, String domainName) {
81 }
82
83 /**
84 * Invoked immediately after a DNS lookup.
85 *
86 * <p>This method is invoked after {@link #dnsStart}.
87 */
88 public void dnsEnd(Call call, String domainName, List<InetAddress> inetAddressList) {
89 }
90
91 /**
92 * Invoked just prior to initiating a socket connection.
93 *
94 * <p>This method will be invoked if no existing connection in the {@link ConnectionPool} can be
95 * reused.
96 *
97 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
98 * to the {@link Call#request()} is a redirect to a different address, or a connection is retried.
99 */
100 public void connectStart(Call call, InetSocketAddress inetSocketAddress, Proxy proxy) {
101 }
102
103 /**
104 * Invoked just prior to initiating a TLS connection.
105 *
106 * <p>This method is invoked if the following conditions are met:
107 * <ul>
108 * <li>The {@link Call#request()} requires TLS.</li>
109 * <li>No existing connection from the {@link ConnectionPool} can be reused.</li>
110 * </ul>
111 *
112 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
113 * to the {@link Call#request()} is a redirect to a different address, or a connection is retried.
114 */
115 public void secureConnectStart(Call call) {
116 }
117
118 /**
119 * Invoked immediately after a TLS connection was attempted.
120 *
121 * <p>This method is invoked after {@link #secureConnectStart}.
122 */
123 public void secureConnectEnd(Call call, @Nullable Handshake handshake) {
124 }
125
126 /**
127 * Invoked immediately after a socket connection was attempted.
128 *
129 * <p>If the {@code call} uses HTTPS, this will be invoked after
130 * {@link #secureConnectEnd(Call, Handshake)}, otherwise it will invoked after
131 * {@link #connectStart(Call, InetSocketAddress, Proxy)}.
132 */
133 public void connectEnd(Call call, InetSocketAddress inetSocketAddress, Proxy proxy,
134 @Nullable Protocol protocol) {
135 }
136
137 /**
138 * Invoked when a connection attempt fails. This failure is not terminal if further routes are
139 * available and failure recovery is enabled.
140 *
141 * <p>If the {@code call} uses HTTPS, this will be invoked after {@link #secureConnectEnd(Call,
142 * Handshake)}, otherwise it will invoked after {@link #connectStart(Call, InetSocketAddress,
143 * Proxy)}.
144 */
145 public void connectFailed(Call call, InetSocketAddress inetSocketAddress, Proxy proxy,
146 @Nullable Protocol protocol, IOException ioe) {
147 }
148
149 /**
150 * Invoked after a connection has been acquired for the {@code call}.
151 *
152 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
153 * to the {@link Call#request()} is a redirect to a different address.
154 */
155 public void connectionAcquired(Call call, Connection connection) {
156 }
157
158 /**
159 * Invoked after a connection has been released for the {@code call}.
160 *
161 * <p>This method is always invoked after {@link #connectionAcquired(Call, Connection)}.
162 *
163 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
164 * to the {@link Call#request()} is a redirect to a different address.
165 */
166 public void connectionReleased(Call call, Connection connection) {
167 }
168
169 /**
170 * Invoked just prior to sending request headers.
171 *
172 * <p>The connection is implicit, and will generally relate to the last
173 * {@link #connectionAcquired(Call, Connection)} event.
174 *
175 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
176 * to the {@link Call#request()} is a redirect to a different address.
177 */
178 public void requestHeadersStart(Call call) {
179 }
180
181 /**
182 * Invoked immediately after sending request headers.
183 *
184 * <p>This method is always invoked after {@link #requestHeadersStart(Call)}.
185 *
186 * @param request the request sent over the network. It is an error to access the body of this
187 * request.
188 */
189 public void requestHeadersEnd(Call call, Request request) {
190 }
191
192 /**
193 * Invoked just prior to sending a request body. Will only be invoked for request allowing and
194 * having a request body to send.
195 *
196 * <p>The connection is implicit, and will generally relate to the last
197 * {@link #connectionAcquired(Call, Connection)} event.
198 *
199 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
200 * to the {@link Call#request()} is a redirect to a different address.
201 */
202 public void requestBodyStart(Call call) {
203 }
204
205 /**
206 * Invoked immediately after sending a request body.
207 *
208 * <p>This method is always invoked after {@link #requestBodyStart(Call)}.
209 */
210 public void requestBodyEnd(Call call, long byteCount) {
211 }
212
213 /**
214 * Invoked when a request fails to be written.
215 *
216 * <p>This method is invoked after {@link #requestHeadersStart} or {@link #requestBodyStart}. Note
217 * that request failures do not necessarily fail the entire call.
218 */
219 public void requestFailed(Call call, IOException ioe) {
220 }
221
222 /**
223 * Invoked just prior to receiving response headers.
224 *
225 * <p>The connection is implicit, and will generally relate to the last
226 * {@link #connectionAcquired(Call, Connection)} event.
227 *
228 * <p>This can be invoked more than 1 time for a single {@link Call}. For example, if the response
229 * to the {@link Call#request()} is a redirect to a different address.
230 */
231 public void responseHeadersStart(Call call) {
232 }
233
234 /**
235 * Invoked immediately after receiving response headers.
236 *
237 * <p>This method is always invoked after {@link #responseHeadersStart}.
238 *
239 * @param response the response received over the network. It is an error to access the body of
240 * this response.
241 */
242 public void responseHeadersEnd(Call call, Response response) {
243 }
244
245 /**
246 * Invoked just prior to receiving the response body.
247 *
248 * <p>The connection is implicit, and will generally relate to the last
249 * {@link #connectionAcquired(Call, Connection)} event.
250 *
251 * <p>This will usually be invoked only 1 time for a single {@link Call},
252 * exceptions are a limited set of cases including failure recovery.
253 */
254 public void responseBodyStart(Call call) {
255 }
256
257 /**
258 * Invoked immediately after receiving a response body and completing reading it.
259 *
260 * <p>Will only be invoked for requests having a response body e.g. won't be invoked for a
261 * websocket upgrade.
262 *
263 * <p>This method is always invoked after {@link #requestBodyStart(Call)}.
264 */
265 public void responseBodyEnd(Call call, long byteCount) {
266 }
267
268 /**
269 * Invoked when a response fails to be read.
270 *
271 * <p>This method is invoked after {@link #responseHeadersStart} or {@link #responseBodyStart}.
272 * Note that response failures do not necessarily fail the entire call.
273 */
274 public void responseFailed(Call call, IOException ioe) {
275 }
276
277 /**
278 * Invoked immediately after a call has completely ended. This includes delayed consumption
279 * of response body by the caller.
280 *
281 * <p>This method is always invoked after {@link #callStart(Call)}.
282 */
283 public void callEnd(Call call) {
284 }
285
286 /**
287 * Invoked when a call fails permanently.
288 *
289 * <p>This method is always invoked after {@link #callStart(Call)}.
290 */
291 public void callFailed(Call call, IOException ioe) {
292 }
293
294 public interface Factory {
295 /**
296 * Creates an instance of the {@link EventListener} for a particular {@link Call}. The returned
297 * {@link EventListener} instance will be used during the lifecycle of the {@code call}.
298 *
299 * <p>This method is invoked after the {@code call} is created. See
300 * {@link OkHttpClient#newCall(Request)}.
301 *
302 * <p><strong>It is an error for implementations to issue any mutating operations on the
303 * {@code call} instance from this method.</strong>
304 */
305 EventListener create(Call call);
306 }
307 }
308