OkHttp Integration

Learn how to capture the performance of OkHttp client.

To be able to capture transactions, you'll need to first set up performance monitoring.

The sentry-okhttp library provides OkHttp support for Sentry via the SentryOkHttpInterceptor and the SentryOkHttpEventListener, which create a span for each outgoing HTTP request executed with an OkHttp client. The source can be found on GitHub.

To install the integration:

Copied
<dependency>
    <groupId>io.sentry</groupId>
    <artifactId>sentry-okhttp</artifactId>
    <version
  >7.9.0</version>
</dependency>

For other dependency managers, see the central Maven repository.

Configuration should happen once you create your OkHttpClient instance.

Copied
import okhttp3.OkHttpClient
import io.sentry.okhttp.SentryOkHttpEventListener
import io.sentry.okhttp.SentryOkHttpInterceptor

private val client = OkHttpClient.Builder()
  .addInterceptor(SentryOkHttpInterceptor())
  .eventListener(SentryOkHttpEventListener())
  .build()

The SDK uses the SentryOkHttpInterceptor to support Distributed Tracing and creates a span for any HTTP call. The SDK can give more in-depth information through the SentryOkHttpEventListener by creating a span for each operation reported by OkHttp, including DNS setup, proxy selection, HTTP connect, SSL setup, send request headers, send request body, receive response headers, and receive response body.

This snippet includes a HTTP Request and captures an intentional message, so you can test that everything is working as soon as you set it up:

Copied
import io.sentry.Sentry
import java.io.IOException
import okhttp3.OkHttpClient
import okhttp3.Request

@Throws(IOException::class)
fun run(url: String): String? {
  val request = Request.Builder()
    .url(url)
    .build()

  val bodyStr = client
    .newCall(request)
    .execute()
    .body?.toString()

  Sentry.captureMessage("The Message $bodyStr")

  return bodyStr
}

To view and resolve the recorded message, log into sentry.io and open your project. Clicking on the error's title will open a page where you can see detailed information and mark it as resolved.

The captured span can be customized or dropped with a BeforeSpanCallback:

Copied
import io.sentry.ISpan
import io.sentry.okhttp.SentryOkHttpInterceptor
import okhttp3.Request
import okhttp3.Response

class CustomBeforeSpanCallback : SentryOkHttpInterceptor.BeforeSpanCallback {
  override fun execute(span: ISpan, request: Request, response: Response?): ISpan? {
    return if (request.url.toUri().toString().contains("/admin")) {
      null
    } else {
      span
    }
  }
}

The callback instance must be set on the SentryOkHttpInterceptor once you create your OkHttpClient instance.

Copied
import okhttp3.OkHttpClient
import io.sentry.okhttp.SentryOkHttpEventListener
import io.sentry.okhttp.SentryOkHttpInterceptor

private val client = OkHttpClient.Builder()
  .eventListener(SentryOkHttpEventListener())
  .addInterceptor(SentryOkHttpInterceptor(CustomBeforeSpanCallback()))
  .build()

The integration's event listener can propagate calls to another EventListener or EventListener.Factory that's set on the SentryOkHttpEventListener once you create your OkHttpClient instance.

Copied
import okhttp3.OkHttpClient
import io.sentry.okhttp.SentryOkHttpEventListener
import io.sentry.okhttp.SentryOkHttpInterceptor

private val client = OkHttpClient.Builder()
  .eventListener(SentryOkHttpEventListener(MyEventListener()))
  .addInterceptor(SentryOkHttpInterceptor(CustomBeforeSpanCallback()))
  .build()

This feature automatically captures HTTP client errors (like bad response codes) as error events and reports them to Sentry. The error event will contain the request and response data, including the url, status_code, and so on.

This feature is enabled by default and can be disabled by setting the captureFailedRequests option to false:

Copied
import okhttp3.OkHttpClient
import io.sentry.okhttp.SentryOkHttpEventListener
import io.sentry.okhttp.SentryOkHttpInterceptor

private val client = OkHttpClient.Builder()
  .eventListener(SentryOkHttpEventListener())
  .addInterceptor(SentryOkHttpInterceptor(captureFailedRequests = false))
  .build()

By default, only HTTP client errors with a response code between 500 and 599 are captured as error events, but you can change this behavior by setting the failedRequestStatusCodes option:

Copied
import okhttp3.OkHttpClient
import io.sentry.okhttp.SentryOkHttpEventListener
import io.sentry.okhttp.SentryOkHttpInterceptor
import io.sentry.HttpStatusCodeRange

private val client = OkHttpClient.Builder()
  .eventListener(SentryOkHttpEventListener())
  .addInterceptor(SentryOkHttpInterceptor(
    captureFailedRequests = true,
    failedRequestStatusCodes = listOf(HttpStatusCodeRange(400, 599))))
  .build()

HTTP client errors from every target (.* regular expression) are automatically captured, but you can change this behavior by setting the failedRequestTargets option with either a regular expression or a plain String. A plain string must contain at least one of the items from the list. Plain strings don't have to be full matches, meaning the URL of a request is matched when it contains a string provided through the option.

Copied
import okhttp3.OkHttpClient
import io.sentry.okhttp.SentryOkHttpEventListener
import io.sentry.okhttp.SentryOkHttpInterceptor
import io.sentry.HttpStatusCodeRange

private val client = OkHttpClient.Builder()
  .eventListener(SentryOkHttpEventListener())
  .addInterceptor(SentryOkHttpInterceptor(
    captureFailedRequests = true,
    failedRequestTargets = listOf("myapi.com")))
  .build()

By default, error events won't contain any PII data, such as Headers and Cookies, but you can change this behavior by setting the sendDefaultPii option to true:

Copied
Sentry.init { options ->
  options.isSendDefaultPii = true
}

HTTP client errors sent to Sentry are searchable and you can set alerts on them if you use the http.url and http.status_code properties. Learn more in our full Searchable Properties documentation.

The captured error event can be customized or dropped with a BeforeSendCallback:

Copied
import io.sentry.Sentry
import io.sentry.SentryOptions.BeforeSendCallback
import okhttp3.Request
import okhttp3.Response
import io.sentry.TypeCheckHint.OKHTTP_REQUEST
import io.sentry.TypeCheckHint.OKHTTP_RESPONSE

Sentry.init { options ->
  // Add a callback that will be used before the event is sent to Sentry.
  // With this callback, you can modify the event or, when returning null, also discard the event.
  options.beforeSend = BeforeSendCallback { event, hint ->
    val request = hint.getAs(OKHTTP_REQUEST, Request::class.java)
    val response = hint.getAs(OKHTTP_RESPONSE, Response::class.java)

    // customize or drop the event
    event
  }
}
Help improve this content
Our documentation is open source and available on GitHub. Your contributions are welcome, whether fixing a typo (drat!) or suggesting an update ("yeah, this would be better").