All Downloads are FREE. Search and download functionalities are using the official Maven repository.

main.okhttp3.EventListener.kt Maven / Gradle / Ivy

There is a newer version: 5.0.0-alpha.14
Show newest version
/*
 * Copyright (C) 2017 Square, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package okhttp3

import java.io.IOException
import java.net.InetAddress
import java.net.InetSocketAddress
import java.net.Proxy

/**
 * Listener for metrics events. Extend this class to monitor the quantity, size, and duration of
 * your application's HTTP calls.
 *
 * All start/connect/acquire events will eventually receive a matching end/release event, either
 * successful (non-null parameters), or failed (non-null throwable). The first common parameters of
 * each event pair are used to link the event in case of concurrent or repeated events e.g.
 * `dnsStart(call, domainName)` → `dnsEnd(call, domainName, inetAddressList)`.
 *
 * Events are typically nested with this structure:
 *
 *  * call ([callStart], [callEnd], [callFailed])
 *    * proxy selection ([proxySelectStart], [proxySelectEnd])
 *    * dns ([dnsStart], [dnsEnd])
 *    * connect ([connectStart], [connectEnd], [connectFailed])
 *      * secure connect ([secureConnectStart], [secureConnectEnd])
 *    * connection held ([connectionAcquired], [connectionReleased])
 *      * request ([requestFailed])
 *        * headers ([requestHeadersStart], [requestHeadersEnd])
 *        * body ([requestBodyStart], [requestBodyEnd])
 *      * response ([responseFailed])
 *        * headers ([responseHeadersStart], [responseHeadersEnd])
 *        * body ([responseBodyStart], [responseBodyEnd])
 *
 * This nesting is typical but not strict. For example, when calls use "Expect: continue" the
 * request body start and end events occur within the response header events. Similarly,
 * [duplex calls][RequestBody.isDuplex] interleave the request and response bodies.
 *
 * Since connections may be reused, the proxy selection, DNS, and connect events may not be present
 * for a call. In future releases of OkHttp these events may also occur concurrently to permit
 * multiple routes to be attempted simultaneously.
 *
 * Events and sequences of events may be repeated for retries and follow-ups.
 *
 * All event methods must execute fast, without external locking, cannot throw exceptions, attempt
 * to mutate the event parameters, or be re-entrant back into the client. Any IO - writing to files
 * or network should be done asynchronously.
 */
abstract class EventListener {
  /**
   * Invoked as soon as a call is enqueued or executed by a client. In case of thread or stream
   * limits, this call may be executed well before processing the request is able to begin.
   *
   * This will be invoked only once for a single [Call]. Retries of different routes or redirects
   * will be handled within the boundaries of a single [callStart] and [callEnd]/[callFailed] pair.
   */
  open fun callStart(call: Call) {
  }

  /**
   * Invoked prior to a proxy selection.
   *
   * This will be invoked for route selection regardless of whether the client
   * is configured with a single proxy, a proxy selector, or neither.
   *
   * @param url a URL with only the scheme, hostname, and port specified.
   */
  open fun proxySelectStart(
    call: Call,
    url: HttpUrl,
  ) {
  }

  /**
   * Invoked after proxy selection.
   *
   * Note that the list of proxies is never null, but it may be a list containing
   * only [Proxy.NO_PROXY]. This comes up in several situations:
   *
   * * If neither a proxy nor proxy selector is configured.
   * * If the proxy is configured explicitly as [Proxy.NO_PROXY].
   * * If the proxy selector returns only [Proxy.NO_PROXY].
   * * If the proxy selector returns an empty list or null.
   *
   * Otherwise it lists the proxies in the order they will be attempted.
   *
   * @param url a URL with only the scheme, hostname, and port specified.
   */
  open fun proxySelectEnd(
    call: Call,
    url: HttpUrl,
    proxies: List<@JvmSuppressWildcards Proxy>,
  ) {
  }

  /**
   * Invoked just prior to a DNS lookup. See [Dns.lookup].
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different host.
   *
   * If the [Call] is able to reuse an existing pooled connection, this method will not be invoked.
   * See [ConnectionPool].
   */
  open fun dnsStart(
    call: Call,
    domainName: String,
  ) {
  }

  /**
   * Invoked immediately after a DNS lookup.
   *
   * This method is invoked after [dnsStart].
   */
  open fun dnsEnd(
    call: Call,
    domainName: String,
    inetAddressList: List<@JvmSuppressWildcards InetAddress>,
  ) {
  }

