Skip to content
Codeskop

Network capture with OkHttp

See failing requests, status codes and latency from real devices. Add one line to your OkHttp client; no per-endpoint setup.

Available on Starter and above

Network monitoring is included from the Starter plan. On Free, the SDK doesn't capture network calls, even with the interceptor installed; upgrading turns it on without a new release. See Plans & features.

Add the adapter

Add the OkHttp artifact next to the core SDK:

app/build.gradle.kts
implementation("com.codeskop.sdk:tracker-okhttp:0.3.0")

Then turn it on for the OkHttp client your app uses:

NetworkModule.kt
import com.codeskop.sdk.okhttp.codeskopimport okhttp3.OkHttpClient val client = OkHttpClient.Builder()    .codeskop()   // failed requests + timing for every request    .build()

The dependency alone captures nothing

OkHttp has no global hook, so adding tracker-okhttp to Gradle doesn't record anything by itself. If you see crashes on your dashboard but no network issues, check that the client your app actually uses was built with .codeskop().

.codeskop() (added in 0.2.0) registers two pieces. You can also add them yourself:

NetworkModule.kt
import com.codeskop.sdk.okhttp.CodeskopEventListenerimport com.codeskop.sdk.okhttp.CodeskopOkHttpInterceptor val client = OkHttpClient.Builder()    .addInterceptor(CodeskopOkHttpInterceptor())               // failed requests    .eventListenerFactory(CodeskopEventListener.factory())    // timing for every request    .build()
  • CodeskopOkHttpInterceptor records a failure whenever a request gets a 4xx or 5xx response, times out, or fails to connect. Your exception is still thrown to your code unchanged. The adapter only watches.
  • CodeskopEventListener.factory() records how long each completed request took, broken down into DNS, connect, TLS, time to first byte and total.

You can use either one alone, but both together give the full picture. OkHttp allows only one event listener factory. If your app already sets its own, keep it and add just the interceptor, so you still get every failed request:

Kotlin
val client = OkHttpClient.Builder()    .addInterceptor(CodeskopOkHttpInterceptor())   // keep your own eventListenerFactory    .eventListenerFactory(myListenerFactory)    .build()

Retrofit

Retrofit uses whatever OkHttp client you give it, so nothing else is needed:

Kotlin
val retrofit = Retrofit.Builder()    .baseUrl("https://api.example.com/")    .client(client)   // the OkHttpClient from above    .addConverterFactory(MoshiConverterFactory.create())    .build()

Ktor with the OkHttp engine

Register the same two pieces on the engine:

Kotlin
val http = HttpClient(OkHttp) {    engine {        addInterceptor(CodeskopOkHttpInterceptor())        config { eventListenerFactory(CodeskopEventListener.factory()) }    }}

Use one shared client

Register the adapter on the client instance your app actually uses for requests. If your app builds several clients, add it to each, or derive them from one base client with newBuilder().

What's captured

  • HTTP method, host and path
  • Status code, or an error kind: http_4xx, http_5xx, timeout or network_error
  • Request and response sizes in bytes
  • Timing: DNS, connect, TLS, time to first byte, total (from the event listener)
  • A small set of harmless headers: Content-Type, Content-Length, Content-Encoding, Accept and Cache-Control
  • The device, app version and user the request came from

Where network data shows up

  • Failed requests become issues. On the dashboard, open Issues and set Type to Network. Failures are grouped by method, path and status, with IDs in the path collapsed, so /orders/42 and /orders/43 are one issue: POST /orders/{id} → 500. Each issue shows the host, status or error kind, request and response sizes, and the devices, OS versions and app versions it happens on.
  • Timings are recorded for every completed request (DNS, connect, TLS, time to first byte, total) and stored with your project. Latency charts built from them are coming to the dashboard. Failed requests are already there.
  • Apps using a test key (cs_test_pk_…) report to the Test environment. Switch the Environment filter on the Issues page to see them.

What's never captured

  • Request and response bodies.
  • Query strings. They're removed from every URL, so tokens in a query string never leave the device.
  • Credentials. Authorization, Cookie and Set-Cookie are never collected. Any header in redactHeaders is masked as a second safeguard.

More in Privacy & security.

Controlling volume

The event listener records every completed request. Codeskop keeps a share of timings by default through remote config, and every failure is always kept. To sample timings further yourself:

Kotlin
CodeskopConfig(apiKey = BuildConfig.CODESKOP_KEY, sampleRates = mapOf("api_timing" to 0.1))

You can also lower the timing sample rate, or switch network capture off, for the whole project in the dashboard under Settings → SDK settings, no new release needed. See Remote config.

Other HTTP clients

If your app doesn't use OkHttp, you can report a failed call yourself with Codeskop.captureApiError. The same redaction rules apply:

Kotlin
import com.codeskop.sdk.core.ApiCallimport com.codeskop.sdk.core.Codeskop Codeskop.captureApiError(    ApiCall(        method = "POST",        url = "https://api.example.com/v1/orders",        status = 503,        errorKind = "http_5xx",    ),)

Next steps