diff options
author | Fiete Ostkamp <Fiete.Ostkamp@telekom.de> | 2023-09-06 08:32:33 +0200 |
---|---|---|
committer | Fiete Ostkamp <Fiete.Ostkamp@telekom.de> | 2023-09-11 10:29:53 +0200 |
commit | c3c2eec967891108459c45786f8e98a85004e678 (patch) | |
tree | 2d79ce5e08658f05d054367693a905813dd80172 | |
parent | 1a23a1bcdf17ba4cf1cafb8e65babd1ad8666e59 (diff) |
Add Micrometer [bff]montreal
- add Micrometer dependencies
- uses Zipkin as trace protocol, typically for port 9411
- requires changing dependency injection of WebClient.Builder [1]
[1] Micrometer is injecting the trace context into the WebClient.Builder bean.
To add the ExchangeFilterFunctions for authentication, errorhandling and logging, the existing bean needs to be modified instead of statically creating a new one
Issue-ID: PORTALNG-57
Change-Id: I13dd18d297cd56fa2dfbb525723c79f4abb41f87
Signed-off-by: Fiete Ostkamp <Fiete.Ostkamp@telekom.de>
-rw-r--r-- | app/src/main/resources/application.yml | 7 | ||||
-rw-r--r-- | build.gradle | 1 | ||||
-rw-r--r-- | development/.env | 4 | ||||
-rw-r--r-- | development/docker-compose.yml | 19 | ||||
-rw-r--r-- | lib/build.gradle | 5 | ||||
-rw-r--r-- | lib/src/main/java/org/onap/portalng/bff/config/BeansConfig.java | 31 | ||||
-rw-r--r-- | lib/src/main/java/org/onap/portalng/bff/config/WebClientConfig.java | 56 | ||||
-rw-r--r-- | version | 2 |
8 files changed, 96 insertions, 29 deletions
diff --git a/app/src/main/resources/application.yml b/app/src/main/resources/application.yml index 0bbd9e2..87493a0 100644 --- a/app/src/main/resources/application.yml +++ b/app/src/main/resources/application.yml @@ -13,6 +13,13 @@ management: web: exposure: include: "*" + tracing: + enabled: true + sampling: + probability: 1.0 # sample every request + zipkin: + tracing: + endpoint: http://${COLLECTOR_HOST}:${COLLECTOR_PORT}/api/v2/spans spring: application: diff --git a/build.gradle b/build.gradle index 4ca21a3..8b484e2 100644 --- a/build.gradle +++ b/build.gradle @@ -12,6 +12,7 @@ ext { mapStructExtensionsVersion = '1.0.2' logbackVersion = '7.4' lombokVersion = '1.18.28' + micrometerVersion = '1.0.0' // app wiremockVersion = '4.0.4' diff --git a/development/.env b/development/.env index 2a2a73d..6cf5579 100644 --- a/development/.env +++ b/development/.env @@ -20,6 +20,10 @@ POSTGRES_VERSION=15rc1 MONGO_IMAGE=mongo MONGO_VERSION=latest +# tracing +COLLECTOR_HOST=jaeger +COLLECTOR_PORT=9411 + # preferences PREFERENCES_IMAGE_NAME=preferences PREFERENCES_IMAGE_TAG=latest diff --git a/development/docker-compose.yml b/development/docker-compose.yml index 1e7d282..10946d4 100644 --- a/development/docker-compose.yml +++ b/development/docker-compose.yml @@ -52,6 +52,8 @@ services: MONGO_PORT: ${HISTORY_MONGO_PORT} KEYCLOAK_URL: ${KEYCLOAK_URL} KEYCLOAK_REALM: ${KEYCLOAK_REALM} + COLLECTOR_HOST: ${COLLECTOR_HOST} + COLLECTOR_PORT: ${COLLECTOR_PORT} depends_on: - mongo-history mongo-preferences: @@ -73,5 +75,20 @@ services: MONGO_PORT: ${PREFERENCES_MONGO_PORT} KEYCLOAK_URL: ${KEYCLOAK_URL} KEYCLOAK_REALM: ${KEYCLOAK_REALM} + COLLECTOR_HOST: ${COLLECTOR_HOST} + COLLECTOR_PORT: ${COLLECTOR_PORT} depends_on: - - mongo-preferences
\ No newline at end of file + - mongo-preferences + jaeger: + image: jaegertracing/all-in-one:latest + container_name: jaeger + ports: + - 5775:5775/udp + - 6831:6831/udp + - 6832:6832/udp + - 5778:5778 + - 16686:16686 + - 14268:14268 + - 9411:9411 + environment: + COLLECTOR_ZIPKIN_HOST_PORT: 9411
\ No newline at end of file diff --git a/lib/build.gradle b/lib/build.gradle index e72062d..93064db 100644 --- a/lib/build.gradle +++ b/lib/build.gradle @@ -30,6 +30,11 @@ dependencies { implementation "org.mapstruct.extensions.spring:mapstruct-spring-annotations:$mapStructExtensionsVersion" implementation "org.mapstruct.extensions.spring:mapstruct-spring-extensions:$mapStructExtensionsVersion" + implementation(platform("io.micrometer:micrometer-tracing-bom:$micrometerVersion")) + implementation("io.micrometer:micrometer-tracing") + implementation("io.micrometer:micrometer-tracing-bridge-otel") + implementation("io.opentelemetry:opentelemetry-exporter-zipkin") + annotationProcessor "org.mapstruct:mapstruct-processor:$mapStructVersion" annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor' diff --git a/lib/src/main/java/org/onap/portalng/bff/config/BeansConfig.java b/lib/src/main/java/org/onap/portalng/bff/config/BeansConfig.java index 926108a..3eb5f87 100644 --- a/lib/src/main/java/org/onap/portalng/bff/config/BeansConfig.java +++ b/lib/src/main/java/org/onap/portalng/bff/config/BeansConfig.java @@ -33,11 +33,8 @@ import java.util.List; import lombok.extern.slf4j.Slf4j; import org.onap.portalng.bff.exceptions.DownstreamApiProblemException; import org.onap.portalng.bff.utils.Logger; -import org.springframework.beans.factory.annotation.Qualifier; -import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Scope; import org.springframework.http.codec.ClientCodecConfigurer; import org.springframework.http.codec.json.Jackson2JsonDecoder; import org.springframework.http.codec.json.Jackson2JsonEncoder; @@ -46,7 +43,6 @@ import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClient import org.springframework.security.oauth2.client.web.reactive.function.client.ServerOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.web.reactive.function.client.ExchangeFilterFunction; import org.springframework.web.reactive.function.client.ExchangeStrategies; -import org.springframework.web.reactive.function.client.WebClient; import org.zalando.problem.jackson.ProblemModule; import reactor.core.publisher.Mono; @@ -55,12 +51,12 @@ import reactor.core.publisher.Mono; public class BeansConfig { public static final String OAUTH2_EXCHANGE_FILTER_FUNCTION = "oauth2ExchangeFilterFunction"; - private static final String ID_TOKEN_EXCHANGE_FILTER_FUNCTION = "idTokenExchangeFilterFunction"; - private static final String ERROR_HANDLING_EXCHANGE_FILTER_FUNCTION = + public static final String ID_TOKEN_EXCHANGE_FILTER_FUNCTION = "idTokenExchangeFilterFunction"; + public static final String ERROR_HANDLING_EXCHANGE_FILTER_FUNCTION = "errorHandlingExchangeFilterFunction"; - private static final String LOG_REQUEST_EXCHANGE_FILTER_FUNCTION = + public static final String LOG_REQUEST_EXCHANGE_FILTER_FUNCTION = "logRequestExchangeFilterFunction"; - private static final String LOG_RESPONSE_EXCHANGE_FILTER_FUNCTION = + public static final String LOG_RESPONSE_EXCHANGE_FILTER_FUNCTION = "logResponseExchangeFilterFunction"; private static final String CLIENT_REGISTRATION_ID = "keycloak"; public static final String X_REQUEST_ID = "X-Request-Id"; @@ -148,25 +144,6 @@ public class BeansConfig { .build(); } - // we need to use prototype scope to always create new instance of the bean - // because internally WebClient.Builder is mutable - @Bean - @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) - WebClient.Builder webClientBuilder( - ExchangeStrategies exchangeStrategies, - @Qualifier(ID_TOKEN_EXCHANGE_FILTER_FUNCTION) - ExchangeFilterFunction idTokenExchangeFilterFunction, - @Qualifier(ERROR_HANDLING_EXCHANGE_FILTER_FUNCTION) - ExchangeFilterFunction errorHandlingExchangeFilterFunction, - @Qualifier(LOG_RESPONSE_EXCHANGE_FILTER_FUNCTION) - ExchangeFilterFunction logResponseExchangeFilterFunction) { - return WebClient.builder() - .exchangeStrategies(exchangeStrategies) - .filter(idTokenExchangeFilterFunction) - .filter(errorHandlingExchangeFilterFunction) - .filter(logResponseExchangeFilterFunction); - } - @Bean Clock clock() { return Clock.systemUTC(); diff --git a/lib/src/main/java/org/onap/portalng/bff/config/WebClientConfig.java b/lib/src/main/java/org/onap/portalng/bff/config/WebClientConfig.java new file mode 100644 index 0000000..7aa31bf --- /dev/null +++ b/lib/src/main/java/org/onap/portalng/bff/config/WebClientConfig.java @@ -0,0 +1,56 @@ +package org.onap.portalng.bff.config; + +import org.springframework.beans.BeansException; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.annotation.Configuration; +import org.springframework.stereotype.Component; +import org.springframework.web.reactive.function.client.ExchangeFilterFunction; +import org.springframework.web.reactive.function.client.ExchangeStrategies; +import org.springframework.web.reactive.function.client.WebClient; + +@Configuration +public class WebClientConfig { + + @Component + public static class WebClientBeanPostProcessor implements BeanPostProcessor { + + private final ExchangeStrategies exchangeStrategies; + private final ExchangeFilterFunction idTokenExchangeFilterFunction; + private final ExchangeFilterFunction errorHandlingExchangeFilterFunction; + private final ExchangeFilterFunction logResponseExchangeFilterFunction; + + public WebClientBeanPostProcessor( + ExchangeStrategies exchangeStrategies, + @Qualifier(BeansConfig.ID_TOKEN_EXCHANGE_FILTER_FUNCTION) + ExchangeFilterFunction idTokenExchangeFilterFunction, + @Qualifier(BeansConfig.ERROR_HANDLING_EXCHANGE_FILTER_FUNCTION) + ExchangeFilterFunction errorHandlingExchangeFilterFunction, + @Qualifier(BeansConfig.LOG_RESPONSE_EXCHANGE_FILTER_FUNCTION) + ExchangeFilterFunction logResponseExchangeFilterFunction) { + this.exchangeStrategies = exchangeStrategies; + this.idTokenExchangeFilterFunction = idTokenExchangeFilterFunction; + this.errorHandlingExchangeFilterFunction = errorHandlingExchangeFilterFunction; + this.logResponseExchangeFilterFunction = logResponseExchangeFilterFunction; + } + + @Override + public Object postProcessBeforeInitialization(Object bean, String beanName) + throws BeansException { + return bean; + } + + @Override + public Object postProcessAfterInitialization(Object bean, String beanName) + throws BeansException { + if (bean instanceof WebClient.Builder builder) { + return builder + .exchangeStrategies(exchangeStrategies) + .filter(idTokenExchangeFilterFunction) + .filter(errorHandlingExchangeFilterFunction) + .filter(logResponseExchangeFilterFunction); + } + return bean; + } + } +} @@ -1 +1 @@ -0.1.1 +0.1.2 |