aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java35
-rw-r--r--cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy3
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/cache/AdminCacheConfig.java10
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitor.java28
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java9
-rw-r--r--cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java39
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/cache/AdminCacheConfigSpec.groovy8
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/impl/inventory/sync/lcm/CmHandleStateMonitorSpec.groovy36
-rw-r--r--cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy6
-rw-r--r--docker-compose/config/grafana/lcm-state-dashboard.json562
-rw-r--r--docker-compose/docker-compose.yml1
11 files changed, 683 insertions, 54 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 39ed6ef5a7..de981164f5 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
@@ -32,8 +32,8 @@ import org.springframework.context.annotation.Configuration;
@RequiredArgsConstructor
public class MicroMeterConfig {
- private static final String TAG = "state";
- private static final String CMHANDLE_STATE_GAUGE = "cmHandlesByState";
+ private static final String STATE_TAG = "state";
+ private static final String CM_HANDLE_STATE_GAUGE = "cmHandlesByState";
final IMap<String, Integer> cmHandlesByState;
@Bean
@@ -49,9 +49,9 @@ public class MicroMeterConfig {
*/
@Bean
public Gauge advisedCmHandles(final MeterRegistry meterRegistry) {
- return Gauge.builder(CMHANDLE_STATE_GAUGE, cmHandlesByState,
+ return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState,
value -> cmHandlesByState.get("advisedCmHandlesCount"))
- .tag(TAG, "ADVISED")
+ .tag(STATE_TAG, "ADVISED")
.description("Current number of cmhandles in advised state")
.register(meterRegistry);
}
@@ -64,9 +64,9 @@ public class MicroMeterConfig {
*/
@Bean
public Gauge readyCmHandles(final MeterRegistry meterRegistry) {
- return Gauge.builder(CMHANDLE_STATE_GAUGE, cmHandlesByState,
+ return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState,
value -> cmHandlesByState.get("readyCmHandlesCount"))
- .tag(TAG, "READY")
+ .tag(STATE_TAG, "READY")
.description("Current number of cmhandles in ready state")
.register(meterRegistry);
}
@@ -79,9 +79,9 @@ public class MicroMeterConfig {
*/
@Bean
public Gauge lockedCmHandles(final MeterRegistry meterRegistry) {
- return Gauge.builder(CMHANDLE_STATE_GAUGE, cmHandlesByState,
+ return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState,
value -> cmHandlesByState.get("lockedCmHandlesCount"))
- .tag(TAG, "LOCKED")
+ .tag(STATE_TAG, "LOCKED")
.description("Current number of cmhandles in locked state")
.register(meterRegistry);
}
@@ -94,26 +94,11 @@ public class MicroMeterConfig {
*/
@Bean
public Gauge deletingCmHandles(final MeterRegistry meterRegistry) {
- return Gauge.builder(CMHANDLE_STATE_GAUGE, cmHandlesByState,
+ return Gauge.builder(CM_HANDLE_STATE_GAUGE, cmHandlesByState,
value -> cmHandlesByState.get("deletingCmHandlesCount"))
- .tag(TAG, "DELETING")
+ .tag(STATE_TAG, "DELETING")
.description("Current number of cmhandles 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(CMHANDLE_STATE_GAUGE, cmHandlesByState,
- value -> cmHandlesByState.get("deletedCmHandlesCount"))
- .tag(TAG, "DELETED")
- .description("Current number of cmhandles in deleted state")
- .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 67ca64624a..da3afc6f2c 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
@@ -43,9 +43,8 @@ class MicroMeterConfigSpec extends Specification {
objectUnderTest.readyCmHandles(simpleMeterRegistry)
objectUnderTest.lockedCmHandles(simpleMeterRegistry)
objectUnderTest.deletingCmHandles(simpleMeterRegistry)
- objectUnderTest.deletedCmHandles(simpleMeterRegistry)
then: 'each state has the correct value when queried'
- def states = ["ADVISED", "READY", "LOCKED", "DELETING", "DELETED"]
+ def states = ["ADVISED", "READY", "LOCKED", "DELETING"]
states.each { state ->
def gaugeValue = simpleMeterRegistry.get("cmHandlesByState").tag("state",state).gauge().value()
assert gaugeValue == 1
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
index a29799b13f..fe933d766f 100644
--- 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
@@ -28,7 +28,7 @@ import org.springframework.context.annotation.Configuration;
@Configuration
public class AdminCacheConfig extends HazelcastCacheConfig {
- private static final MapConfig adminCacheMapConfig = createMapConfig("adminCacheMapConfig");
+ private static final MapConfig cmHandleStateCacheMapConfig = createMapConfig("cmHandleStateCacheMapConfig");
/**
* Distributed instance admin cache map for cm handles by state for use of gauge metrics.
@@ -37,13 +37,7 @@ public class AdminCacheConfig extends HazelcastCacheConfig {
*/
@Bean
public IMap<String, Integer> cmHandlesByState() {
- final IMap<String, Integer> cmHandlesByState = getOrCreateHazelcastInstance(adminCacheMapConfig).getMap(
+ return getOrCreateHazelcastInstance(cmHandleStateCacheMapConfig).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
index 31270ca9fc..708508e9d8 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
@@ -25,18 +25,42 @@ import com.hazelcast.map.IMap;
import java.util.Collection;
import java.util.Map;
import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.onap.cps.ncmp.api.inventory.models.CmHandleState;
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.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
+@Slf4j
public class CmHandleStateMonitor {
-
private static final String METRIC_POSTFIX = "CmHandlesCount";
- final IMap<String, Integer> cmHandlesByState;
+
+ private final CmHandleQueryService cmHandleQueryService;
+ private final IMap<String, Integer> cmHandlesByState;
+
+ /**
+ * Method to initialise cm handle state monitor by querying the current state counts
+ * and storing them in the provided map. This method is triggered by NcmpInventoryModelOnboardingFinishedEvent.
+ *
+ * @param ncmpInventoryModelOnboardingFinishedEvent the event that triggers the initialization
+ */
+ @EventListener
+ public void initialiseCmHandleStateMonitor(
+ final NcmpInventoryModelOnboardingFinishedEvent ncmpInventoryModelOnboardingFinishedEvent) {
+ for (final CmHandleState cmHandleState : CmHandleState.values()) {
+ final String cmHandleStateAsString = cmHandleState.name().toLowerCase();
+ final String stateMetricKey = cmHandleStateAsString + METRIC_POSTFIX;
+ final int cmHandleCountForState = cmHandleQueryService.queryCmHandleIdsByState(cmHandleState).size();
+ cmHandlesByState.putIfAbsent(stateMetricKey, cmHandleCountForState);
+ log.info("Cm handle state monitor has set " + stateMetricKey + " to " + cmHandleCountForState);
+ }
+ }
/**
* Asynchronously update the cm handle state metrics.
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
index 58a5f553af..514d9b8fe4 100644
--- a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/init/InventoryModelLoader.java
@@ -30,11 +30,15 @@ import org.onap.cps.api.CpsDataService;
import org.onap.cps.api.CpsDataspaceService;
import org.onap.cps.api.CpsModuleService;
import org.onap.cps.init.AbstractModelLoader;
+import org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent;
+import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service;
@Slf4j
@Service
public class InventoryModelLoader extends AbstractModelLoader {
+
+ private final ApplicationEventPublisher applicationEventPublisher;
private static final String NEW_MODEL_FILE_NAME = "dmi-registry@2024-02-23.yang";
private static final String NEW_SCHEMA_SET_NAME = "dmi-registry-2024-02-23";
private static final String REGISTRY_DATANODE_NAME = "dmi-registry";
@@ -42,14 +46,17 @@ public class InventoryModelLoader extends AbstractModelLoader {
public InventoryModelLoader(final CpsDataspaceService cpsDataspaceService,
final CpsModuleService cpsModuleService,
final CpsAnchorService cpsAnchorService,
- final CpsDataService cpsDataService) {
+ final CpsDataService cpsDataService,
+ final ApplicationEventPublisher applicationEventPublisher) {
super(cpsDataspaceService, cpsModuleService, cpsAnchorService, cpsDataService);
+ this.applicationEventPublisher = applicationEventPublisher;
}
@Override
public void onboardOrUpgradeModel() {
updateInventoryModel();
log.info("Inventory Model updated successfully");
+ applicationEventPublisher.publishEvent(new NcmpInventoryModelOnboardingFinishedEvent(this));
}
private void updateInventoryModel() {
diff --git a/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java
new file mode 100644
index 0000000000..92d5e8241d
--- /dev/null
+++ b/cps-ncmp-service/src/main/java/org/onap/cps/ncmp/utils/events/NcmpInventoryModelOnboardingFinishedEvent.java
@@ -0,0 +1,39 @@
+/*
+ * ============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.utils.events;
+
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * Custom event triggered when the NCMP inventory model onboarding process is completed.
+ * Extends Spring's {@link ApplicationEvent} to be used within Spring's event-driven architecture.
+ */
+public class NcmpInventoryModelOnboardingFinishedEvent extends ApplicationEvent {
+
+ /**
+ * Creates a new instance of NcmpModelOnboardingFinishedEvent.
+ *
+ * @param source the object that is the source of the event (i.e. the source that completed the onboarding process)
+ */
+ public NcmpInventoryModelOnboardingFinishedEvent(final Object source) {
+ super(source);
+ }
+}
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
index 9b9603369d..a576865262 100644
--- 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
@@ -45,13 +45,5 @@ class AdminCacheConfigSpec extends Specification {
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
index 9fd40b9605..4d7c22a200 100644
--- 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
@@ -26,16 +26,19 @@ import static org.onap.cps.ncmp.api.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.CmHandleQueryService
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 org.onap.cps.ncmp.utils.events.NcmpInventoryModelOnboardingFinishedEvent
import spock.lang.Shared
import spock.lang.Specification;
class CmHandleStateMonitorSpec extends Specification {
- def cmHandlesByState = Mock(IMap)
- def objectUnderTest = new CmHandleStateMonitor(cmHandlesByState)
+ def mockCmHandlesByState = Mock(IMap)
+ def mockCmHandleQueryService = Mock(CmHandleQueryService)
+ def objectUnderTest = new CmHandleStateMonitor(mockCmHandleQueryService, mockCmHandlesByState)
@Shared
def entryProcessingMap = Hazelcast.newHazelcastInstance().getMap('entryProcessingMap')
@@ -49,6 +52,25 @@ class CmHandleStateMonitorSpec extends Specification {
Hazelcast.shutdownAll()
}
+ def 'Initialise cm handle state monitor: #scenario'() {
+ given: 'the query service returns a list of cm-handle ids for the given state'
+ mockCmHandleQueryService.queryCmHandleIdsByState(_) >> queryResult
+ and: 'a mocked NcmpModelOnboardingFinishedEvent is triggered'
+ def mockNcmpModelOnboardingFinishedEvent = Mock(NcmpInventoryModelOnboardingFinishedEvent)
+ when: 'the method to initialise cm handle state monitor is triggered by onboarding event'
+ objectUnderTest.initialiseCmHandleStateMonitor(mockNcmpModelOnboardingFinishedEvent)
+ then: 'metrics map is called correct number of times for each state except DELETED, with expected value'
+ 1 * mockCmHandlesByState.putIfAbsent("advisedCmHandlesCount", expectedValue)
+ 1 * mockCmHandlesByState.putIfAbsent("readyCmHandlesCount", expectedValue)
+ 1 * mockCmHandlesByState.putIfAbsent("lockedCmHandlesCount", expectedValue)
+ 1 * mockCmHandlesByState.putIfAbsent("deletingCmHandlesCount", expectedValue)
+ where:
+ scenario | queryResult || expectedValue
+ 'query service returns zero cm handle id'| [] || 0
+ 'query service returns 1 cm handle id' | ['someId'] || 1
+ }
+
+
def 'Update cm handle state metric'() {
given: 'a collection of cm handle state pair'
def cmHandleTransitionPair = new LcmEventsCmHandleStateHandlerImpl.CmHandleTransitionPair()
@@ -57,19 +79,19 @@ class CmHandleStateMonitorSpec extends Specification {
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', _)
+ 1 * mockCmHandlesByState.executeOnKey('advisedCmHandlesCount', _)
+ 1 * mockCmHandlesByState.executeOnKey('readyCmHandlesCount', _)
}
- def 'Updating cm handle state metric with no previous state'() {
+ def 'Update 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'
+ when: 'updating cm handle state metrics'
objectUnderTest.updateCmHandleStateMetrics([cmHandleTransitionPair])
then: 'cm handle by state cache map is called only once'
- 1 * cmHandlesByState.executeOnKey(_, _)
+ 1 * mockCmHandlesByState.executeOnKey(_, _)
}
def 'Applying decreasing entry processor to a key on map where #scenario'() {
diff --git a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
index ffd1d89fe1..dc6ec4120b 100644
--- a/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
+++ b/cps-ncmp-service/src/test/groovy/org/onap/cps/ncmp/init/InventoryModelLoaderSpec.groovy
@@ -30,6 +30,7 @@ import org.onap.cps.api.CpsModuleService
import org.onap.cps.api.model.Dataspace
import org.slf4j.LoggerFactory
import org.springframework.boot.context.event.ApplicationStartedEvent
+import org.springframework.context.ApplicationEventPublisher
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import spock.lang.Specification
@@ -42,7 +43,8 @@ class InventoryModelLoaderSpec extends Specification {
def mockCpsModuleService = Mock(CpsModuleService)
def mockCpsDataService = Mock(CpsDataService)
def mockCpsAnchorService = Mock(CpsAnchorService)
- def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsAnchorService, mockCpsDataService)
+ def mockApplicationEventPublisher = Mock(ApplicationEventPublisher)
+ def objectUnderTest = new InventoryModelLoader(mockCpsAdminService, mockCpsModuleService, mockCpsAnchorService, mockCpsDataService, mockApplicationEventPublisher)
def applicationContext = new AnnotationConfigApplicationContext()
@@ -75,6 +77,8 @@ class InventoryModelLoaderSpec extends Specification {
1 * mockCpsAnchorService.updateAnchorSchemaSet(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, 'dmi-registry-2024-02-23')
and: 'No schema sets are being removed by the module service (yet)'
0 * mockCpsModuleService.deleteSchemaSet(NCMP_DATASPACE_NAME, _, _)
+ and: 'application event publisher is called once'
+ 1 * mockApplicationEventPublisher.publishEvent(_)
}
}
diff --git a/docker-compose/config/grafana/lcm-state-dashboard.json b/docker-compose/config/grafana/lcm-state-dashboard.json
new file mode 100644
index 0000000000..5339b038d7
--- /dev/null
+++ b/docker-compose/config/grafana/lcm-state-dashboard.json
@@ -0,0 +1,562 @@
+{
+ "annotations": {
+ "list": [
+ {
+ "builtIn": 1,
+ "datasource": {
+ "type": "grafana",
+ "uid": "-- Grafana --"
+ },
+ "enable": true,
+ "hide": true,
+ "iconColor": "rgba(0, 211, 255, 1)",
+ "name": "Annotations & Alerts",
+ "type": "dashboard"
+ }
+ ]
+ },
+ "editable": true,
+ "fiscalYearStartMonth": 0,
+ "graphTooltip": 0,
+ "id": 2,
+ "links": [],
+ "panels": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 9,
+ "w": 24,
+ "x": 0,
+ "y": 0
+ },
+ "id": 5,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "cmHandlesByState{instance=\"$Instance\", job=\"$Job\"}",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "All LCM States",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 9
+ },
+ "id": 1,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "cmHandlesByState{state=\"ADVISED\", instance=\"$Instance\", job=\"$Job\"}",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "ADVISED",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 9
+ },
+ "id": 3,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "cmHandlesByState{state=\"READY\", instance=\"$Instance\", job=\"$Job\"}",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "READY",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 0,
+ "y": 17
+ },
+ "id": 2,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "cmHandlesByState{state=\"LOCKED\", instance=\"$Instance\", job=\"$Job\"}",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "LOCKED",
+ "type": "timeseries"
+ },
+ {
+ "datasource": {
+ "type": "prometheus",
+ "uid": "PBFA97CFB590B2093"
+ },
+ "fieldConfig": {
+ "defaults": {
+ "color": {
+ "mode": "palette-classic"
+ },
+ "custom": {
+ "axisBorderShow": false,
+ "axisCenteredZero": false,
+ "axisColorMode": "text",
+ "axisLabel": "",
+ "axisPlacement": "auto",
+ "barAlignment": 0,
+ "barWidthFactor": 0.6,
+ "drawStyle": "line",
+ "fillOpacity": 0,
+ "gradientMode": "none",
+ "hideFrom": {
+ "legend": false,
+ "tooltip": false,
+ "viz": false
+ },
+ "insertNulls": false,
+ "lineInterpolation": "linear",
+ "lineWidth": 1,
+ "pointSize": 5,
+ "scaleDistribution": {
+ "type": "linear"
+ },
+ "showPoints": "auto",
+ "spanNulls": false,
+ "stacking": {
+ "group": "A",
+ "mode": "none"
+ },
+ "thresholdsStyle": {
+ "mode": "off"
+ }
+ },
+ "mappings": [],
+ "thresholds": {
+ "mode": "absolute",
+ "steps": [
+ {
+ "color": "green",
+ "value": null
+ },
+ {
+ "color": "red",
+ "value": 80
+ }
+ ]
+ }
+ },
+ "overrides": []
+ },
+ "gridPos": {
+ "h": 8,
+ "w": 12,
+ "x": 12,
+ "y": 17
+ },
+ "id": 4,
+ "options": {
+ "legend": {
+ "calcs": [],
+ "displayMode": "list",
+ "placement": "bottom",
+ "showLegend": true
+ },
+ "tooltip": {
+ "mode": "single",
+ "sort": "none"
+ }
+ },
+ "pluginVersion": "11.4.0",
+ "targets": [
+ {
+ "disableTextWrap": false,
+ "editorMode": "builder",
+ "expr": "cmHandlesByState{state=\"DELETING\", instance=\"$Instance\", job=\"$Job\"}",
+ "fullMetaSearch": false,
+ "includeNullMetadata": true,
+ "legendFormat": "__auto",
+ "range": true,
+ "refId": "A",
+ "useBackend": false
+ }
+ ],
+ "title": "DELETING",
+ "type": "timeseries"
+ }
+ ],
+ "preload": false,
+ "schemaVersion": 40,
+ "tags": [],
+ "templating": {
+ "list": [
+ {
+ "current": {
+ "text": "172.17.0.1:8799",
+ "value": "172.17.0.1:8799"
+ },
+ "definition": "label_values(instance)",
+ "label": "Instance",
+ "name": "Instance",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(instance)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "type": "query"
+ },
+ {
+ "current": {
+ "text": "cps-and-ncmp-endurance",
+ "value": "cps-and-ncmp-endurance"
+ },
+ "definition": "label_values(job)",
+ "label": "job",
+ "name": "Job",
+ "options": [],
+ "query": {
+ "qryType": 1,
+ "query": "label_values(job)",
+ "refId": "PrometheusVariableQueryEditor-VariableQuery"
+ },
+ "refresh": 1,
+ "regex": "",
+ "type": "query"
+ }
+ ]
+ },
+ "time": {
+ "from": "now-1h",
+ "to": "now"
+ },
+ "timepicker": {},
+ "timezone": "browser",
+ "title": "LCM State",
+ "uid": "ae9zcowku03k0d",
+ "version": 1,
+ "weekStart": ""
+} \ No newline at end of file
diff --git a/docker-compose/docker-compose.yml b/docker-compose/docker-compose.yml
index bcb2c2b88c..4263329eed 100644
--- a/docker-compose/docker-compose.yml
+++ b/docker-compose/docker-compose.yml
@@ -199,6 +199,7 @@ services:
volumes:
- ./config/grafana/provisioning/:/etc/grafana/provisioning/
- ./config/grafana/jvm-micrometer-dashboard.json:/var/lib/grafana/dashboards/jvm-micrometer-dashboard.json
+ - ./config/grafana/lcm-state-dashboard.json:/var/lib/grafana/dashboards/lcm-state-dashboard.json
- grafana:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin