Skip to content

Commit da263ce

Browse files
committed
use Retrofit to make Datadog calls
1 parent 5fa3120 commit da263ce

4 files changed

Lines changed: 91 additions & 55 deletions

File tree

datadog-event-listener-echo/datadog-event-listener-echo.gradle

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ dependencies {
3838

3939
kapt(group: 'org.pf4j', name: 'pf4j', version: "${pf4jVersion}")
4040

41+
compileOnly 'com.squareup.retrofit2:retrofit:2.8.1'
42+
compileOnly 'com.squareup.retrofit2:converter-jackson:2.8.1'
43+
44+
testImplementation 'com.squareup.retrofit2:retrofit:2.8.1'
45+
testImplementation 'com.squareup.retrofit2:converter-jackson:2.8.1'
4146
testImplementation (group: 'com.netflix.spinnaker.echo', name: 'echo-api', version: "${echoVersion}") {
4247
exclude group: "org.slf4j"
4348
}

datadog-event-listener-echo/src/main/kotlin/io/armory/plugin/events/listener/datadog/DataDogEventListenerPlugin.kt

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,16 @@
1515
*/
1616
package io.armory.plugin.events.listener.datadog
1717

18+
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
1819
import com.netflix.spinnaker.echo.api.events.Event
1920
import com.netflix.spinnaker.echo.api.events.EventListener
20-
import org.slf4j.LoggerFactory
2121
import org.pf4j.Extension
2222
import org.pf4j.Plugin
2323
import org.pf4j.PluginWrapper
24-
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
25-
import com.netflix.spinnaker.kork.plugins.api.PluginSdks
26-
import com.netflix.spinnaker.kork.plugins.api.httpclient.HttpClient
27-
import com.netflix.spinnaker.kork.plugins.api.httpclient.HttpClientConfig
28-
import com.netflix.spinnaker.kork.plugins.api.httpclient.Request
29-
3024
import org.slf4j.Logger
25+
import org.slf4j.LoggerFactory
26+
import retrofit2.Retrofit
27+
import retrofit2.converter.jackson.JacksonConverterFactory
3128

3229
class DataDogEventListenerPlugin(wrapper: PluginWrapper) : Plugin(wrapper) {
3330
private val logger = LoggerFactory.getLogger(DataDogEventListenerPlugin::class.java)
@@ -50,18 +47,25 @@ data class DataDogEvent(
5047
)
5148

5249
@Extension
53-
open class DataDogEventListener(val configuration: DataDogEventListenerConfig, val pluginSdks: PluginSdks) : EventListener {
50+
open class DataDogEventListener(val configuration: DataDogEventListenerConfig) : EventListener {
5451

55-
private val httpClientName = "datadog"
5652
private val dataDogUrl = "https://api.datadoghq.com/"
5753

5854
private val log = LoggerFactory.getLogger(DataDogEventListener::class.java)
5955

6056
private val mapper = jacksonObjectMapper()
6157

62-
protected open fun getHttpClient() : HttpClient {
63-
pluginSdks.http().configure(httpClientName, dataDogUrl, HttpClientConfig())
64-
return pluginSdks.http().get(httpClientName)
58+
private var datadogClient: DatadogClient? = null
59+
60+
protected open fun getDataDogClient() : DatadogClient {
61+
if (datadogClient == null) {
62+
val retrofit = Retrofit.Builder()
63+
.baseUrl(dataDogUrl)
64+
.addConverterFactory(JacksonConverterFactory.create())
65+
.build()
66+
datadogClient = retrofit.create(DatadogClient::class.java)
67+
}
68+
return datadogClient!!
6569
}
6670

6771
protected open fun getLogger() : Logger {
@@ -97,13 +101,9 @@ open class DataDogEventListener(val configuration: DataDogEventListenerConfig, v
97101
"info"
98102
)
99103

100-
val request = Request("send_events_to_datadog", "api/v1/events")
101-
.setQueryParams(mapOf("api_key" to configuration.apiKey))
102-
.setBody(dataDogEvent)
103-
val response = getHttpClient().post(request)
104-
105-
if (response.isError) {
106-
getLogger().error("DataDog event listener failed with response: ${response.statusCode}")
104+
val response = getDataDogClient().sendEvent(configuration.apiKey, dataDogEvent).execute()
105+
if (!response.isSuccessful) {
106+
getLogger().error("DataDog event listener failed with response: ${response.code()} - ${response.message()}")
107107
}
108108
}
109109
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2020 Armory, Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package io.armory.plugin.events.listener.datadog
18+
19+
import retrofit2.Call
20+
import retrofit2.http.Body
21+
import retrofit2.http.POST
22+
import retrofit2.http.Query
23+
24+
interface DatadogClient {
25+
26+
@POST("api/v1/events")
27+
fun sendEvent(@Query("api_key") apiKey: String, @Body event: DataDogEvent) : Call<Any>
28+
29+
}

datadog-event-listener-echo/src/test/kotlin/io/armory/plugin/events/listener/datadog/DataDogEventListenerTest.kt

Lines changed: 38 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,6 @@ package io.armory.plugin.events.listener.datadog
1818
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
1919
import com.netflix.spinnaker.echo.api.events.Event
2020
import com.netflix.spinnaker.echo.api.events.Metadata
21-
import com.netflix.spinnaker.kork.plugins.api.PluginSdks
22-
import com.netflix.spinnaker.kork.plugins.api.httpclient.HttpClient
2321
import dev.minutest.junit.JUnit5Minutests
2422
import dev.minutest.rootContext
2523
import io.mockk.Called
@@ -35,15 +33,12 @@ class DataDogEventListenerTest : JUnit5Minutests {
3533

3634
private val mapper = jacksonObjectMapper()
3735

38-
val pluginSdks = mockk<PluginSdks>()
39-
4036
class HttpMockableDataDogEventListener(
41-
val http: HttpClient,
42-
val log: Logger,
43-
pluginSdks: PluginSdks) : DataDogEventListener(DataDogEventListenerConfig("asdf"), pluginSdks) {
37+
val client: DatadogClient,
38+
val log: Logger) : DataDogEventListener(DataDogEventListenerConfig("asdf")) {
4439

45-
override fun getHttpClient() : HttpClient {
46-
return http
40+
override fun getDataDogClient() : DatadogClient {
41+
return client
4742
}
4843

4944
override fun getLogger() : Logger {
@@ -77,23 +72,25 @@ class DataDogEventListenerTest : JUnit5Minutests {
7772
"pipelineConfigId" to "f514b57a-63af-4f5f-ac0a-2bc12d6c363b"
7873
)
7974
)
80-
val httpClient = mockk<HttpClient> {
81-
every { post(any()) } returns mockk {
82-
every { isError } returns false
75+
val datadogClient = mockk<DatadogClient> {
76+
every { sendEvent(any(), any()) } returns mockk {
77+
every { execute() } returns mockk {
78+
every { isSuccessful } returns true
79+
}
8380
}
8481
}
8582
val log = mockk<Logger>()
8683

87-
val eventListener = HttpMockableDataDogEventListener(httpClient, log, pluginSdks)
84+
val eventListener = HttpMockableDataDogEventListener(datadogClient, log)
8885
eventListener.processEvent(event)
8986

9087
verify(exactly = 1) {
91-
httpClient.post(
88+
datadogClient.sendEvent(
89+
withArg {
90+
expectThat(it).isEqualTo("asdf")
91+
},
9292
withArg {
93-
expectThat(it.path).isEqualTo("api/v1/events")
94-
expectThat(it.queryParams).isEqualTo(mapOf("api_key" to "asdf"))
95-
val dataDogEvent = it.body as DataDogEvent
96-
expectThat(dataDogEvent.tags).isEqualTo(setOf(
93+
expectThat(it.tags).isEqualTo(setOf(
9794
"source:orca",
9895
"eventType:orca:task:complete",
9996
"application:plugintest",
@@ -103,7 +100,7 @@ class DataDogEventListenerTest : JUnit5Minutests {
103100
"pipelineName:testNewStageFromPlugin",
104101
"pipelineConfigId:f514b57a-63af-4f5f-ac0a-2bc12d6c363b"
105102
))
106-
val actualJson = mapper.readValue(dataDogEvent.text, Map::class.java)
103+
val actualJson = mapper.readValue(it.text, Map::class.java)
107104
expectThat(actualJson).isEqualTo(mapOf(
108105
"details" to mapOf(
109106
"source" to "orca",
@@ -158,31 +155,33 @@ class DataDogEventListenerTest : JUnit5Minutests {
158155
"status" to "SUCCEEDED"
159156
)
160157
)
161-
val httpClient = mockk<HttpClient> {
162-
every { post(any()) } returns mockk {
163-
every { isError } returns false
158+
val datadogClient = mockk<DatadogClient> {
159+
every { sendEvent(any(), any()) } returns mockk {
160+
every { execute() } returns mockk {
161+
every { isSuccessful } returns true
162+
}
164163
}
165164
}
166165
val log = mockk<Logger>()
167166

168-
val eventListener = HttpMockableDataDogEventListener(httpClient, log, pluginSdks)
167+
val eventListener = HttpMockableDataDogEventListener(datadogClient, log)
169168
eventListener.processEvent(event)
170169

171170
verify(exactly = 1) {
172-
httpClient.post(
171+
datadogClient.sendEvent(
172+
withArg {
173+
expectThat(it).isEqualTo("asdf")
174+
},
173175
withArg {
174-
expectThat(it.path).isEqualTo("api/v1/events")
175-
expectThat(it.queryParams).isEqualTo(mapOf("api_key" to "asdf"))
176-
val dataDogEvent = it.body as DataDogEvent
177-
expectThat(dataDogEvent.tags).isEqualTo(setOf(
176+
expectThat(it.tags).isEqualTo(setOf(
178177
"source:orca",
179178
"eventType:orca:orchestration:complete",
180179
"application:plugintest",
181180
"executionId:01E307DBPNB1YJ9D0BW5X4NAEY",
182181
"executionType:ORCHESTRATION",
183182
"executionStatus:SUCCEEDED"
184183
))
185-
val actualJson = mapper.readValue(dataDogEvent.text, Map::class.java)
184+
val actualJson = mapper.readValue(it.text, Map::class.java)
186185
expectThat(actualJson).isEqualTo(mapOf(
187186
"details" to mapOf(
188187
"source" to "orca",
@@ -229,25 +228,28 @@ class DataDogEventListenerTest : JUnit5Minutests {
229228
event.content = mapOf(
230229
"execution" to mapOf("type" to "ORCHESTRATION")
231230
)
232-
val httpClient = mockk<HttpClient> {
233-
every { post(any()) } returns mockk {
234-
every { isError } returns true
235-
every { statusCode } returns 400
231+
val datadogClient = mockk<DatadogClient> {
232+
every { sendEvent(any(), any()) } returns mockk {
233+
every { execute() } returns mockk {
234+
every { isSuccessful } returns false
235+
every { code() } returns 400
236+
every { message() } returns "it failed"
237+
}
236238
}
237239
}
238240
val log = mockk<Logger>(relaxed = true)
239241

240-
val eventListener = HttpMockableDataDogEventListener(httpClient, log, pluginSdks)
242+
val eventListener = HttpMockableDataDogEventListener(datadogClient, log)
241243
eventListener.processEvent(event)
242244

243245
verify(exactly = 1) {
244-
httpClient.post(any())
246+
datadogClient.sendEvent(any(), any())
245247
}
246248

247249
verify(exactly = 1) {
248250
log.error(
249251
withArg {
250-
expectThat(it).startsWith("DataDog event listener failed with response: 400")
252+
expectThat(it).startsWith("DataDog event listener failed with response: 400 - it failed")
251253
}
252254
)
253255
}

0 commit comments

Comments
 (0)