diff options
author | lapentafd <francesco.lapenta@est.tech> | 2024-06-24 10:54:54 +0100 |
---|---|---|
committer | lapentafd <francesco.lapenta@est.tech> | 2024-06-26 14:41:42 +0100 |
commit | ad800650d7958985a34ac30d77407a9ce7c2de1a (patch) | |
tree | dfb0f1cc3bcfb9c59cf68ba7ab45eb22842a34fb | |
parent | f734a409bfab49b88deb9979315b593d964ecfa2 (diff) |
Wrap AsyncWebClient to use less the ApplicationContextProvider1.7.0
Issue-ID: CCSDK-4022
Change-Id: I2ecc3431ef646fe408de0de35698e8f369a55ee4
Signed-off-by: lapentafd <francesco.lapenta@est.tech>
9 files changed, 139 insertions, 136 deletions
diff --git a/a1-policy-management/config/application.yaml b/a1-policy-management/config/application.yaml index 52b70d10..39b44863 100644 --- a/a1-policy-management/config/application.yaml +++ b/a1-policy-management/config/application.yaml @@ -29,18 +29,7 @@ spring: aop: auto: false management: - otlp: - metrics: - export: - enabled: false tracing: - sampler: - jaeger_remote: - endpoint: ${ONAP_OTEL_SAMPLER_JAEGER_REMOTE_ENDPOINT:http://jaeger:14250} - exporter: - endpoint: ${ONAP_OTEL_EXPORTER_ENDPOINT:http://jaeger:4317} - protocol: ${ONAP_OTEL_EXPORTER_PROTOCOL:grpc} - enabled: ${ONAP_TRACING_ENABLED:false} propagation: produce: ${ONAP_PROPAGATOR_PRODUCE:[W3C]} sampling: @@ -119,7 +108,19 @@ app: secretAccessKey: miniostorage bucket: otel: + sdk: + disabled: ${ONAP_SDK_DISABLED:true} + south: ${ONAP_TRACING_SOUTHBOUND:true} + tracing: + sampler: + jaeger_remote: + endpoint: ${ONAP_OTEL_SAMPLER_JAEGER_REMOTE_ENDPOINT:http://jaeger:14250} exporter: otlp: traces: - protocol: ${ONAP_OTEL_EXPORTER_OTLP_TRACES_PROTOCOL:grpc} + protocol: ${ONAP_OTEL_EXPORTER_PROTOCOL:grpc} + endpoint: ${ONAP_OTEL_EXPORTER_ENDPOINT:http://jaeger:4317} + metrics: + exporter: none + logs: + exporter: none diff --git a/a1-policy-management/pom.xml b/a1-policy-management/pom.xml index c383ba2f..0d53b90c 100644 --- a/a1-policy-management/pom.xml +++ b/a1-policy-management/pom.xml @@ -222,24 +222,15 @@ </dependency> <dependency> <groupId>io.opentelemetry</groupId> - <artifactId>opentelemetry-exporter-otlp</artifactId> - </dependency> - <dependency> - <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk-extension-jaeger-remote-sampler</artifactId> </dependency> <dependency> - <groupId>io.opentelemetry</groupId> - <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId> - </dependency> - <dependency> <groupId>io.opentelemetry.instrumentation</groupId> <artifactId>opentelemetry-spring-webflux-5.3</artifactId> </dependency> <dependency> - <groupId>io.micrometer</groupId> - <artifactId>context-propagation</artifactId> - <version>1.0.2</version> + <groupId>io.opentelemetry.instrumentation</groupId> + <artifactId>opentelemetry-spring-boot-starter</artifactId> </dependency> <!-- For ObservationRegistryCustomizer --> <dependency> diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java index ddcfd068..476c1606 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/clients/AsyncRestClient.java @@ -25,22 +25,16 @@ import io.netty.channel.ChannelOption; import io.netty.handler.ssl.SslContext; import io.netty.handler.timeout.ReadTimeoutHandler; import io.netty.handler.timeout.WriteTimeoutHandler; -import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; import java.lang.invoke.MethodHandles; -import java.util.concurrent.atomic.AtomicInteger; -import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationContextProvider; -import org.onap.ccsdk.oran.a1policymanagementservice.configuration.OtelConfig; import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientConfig.HttpProxyConfig; +import org.onap.ccsdk.oran.a1policymanagementservice.configuration.WebClientUtil; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.http.MediaType; import org.springframework.http.ResponseEntity; -import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.lang.Nullable; -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.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec; import org.springframework.web.reactive.function.client.WebClientResponseException; @@ -57,11 +51,9 @@ public class AsyncRestClient { private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private WebClient webClient = null; private final String baseUrl; - private static final AtomicInteger sequenceNumber = new AtomicInteger(); private final SslContext sslContext; private final HttpProxyConfig httpProxyConfig; private final SecurityContext securityContext; - private OtelConfig otelConfig = ApplicationContextProvider.getApplicationContext().getBean(OtelConfig.class); public AsyncRestClient(String baseUrl, @Nullable SslContext sslContext, @Nullable HttpProxyConfig httpProxyConfig, SecurityContext securityContext) { @@ -156,10 +148,6 @@ public class AsyncRestClient { } } - private static Object createTraceTag() { - return sequenceNumber.incrementAndGet(); - } - private String toBody(ResponseEntity<String> entity) { if (entity.getBody() == null) { return ""; @@ -193,36 +181,8 @@ public class AsyncRestClient { } public WebClient buildWebClient(String baseUrl) { - Object traceTag = createTraceTag(); - final HttpClient httpClient = buildHttpClient(); - ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() // - .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) // - .build(); - - ExchangeFilterFunction reqLogger = ExchangeFilterFunction.ofRequestProcessor(req -> { - logger.debug("{} {} uri = '{}''", traceTag, req.method(), req.url()); - return Mono.just(req); - }); - - ExchangeFilterFunction respLogger = ExchangeFilterFunction.ofResponseProcessor(resp -> { - logger.debug("{} resp: {}", traceTag, resp.statusCode()); - return Mono.just(resp); - }); - - WebClient.Builder webClientBuilder = WebClient.builder() - .clientConnector(new ReactorClientHttpConnector(httpClient)) - .baseUrl(baseUrl) - .exchangeStrategies(exchangeStrategies) - .filter(reqLogger) - .filter(respLogger); - - if (otelConfig.isTracingEnabled()) { - SpringWebfluxTelemetry webfluxTelemetry = ApplicationContextProvider.getApplicationContext().getBean(SpringWebfluxTelemetry.class); - webClientBuilder.filters(webfluxTelemetry::addClientTracingFilter); - } - - return webClientBuilder.build(); + return WebClientUtil.buildWebClient(baseUrl, httpClient); } private WebClient getWebClient() { diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationContextProvider.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationContextProvider.java deleted file mode 100644 index a7130201..00000000 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/ApplicationContextProvider.java +++ /dev/null @@ -1,39 +0,0 @@ -/*- - * ========================LICENSE_START================================= - * ONAP : ccsdk oran - * ====================================================================== - * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. - * ====================================================================== - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * ========================LICENSE_END=================================== - */ -package org.onap.ccsdk.oran.a1policymanagementservice.configuration; - -import org.springframework.beans.BeansException; -import org.springframework.context.ApplicationContext; -import org.springframework.context.ApplicationContextAware; -import org.springframework.context.annotation.Configuration; - -@Configuration -public class ApplicationContextProvider implements ApplicationContextAware { - private static ApplicationContext context; - - @Override - public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { - context = applicationContext; - } - - public static ApplicationContext getApplicationContext() { - return context; - } -}
\ No newline at end of file diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfig.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfig.java index a66bc062..cac03208 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfig.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfig.java @@ -27,11 +27,8 @@ import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler; import io.opentelemetry.sdk.trace.samplers.Sampler; -import lombok.Getter; -import reactor.core.publisher.Hooks; import java.time.Duration; - import javax.annotation.PostConstruct; import org.slf4j.Logger; @@ -57,40 +54,50 @@ public class OtelConfig { @Value("${spring.application.name}") private String serviceId; - @Value("${management.tracing.exporter.endpoint}") + @Value("${otel.exporter.otlp.traces.endpoint}") private String tracingExporterEndpointUrl; - @Value("${management.tracing.sampler.jaeger-remote.endpoint}") + @Value("${otel.tracing.sampler.jaeger-remote.endpoint}") private String jaegerRemoteSamplerUrl; - @Value("${management.tracing.exporter.protocol}") + @Value("${otel.exporter.otlp.traces.protocol}") private String tracingProtocol; - @Getter - @Value("${management.tracing.enabled}") - private boolean tracingEnabled; + @Value("${otel.sdk.disabled}") + private boolean tracingDisabled; + + @Value("${otel.sdk.south}") + private boolean southTracingEnabled; @PostConstruct public void checkTracingConfig() { - logger.info("Application Yaml Tracing Enabled: " + tracingEnabled); + logger.info("Application Yaml Tracing Enabled: " + !tracingDisabled); + } + + public boolean isTracingEnabled() { + return !tracingDisabled; + } + + public boolean isSouthTracingEnabled() { + return isTracingEnabled() && southTracingEnabled; } @Bean - @ConditionalOnProperty(prefix = "management.tracing", name = "enabled", havingValue = "true", matchIfMissing = false) - @ConditionalOnExpression("'grpc'.equals('${management.tracing.exporter.protocol}')") + @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false) + @ConditionalOnExpression("'grpc'.equals('${otel.exporter.otlp.traces.protocol}')") public OtlpGrpcSpanExporter otlpExporterGrpc() { return OtlpGrpcSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); } @Bean - @ConditionalOnProperty(prefix = "management.tracing", name = "enabled", havingValue = "true", matchIfMissing = false) - @ConditionalOnExpression("'http'.equals('${management.tracing.exporter.protocol}')") + @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false) + @ConditionalOnExpression("'http'.equals('${otel.exporter.otlp.traces.protocol}')") public OtlpHttpSpanExporter otlpExporterHttp() { return OtlpHttpSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build(); } @Bean - @ConditionalOnProperty(prefix = "management.tracing", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false) public JaegerRemoteSampler jaegerRemoteSampler() { return JaegerRemoteSampler.builder().setEndpoint(jaegerRemoteSamplerUrl) .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND)) @@ -98,15 +105,13 @@ public class OtelConfig { } @Bean - @ConditionalOnProperty(prefix = "management.tracing", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnExpression("!${otel.sdk.disabled:true} and ${otel.sdk.south:true}") public SpringWebfluxTelemetry webfluxTelemetry (OpenTelemetry openTelemetry) { - //enables automatic context propagation to ThreadLocals used by FLUX and MONO operators - Hooks.enableAutomaticContextPropagation(); return SpringWebfluxTelemetry.builder(openTelemetry).build(); } @Bean - @ConditionalOnProperty(prefix = "management.tracing", name = "enabled", havingValue = "true", matchIfMissing = false) + @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false) ObservationRegistryCustomizer<ObservationRegistry> skipActuatorEndpointsFromObservation() { PathMatcher pathMatcher = new AntPathMatcher("/"); return registry -> diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientUtil.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientUtil.java new file mode 100644 index 00000000..68d9ea71 --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/WebClientUtil.java @@ -0,0 +1,87 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved. + * ====================================================================== + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ========================LICENSE_END=================================== + */ +package org.onap.ccsdk.oran.a1policymanagementservice.configuration; + +import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.DependsOn; +import org.springframework.http.client.reactive.ReactorClientHttpConnector; +import org.springframework.stereotype.Service; +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 reactor.core.publisher.Mono; +import reactor.netty.http.client.HttpClient; + +import java.lang.invoke.MethodHandles; +import java.util.concurrent.atomic.AtomicInteger; + +@Service +@DependsOn({"otelConfig"}) +public class WebClientUtil { + + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private static OtelConfig otelConfig; + + private static SpringWebfluxTelemetry springWebfluxTelemetry; + + public WebClientUtil(OtelConfig otelConfig, @Autowired(required = false) SpringWebfluxTelemetry springWebfluxTelemetry) { + WebClientUtil.otelConfig = otelConfig; + if (otelConfig.isTracingEnabled()) { + WebClientUtil.springWebfluxTelemetry = springWebfluxTelemetry; + } + } + + public static WebClient buildWebClient(String baseURL, final HttpClient httpClient) { + + Object traceTag = new AtomicInteger().incrementAndGet(); + + ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() // + .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) // + .build(); + + ExchangeFilterFunction reqLogger = ExchangeFilterFunction.ofRequestProcessor(req -> { + logger.debug("{} {} uri = '{}''", traceTag, req.method(), req.url()); + return Mono.just(req); + }); + + ExchangeFilterFunction respLogger = ExchangeFilterFunction.ofResponseProcessor(resp -> { + logger.debug("{} resp: {}", traceTag, resp.statusCode()); + return Mono.just(resp); + }); + + WebClient.Builder webClientBuilder = WebClient.builder() + .clientConnector(new ReactorClientHttpConnector(httpClient)) + .baseUrl(baseURL) + .exchangeStrategies(exchangeStrategies) + .filter(reqLogger) + .filter(respLogger); + + if (otelConfig.isSouthTracingEnabled()) { + webClientBuilder.filters(springWebfluxTelemetry::addClientTracingFilter); + } + + return webClientBuilder.build(); + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/authorization/AuthorizationCheck.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/authorization/AuthorizationCheck.java index 5ad50688..0f376c06 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/authorization/AuthorizationCheck.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/authorization/AuthorizationCheck.java @@ -36,14 +36,12 @@ import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.context.annotation.DependsOn; import org.springframework.http.HttpStatus; import org.springframework.stereotype.Component; import reactor.core.publisher.Mono; @Component -@DependsOn("applicationContextProvider") public class AuthorizationCheck { private final ApplicationConfig applicationConfig; diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfigTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfigTest.java index 7c04de20..bd011193 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfigTest.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/configuration/OtelConfigTest.java @@ -28,9 +28,7 @@ import static org.mockito.Mockito.when; import io.micrometer.observation.Observation; import io.micrometer.observation.ObservationRegistry; -import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter; -import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdk; import jakarta.servlet.http.HttpServletRequest; import java.util.Objects; import org.junit.jupiter.api.Test; @@ -40,8 +38,8 @@ import org.springframework.boot.test.autoconfigure.actuate.observability.AutoCon import org.springframework.boot.test.context.SpringBootTest; import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; import org.springframework.context.ApplicationContext; -import org.springframework.context.annotation.Bean; import org.springframework.http.server.observation.ServerRequestObservationContext; +import org.springframework.test.annotation.DirtiesContext; import org.springframework.test.context.TestPropertySource; import org.springframework.util.AntPathMatcher; @@ -54,12 +52,14 @@ import org.springframework.util.AntPathMatcher; "app.filepath=", "app.s3.bucket=", "spring.application.name=a1-pms", - "management.tracing.enabled=true", - "management.tracing.exporter.protocol=grpc", - "management.tracing.sampler.jaeger_remote.endpoint=http://127.0.0.1:14250", + "otel.sdk.disabled=false", + "otel.sdk.south=true", + "otel.exporter.otlp.traces.protocol=grpc", + "otel.tracing.sampler.jaeger-remote.endpoint=http://127.0.0.1:14250", "management.tracing.propagator.type=W3C" }) @AutoConfigureObservability +@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS) class OtelConfigTest { @Autowired private ApplicationContext context; @@ -68,11 +68,6 @@ class OtelConfigTest { @Autowired ObservationRegistry observationRegistry; - @Bean - OpenTelemetry openTelemetry() { - return AutoConfiguredOpenTelemetrySdk.initialize().getOpenTelemetrySdk(); - } - @Test void otlpExporterGrpc() { assertNotNull(otelConfig); diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java index 4f3fa5f5..69ee12ba 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/ApplicationTest.java @@ -195,6 +195,11 @@ class ApplicationTest { @BeforeEach void init() { this.applicationConfig.setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL); + rics.clear(); + policies.clear(); + policyTypes.clear(); + services.clear(); + a1ClientFactory.reset(); } @AfterEach |