From 8eadcb635a4d3dfaa7f2ac83f4081120a62e1781 Mon Sep 17 00:00:00 2001 From: "halil.cakal" Date: Thu, 29 Sep 2022 09:47:09 +0100 Subject: Metrics and statistics for A1 PMS Enable app metrics to be collected by Prometheus Patch set 2: Remove hardcoded defines ccsdk.sli dependency Issue-ID: CCSDK-3766 Change-Id: I58f05390007b74e58427b9be2711912c551d6e1e Signed-off-by: halil.cakal --- a1-policy-management/config/prometheus.yml | 37 +++++ a1-policy-management/pom.xml | 8 ++ .../a1policymanagementservice/BeanFactory.java | 1 - .../controllers/v2/PolicyController.java | 4 - .../tasks/RefreshCounterTask.java | 78 +++++++++++ .../tasks/RicSupervision.java | 4 +- .../tasks/RefreshCounterTaskTest.java | 156 +++++++++++++++++++++ .../tasks/RicSupervisionTest.java | 1 - 8 files changed, 281 insertions(+), 8 deletions(-) create mode 100644 a1-policy-management/config/prometheus.yml create mode 100644 a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTask.java create mode 100644 a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTaskTest.java (limited to 'a1-policy-management') diff --git a/a1-policy-management/config/prometheus.yml b/a1-policy-management/config/prometheus.yml new file mode 100644 index 00000000..9219c7f4 --- /dev/null +++ b/a1-policy-management/config/prometheus.yml @@ -0,0 +1,37 @@ +# +# ============LICENSE_START======================================================= +# ONAP : ccsdk oran +# ================================================================================ +# Copyright (C) 2022 Nordix Foundation. 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. +# +# SPDX-License-Identifier: Apache-2.0 +# ============LICENSE_END========================================================= +# + +# Sample Prometheus config +# This assumes that your Prometheus instance can access this application on localhost:8081 +# host.docker.internal could be overridden as per the application's end-point e.g. localhost + +global: + scrape_interval: 15s # Set the scrape interval to every 15 seconds. Default is every 1 minute. + evaluation_interval: 15s # Evaluate rules every 15 seconds. The default is every 1 minute. + # scrape_timeout is set to the global default (10s). + +scrape_configs: + - job_name: 'A1 PMS scrape' + metrics_path: '/actuator/prometheus' + scrape_interval: 15s + static_configs: + - targets: ['host.docker.internal:8081'] diff --git a/a1-policy-management/pom.xml b/a1-policy-management/pom.xml index 170d8530..d47019b6 100644 --- a/a1-policy-management/pom.xml +++ b/a1-policy-management/pom.xml @@ -137,6 +137,14 @@ spring-boot-starter-actuator runtime + + io.micrometer + micrometer-registry-prometheus + + + org.springframework.boot + spring-boot-starter-aop + io.springfox diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java index bf161954..8fc8bc8c 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/BeanFactory.java @@ -21,7 +21,6 @@ package org.onap.ccsdk.oran.a1policymanagementservice; import com.fasterxml.jackson.databind.ObjectMapper; - import org.apache.catalina.connector.Connector; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.clients.SecurityContext; diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java index 500ddd2a..ee2cae58 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/controllers/v2/PolicyController.java @@ -22,7 +22,6 @@ package org.onap.ccsdk.oran.a1policymanagementservice.controllers.v2; import com.google.gson.Gson; import com.google.gson.GsonBuilder; - import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.media.Content; @@ -30,15 +29,12 @@ import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.responses.ApiResponse; import io.swagger.v3.oas.annotations.responses.ApiResponses; import io.swagger.v3.oas.annotations.tags.Tag; - import java.lang.invoke.MethodHandles; import java.time.Instant; import java.util.ArrayList; import java.util.Collection; import java.util.List; - import lombok.Getter; - import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.controllers.VoidResponse; import org.onap.ccsdk.oran.a1policymanagementservice.exceptions.EntityNotFoundException; diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTask.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTask.java new file mode 100644 index 00000000..8eb8fbcb --- /dev/null +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTask.java @@ -0,0 +1,78 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2022 Nordix Foundation. 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.tasks; + +import io.micrometer.core.instrument.MeterRegistry; +import java.lang.invoke.MethodHandles; +import java.util.concurrent.atomic.AtomicLong; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Component; + +/** + * The aim is to collect statistical values from the A1 Policy Management Service. + * The counters are being updated every minute. + */ +@EnableScheduling +@Component +public class RefreshCounterTask { + + private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final Rics rics; + private final PolicyTypes policyTypes; + private final Policies policies; + + private final MeterRegistry meterRegistry; + + private final AtomicLong ricCount; + private final AtomicLong policyTypeCount; + private final AtomicLong policyCount; + + @Autowired + public RefreshCounterTask(Rics rics, PolicyTypes policyTypes, Policies policies, MeterRegistry meterRegistry) { + this.rics = rics; + this.policyTypes = policyTypes; + this.policies = policies; + this.meterRegistry = meterRegistry; + + ricCount = meterRegistry.gauge("total_ric_count", new AtomicLong(0)); + policyTypeCount = meterRegistry.gauge("total_policy_type_count", new AtomicLong(0)); + policyCount = meterRegistry.gauge("total_policy_count", new AtomicLong(0)); + } + + /** + * Every minute, updates counters for statistical purposes. + */ + @Scheduled(fixedRate = 1000 * 60) + public void checkAllCounters() { + logger.trace("Checking counters starting..."); + ricCount.set(rics.size()); + policyCount.set(policies.size()); + policyTypeCount.set(policyTypes.size()); + } +} diff --git a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java index e3edaf44..7a5f73d4 100644 --- a/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java +++ b/a1-policy-management/src/main/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervision.java @@ -21,7 +21,6 @@ package org.onap.ccsdk.oran.a1policymanagementservice.tasks; import java.util.Collection; - import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1Client; import org.onap.ccsdk.oran.a1policymanagementservice.clients.A1ClientFactory; import org.onap.ccsdk.oran.a1policymanagementservice.clients.AsyncRestClientFactory; @@ -41,7 +40,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; - import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -181,6 +179,7 @@ public class RicSupervision { return Mono.error(new SynchNeededException(ric)); } } + return Mono.just(ric); } } @@ -204,6 +203,7 @@ public class RicSupervision { return Mono.error(new SynchNeededException(ric)); } } + return Mono.just(ric); } diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTaskTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTaskTest.java new file mode 100644 index 00000000..3adfb316 --- /dev/null +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RefreshCounterTaskTest.java @@ -0,0 +1,156 @@ +/*- + * ========================LICENSE_START================================= + * ONAP : ccsdk oran + * ====================================================================== + * Copyright (C) 2022 Nordix Foundation. 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.tasks; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.spy; + +import io.micrometer.prometheus.PrometheusConfig; +import io.micrometer.prometheus.PrometheusMeterRegistry; +import java.time.Instant; +import java.util.Arrays; +import java.util.Vector; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; +import org.onap.ccsdk.oran.a1policymanagementservice.configuration.ApplicationConfig; +import org.onap.ccsdk.oran.a1policymanagementservice.configuration.RicConfig; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policies; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.Policy; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyType; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.PolicyTypes; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.Ric; +import org.onap.ccsdk.oran.a1policymanagementservice.repository.Rics; + +@ExtendWith(MockitoExtension.class) +public class RefreshCounterTaskTest { + + private static final String POLICY_TYPE_1_NAME = "type1"; + private static final PolicyType POLICY_TYPE_1 = PolicyType.builder().id(POLICY_TYPE_1_NAME).schema("").build(); + + private static final Ric RIC_1 = new Ric(RicConfig.builder().ricId("ric_1").baseUrl("baseUrl1") + .managedElementIds(new Vector(Arrays.asList("kista_1", "kista_2"))).controllerName("controllerName") + .build()); + + private static final String POLICY_1_ID = "policyId1"; + private static final Policy POLICY_1 = Policy.builder().id(POLICY_1_ID).json("").ownerServiceId("service") + .ric(RIC_1).type(POLICY_TYPE_1).lastModified(Instant.now()).isTransient(false) + .statusNotificationUri("statusNotificationUri").build(); + + private PrometheusMeterRegistry prometheusMeterRegistry = new PrometheusMeterRegistry(PrometheusConfig.DEFAULT); + private final ApplicationConfig appConfig = new ApplicationConfig(); + + private PolicyTypes types; + private Policies policies; + private Rics rics = new Rics(); + + @BeforeEach + void init() { + types = new PolicyTypes(appConfig); + policies = new Policies(appConfig); + + rics.clear(); + RIC_1.setState(Ric.RicState.AVAILABLE); + RIC_1.clearSupportedPolicyTypes(); + } + + @Test + void testCounters_whenNeitherChangedPoliciesNorPolicyTypes() { + RIC_1.setState(Ric.RicState.AVAILABLE); + RIC_1.addSupportedPolicyType(POLICY_TYPE_1); + rics.put(RIC_1); + + types.put(POLICY_TYPE_1); + + policies.put(POLICY_1); + + RefreshCounterTask refreshCounterTaskUnderTest = spy(createRefreshCounterTask()); + refreshCounterTaskUnderTest.checkAllCounters(); + + assertThat(prometheusMeterRegistry.get("total_ric_count").gauge().value()).isEqualTo(1); + assertThat(prometheusMeterRegistry.get("total_policy_type_count").gauge().value()).isEqualTo(1); + assertThat(prometheusMeterRegistry.get("total_policy_count").gauge().value()).isEqualTo(1); + } + + @Test + void testCounters_whenChangedPoliciesAndNoChangedPolicyTypes() { + RIC_1.setState(Ric.RicState.AVAILABLE); + RIC_1.addSupportedPolicyType(POLICY_TYPE_1); + rics.put(RIC_1); + + types.put(POLICY_TYPE_1); + + policies.put(POLICY_1); + + String POLICY_2_ID = "policyId2"; + Policy POLICY_2 = Policy.builder() // + .id(POLICY_2_ID) // + .json("") // + .ownerServiceId("service") // + .ric(RIC_1) // + .type(POLICY_TYPE_1) // + .lastModified(Instant.now()) // + .isTransient(false) // + .statusNotificationUri("statusNotificationUri") // + .build(); + + policies.put(POLICY_2); + + RefreshCounterTask refreshCounterTaskUnderTest = spy(createRefreshCounterTask()); + refreshCounterTaskUnderTest.checkAllCounters(); + + assertThat(prometheusMeterRegistry.get("total_ric_count").gauge().value()).isEqualTo(1); + assertThat(prometheusMeterRegistry.get("total_policy_type_count").gauge().value()).isEqualTo(1); + assertThat(prometheusMeterRegistry.get("total_policy_count").gauge().value()).isEqualTo(2); + } + + @Test + void testCounters_whenNoChangedPoliciesAndChangedPolicyTypes() { + RIC_1.setState(Ric.RicState.AVAILABLE); + + String POLICY_TYPE_2_NAME = "type2"; + PolicyType POLICY_TYPE_2 = PolicyType.builder() // + .id(POLICY_TYPE_2_NAME) // + .schema("") // + .build(); + + RIC_1.addSupportedPolicyType(POLICY_TYPE_1); + RIC_1.addSupportedPolicyType(POLICY_TYPE_2); + rics.put(RIC_1); + + types.put(POLICY_TYPE_1); + types.put(POLICY_TYPE_2); + + policies.put(POLICY_1); + + RefreshCounterTask refreshCounterTaskUnderTest = spy(createRefreshCounterTask()); + refreshCounterTaskUnderTest.checkAllCounters(); + + assertThat(prometheusMeterRegistry.get("total_ric_count").gauge().value()).isEqualTo(1); + assertThat(prometheusMeterRegistry.get("total_policy_type_count").gauge().value()).isEqualTo(2); + assertThat(prometheusMeterRegistry.get("total_policy_count").gauge().value()).isEqualTo(1); + } + + private RefreshCounterTask createRefreshCounterTask() { + return new RefreshCounterTask(rics, types, policies, prometheusMeterRegistry); + } +} diff --git a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervisionTest.java b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervisionTest.java index b2bf58e4..d9b36d9c 100644 --- a/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervisionTest.java +++ b/a1-policy-management/src/test/java/org/onap/ccsdk/oran/a1policymanagementservice/tasks/RicSupervisionTest.java @@ -34,7 +34,6 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; import java.util.Vector; - import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -- cgit 1.2.3-korg