Skip to content

Commit aae4ec2

Browse files
authored
Merge pull request #2333 from bugsnag/PLAT-15130/okhttp-interceptor
Deprecate BugsnagOkHttpPlugin in favour of BugsnagOkHttp
2 parents 849caa3 + 57279d8 commit aae4ec2

22 files changed

Lines changed: 1673 additions & 2 deletions

bugsnag-android-core/detekt-baseline.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,6 @@
6464
<ID>MagicNumber:JsonHelper.kt$JsonHelper$8</ID>
6565
<ID>MagicNumber:JsonStream.kt$JsonStream$128</ID>
6666
<ID>MagicNumber:JsonStream.kt$JsonStream$32</ID>
67-
<ID>MagicNumber:JsonStream.kt$JsonStream.Companion$128</ID>
6867
<ID>MagicNumber:LastRunInfoStore.kt$LastRunInfoStore$3</ID>
6968
<ID>MagicNumber:SessionStore.kt$SessionStore$60</ID>
7069
<ID>MaxLineLength:LastRunInfo.kt$LastRunInfo$return "LastRunInfo(consecutiveLaunchCrashes=$consecutiveLaunchCrashes, crashed=$crashed, crashedDuringLaunch=$crashedDuringLaunch)"</ID>

bugsnag-plugin-android-okhttp/api/bugsnag-plugin-android-okhttp.api

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,29 @@
1+
public final class com/bugsnag/android/okhttp/BugsnagOkHttp : com/bugsnag/android/http/HttpInstrumentationBuilder {
2+
public fun <init> ()V
3+
public synthetic fun addHttpErrorCode (I)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
4+
public fun addHttpErrorCode (I)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
5+
public synthetic fun addHttpErrorCodes (II)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
6+
public fun addHttpErrorCodes (II)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
7+
public synthetic fun addRequestCallback (Lcom/bugsnag/android/http/HttpRequestCallback;)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
8+
public fun addRequestCallback (Lcom/bugsnag/android/http/HttpRequestCallback;)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
9+
public synthetic fun addResponseCallback (Lcom/bugsnag/android/http/HttpResponseCallback;)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
10+
public fun addResponseCallback (Lcom/bugsnag/android/http/HttpResponseCallback;)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
11+
public final fun createInterceptor ()Lokhttp3/Interceptor;
12+
public final fun createInterceptor (Lcom/bugsnag/android/Client;)Lokhttp3/Interceptor;
13+
public synthetic fun logBreadcrumbs ()Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
14+
public fun logBreadcrumbs ()Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
15+
public synthetic fun logBreadcrumbs (Z)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
16+
public fun logBreadcrumbs (Z)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
17+
public synthetic fun maxRequestBodyCapture (J)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
18+
public fun maxRequestBodyCapture (J)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
19+
public synthetic fun maxResponseBodyCapture (J)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
20+
public fun maxResponseBodyCapture (J)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
21+
public synthetic fun removeHttpErrorCode (I)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
22+
public fun removeHttpErrorCode (I)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
23+
public synthetic fun removeHttpErrorCodes (II)Lcom/bugsnag/android/http/HttpInstrumentationBuilder;
24+
public fun removeHttpErrorCodes (II)Lcom/bugsnag/android/okhttp/BugsnagOkHttp;
25+
}
26+
127
public final class com/bugsnag/android/okhttp/BugsnagOkHttpPlugin : com/bugsnag/android/okhttp/util/DelegateEventListener, com/bugsnag/android/Plugin {
228
public fun <init> ()V
329
public fun <init> (Lokhttp3/EventListener;)V

bugsnag-plugin-android-okhttp/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ android {
6464
dependencies {
6565
api(libs.bundles.common.api)
6666
add("api", project(":bugsnag-android-core"))
67+
add("api", project(":bugsnag-android-http-api"))
6768

6869
add("compileOnly", "com.squareup.okhttp3:okhttp:4.9.1") {
6970
exclude(group = "org.jetbrains.kotlin")

bugsnag-plugin-android-okhttp/detekt-baseline.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@
22
<SmellBaseline>
33
<ManuallySuppressedIssues/>
44
<CurrentIssues>
5+
<ID>LongParameterList:BugsnagOkHttpInterceptor.kt$BugsnagOkHttpInterceptor$( private val errorCodes: BitSet, private var maxRequestBodyCapture: Long, private var maxResponseBodyCapture: Long, private var logRequestBreadcrumbs: Boolean, private val requestCallbacks: List&lt;HttpRequestCallback&lt;Request>>, private val responseCallbacks: List&lt;HttpResponseCallback&lt;Request, Response>>, private val clientSource: () -> Client?, private val timeProvider: () -> Long = { SystemClock.elapsedRealtime() } )</ID>
6+
<ID>LongParameterList:BugsnagOkHttpInterceptorBreadcrumbsTest.kt$BugsnagOkHttpInterceptorBreadcrumbsTest$( client: Client, request: Request.Builder, response: MockResponse? = null, path: String = "/test", breadcrumbsEnabled: Boolean = true, configureErrorCodes: ((BugsnagOkHttp) -> BugsnagOkHttp)? = null )</ID>
7+
<ID>MagicNumber:BugsnagOkHttpInterceptor.kt$BugsnagOkHttpInterceptor$100</ID>
8+
<ID>MagicNumber:BugsnagOkHttpInterceptor.kt$BugsnagOkHttpInterceptor$399</ID>
9+
<ID>MagicNumber:BugsnagOkHttpInterceptor.kt$BugsnagOkHttpInterceptor$400</ID>
10+
<ID>MagicNumber:BugsnagOkHttpInterceptor.kt$BugsnagOkHttpInterceptor$499</ID>
511
<ID>MagicNumber:BugsnagOkHttpPlugin.kt$100</ID>
612
<ID>MagicNumber:BugsnagOkHttpPlugin.kt$399</ID>
713
<ID>MagicNumber:BugsnagOkHttpPlugin.kt$400</ID>
Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
11
package com.bugsnag.android
22

3-
internal fun Client.shouldDiscardNetworkBreadcrumb() = config.shouldDiscardBreadcrumb(BreadcrumbType.REQUEST)
3+
internal fun Client.shouldDiscardNetworkBreadcrumb() =
4+
config.shouldDiscardBreadcrumb(BreadcrumbType.REQUEST)
5+
6+
internal val Client.log
7+
get() = this.logger
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
package com.bugsnag.android.okhttp
2+
3+
import com.bugsnag.android.Bugsnag
4+
import com.bugsnag.android.Client
5+
import com.bugsnag.android.http.HttpInstrumentationBuilder
6+
import com.bugsnag.android.http.HttpRequestCallback
7+
import com.bugsnag.android.http.HttpResponseCallback
8+
import okhttp3.Interceptor
9+
import okhttp3.Request
10+
import okhttp3.Response
11+
import java.util.BitSet
12+
import kotlin.math.max
13+
14+
/**
15+
* This class builds [Interceptor] integrations for OkHttp that can be configured to capture requests
16+
* as breadcrumbs and/or errors.
17+
*
18+
* To enable this functionality use [createInterceptor] to create an interceptor and use
19+
* [addInterceptor](okhttp3.OkHttpClient.Builder.addInterceptor) to configure it with your
20+
* `OkHttpClient`.
21+
*/
22+
class BugsnagOkHttp : HttpInstrumentationBuilder<Request, Response> {
23+
private val errorCodes = BitSet()
24+
private var maxRequestBodyCapture = DEFAULT_BODY_CAPTURE_SIZE
25+
private var maxResponseBodyCapture = DEFAULT_BODY_CAPTURE_SIZE
26+
private var logRequestBreadcrumbs = false
27+
private val requestCallbacks = ArrayList<HttpRequestCallback<Request>>()
28+
private val responseCallbacks = ArrayList<HttpResponseCallback<Request, Response>>()
29+
30+
override fun addHttpErrorCode(statusCode: Int): BugsnagOkHttp {
31+
errorCodes.set(statusCode)
32+
return this
33+
}
34+
35+
override fun addHttpErrorCodes(
36+
minStatusCode: Int,
37+
maxStatusCode: Int
38+
): BugsnagOkHttp {
39+
val start = max(0, minStatusCode)
40+
val end = max(start, maxStatusCode + 1)
41+
42+
if (start < end) {
43+
errorCodes.set(start, end)
44+
}
45+
46+
return this
47+
}
48+
49+
override fun removeHttpErrorCode(statusCode: Int): BugsnagOkHttp {
50+
errorCodes.clear(statusCode)
51+
return this
52+
}
53+
54+
override fun removeHttpErrorCodes(
55+
minStatusCode: Int,
56+
maxStatusCode: Int
57+
): BugsnagOkHttp {
58+
val start = max(0, minStatusCode)
59+
val end = max(start, maxStatusCode + 1)
60+
61+
if (start < end) {
62+
errorCodes.clear(start, end)
63+
}
64+
65+
return this
66+
}
67+
68+
override fun maxRequestBodyCapture(maxBytes: Long): BugsnagOkHttp {
69+
maxRequestBodyCapture = max(maxBytes, 0L)
70+
return this
71+
}
72+
73+
override fun maxResponseBodyCapture(maxBytes: Long): BugsnagOkHttp {
74+
maxResponseBodyCapture = max(maxBytes, 0L)
75+
return this
76+
}
77+
78+
override fun logBreadcrumbs(): BugsnagOkHttp {
79+
return logBreadcrumbs(true)
80+
}
81+
82+
override fun logBreadcrumbs(logBreadcrumbs: Boolean): BugsnagOkHttp {
83+
logRequestBreadcrumbs = logBreadcrumbs
84+
return this
85+
}
86+
87+
override fun addRequestCallback(callback: HttpRequestCallback<Request>): BugsnagOkHttp {
88+
@Suppress("SENSELESS_COMPARISON")
89+
if (callback != null) {
90+
requestCallbacks.add(callback)
91+
}
92+
93+
return this
94+
}
95+
96+
override fun addResponseCallback(callback: HttpResponseCallback<Request, Response>): BugsnagOkHttp {
97+
@Suppress("SENSELESS_COMPARISON")
98+
if (callback != null) {
99+
responseCallbacks.add(callback)
100+
}
101+
102+
return this
103+
}
104+
105+
/**
106+
* Create an OkHttp `Interceptor` based on the current config of this `BugsnagOkHttp` instance.
107+
* The new `Interceptor` should be added using [okhttp3.OkHttpClient.Builder.addInterceptor]
108+
* to instrument the configured requests.
109+
*
110+
* The `Interceptor` returned here will sent all breadcrumbs and errors to the global
111+
* [Bugsnag.getClient].
112+
*/
113+
fun createInterceptor(): Interceptor {
114+
// shortcut if Bugsnag is already started, we can skip the check on every call
115+
if (Bugsnag.isStarted()) {
116+
return createInterceptor(Bugsnag.getClient())
117+
}
118+
119+
return createInterceptor {
120+
if (Bugsnag.isStarted()) {
121+
Bugsnag.getClient()
122+
} else {
123+
null
124+
}
125+
}
126+
}
127+
128+
/**
129+
* Create an OkHttp `Interceptor` based on the current config of this `BugsnagOkHttp` instance,
130+
* and send all its breadcrumbs and errors to the given [client]. The new `Interceptor` should
131+
* be added using [okhttp3.OkHttpClient.Builder.addInterceptor] to instrument the configured
132+
* requests.
133+
*/
134+
fun createInterceptor(client: Client): Interceptor {
135+
return createInterceptor { client }
136+
}
137+
138+
private fun createInterceptor(clientSupplier: () -> Client?): Interceptor {
139+
return BugsnagOkHttpInterceptor(
140+
errorCodes,
141+
maxRequestBodyCapture,
142+
maxResponseBodyCapture,
143+
logRequestBreadcrumbs,
144+
requestCallbacks.toList(),
145+
responseCallbacks.toList(),
146+
clientSupplier
147+
)
148+
}
149+
150+
internal companion object {
151+
private const val DEFAULT_BODY_CAPTURE_SIZE = 4096L
152+
}
153+
}

0 commit comments

Comments
 (0)