aboutsummaryrefslogtreecommitdiffstats
path: root/cps-ncmp-service/src
diff options
context:
space:
mode:
authoremaclee <lee.anjella.macabuhay@est.tech>2024-12-11 14:58:25 +0000
committerLee Anjella Macabuhay <lee.anjella.macabuhay@est.tech>2025-01-07 12:02:29 +0000
commit0d61c432b2604f0459dea95bbd328c279b04fbef (patch)
tree3cd35b93ed02048699006082ad1086c986c0990f /cps-ncmp-service/src
parentffac9f27f7183d8e80aa74a7b113f68dcadb3f87 (diff)
Add gauge metric for NCMP "cmhandle states"
Issue-ID: CPS-2456 Change-Id: I1aebcc68dfdc9c48c230c74376742d67b05c0615 Signed-off-by: emaclee <lee.anjella.macabuhay@est.tech>
Diffstat (limited to 'cps-ncmp-service/src')
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java49
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java100
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java6
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy57
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy92
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy5
6 files changed, 305 insertions, 4 deletions
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java
new file mode 100644
index 0000000000..a29799b13f
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java
@@ -0,0 +1,49 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 Nordix Foundation
+ * ================================================================================
+ * 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=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.cache;
+
+import com.hazelcast.config.MapConfig;
+import com.hazelcast.map.IMap;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class AdminCacheConfig extends HazelcastCacheConfig {
+
+ private static final MapConfig adminCacheMapConfig = createMapConfig("adminCacheMapConfig");
+
+ /**
+ * Distributed instance admin cache map for cm handles by state for use of gauge metrics.
+ *
+ * @return configured map of cm handles by state.
+ */
+ @Bean
+ public IMap<String, Integer> cmHandlesByState() {
+ final IMap<String, Integer> cmHandlesByState = getOrCreateHazelcastInstance(adminCacheMapConfig).getMap(
+ "cmHandlesByState");
+ cmHandlesByState.putIfAbsent("advisedCmHandlesCount", 0);
+ cmHandlesByState.putIfAbsent("readyCmHandlesCount", 0);
+ cmHandlesByState.putIfAbsent("lockedCmHandlesCount", 0);
+ cmHandlesByState.putIfAbsent("deletingCmHandlesCount", 0);
+ cmHandlesByState.putIfAbsent("deletedCmHandlesCount", 0);
+ return cmHandlesByState;
+ }
+}
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java
new file mode 100644
index 0000000000..4fd752c0d1
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java
@@ -0,0 +1,100 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 Nordix Foundation.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.inventory.sync.lcm;
+
+import com.hazelcast.map.EntryProcessor;
+import com.hazelcast.map.IMap;
+import java.util.Collection;
+import java.util.Map;
+import lombok.RequiredArgsConstructor;
+import org.onap.cps.ncmp.api.inventory.models.CompositeState;
+import org.onap.cps.ncmp.impl.inventory.models.CmHandleState;
+import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
+
+@Component
+@RequiredArgsConstructor
+public class CmHandleStateMonitor {
+
+ private static final String METRIC_POSTFIX = "CmHandlesCount";
+ final IMap<String, Integer> cmHandlesByState;
+
+ /**
+ * Asynchronously update the cm handle state metrics.
+ *
+ * @param cmHandleTransitionPairs cm handle transition pairs
+ */
+ @Async
+ public void updateCmHandleStateMetrics(final Collection<CmHandleTransitionPair>
+ cmHandleTransitionPairs) {
+ cmHandleTransitionPairs.forEach(this::updateMetricWithStateChange);
+ }
+
+ private void updateMetricWithStateChange(final CmHandleTransitionPair cmHandleTransitionPair) {
+ final CmHandleState targetCmHandleState = cmHandleTransitionPair.getTargetYangModelCmHandle()
+ .getCompositeState().getCmHandleState();
+ if (isNew(cmHandleTransitionPair.getCurrentYangModelCmHandle().getCompositeState())) {
+ updateTargetStateCount(targetCmHandleState);
+ } else {
+ final CmHandleState previousCmHandleState = cmHandleTransitionPair.getCurrentYangModelCmHandle()
+ .getCompositeState().getCmHandleState();
+ updatePreviousStateCount(previousCmHandleState);
+ updateTargetStateCount(targetCmHandleState);
+ }
+ }
+
+ private void updatePreviousStateCount(final CmHandleState previousCmHandleState) {
+ final String keyName = previousCmHandleState.name().toLowerCase() + METRIC_POSTFIX;
+ cmHandlesByState.executeOnKey(keyName, new DecreasingEntryProcessor());
+ }
+
+ private void updateTargetStateCount(final CmHandleState targetCmHandleState) {
+ final String keyName = targetCmHandleState.name().toLowerCase() + METRIC_POSTFIX;
+ cmHandlesByState.executeOnKey(keyName, new IncreasingEntryProcessor());
+ }
+
+ private boolean isNew(final CompositeState existingCompositeState) {
+ return (existingCompositeState == null);
+ }
+
+ static class DecreasingEntryProcessor implements EntryProcessor<String, Integer, Void> {
+ @Override
+ public Void process(final Map.Entry<String, Integer> entry) {
+ final int currentValue = entry.getValue();
+ if (currentValue > 0) {
+ entry.setValue(currentValue - 1);
+ }
+ return null;
+ }
+ }
+
+ static class IncreasingEntryProcessor implements EntryProcessor<String, Integer, Void> {
+ @Override
+ public Void process(final Map.Entry<String, Integer> entry) {
+ final int currentValue = entry.getValue();
+ entry.setValue(currentValue + 1);
+ return null;
+ }
+ }
+
+
+} \ No newline at end of file
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java
index e9bd37219a..3e6597ea39 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImpl.java
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2024 Nordix Foundation
+ * Copyright (C) 2022-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -51,6 +51,7 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
private final InventoryPersistence inventoryPersistence;
private final LcmEventsCmHandleStateHandlerAsyncHelper lcmEventsCmHandleStateHandlerAsyncHelper;
+ private final CmHandleStateMonitor cmHandleStateMonitor;
@Override
@Timed(value = "cps.ncmp.cmhandle.state.update.batch",
@@ -60,6 +61,7 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
prepareCmHandleTransitionBatch(cmHandleStatePerCmHandle);
persistCmHandleBatch(cmHandleTransitionPairs);
lcmEventsCmHandleStateHandlerAsyncHelper.publishLcmEventBatchAsynchronously(cmHandleTransitionPairs);
+ cmHandleStateMonitor.updateCmHandleStateMetrics(cmHandleTransitionPairs);
}
@Override
@@ -168,7 +170,7 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
@Getter
@Setter
@NoArgsConstructor
- static class CmHandleTransitionPair {
+ public static class CmHandleTransitionPair {
private YangModelCmHandle currentYangModelCmHandle;
private YangModelCmHandle targetYangModelCmHandle;
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy
new file mode 100644
index 0000000000..9b9603369d
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy
@@ -0,0 +1,57 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 Nordix Foundation.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.cache
+
+import com.hazelcast.core.Hazelcast
+import com.hazelcast.map.IMap
+import org.springframework.beans.factory.annotation.Autowired
+import org.springframework.boot.test.context.SpringBootTest
+import org.springframework.test.context.ContextConfiguration;
+import spock.lang.Specification;
+
+@SpringBootTest
+@ContextConfiguration(classes = [AdminCacheConfig])
+class AdminCacheConfigSpec extends Specification {
+
+ @Autowired
+ IMap<String, Integer> cmHandlesByState
+
+ def cleanupSpec() {
+ Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').shutdown()
+ }
+
+ def 'Hazelcast cache for cm handle by state gauge'() {
+ expect: 'system is able to create an instance of the cm handle by state cache'
+ assert null != cmHandlesByState
+ and: 'there is at least 1 instance'
+ assert Hazelcast.allHazelcastInstances.size() > 0
+ and: 'Hazelcast cache instance for cm handle by state is present'
+ assert Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').getMap('cmHandlesByState') != null
+ and: 'the cache already contains 5 entries, an entry for each state'
+ def cmHandleByState = Hazelcast.getHazelcastInstanceByName('cps-and-ncmp-hazelcast-instance-test-config').getMap('cmHandlesByState')
+ assert cmHandleByState.size() == 5
+ assert cmHandleByState.containsKey('advisedCmHandlesCount')
+ assert cmHandleByState.containsKey('lockedCmHandlesCount')
+ assert cmHandleByState.containsKey('readyCmHandlesCount')
+ assert cmHandleByState.containsKey('deletingCmHandlesCount')
+ assert cmHandleByState.containsKey('deletedCmHandlesCount')
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy
new file mode 100644
index 0000000000..2833ca838f
--- /dev/null
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy
@@ -0,0 +1,92 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2025 Nordix Foundation.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+package org.onap.cps.ncmp.impl.inventory.sync.lcm
+
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.ADVISED
+import static org.onap.cps.ncmp.impl.inventory.models.CmHandleState.READY
+
+import com.hazelcast.core.Hazelcast
+import com.hazelcast.map.IMap
+import org.onap.cps.ncmp.api.inventory.models.CompositeState
+import org.onap.cps.ncmp.impl.inventory.models.YangModelCmHandle
+import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor.DecreasingEntryProcessor
+import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor.IncreasingEntryProcessor
+import spock.lang.Shared
+import spock.lang.Specification;
+
+class CmHandleStateMonitorSpec extends Specification {
+
+ def cmHandlesByState = Mock(IMap)
+ def objectUnderTest = new CmHandleStateMonitor(cmHandlesByState)
+
+ @Shared
+ def entryProcessingMap = Hazelcast.newHazelcastInstance().getMap('entryProcessingMap')
+
+ def setup() {
+ entryProcessingMap.put('zeroCmHandlesCount', 0)
+ entryProcessingMap.put('tenCmHandlesCount', 10)
+ }
+
+ def cleanupSpec() {
+ Hazelcast.shutdownAll()
+ }
+
+ def 'Update cm handle state metric'() {
+ given: 'a collection of cm handle state pair'
+ def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair()
+ cmHandleTransitionPair.currentYangModelCmHandle = new YangModelCmHandle(compositeState: new CompositeState(cmHandleState: ADVISED))
+ cmHandleTransitionPair.targetYangModelCmHandle = new YangModelCmHandle(compositeState: new CompositeState(cmHandleState: READY))
+ when: 'method to update cm handle state metrics is called'
+ objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair])
+ then: 'cm handle by state cache map is called once for current and target state for entry processing'
+ 1 * cmHandlesByState.executeOnKey('advisedCmHandlesCount', _)
+ 1 * cmHandlesByState.executeOnKey('readyCmHandlesCount', _)
+ }
+
+ def 'Updating cm handle state metric with no previous state'() {
+ given: 'a collection of cm handle state pair wherein current state is null'
+ def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair()
+ cmHandleTransitionPair.currentYangModelCmHandle = new YangModelCmHandle(compositeState: null)
+ cmHandleTransitionPair.targetYangModelCmHandle = new YangModelCmHandle(compositeState: new CompositeState(cmHandleState: ADVISED))
+ when: 'method to update cm handle state metrics is called'
+ objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair])
+ then: 'cm handle by state cache map is called only once'
+ 1 * cmHandlesByState.executeOnKey(_, _)
+ }
+
+ def 'Applying decreasing entry processor to a key on map where #scenario'() {
+ when: 'decreasing entry processor is applied to subtract 1 to the value'
+ entryProcessingMap.executeOnKey(key, new DecreasingEntryProcessor())
+ then: 'the new value is as expected'
+ assert entryProcessingMap.get(key) == expectedValue
+ where: 'the following data is used'
+ scenario | key || expectedValue
+ 'current value of count is zero'| 'zeroCmHandlesCount'|| 0
+ 'current value of count is >0' | 'tenCmHandlesCount' || 9
+ }
+
+ def 'Applying increasing entry processor to a key on map'() {
+ when: 'increasing entry processor is applied to add 1 to the value'
+ entryProcessingMap.executeOnKey('tenCmHandlesCount', new IncreasingEntryProcessor())
+ then: 'the new value is as expected'
+ assert entryProcessingMap.get('tenCmHandlesCount') == 11
+ }
+}
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy
index 4b676e1b4c..5e614a6f88 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/LcmEventsCmHandleStateHandlerImplSpec.groovy
@@ -1,6 +1,6 @@
/*
* ============LICENSE_START=======================================================
- * Copyright (C) 2022-2024 Nordix Foundation
+ * Copyright (C) 2022-2025 Nordix Foundation
* ================================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -56,9 +56,10 @@ class LcmEventsCmHandleStateHandlerImplSpec extends Specification {
def mockInventoryPersistence = Mock(InventoryPersistence)
def mockLcmEventsCreator = Mock(LcmEventsCreator)
def mockLcmEventsService = Mock(LcmEventsService)
+ def mockCmHandleStateMonitor = Mock(CmHandleStateMonitor)
def lcmEventsCmHandleStateHandlerAsyncHelper = new LcmEventsCmHandleStateHandlerAsyncHelper(mockLcmEventsCreator, mockLcmEventsService)
- def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, lcmEventsCmHandleStateHandlerAsyncHelper)
+ def objectUnderTest = new LcmEventsCmHandleStateHandlerImpl(mockInventoryPersistence, lcmEventsCmHandleStateHandlerAsyncHelper, mockCmHandleStateMonitor)
def cmHandleId = 'cmhandle-id-1'
def compositeState