Wrap AsyncWebClient to use less the ApplicationContextProvider
Issue-ID: CCSDK-4022
Change-Id: I2ecc3431ef646fe408de0de35698e8f369a55ee4
Signed-off-by: lapentafd <francesco.lapenta@est.tech>
diff --git a/a1-policy-management/config/application.yaml b/a1-policy-management/config/application.yaml
index 52b70d1..39b4486 100644
--- a/a1-policy-management/config/application.yaml
+++ b/a1-policy-management/config/application.yaml
@@ -29,18 +29,7 @@
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 @@
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 c383ba2..0d53b90 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 ddcfd06..476c160 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.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 @@
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 @@
}
}
- private static Object createTraceTag() {
- return sequenceNumber.incrementAndGet();
- }
-
private String toBody(ResponseEntity<String> entity) {
if (entity.getBody() == null) {
return "";
@@ -193,36 +181,8 @@
}
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 a713020..0000000
--- 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 a66bc06..cac0320 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.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 @@
@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 @@
}
@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 0000000..68d9ea7
--- /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 5ad5068..0f376c0 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.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 7c04de2..bd01119 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 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.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 @@
"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 @@
@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 4f3fa5f..69ee12b 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 @@
@BeforeEach
void init() {
this.applicationConfig.setAuthProviderUrl(baseUrl() + OpenPolicyAgentSimulatorController.ACCESS_CONTROL_URL);
+ rics.clear();
+ policies.clear();
+ policyTypes.clear();
+ services.clear();
+ a1ClientFactory.reset();
}
@AfterEach