Skip to content

Commit a8acf75

Browse files
authored
Provide custom OkHttpClient for MetricsReporter (#65)
* Provide custom OkHttpClient for MetricsReporter * Updated tests
1 parent 9ef063d commit a8acf75

File tree

7 files changed

+74
-16
lines changed

7 files changed

+74
-16
lines changed

src/main/kotlin/io/getunleash/UnleashClient.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ class UnleashClient(
4040
)
4141
).build(),
4242
val cache: ToggleCache = InMemoryToggleCache(),
43-
val metricsReporter: MetricsReporter = unleashConfig.reportMetrics?.let { HttpMetricsReporter(unleashConfig) } ?: NonReporter()
43+
val metricsReporter: MetricsReporter = unleashConfig.reportMetrics?.let { HttpMetricsReporter(unleashConfig, it.httpClient) } ?: NonReporter()
4444
) : UnleashClientSpec {
4545
private val fetcher: UnleashFetcher = UnleashFetcher(unleashConfig = unleashConfig, httpClient = httpClient)
4646
private val refreshPolicy: RefreshPolicy = when (unleashConfig.pollingMode) {

src/main/kotlin/io/getunleash/UnleashConfig.kt

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,18 @@ package io.getunleash
22

33
import io.getunleash.polling.AutoPollingMode
44
import io.getunleash.polling.PollingMode
5+
import okhttp3.OkHttpClient
56
import java.util.UUID
7+
import java.util.concurrent.TimeUnit
68

9+
data class ReportMetrics(
10+
val metricsInterval: Long,
11+
val httpClient: OkHttpClient,
12+
)
713

8-
data class ReportMetrics(val metricsInterval: Long = 60000)
914
/**
1015
* Represents configuration for Unleash.
11-
* @property url HTTP(s) URL to the Unleash Proxy (Required).
16+
* @property proxyUrl HTTP(s) URL to the Unleash Proxy (Required).
1217
* @property clientKey the key added as the Authorization header sent to the unleash-proxy (Required)
1318
* @property appName: name of the underlying application. Will be used as default in the [io.getunleash.UnleashContext] call (Required).
1419
* @property environment which environment is the application running in. Will be used as default argument for the [io.getunleash.UnleashContext]. (Optional - Defaults to 'default')
@@ -69,9 +74,9 @@ data class UnleashConfig(
6974
var httpClientReadTimeout: Long? = null,
7075
var httpClientCacheSize: Long? = null,
7176
var enableMetrics: Boolean = false,
77+
var metricsHttpClient: OkHttpClient? = null,
7278
var metricsInterval: Long? = null,
7379
var instanceId: String? = null,
74-
7580
) {
7681
fun proxyUrl(proxyUrl: String) = apply { this.proxyUrl = proxyUrl }
7782

@@ -88,6 +93,7 @@ data class UnleashConfig(
8893
fun httpClientCacheSize(cacheSize: Long) = apply { this.httpClientCacheSize = cacheSize }
8994
fun enableMetrics() = apply { this.enableMetrics = true }
9095
fun disableMetrics() = apply { this.enableMetrics = false }
96+
fun metricsHttpClient(client: OkHttpClient) = apply { this.metricsHttpClient = client }
9197
fun metricsInterval(intervalInMs: Long) = apply { this.metricsInterval = intervalInMs }
9298
fun metricsIntervalInSeconds(seconds: Long) = apply { this.metricsInterval = seconds * 1000 }
9399
fun instanceId(id: String) = apply { this.instanceId = id }
@@ -102,7 +108,13 @@ data class UnleashConfig(
102108
httpClientReadTimeout = httpClientReadTimeout ?: 5000,
103109
httpClientCacheSize = httpClientCacheSize ?: (1024 * 1024 * 10),
104110
reportMetrics = if (enableMetrics) {
105-
ReportMetrics(metricsInterval ?: 60000)
111+
ReportMetrics(
112+
metricsInterval = metricsInterval ?: 60000,
113+
httpClient = metricsHttpClient ?: OkHttpClient.Builder()
114+
.connectTimeout(httpClientConnectionTimeout ?: 2000, TimeUnit.MILLISECONDS)
115+
.readTimeout(httpClientReadTimeout ?: 5000, TimeUnit.MILLISECONDS)
116+
.build(),
117+
)
106118
} else {
107119
null
108120
},

src/main/kotlin/io/getunleash/metrics/MetricsReporter.kt

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -66,13 +66,20 @@ data class Bucket(
6666

6767
data class Report(val appName: String, val environment: String, val instanceId: String, val bucket: Bucket)
6868

69-
class HttpMetricsReporter(val config: UnleashConfig, val started: Date = Date()) : MetricsReporter,
69+
/**
70+
* @param config - Configuration for unleash - see docs for [io.getunleash.UnleashConfig]
71+
* @param httpClient - the http client to use for reporting metrics to Unleash proxy.
72+
*/
73+
class HttpMetricsReporter(
74+
val config: UnleashConfig,
75+
val httpClient: OkHttpClient,
76+
started: Date = Date(),
77+
) : MetricsReporter,
7078
Closeable {
7179
companion object {
7280
val logger: Logger = LoggerFactory.getLogger(MetricsReporter::class.java)
7381
}
7482

75-
val client = OkHttpClient.Builder().callTimeout(2, TimeUnit.SECONDS).readTimeout(5, TimeUnit.SECONDS).build()
7683
val metricsUrl = config.proxyUrl.toHttpUrl().newBuilder().addPathSegment("client").addPathSegment("metrics").build()
7784
private var bucket: Bucket = Bucket(start = started)
7885

@@ -86,7 +93,7 @@ class HttpMetricsReporter(val config: UnleashConfig, val started: Date = Date())
8693
val request = Request.Builder().header("Authorization", config.clientKey).url(metricsUrl).post(
8794
Parser.jackson.writeValueAsString(report).toRequestBody("application/json".toMediaType())
8895
).build()
89-
client.newCall(request).enqueue(object : Callback {
96+
httpClient.newCall(request).enqueue(object : Callback {
9097
override fun onFailure(call: Call, e: IOException) {
9198
logger.info("Failed to report metrics for interval")
9299
}
@@ -123,8 +130,8 @@ class HttpMetricsReporter(val config: UnleashConfig, val started: Date = Date())
123130
}
124131

125132
override fun close() {
126-
client.connectionPool.evictAll()
127-
client.cache?.closeQuietly()
128-
client.dispatcher.executorService.shutdown()
133+
httpClient.dispatcher.executorService.shutdownNow()
134+
httpClient.connectionPool.evictAll()
135+
httpClient.cache?.closeQuietly()
129136
}
130137
}

src/main/kotlin/io/getunleash/polling/UnleashFetcher.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -121,8 +121,8 @@ open class UnleashFetcher(
121121
}
122122

123123
override fun close() {
124-
this.httpClient.dispatcher.executorService.shutdownNow()
125-
this.httpClient.connectionPool.evictAll()
126-
this.httpClient.cache?.closeQuietly()
124+
httpClient.dispatcher.executorService.shutdownNow()
125+
httpClient.connectionPool.evictAll()
126+
httpClient.cache?.closeQuietly()
127127
}
128128
}

src/test/kotlin/io/getunleash/UnleashConfigTest.kt

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package io.getunleash
22

3+
import okhttp3.OkHttpClient
34
import org.assertj.core.api.Assertions.assertThat
45
import org.assertj.core.api.Assertions.assertThatThrownBy
56
import org.junit.jupiter.api.Test
7+
import java.util.concurrent.TimeUnit
8+
import kotlin.test.assertEquals
69

710
class UnleashConfigTest {
811

@@ -107,4 +110,34 @@ class UnleashConfigTest {
107110
val configWithMetricsSetInSeconds = config.newBuilder().enableMetrics().metricsIntervalInSeconds(5).build()
108111
assertThat(configInMs.reportMetrics!!.metricsInterval).isEqualTo(configWithMetricsSetInSeconds.reportMetrics!!.metricsInterval)
109112
}
113+
114+
@Test
115+
fun `Default http client for metrics uses config`() {
116+
val config = UnleashConfig(
117+
proxyUrl = "https://localhost:4242/proxy",
118+
clientKey = "some-key",
119+
appName = "my-app",
120+
environment = "default"
121+
)
122+
assertThat(config.reportMetrics).isNull()
123+
val withMetrics = config.newBuilder().enableMetrics().build()
124+
assertThat(withMetrics.reportMetrics).isNotNull
125+
assertThat(withMetrics.reportMetrics!!.httpClient.connectTimeoutMillis).isEqualTo(config.httpClientConnectionTimeout)
126+
assertThat(withMetrics.reportMetrics!!.httpClient.readTimeoutMillis).isEqualTo(config.httpClientReadTimeout)
127+
}
128+
129+
@Test
130+
fun `Can override http client for metrics`() {
131+
val config = UnleashConfig(
132+
proxyUrl = "https://localhost:4242/proxy",
133+
clientKey = "some-key",
134+
appName = "my-app",
135+
environment = "default"
136+
)
137+
assertThat(config.reportMetrics).isNull()
138+
val okHttpClient = OkHttpClient.Builder().build()
139+
val withMetrics = config.newBuilder().enableMetrics().metricsHttpClient(okHttpClient).build()
140+
assertThat(withMetrics.reportMetrics).isNotNull
141+
assertEquals(okHttpClient, withMetrics.reportMetrics!!.httpClient)
142+
}
110143
}

src/test/kotlin/io/getunleash/metrics/HttpMetricsReporterTest.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,19 @@ package io.getunleash.metrics
22

33
import io.getunleash.UnleashConfig
44
import io.getunleash.data.Variant
5+
import okhttp3.OkHttpClient
56
import okhttp3.mockwebserver.MockResponse
67
import okhttp3.mockwebserver.MockWebServer
78
import org.assertj.core.api.Assertions.assertThat
89
import org.junit.jupiter.api.Test
10+
import java.util.concurrent.TimeUnit
911

1012
class HttpMetricsReporterTest {
1113

1214
@Test
1315
fun metricsUrlIsCorrect() {
14-
HttpMetricsReporter(UnleashConfig.newBuilder().proxyUrl("http://localhost:4242/proxy").clientKey("some-key").build()).use { reporter ->
16+
val okHttpClient = OkHttpClient.Builder().build()
17+
HttpMetricsReporter(UnleashConfig.newBuilder().proxyUrl("http://localhost:4242/proxy").clientKey("some-key").build(), okHttpClient).use { reporter ->
1518
assertThat(reporter.metricsUrl.toString()).isEqualTo("http://localhost:4242/proxy/client/metrics")
1619
}
1720
}

src/test/kotlin/io/getunleash/metrics/MetricsTest.kt

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import io.getunleash.UnleashContext
77
import io.getunleash.data.Parser
88
import io.getunleash.data.Variant
99
import io.getunleash.polling.PollingModes
10+
import okhttp3.OkHttpClient
1011
import okhttp3.mockwebserver.MockResponse
1112
import okhttp3.mockwebserver.MockWebServer
1213
import org.assertj.core.api.Assertions.assertThat
@@ -18,6 +19,7 @@ import java.time.ZoneOffset
1819
import java.time.ZonedDateTime
1920
import java.util.Date
2021
import java.util.concurrent.ConcurrentHashMap
22+
import java.util.concurrent.TimeUnit
2123

2224
fun <K, V> concurrentHashMapOf(vararg pairs: Pair<K, V>): ConcurrentHashMap<K, V> {
2325
val map: ConcurrentHashMap<K, V> = ConcurrentHashMap()
@@ -158,7 +160,8 @@ class MetricsTest {
158160

159161
@Test
160162
fun `http reporter does actually report toggles to metrics endpoint`() {
161-
val reporter = HttpMetricsReporter(config)
163+
val okHttpClient = OkHttpClient.Builder().build()
164+
val reporter = HttpMetricsReporter(config, okHttpClient)
162165
val client = UnleashClient(config, context, metricsReporter = reporter)
163166
repeat(100) {
164167
client.isEnabled("unleash-android-proxy-sdk")

0 commit comments

Comments
 (0)