Skip to content

Commit

Permalink
feat: add metrics for spring rest client
Browse files Browse the repository at this point in the history
  • Loading branch information
Lukinhasssss committed Jun 1, 2024
1 parent 174e644 commit cf752d5
Show file tree
Hide file tree
Showing 3 changed files with 71 additions and 9 deletions.
1 change: 1 addition & 0 deletions infrastructure/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ dependencies {

implementation("org.springframework.boot:spring-boot-starter-actuator")
implementation("io.micrometer:micrometer-registry-prometheus:1.10.5")
implementation("io.opentelemetry:opentelemetry-exporter-otlp:1.38.0")
implementation("ch.qos.logback:logback-classic:1.4.14")
implementation("ch.qos.logback:logback-core:1.4.14")
implementation("net.logstash.logback:logstash-logback-encoder:7.3")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Genres
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Keycloak
import com.lukinhasssss.catalogo.infrastructure.configuration.annotations.Videos
import com.lukinhasssss.catalogo.infrastructure.configuration.properties.RestClientProperties
import io.micrometer.observation.ObservationRegistry
import org.springframework.boot.context.properties.ConfigurationProperties
import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
Expand All @@ -19,7 +20,11 @@ import org.springframework.web.client.RestClient
class RestClientConfig {

companion object {
fun restClient(properties: RestClientProperties, objectMapper: ObjectMapper) = with(properties) {
fun restClient(
properties: RestClientProperties,
objectMapper: ObjectMapper,
observationRegistry: ObservationRegistry
) = with(properties) {
val factory = JdkClientHttpRequestFactory()
factory.setReadTimeout(readTimeout)

Expand All @@ -31,6 +36,8 @@ class RestClientConfig {
converters.add(jsonConverter(objectMapper))
converters.add(FormHttpMessageConverter())
}
.observationRegistry(observationRegistry)
.observationConvention(RestClientObservationConfig())
.build()
}

Expand Down Expand Up @@ -65,27 +72,31 @@ class RestClientConfig {
@Keycloak
fun keycloakHttpClient(
@Keycloak properties: RestClientProperties,
objectMapper: ObjectMapper
) = restClient(properties, objectMapper)
objectMapper: ObjectMapper,
observationRegistry: ObservationRegistry
) = restClient(properties, objectMapper, observationRegistry)

@Bean
@Categories
fun categoryHttpClient(
@Categories properties: RestClientProperties,
objectMapper: ObjectMapper
) = restClient(properties, objectMapper)
objectMapper: ObjectMapper,
observationRegistry: ObservationRegistry
) = restClient(properties, objectMapper, observationRegistry)

@Bean
@Genres
fun genreHttpClient(
@Genres properties: RestClientProperties,
objectMapper: ObjectMapper
) = restClient(properties, objectMapper)
objectMapper: ObjectMapper,
observationRegistry: ObservationRegistry
) = restClient(properties, objectMapper, observationRegistry)

@Bean
@Videos
fun videoHttpClient(
@Videos properties: RestClientProperties,
objectMapper: ObjectMapper
) = restClient(properties, objectMapper)
objectMapper: ObjectMapper,
observationRegistry: ObservationRegistry
) = restClient(properties, objectMapper, observationRegistry)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.lukinhasssss.catalogo.infrastructure.configuration

import io.micrometer.common.KeyValues
import org.springframework.http.client.observation.ClientRequestObservationContext
import org.springframework.http.client.observation.ClientRequestObservationConvention

class RestClientObservationConfig : ClientRequestObservationConvention {

override fun getName(): String {
// will be used as the metric name
return "rest_client"
}

override fun getContextualName(context: ClientRequestObservationContext): String {
// will be used for the trace name
return "http ${context.carrier?.method?.name().orEmpty()}"
}

override fun getLowCardinalityKeyValues(context: ClientRequestObservationContext): KeyValues {
var keyValues = super.getLowCardinalityKeyValues(context)

val request = context.carrier
val response = context.response
val error = context.error

request?.let {
val uuidRegex = "[0-9a-fA-F]{32}".toRegex()
val uri = it.uri.path.replace(uuidRegex, "{id}")

keyValues = keyValues.and("method", it.method.name())
.and("uri", uri)
.and("client.name", it.uri.host)
}

response?.let {
keyValues = keyValues.and("status", it.statusText)
}

error?.let {
keyValues = keyValues.and("outcome", it.localizedMessage)
.and("error", it.javaClass.name)
}

return keyValues
}

override fun getHighCardinalityKeyValues(context: ClientRequestObservationContext): KeyValues {
return super.getHighCardinalityKeyValues(context)
}
}

0 comments on commit cf752d5

Please sign in to comment.