2 * ========================LICENSE_START=================================
4 * ======================================================================
5 * Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved.
6 * ======================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ========================LICENSE_END===================================
20 package org.onap.ccsdk.oran.a1policymanagementservice.configuration;
22 import io.micrometer.observation.ObservationPredicate;
23 import io.micrometer.observation.ObservationRegistry;
24 import io.opentelemetry.api.OpenTelemetry;
25 import io.opentelemetry.exporter.otlp.http.trace.OtlpHttpSpanExporter;
26 import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter;
27 import io.opentelemetry.instrumentation.spring.webflux.v5_3.SpringWebfluxTelemetry;
28 import io.opentelemetry.sdk.extension.trace.jaeger.sampler.JaegerRemoteSampler;
29 import io.opentelemetry.sdk.trace.samplers.Sampler;
31 import java.time.Duration;
32 import javax.annotation.PostConstruct;
34 import org.slf4j.Logger;
35 import org.slf4j.LoggerFactory;
36 import org.springframework.beans.factory.annotation.Value;
37 import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
38 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
39 import org.springframework.context.annotation.Bean;
40 import org.springframework.context.annotation.ComponentScan;
41 import org.springframework.context.annotation.Configuration;
42 import org.springframework.http.server.observation.ServerRequestObservationContext;
43 import org.springframework.boot.actuate.autoconfigure.observation.ObservationRegistryCustomizer;
44 import org.springframework.util.AntPathMatcher;
45 import org.springframework.util.PathMatcher;
48 @ComponentScan(basePackages = {"org.onap.ccsdk.oran.a1policymanagementservice"})
49 public class OtelConfig {
50 private static final Logger logger = LoggerFactory.getLogger(OtelConfig.class);
52 public static final int JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND = 30;
54 @Value("${spring.application.name}")
55 private String serviceId;
57 @Value("${otel.exporter.otlp.traces.endpoint}")
58 private String tracingExporterEndpointUrl;
60 @Value("${otel.tracing.sampler.jaeger-remote.endpoint}")
61 private String jaegerRemoteSamplerUrl;
63 @Value("${otel.exporter.otlp.traces.protocol}")
64 private String tracingProtocol;
66 @Value("${otel.sdk.disabled}")
67 private boolean tracingDisabled;
69 @Value("${otel.sdk.south}")
70 private boolean southTracingEnabled;
73 public void checkTracingConfig() {
74 logger.info("Application Yaml Tracing Enabled: " + !tracingDisabled);
77 public boolean isTracingEnabled() {
78 return !tracingDisabled;
81 public boolean isSouthTracingEnabled() {
82 return isTracingEnabled() && southTracingEnabled;
86 @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false)
87 @ConditionalOnExpression("'grpc'.equals('${otel.exporter.otlp.traces.protocol}')")
88 public OtlpGrpcSpanExporter otlpExporterGrpc() {
89 return OtlpGrpcSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build();
93 @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false)
94 @ConditionalOnExpression("'http'.equals('${otel.exporter.otlp.traces.protocol}')")
95 public OtlpHttpSpanExporter otlpExporterHttp() {
96 return OtlpHttpSpanExporter.builder().setEndpoint(tracingExporterEndpointUrl).build();
100 @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false)
101 public JaegerRemoteSampler jaegerRemoteSampler() {
102 return JaegerRemoteSampler.builder().setEndpoint(jaegerRemoteSamplerUrl)
103 .setPollingInterval(Duration.ofSeconds(JAEGER_REMOTE_SAMPLER_POLLING_INTERVAL_IN_SECOND))
104 .setInitialSampler(Sampler.alwaysOff()).setServiceName(serviceId).build();
108 @ConditionalOnExpression("!${otel.sdk.disabled:true} and ${otel.sdk.south:true}")
109 public SpringWebfluxTelemetry webfluxTelemetry (OpenTelemetry openTelemetry) {
110 return SpringWebfluxTelemetry.builder(openTelemetry).build();
114 @ConditionalOnProperty(prefix = "otel.sdk", name = "disabled", havingValue = "false", matchIfMissing = false)
115 ObservationRegistryCustomizer<ObservationRegistry> skipActuatorEndpointsFromObservation() {
116 PathMatcher pathMatcher = new AntPathMatcher("/");
118 registry.observationConfig().observationPredicate(observationPredicate(pathMatcher));
121 static ObservationPredicate observationPredicate(PathMatcher pathMatcher) {
122 return (name, context) -> {
123 if (context instanceof ServerRequestObservationContext observationContext) {
124 return !pathMatcher.match("/actuator/**", observationContext.getCarrier().getRequestURI());