  /**
   * Invoked just prior to initiating a socket connection.
   *
   * This method will be invoked if no existing connection in the [ConnectionPool] can be reused.
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different address, or a connection is retried.
   */
  open fun connectStart(
    call: Call,
    inetSocketAddress: InetSocketAddress,
    proxy: Proxy,
  ) {
  }

  /**
   * Invoked just prior to initiating a TLS connection.
   *
   * This method is invoked if the following conditions are met:
   *
   *  * The [Call.request] requires TLS.
   *
   *  * No existing connection from the [ConnectionPool] can be reused.
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different address, or a connection is retried.
   */
  open fun secureConnectStart(call: Call) {
  }

  /**
   * Invoked immediately after a TLS connection was attempted.
   *
   * This method is invoked after [secureConnectStart].
   */
  open fun secureConnectEnd(
    call: Call,
    handshake: Handshake?,
  ) {
  }

  /**
   * Invoked immediately after a socket connection was attempted.
   *
   * If the `call` uses HTTPS, this will be invoked after [secureConnectEnd], otherwise it will
   * invoked after [connectStart].
   */
  open fun connectEnd(
    call: Call,
    inetSocketAddress: InetSocketAddress,
    proxy: Proxy,
    protocol: Protocol?,
  ) {
  }

  /**
   * Invoked when a connection attempt fails. This failure is not terminal if further routes are
   * available and failure recovery is enabled.
   *
   * If the `call` uses HTTPS, this will be invoked after [secureConnectStart], otherwise it will
   * invoked after [connectStart].
   */
  open fun connectFailed(
    call: Call,
    inetSocketAddress: InetSocketAddress,
    proxy: Proxy,
    protocol: Protocol?,
    ioe: IOException,
  ) {
  }

  /**
   * Invoked after a connection has been acquired for the `call`.
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response
   * to the [Call.request] is a redirect to a different address.
   */
  open fun connectionAcquired(
    call: Call,
    connection: Connection,
  ) {
  }

  /**
   * Invoked after a connection has been released for the `call`.
   *
   * This method is always invoked after [connectionAcquired].
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different address.
   */
  open fun connectionReleased(
    call: Call,
    connection: Connection,
  ) {
  }

  /**
   * Invoked just prior to sending request headers.
   *
   * The connection is implicit, and will generally relate to the last [connectionAcquired] event.
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different address.
   */
  open fun requestHeadersStart(call: Call) {
  }

  /**
   * Invoked immediately after sending request headers.
   *
   * This method is always invoked after [requestHeadersStart].
   *
   * @param request the request sent over the network. It is an error to access the body of this
   *     request.
   */
  open fun requestHeadersEnd(
    call: Call,
    request: Request,
  ) {
  }

  /**
   * Invoked just prior to sending a request body.  Will only be invoked for request allowing and
   * having a request body to send.
   *
   * The connection is implicit, and will generally relate to the last [connectionAcquired] event.
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different address.
   */
  open fun requestBodyStart(call: Call) {
  }

  /**
   * Invoked immediately after sending a request body.
   *
   * This method is always invoked after [requestBodyStart].
   */
  open fun requestBodyEnd(
    call: Call,
    byteCount: Long,
  ) {
  }

  /**
   * Invoked when a request fails to be written.
   *
   * This method is invoked after [requestHeadersStart] or [requestBodyStart]. Note that request
   * failures do not necessarily fail the entire call.
   */
  open fun requestFailed(
    call: Call,
    ioe: IOException,
  ) {
  }

  /**
   * Invoked when response headers are first returned from the server.
   *
   * The connection is implicit, and will generally relate to the last [connectionAcquired] event.
   *
   * This can be invoked more than 1 time for a single [Call]. For example, if the response to the
   * [Call.request] is a redirect to a different address.
   *
   * Prior to OkHttp 4.3 this was incorrectly invoked when the client was ready to read headers.
   * This was misleading for tracing because it was too early.
   */
  open fun responseHeadersStart(call: Call) {
  }

  /**
   * Invoked immediately after receiving response headers.
   *
   * This method is always invoked after [responseHeadersStart].
   *
   * @param response the response received over the network. It is an error to access the body of
   *     this response.
   */
  open fun responseHeadersEnd(
    call: Call,
    response: Response,
  ) {
  }

