diff options
author | 2025-03-27 10:14:21 +0000 | |
---|---|---|
committer | 2025-03-27 10:14:21 +0000 | |
commit | c79c4234c525ae29590096d1f3f107813be1cfd0 (patch) | |
tree | c419db6108758fe0af312ba021491a1b37edd63e | |
parent | 87783dedf94407cef5c3552419a96297ef034871 (diff) | |
parent | 8a9d055c88f63c651c7574dadd24c2679e6467b2 (diff) |
Merge "Fix NullPointerException for cm handle state metrics"
5 files changed, 195 insertions, 103 deletions
diff --git a/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java b/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java index 6782669db2..6bf3f87d17 100644 --- a/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java +++ b/cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2025 Nordix Foundation. + * Copyright (C) 2023-2025 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. @@ -20,11 +20,9 @@ package org.onap.cps.config; -import com.hazelcast.map.IMap; import io.github.mweirauch.micrometer.jvm.extras.ProcessMemoryMetrics; import io.github.mweirauch.micrometer.jvm.extras.ProcessThreadMetrics; import io.micrometer.core.aop.TimedAspect; -import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.binder.MeterBinder; import lombok.RequiredArgsConstructor; @@ -36,10 +34,6 @@ import org.springframework.context.annotation.Configuration; @RequiredArgsConstructor public class MicroMeterConfig { - private static final String STATE_TAG = "state"; - private static final String CM_HANDLE_STATE_GAUGE = "cps_ncmp_inventory_cm_handles_by_state"; - final IMap<String, Integer> cmHandlesByState; - @Bean public TimedAspect timedAspect(final MeterRegistry meterRegistry) { return new TimedAspect(meterRegistry); @@ -57,79 +51,4 @@ public class MicroMeterConfig { return new ProcessThreadMetrics(); } - /** - * Register gauge metric for cm handles with state 'advised'. - * - * @param meterRegistry meter registry - * @return cm handle state gauge - */ - @Bean - public Gauge advisedCmHandles(final MeterRegistry meterRegistry) { - return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, - value -> cmHandlesByState.get("advisedCmHandlesCount")) - .tag(STATE_TAG, "ADVISED") - .description("Current number of cm handles in advised state") - .register(meterRegistry); - } - - /** - * Register gauge metric for cm handles with state 'ready'. - * - * @param meterRegistry meter registry - * @return cm handle state gauge - */ - @Bean - public Gauge readyCmHandles(final MeterRegistry meterRegistry) { - return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, - value -> cmHandlesByState.get("readyCmHandlesCount")) - .tag(STATE_TAG, "READY") - .description("Current number of cm handles in ready state") - .register(meterRegistry); - } - - /** - * Register gauge metric for cm handles with state 'locked'. - * - * @param meterRegistry meter registry - * @return cm handle state gauge - */ - @Bean - public Gauge lockedCmHandles(final MeterRegistry meterRegistry) { - return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, - value -> cmHandlesByState.get("lockedCmHandlesCount")) - .tag(STATE_TAG, "LOCKED") - .description("Current number of cm handles in locked state") - .register(meterRegistry); - } - - /** - * Register gauge metric for cm handles with state 'deleting'. - * - * @param meterRegistry meter registry - * @return cm handle state gauge - */ - @Bean - public Gauge deletingCmHandles(final MeterRegistry meterRegistry) { - return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, - value -> cmHandlesByState.get("deletingCmHandlesCount")) - .tag(STATE_TAG, "DELETING") - .description("Current number of cm handles in deleting state") - .register(meterRegistry); - } - - /** - * Register gauge metric for cm handles with state 'deleted'. - * - * @param meterRegistry meter registry - * @return cm handle state gauge - */ - @Bean - public Gauge deletedCmHandles(final MeterRegistry meterRegistry) { - return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, - value -> cmHandlesByState.get("deletedCmHandlesCount")) - .tag(STATE_TAG, "DELETED") - .description("Number of cm handles that have been deleted since the application started") - .register(meterRegistry); - } - } diff --git a/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy b/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy index faef32b04b..29cb65cfbb 100644 --- a/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy +++ b/cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2023-2025 Nordix Foundation. + * Copyright (C) 2023-2025 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. @@ -20,14 +20,12 @@ package org.onap.cps.config -import com.hazelcast.map.IMap import io.micrometer.core.instrument.simple.SimpleMeterRegistry import spock.lang.Specification class MicroMeterConfigSpec extends Specification { - def cmHandlesByState = Mock(IMap) - def objectUnderTest = new MicroMeterConfig(cmHandlesByState) + def objectUnderTest = new MicroMeterConfig() def simpleMeterRegistry = new SimpleMeterRegistry() def 'Creating a timed aspect.'() { @@ -42,20 +40,4 @@ class MicroMeterConfigSpec extends Specification { assert objectUnderTest.processThreadMetrics() != null } - def 'Creating gauges for cm handle states.'() { - given: 'cache returns value for each state' - cmHandlesByState.get(_) >> 1 - when: 'gauges for each state are created' - objectUnderTest.advisedCmHandles(simpleMeterRegistry) - objectUnderTest.readyCmHandles(simpleMeterRegistry) - objectUnderTest.lockedCmHandles(simpleMeterRegistry) - objectUnderTest.deletingCmHandles(simpleMeterRegistry) - objectUnderTest.deletedCmHandles(simpleMeterRegistry) - then: 'each state has the correct value when queried' - ['ADVISED', 'READY', 'LOCKED', 'DELETING', 'DELETED'].each { state -> - def gaugeValue = simpleMeterRegistry.get(objectUnderTest.CM_HANDLE_STATE_GAUGE).tag('state',state).gauge().value() - assert gaugeValue == 1 - } - } - } diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CmHandleStateGaugeConfig.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CmHandleStateGaugeConfig.java new file mode 100644 index 0000000000..f63a1bf67c --- /dev/null +++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/config/CmHandleStateGaugeConfig.java @@ -0,0 +1,114 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.config; + +import com.hazelcast.map.IMap; +import io.micrometer.core.instrument.Gauge; +import io.micrometer.core.instrument.MeterRegistry; +import lombok.RequiredArgsConstructor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.DependsOn; + +@Configuration +@RequiredArgsConstructor +@DependsOn("cmHandleStateMonitor") +public class CmHandleStateGaugeConfig { + + private static final String STATE_TAG = "state"; + private static final String CM_HANDLE_STATE_GAUGE = "cps_ncmp_inventory_cm_handles_by_state"; + private final IMap<String, Integer> cmHandlesByState; + + /** + * Register gauge metric for cm handles with state 'advised'. + * + * @param meterRegistry meter registry + * @return cm handle state gauge + */ + @Bean + public Gauge advisedCmHandles(final MeterRegistry meterRegistry) { + return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, + value -> cmHandlesByState.get("advisedCmHandlesCount")) + .tag(STATE_TAG, "ADVISED") + .description("Current number of cm handles in advised state") + .register(meterRegistry); + } + + /** + * Register gauge metric for cm handles with state 'ready'. + * + * @param meterRegistry meter registry + * @return cm handle state gauge + */ + @Bean + public Gauge readyCmHandles(final MeterRegistry meterRegistry) { + return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, + value -> cmHandlesByState.get("readyCmHandlesCount")) + .tag(STATE_TAG, "READY") + .description("Current number of cm handles in ready state") + .register(meterRegistry); + } + + /** + * Register gauge metric for cm handles with state 'locked'. + * + * @param meterRegistry meter registry + * @return cm handle state gauge + */ + @Bean + public Gauge lockedCmHandles(final MeterRegistry meterRegistry) { + return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, + value -> cmHandlesByState.get("lockedCmHandlesCount")) + .tag(STATE_TAG, "LOCKED") + .description("Current number of cm handles in locked state") + .register(meterRegistry); + } + + /** + * Register gauge metric for cm handles with state 'deleting'. + * + * @param meterRegistry meter registry + * @return cm handle state gauge + */ + @Bean + public Gauge deletingCmHandles(final MeterRegistry meterRegistry) { + return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, + value -> cmHandlesByState.get("deletingCmHandlesCount")) + .tag(STATE_TAG, "DELETING") + .description("Current number of cm handles in deleting state") + .register(meterRegistry); + } + + /** + * Register gauge metric for cm handles with state 'deleted'. + * + * @param meterRegistry meter registry + * @return cm handle state gauge + */ + @Bean + public Gauge deletedCmHandles(final MeterRegistry meterRegistry) { + return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState, + value -> cmHandlesByState.get("deletedCmHandlesCount")) + .tag(STATE_TAG, "DELETED") + .description("Number of cm handles that have been deleted since the application started") + .register(meterRegistry); + } +} 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 index 708508e9d8..3d8e8b6e31 100644 --- 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 @@ -1,6 +1,6 @@ /* * ============LICENSE_START======================================================= - * Copyright (C) 2025 Nordix Foundation. + * Copyright (C) 2025 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. @@ -31,12 +31,14 @@ import org.onap.cps.ncmp.api.inventory.models.CompositeState; import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService; import org.onap.cps.ncmp.impl.inventory.sync.lcm.LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair; import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent; +import org.springframework.context.annotation.DependsOn; import org.springframework.context.event.EventListener; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; @Component @RequiredArgsConstructor +@DependsOn("adminCacheConfig") @Slf4j public class CmHandleStateMonitor { private static final String METRIC_POSTFIX = "CmHandlesCount"; diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/CmHandleStateGaugeConfigSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/CmHandleStateGaugeConfigSpec.groovy new file mode 100644 index 0000000000..499f8b8e54 --- /dev/null +++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/config/CmHandleStateGaugeConfigSpec.groovy @@ -0,0 +1,75 @@ +/* + * ============LICENSE_START======================================================= + * Copyright (C) 2025 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. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.cps.ncmp.config + +import com.hazelcast.map.IMap +import io.micrometer.core.instrument.MeterRegistry +import io.micrometer.core.instrument.simple.SimpleMeterRegistry +import org.onap.cps.ncmp.impl.cache.AdminCacheConfig +import org.onap.cps.ncmp.impl.inventory.CmHandleQueryService +import org.onap.cps.ncmp.impl.inventory.sync.lcm.CmHandleStateMonitor +import org.spockframework.spring.SpringBean +import org.springframework.beans.factory.annotation.Autowired +import org.springframework.boot.test.context.SpringBootTest +import org.springframework.test.context.ContextConfiguration +import org.springframework.test.context.TestPropertySource +import spock.lang.Specification + +@SpringBootTest(classes = [CmHandleStateGaugeConfig, CmHandleStateMonitor, AdminCacheConfig]) +@ContextConfiguration(classes = [CpsApplicationContext]) +@TestPropertySource(properties = ["hazelcast.mode.kubernetes.enabled=false"]) +class CmHandleStateGaugeConfigSpec extends Specification { + + @Autowired + CpsApplicationContext cpsApplicationContext + @SpringBean + CmHandleQueryService cmHandleQueryService = Mock() + @SpringBean + MeterRegistry meterRegistry = Mock() + + def cmHandlesByState = Mock(IMap) + def objectUnderTest = new CmHandleStateGaugeConfig(cmHandlesByState) + def simpleMeterRegistry = new SimpleMeterRegistry() + + def 'Creating gauges for cm handle states.'() { + given: 'cache returns a test value (123) for each state' + cmHandlesByState.get(_) >> 123 + when: 'gauges for each state are created' + objectUnderTest.advisedCmHandles(simpleMeterRegistry) + objectUnderTest.readyCmHandles(simpleMeterRegistry) + objectUnderTest.lockedCmHandles(simpleMeterRegistry) + objectUnderTest.deletingCmHandles(simpleMeterRegistry) + objectUnderTest.deletedCmHandles(simpleMeterRegistry) + then: 'each state has the correct value when queried' + ['ADVISED', 'READY', 'LOCKED', 'DELETING', 'DELETED'].each { state -> + def gaugeValue = simpleMeterRegistry.get(objectUnderTest.CM_HANDLE_STATE_GAUGE).tag('state',state).gauge().value() + assert gaugeValue == 123 + } + } + + def 'Controlling order of bean initialization'() { + when: 'cm handle state gauge config is retrieved' + cpsApplicationContext.getCpsBean(CmHandleStateGaugeConfig.class) + then: 'cm handle state monitor should already be available' + cpsApplicationContext.getCpsBean(CmHandleStateMonitor.class) != null + } + +} |