  /**
   * Invoked when data from the response body is first available to the application.
   *
   * This is typically invoked immediately before bytes are returned to the application. If the
   * response body is empty this is invoked immediately before returning that to the application.
   *
   * If the application closes the response body before attempting a read, this is invoked at the
   * time it is closed.
   *
   * The connection is implicit, and will generally relate to the last [connectionAcquired] event.
   *
   * This will usually be invoked only 1 time for a single [Call], exceptions are a limited set of
   * cases including failure recovery.
   *
   * Prior to OkHttp 4.3 this was incorrectly invoked when the client was ready to read the response
   * body. This was misleading for tracing because it was too early.
   */
  open fun responseBodyStart(call: Call) {
  }

  /**
   * Invoked immediately after receiving a response body and completing reading it.
   *
   * Will only be invoked for requests having a response body e.g. won't be invoked for a web socket
   * upgrade.
   *
   * If the response body is closed before the response body is exhausted, this is invoked at the
   * time it is closed. In such calls [byteCount] is the number of bytes returned to the
   * application. This may be smaller than the resource's byte count if were read to completion.
   *
   * This method is always invoked after [responseBodyStart].
   */
  open fun responseBodyEnd(
    call: Call,
    byteCount: Long,
  ) {
  }

  /**
   * Invoked when a response fails to be read.
   *
   * Note that response failures do not necessarily fail the entire call.
   *
   * Starting with OkHttp 4.3 this may be invoked without a prior call to [responseHeadersStart]
   * or [responseBodyStart]. In earlier releases this method was documented to only be invoked after
   * one of those methods.
   */
  open fun responseFailed(
    call: Call,
    ioe: IOException,
  ) {
  }

  /**
   * Invoked immediately after a call has completely ended.  This includes delayed consumption
   * of response body by the caller.
   *
   * This method is always invoked after [callStart].
   */
  open fun callEnd(call: Call) {
  }

  /**
   * Invoked when a call fails permanently.
   *
   * This method is always invoked after [callStart].
   */
  open fun callFailed(
    call: Call,
    ioe: IOException,
  ) {
  }

  /**
   * Invoked when a call is canceled.
   *
   * Like all methods in this interface, this is invoked on the thread that triggered the event. But
   * while other events occur sequentially; cancels may occur concurrently with other events. For
   * example, thread A may be executing [responseBodyStart] while thread B executes [canceled].
   * Implementations must support such concurrent calls.
   *
   * Note that cancellation is best-effort and that a call may proceed normally after it has been
   * canceled. For example, happy-path events like [requestHeadersStart] and [requestHeadersEnd] may
   * occur after a call is canceled. Typically cancellation takes effect when an expensive I/O
   * operation is required.
   *
   * This is invoked at most once, even if [Call.cancel] is invoked multiple times. It may be
   * invoked at any point in a call's life, including before [callStart] and after [callEnd].
   */
  open fun canceled(call: Call) {
  }

  /**
   * Invoked when a call fails due to cache rules.
   * For example, we're forbidden from using the network and the cache is insufficient
   */
  open fun satisfactionFailure(
    call: Call,
    response: Response,
  ) {
  }

  /**
   * Invoked when a result is served from the cache. The Response provided is the top level
   * Response and normal event sequences will not be received.
   *
   * This event will only be received when a Cache is configured for the client.
   */
  open fun cacheHit(
    call: Call,
    response: Response,
  ) {
  }

  /**
   * Invoked when a response will be served from the network. The Response will be
   * available from normal event sequences.
   *
   * This event will only be received when a Cache is configured for the client.
   */
  open fun cacheMiss(call: Call) {
  }

  /**
   * Invoked when a response will be served from the cache or network based on validating the
   * cached Response freshness. Will be followed by cacheHit or cacheMiss after the network
   * Response is available.
   *
   * This event will only be received when a Cache is configured for the client.
   */
  open fun cacheConditionalHit(
    call: Call,
    cachedResponse: Response,
  ) {
  }

  fun interface Factory {
    /**
     * Creates an instance of the [EventListener] for a particular [Call]. The returned
     * [EventListener] instance will be used during the lifecycle of [call].
     *
     * This method is invoked after [call] is created. See [OkHttpClient.newCall].
     *
     * **It is an error for implementations to issue any mutating operations on the [call] instance
     * from this method.**
     */
    fun create(call: Call): EventListener
  }

  companion object {
    @JvmField
    val NONE: EventListener =
      object : EventListener() {
      }
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy