Introduce Instrumentation 60/132960/7
authorToineSiebelink <toine.siebelink@est.tech>
Thu, 19 Jan 2023 16:45:58 +0000 (16:45 +0000)
committerToineSiebelink <toine.siebelink@est.tech>
Tue, 31 Jan 2023 11:26:22 +0000 (11:26 +0000)
- Add instrumentation related dependency
- Added Timed Instrumentation
- CPS-Service Crud methods
      - CPS Yang parsing
      - NCMP Registration methods
      - NCMP Events handling
- Remove manual Gauge for YanResources Cache
 as (better!) instrumentation is already built into the 3PP
- Sorted dependecies alphabetically (as we used to enforce, to prevent duplicates)
- Added ##  P E R F O R M A N C E   T E S T   R E S U L T S  ### mini report
- (unrelated) test improvement (because of bug that turned out to be invalid)
Reviewers: Sourabh,Priyank, Luke

Issue-ID: CPS-1457

Signed-off-by: ToineSiebelink <toine.siebelink@est.tech>
Change-Id: I34b20bece2f59488b022b8effa9470704c57be4d

27 files changed:
cps-application/src/main/java/org/onap/cps/Application.java
cps-application/src/main/java/org/onap/cps/config/MicroMeterConfig.java [new file with mode: 0644]
cps-application/src/test/groovy/org/onap/cps/config/MicroMeterConfigSpec.groovy [new file with mode: 0644]
cps-application/src/test/groovy/org/onap/cps/rest/controller/ControllerSecuritySpec.groovy
cps-application/src/test/java/org/onap/cps/rest/controller/TestController.java
cps-ncmp-rest/src/main/java/org/onap/cps/ncmp/rest/controller/NetworkCmProxyInventoryController.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsCmHandleStateHandlerImpl.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/impl/event/lcm/LcmEventsService.java
cps-ncmp-service/src/main/java/org/onap/cps/ncmp/api/inventory/InventoryPersistenceImpl.java
cps-rest/src/main/java/org/onap/cps/rest/controller/AdminRestController.java
cps-rest/src/test/groovy/org/onap/cps/rest/exceptions/CpsRestExceptionHandlerSpec.groovy
cps-ri/src/test/groovy/org/onap/cps/spi/impl/CpsPersistencePerfSpecBase.groovy
cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServiceDeletePerfTest.groovy
cps-ri/src/test/groovy/org/onap/cps/spi/performance/CpsDataPersistenceServicePerfTest.groovy
cps-service/pom.xml
cps-service/src/main/java/org/onap/cps/api/impl/CpsDataServiceImpl.java
cps-service/src/main/java/org/onap/cps/api/impl/CpsModuleServiceImpl.java
cps-service/src/main/java/org/onap/cps/api/impl/YangTextSchemaSourceSetCache.java
cps-service/src/main/java/org/onap/cps/utils/TimedYangParser.java [new file with mode: 0644]
cps-service/src/main/java/org/onap/cps/utils/YangUtils.java
cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java [new file with mode: 0644]
cps-service/src/main/java/org/onap/cps/yang/YangTextSchemaSourceSetBuilder.java
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsDataServiceImplSpec.groovy
cps-service/src/test/groovy/org/onap/cps/api/impl/CpsModuleServiceImplSpec.groovy
cps-service/src/test/groovy/org/onap/cps/api/impl/E2ENetworkSliceSpec.groovy
docker-compose/docker-compose.yml
integration-test/src/test/groovy/org/onap/cps/integration/TestConfig.groovy

index 79d5950..053139f 100644 (file)
@@ -27,7 +27,6 @@ import org.springframework.retry.annotation.EnableRetry;
 @EnableRetry\r
 @SpringBootApplication\r
 public class Application {\r
 @EnableRetry\r
 @SpringBootApplication\r
 public class Application {\r
-\r
     public static void main(final String[] args) {\r
         SpringApplication.run(Application.class, args);\r
     }\r
     public static void main(final String[] args) {\r
         SpringApplication.run(Application.class, args);\r
     }\r
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
new file mode 100644 (file)
index 0000000..22194f3
--- /dev/null
@@ -0,0 +1,36 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.config;
+
+import io.micrometer.core.aop.TimedAspect;
+import io.micrometer.core.instrument.MeterRegistry;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MicroMeterConfig {
+
+    @Bean
+    public TimedAspect timedAspect(final MeterRegistry registry) {
+        return new TimedAspect(registry);
+    }
+
+}
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
new file mode 100644 (file)
index 0000000..61bc2cf
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.config
+
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry
+import spock.lang.Specification
+
+class MicroMeterConfigSpec extends Specification {
+
+    def objectUnderTest = new MicroMeterConfig()
+
+    def 'Creating a tined aspect.'() {
+        expect: ' a timed aspect can be created'
+            assert objectUnderTest.timedAspect(new SimpleMeterRegistry()) != null
+    }
+
+}
index 01d3735..5c255f1 100755 (executable)
@@ -1,20 +1,21 @@
 /*
 /*
- *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020 Pantheon.tech
- *  ================================================================================
- *  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
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2020 Pantheon.tech
+ * Modifications Copyright (C) 2023 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
  *
  *        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.
+ * 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=========================================================
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
  */
 
 package org.onap.cps.rest.controller
  */
 
 package org.onap.cps.rest.controller
@@ -27,7 +28,7 @@ import org.springframework.http.HttpStatus
 import org.springframework.test.web.servlet.MockMvc
 import spock.lang.Specification
 
 import org.springframework.test.web.servlet.MockMvc
 import spock.lang.Specification
 
-@WebMvcTest(controllers = TestController.class)
+@WebMvcTest(TestController)
 class ControllerSecuritySpec extends Specification {
 
     @Autowired
 class ControllerSecuritySpec extends Specification {
 
     @Autowired
index 34325c7..75aab83 100644 (file)
@@ -1,6 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
+ *  Modifications Copyright (C) 2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -19,6 +20,9 @@
 
 package org.onap.cps.rest.controller;
 
 
 package org.onap.cps.rest.controller;
 
+import io.micrometer.core.instrument.MeterRegistry;
+import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
+import org.springframework.context.annotation.Bean;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.ResponseEntity;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -27,8 +31,14 @@ import org.springframework.web.bind.annotation.RestController;
 @RestController
 public class TestController {
 
 @RestController
 public class TestController {
 
+    @Bean
+    public MeterRegistry meterRegistry() {
+        return new SimpleMeterRegistry();
+    }
+
     @GetMapping("/test")
     ResponseEntity<String> test() {
         return new ResponseEntity<>(HttpStatus.OK);
     }
     @GetMapping("/test")
     ResponseEntity<String> test() {
         return new ResponseEntity<>(HttpStatus.OK);
     }
+
 }
 }
index 98da150..0c27d3e 100755 (executable)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021-2022 Bell Canada
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021-2022 Bell Canada
- *  Modifications Copyright (C) 2022 Nordix Foundation
+ *  Modifications Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -21,6 +21,7 @@
 
 package org.onap.cps.ncmp.rest.controller;
 
 
 package org.onap.cps.ncmp.rest.controller;
 
+import io.micrometer.core.annotation.Timed;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.List;
 import java.util.Set;
 import java.util.stream.Collectors;
@@ -78,6 +79,8 @@ public class NetworkCmProxyInventoryController implements NetworkCmProxyInventor
      * @param restDmiPluginRegistration the registration data
      */
     @Override
      * @param restDmiPluginRegistration the registration data
      */
     @Override
+    @Timed(value = "cps.ncmp.inventory.controller.update",
+        description = "Time taken to handle registration request")
     public ResponseEntity updateDmiPluginRegistration(
         final @Valid RestDmiPluginRegistration restDmiPluginRegistration) {
         final DmiPluginRegistrationResponse dmiPluginRegistrationResponse =
     public ResponseEntity updateDmiPluginRegistration(
         final @Valid RestDmiPluginRegistration restDmiPluginRegistration) {
         final DmiPluginRegistrationResponse dmiPluginRegistrationResponse =
index eba0389..6485fdf 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
 /*
  * ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import static org.onap.cps.ncmp.api.inventory.CmHandleState.DELETED;
 import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED;
 import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY;
 
 import static org.onap.cps.ncmp.api.inventory.CmHandleState.LOCKED;
 import static org.onap.cps.ncmp.api.inventory.CmHandleState.READY;
 
+import io.micrometer.core.annotation.Timed;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.LinkedHashMap;
@@ -74,6 +75,8 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.ncmp.cmhandle.state.update.batch",
+        description = "Time taken to update a batch of cm handle states")
     public void updateCmHandleStateBatch(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) {
         final Collection<CmHandleTransitionPair> cmHandleTransitionPairs =
                 prepareCmHandleTransitionBatch(cmHandleStatePerCmHandle);
     public void updateCmHandleStateBatch(final Map<YangModelCmHandle, CmHandleState> cmHandleStatePerCmHandle) {
         final Collection<CmHandleTransitionPair> cmHandleTransitionPairs =
                 prepareCmHandleTransitionBatch(cmHandleStatePerCmHandle);
@@ -164,7 +167,6 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
 
     }
 
 
     }
 
-
     private void updateToSpecifiedCmHandleState(final YangModelCmHandle yangModelCmHandle,
             final CmHandleState targetCmHandleState) {
 
     private void updateToSpecifiedCmHandleState(final YangModelCmHandle yangModelCmHandle,
             final CmHandleState targetCmHandleState) {
 
@@ -219,7 +221,6 @@ public class LcmEventsCmHandleStateHandlerImpl implements LcmEventsCmHandleState
     @Setter
     @NoArgsConstructor
     static class CmHandleTransitionPair {
     @Setter
     @NoArgsConstructor
     static class CmHandleTransitionPair {
-
         private YangModelCmHandle currentYangModelCmHandle;
         private YangModelCmHandle targetYangModelCmHandle;
     }
         private YangModelCmHandle currentYangModelCmHandle;
         private YangModelCmHandle targetYangModelCmHandle;
     }
index d6857d3..a94d664 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * ============LICENSE_START=======================================================
 /*
  * ============LICENSE_START=======================================================
- * Copyright (C) 2022 Nordix Foundation
+ * Copyright (C) 2022-2023 Nordix Foundation
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * ================================================================================
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -20,6 +20,7 @@
 
 package org.onap.cps.ncmp.api.impl.event.lcm;
 
 
 package org.onap.cps.ncmp.api.impl.event.lcm;
 
+import io.micrometer.core.annotation.Timed;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.ncmp.cmhandle.event.lcm.LcmEvent;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.onap.ncmp.cmhandle.event.lcm.LcmEvent;
@@ -50,6 +51,8 @@ public class LcmEventsService {
      * @param cmHandleId Cm Handle Id
      * @param lcmEvent  Lcm Event
      */
      * @param cmHandleId Cm Handle Id
      * @param lcmEvent  Lcm Event
      */
+    @Timed(value = "cps.ncmp.lcm.events.publish",
+        description = "Time taken to publish a LCM event")
     public void publishLcmEvent(final String cmHandleId, final LcmEvent lcmEvent) {
         if (notificationsEnabled) {
             try {
     public void publishLcmEvent(final String cmHandleId, final LcmEvent lcmEvent) {
         if (notificationsEnabled) {
             try {
index 5b0b5ea..dd16585 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2022 Nordix Foundation
+ *  Copyright (C) 2022-2023 Nordix Foundation
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
@@ -26,6 +26,7 @@ import static org.onap.cps.ncmp.api.impl.constants.DmiRegistryConstants.NO_TIMES
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
 
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_ALLOWED;
 import static org.onap.cps.spi.FetchDescendantsOption.INCLUDE_ALL_DESCENDANTS;
 
+import io.micrometer.core.annotation.Timed;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -140,6 +141,8 @@ public class InventoryPersistenceImpl implements InventoryPersistence {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.ncmp.inventory.persistence.schemaset.delete",
+        description = "Time taken to delete a schemaset")
     public void deleteSchemaSetWithCascade(final String schemaSetName) {
         try {
             cpsValidator.validateNameCharacters(schemaSetName);
     public void deleteSchemaSetWithCascade(final String schemaSetName) {
         try {
             cpsValidator.validateNameCharacters(schemaSetName);
@@ -156,6 +159,8 @@ public class InventoryPersistenceImpl implements InventoryPersistence {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.ncmp.inventory.persistence.datanode.get",
+        description = "Time taken to get a data node (from ncmp dmi registry)")
     public DataNode getDataNode(final String xpath, final FetchDescendantsOption fetchDescendantsOption) {
         return cpsDataService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
                 xpath, fetchDescendantsOption);
     public DataNode getDataNode(final String xpath, final FetchDescendantsOption fetchDescendantsOption) {
         return cpsDataService.getDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR,
                 xpath, fetchDescendantsOption);
@@ -182,4 +187,4 @@ public class InventoryPersistenceImpl implements InventoryPersistence {
         cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath,
                 NO_TIMESTAMP);
     }
         cpsDataService.deleteDataNode(NCMP_DATASPACE_NAME, NCMP_DMI_REGISTRY_ANCHOR, dataNodeXpath,
                 NO_TIMESTAMP);
     }
-}
\ No newline at end of file
+}
index b8ba089..993c5a3 100755 (executable)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2022 Nordix Foundation
+ *  Copyright (C) 2020-2023 Nordix Foundation
  *  Modifications Copyright (C) 2020-2021 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2020-2021 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -26,6 +26,7 @@ package org.onap.cps.rest.controller;
 import static org.onap.cps.rest.utils.MultipartFileUtil.extractYangResourcesMap;
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED;
 
 import static org.onap.cps.rest.utils.MultipartFileUtil.extractYangResourcesMap;
 import static org.onap.cps.spi.CascadeDeleteAllowed.CASCADE_DELETE_PROHIBITED;
 
+import io.micrometer.core.annotation.Timed;
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
 import java.util.Collection;
 import java.util.List;
 import java.util.stream.Collectors;
@@ -116,6 +117,8 @@ public class AdminRestController implements CpsAdminApi {
      * @return a {@Link ResponseEntity} of created schema set without any response body & {@link HttpStatus} CREATED
      */
     @Override
      * @return a {@Link ResponseEntity} of created schema set without any response body & {@link HttpStatus} CREATED
      */
     @Override
+    @Timed(value = "cps.rest.admin.controller.schemaset.create",
+        description = "Time taken to create schemaset from controller")
     public ResponseEntity<Void> createSchemaSetV2(@NotNull @Valid final String schemaSetName,
         final String dataspaceName, @Valid final MultipartFile multipartFile) {
         cpsModuleService.createSchemaSet(dataspaceName, schemaSetName, extractYangResourcesMap(multipartFile));
     public ResponseEntity<Void> createSchemaSetV2(@NotNull @Valid final String schemaSetName,
         final String dataspaceName, @Valid final MultipartFile multipartFile) {
         cpsModuleService.createSchemaSet(dataspaceName, schemaSetName, extractYangResourcesMap(multipartFile));
index 0821b6b..535b83d 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Pantheon.tech
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Pantheon.tech
- *  Modifications Copyright (C) 2021-2022 Nordix Foundation
+ *  Modifications Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2022 Deutsche Telekom AG
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2022 Deutsche Telekom AG
@@ -136,8 +136,18 @@ class CpsRestExceptionHandlerSpec extends Specification {
                 "Anchor with name ${existingObjectName} already exists for ${dataspaceName}.")
     }
 
                 "Anchor with name ${existingObjectName} already exists for ${dataspaceName}.")
     }
 
+    def 'Request with a schema set in use exception returns HTTP Status Conflict.'() {
+        when: 'Schema set in use exception is thrown by the service'
+            setupTestException(new SchemaSetInUseException(dataspaceName, existingObjectName))
+            def response = performTestRequest()
+        then: 'a HTTP conflict response is returned with correct message an details'
+            assertTestResponse(response, CONFLICT,
+                "Schema Set is being used.",
+                "Schema Set with name ${existingObjectName} in dataspace ${dataspaceName} is having Anchor records associated.")
+    }
+
     def 'Get request with a #exceptionThrown.class.simpleName returns HTTP Status Bad Request'() {
     def 'Get request with a #exceptionThrown.class.simpleName returns HTTP Status Bad Request'() {
-        when: 'CPS validation exception is thrown by the service'
+        when: '#exceptionThrown.class.simpleName is thrown by the service'
             setupTestException(exceptionThrown)
             def response = performTestRequest()
         then: 'an HTTP Bad Request response is returned with correct message and details'
             setupTestException(exceptionThrown)
             def response = performTestRequest()
         then: 'an HTTP Bad Request response is returned with correct message and details'
index 3bbae2d..b67a5cc 100644 (file)
@@ -22,6 +22,7 @@ package org.onap.cps.spi.impl
 
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
 
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
+import org.springframework.util.StopWatch
 
 class CpsPersistencePerfSpecBase extends CpsPersistenceSpecBase {
 
 
 class CpsPersistencePerfSpecBase extends CpsPersistenceSpecBase {
 
@@ -32,6 +33,18 @@ class CpsPersistencePerfSpecBase extends CpsPersistenceSpecBase {
 
     static def xpathsToAllGrandChildren = []
 
 
     static def xpathsToAllGrandChildren = []
 
+    static def PERFORMANCE_RECORD = []
+
+    def stopWatch = new StopWatch()
+
+    def cleanupSpec() {
+        println('#############################################################################')
+        println('##             P E R F O R M A N C E   T E S T   R E S U L T S             ##')
+        println('#############################################################################')
+        PERFORMANCE_RECORD.sort().each { println(it) }
+        PERFORMANCE_RECORD.clear()
+    }
+
     def createLineage(cpsDataPersistenceService, numberOfChildren, numberOfGrandChildren, createLists) {
         xpathsToAllGrandChildren = []
         (1..numberOfChildren).each {
     def createLineage(cpsDataPersistenceService, numberOfChildren, numberOfGrandChildren, createLists) {
         xpathsToAllGrandChildren = []
         (1..numberOfChildren).each {
@@ -71,4 +84,16 @@ class CpsPersistencePerfSpecBase extends CpsPersistenceSpecBase {
         }
         return nodeCount
     }
         }
         return nodeCount
     }
+
+    def recordAndAssertPerformance(String shortTitle, thresholdInMs, recordedTimeInMs) {
+        def pass = recordedTimeInMs <= thresholdInMs
+        if (shortTitle.length()>40) {
+            shortTitle = shortTitle.substring(0,40)
+        }
+        def record = String.format('%2d.%-40s limit%,7d took %,7d ms ', PERFORMANCE_RECORD.size()+1, shortTitle, thresholdInMs, recordedTimeInMs)
+        record += pass?'PASS':'FAIL'
+        PERFORMANCE_RECORD.add(record)
+        assert recordedTimeInMs <= thresholdInMs
+        return true
+    }
 }
 }
index 4dd4823..91da53d 100644 (file)
@@ -25,6 +25,7 @@ import org.onap.cps.spi.impl.CpsPersistencePerfSpecBase
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.test.context.jdbc.Sql
 import org.springframework.util.StopWatch
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.test.context.jdbc.Sql
 import org.springframework.util.StopWatch
+import spock.lang.Shared
 
 import java.util.concurrent.TimeUnit
 
 
 import java.util.concurrent.TimeUnit
 
@@ -43,13 +44,13 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
-        given: 'a node with a large number of descendants is created'
+        when: 'a node with a large number of descendants is created'
             stopWatch.start()
             createLineage(objectUnderTest, NUMBER_OF_CHILDREN, NUMBER_OF_GRAND_CHILDREN, false)
             stopWatch.stop()
             def setupDurationInMillis = stopWatch.getTotalTimeMillis()
             stopWatch.start()
             createLineage(objectUnderTest, NUMBER_OF_CHILDREN, NUMBER_OF_GRAND_CHILDREN, false)
             stopWatch.stop()
             def setupDurationInMillis = stopWatch.getTotalTimeMillis()
-        and: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
-            assert setupDurationInMillis < ALLOWED_SETUP_TIME_MS
+        then: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
+            recordAndAssertPerformance('Setup',ALLOWED_SETUP_TIME_MS, setupDurationInMillis)
     }
 
     def 'Delete 5 children with grandchildren'() {
     }
 
     def 'Delete 5 children with grandchildren'() {
@@ -62,7 +63,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 300 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 300 milliseconds'
-            assert deleteDurationInMillis < 300
+            recordAndAssertPerformance('Delete 5 children', 300, deleteDurationInMillis)
     }
 
     def 'Delete 50 grandchildren (that have no descendants)'() {
     }
 
     def 'Delete 50 grandchildren (that have no descendants)'() {
@@ -75,7 +76,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 350 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 350 milliseconds'
-            assert deleteDurationInMillis < 350
+            recordAndAssertPerformance('Delete 50 grandchildren', 350, deleteDurationInMillis)
     }
 
     def 'Delete 1 large data node with many descendants'() {
     }
 
     def 'Delete 1 large data node with many descendants'() {
@@ -85,7 +86,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 250 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 250 milliseconds'
-            assert deleteDurationInMillis < 250
+            recordAndAssertPerformance('Delete one large node', 250, deleteDurationInMillis)
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
@@ -96,7 +97,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def setupDurationInMillis = stopWatch.getTotalTimeMillis()
         and: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
             stopWatch.stop()
             def setupDurationInMillis = stopWatch.getTotalTimeMillis()
         and: 'setup duration is under #ALLOWED_SETUP_TIME_MS milliseconds'
-            assert setupDurationInMillis < ALLOWED_SETUP_TIME_MS
+            recordAndAssertPerformance('Create node with many list elements', ALLOWED_SETUP_TIME_MS, setupDurationInMillis)
     }
 
     def 'Delete 5 whole lists with many elements'() {
     }
 
     def 'Delete 5 whole lists with many elements'() {
@@ -109,7 +110,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 1000 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 1000 milliseconds'
-            assert deleteDurationInMillis < 1000
+            recordAndAssertPerformance('Delete 5 whole lists', 1500, deleteDurationInMillis)
     }
 
     def 'Delete 10 list elements with keys'() {
     }
 
     def 'Delete 10 list elements with keys'() {
@@ -123,7 +124,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 1200 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 1200 milliseconds'
-            assert deleteDurationInMillis < 1200
+            recordAndAssertPerformance('Delete 10 lists elements', 1500, deleteDurationInMillis)
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
@@ -136,7 +137,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 250 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 250 milliseconds'
-            assert deleteDurationInMillis < 250
+            recordAndAssertPerformance('Delete root node', 250, deleteDurationInMillis)
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     }
 
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
@@ -149,6 +150,7 @@ class CpsDataPersistenceServiceDeletePerfTest extends CpsPersistencePerfSpecBase
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 250 milliseconds'
             stopWatch.stop()
             def deleteDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'delete duration is under 250 milliseconds'
-            assert deleteDurationInMillis < 250
+            recordAndAssertPerformance('Delete data nodes for anchor', 250, deleteDurationInMillis)
     }
     }
+
 }
 }
index 0407490..0c4f5ec 100644 (file)
@@ -50,9 +50,6 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
     static def NUMBER_OF_GRAND_CHILDREN = 50
     static def TOTAL_NUMBER_OF_NODES = 1 + NUMBER_OF_CHILDREN + (NUMBER_OF_CHILDREN * NUMBER_OF_GRAND_CHILDREN)  //  Parent + Children +  Grand-children
 
     static def NUMBER_OF_GRAND_CHILDREN = 50
     static def TOTAL_NUMBER_OF_NODES = 1 + NUMBER_OF_CHILDREN + (NUMBER_OF_CHILDREN * NUMBER_OF_GRAND_CHILDREN)  //  Parent + Children +  Grand-children
 
-    def stopWatch = new StopWatch()
-    def readStopWatch = new StopWatch()
-
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
         given: 'a node with a large number of descendants is created'
     @Sql([CLEAR_DATA, PERF_TEST_DATA])
     def 'Create a node with many descendants (please note, subsequent tests depend on this running first).'() {
         given: 'a node with a large number of descendants is created'
@@ -61,7 +58,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
             stopWatch.stop()
             def setupDurationInMillis = stopWatch.getTotalTimeMillis()
         and: 'setup duration is under 10 seconds'
             stopWatch.stop()
             def setupDurationInMillis = stopWatch.getTotalTimeMillis()
         and: 'setup duration is under 10 seconds'
-            assert setupDurationInMillis < 10000
+            recordAndAssertPerformance('Setup', 10000, setupDurationInMillis)
     }
 
     def 'Get data node with many descendants by xpath #scenario'() {
     }
 
     def 'Get data node with many descendants by xpath #scenario'() {
@@ -71,7 +68,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
             stopWatch.stop()
             def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'read duration is under 500 milliseconds'
             stopWatch.stop()
             def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'read duration is under 500 milliseconds'
-            assert readDurationInMillis < 500
+            recordAndAssertPerformance("Get ${scenario}", 500, readDurationInMillis)
         and: 'data node is returned with all the descendants populated'
             assert countDataNodes(result) == TOTAL_NUMBER_OF_NODES
         where: 'the following xPaths are used'
         and: 'data node is returned with all the descendants populated'
             assert countDataNodes(result) == TOTAL_NUMBER_OF_NODES
         where: 'the following xPaths are used'
@@ -87,7 +84,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
             stopWatch.stop()
             def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'read duration is under 500 milliseconds'
             stopWatch.stop()
             def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'read duration is under 500 milliseconds'
-            assert readDurationInMillis < 500
+            recordAndAssertPerformance('Query with many descendants', 500, readDurationInMillis)
         and: 'data node is returned with all the descendants populated'
             assert countDataNodes(result) == TOTAL_NUMBER_OF_NODES
     }
         and: 'data node is returned with all the descendants populated'
             assert countDataNodes(result) == TOTAL_NUMBER_OF_NODES
     }
@@ -95,14 +92,14 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
     def 'Performance of finding multiple xpaths'() {
         when: 'we query for all grandchildren (except 1 for fun) with the new native method'
             xpathsToAllGrandChildren.remove(0)
     def 'Performance of finding multiple xpaths'() {
         when: 'we query for all grandchildren (except 1 for fun) with the new native method'
             xpathsToAllGrandChildren.remove(0)
-            readStopWatch.start()
+            stopWatch.start()
             def result = objectUnderTest.getDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToAllGrandChildren, INCLUDE_ALL_DESCENDANTS)
             def result = objectUnderTest.getDataNodes(PERF_DATASPACE, PERF_ANCHOR, xpathsToAllGrandChildren, INCLUDE_ALL_DESCENDANTS)
-            readStopWatch.stop()
-            def readDurationInMillis = readStopWatch.getTotalTimeMillis()
+            stopWatch.stop()
+            def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'the returned number of entities equal to the number of children * number of grandchildren'
             assert result.size() == xpathsToAllGrandChildren.size()
         and: 'it took less then 4000ms'
         then: 'the returned number of entities equal to the number of children * number of grandchildren'
             assert result.size() == xpathsToAllGrandChildren.size()
         and: 'it took less then 4000ms'
-            assert readDurationInMillis < 4000
+            recordAndAssertPerformance('Find multiple xpaths', 4000, readDurationInMillis)
     }
 
     def 'Query many descendants by cps-path with #scenario'() {
     }
 
     def 'Query many descendants by cps-path with #scenario'() {
@@ -113,6 +110,7 @@ class CpsDataPersistenceServicePerfTest extends CpsPersistencePerfSpecBase {
             def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'read duration is under #allowedDuration milliseconds'
             assert readDurationInMillis < allowedDuration
             def readDurationInMillis = stopWatch.getTotalTimeMillis()
         then: 'read duration is under #allowedDuration milliseconds'
             assert readDurationInMillis < allowedDuration
+            recordAndAssertPerformance("Query many descendants by cpspath (${scenario})", allowedDuration, readDurationInMillis)
         and: 'data node is returned with all the descendants populated'
             assert result.size() == NUMBER_OF_CHILDREN
         where: 'the following options are used'
         and: 'data node is returned with all the descendants populated'
             assert result.size() == NUMBER_OF_CHILDREN
         where: 'the following options are used'
index 888ef46..d9babf5 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
   ============LICENSE_START=======================================================
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
   ============LICENSE_START=======================================================
-  Copyright (C) 2021-2022 Nordix Foundation
+  Copyright (C) 2021-2023 Nordix Foundation
   Modifications Copyright (C) 2021 Bell Canada.
   Modifications Copyright (C) 2021 Pantheon.tech
   Modifications Copyright (C) 2022 Deutsche Telekom AG
   Modifications Copyright (C) 2021 Bell Canada.
   Modifications Copyright (C) 2021 Pantheon.tech
   Modifications Copyright (C) 2022 Deutsche Telekom AG
   </properties>
 
   <dependencies>
   </properties>
 
   <dependencies>
+    <dependency>
+      <groupId>com.github.ben-manes.caffeine</groupId>
+      <artifactId>caffeine</artifactId>
+    </dependency>
+    <dependency>
+      <!-- For parsing JSON object -->
+      <groupId>com.google.code.gson</groupId>
+      <artifactId>gson</artifactId>
+    </dependency>
+    <dependency>
+      <!-- Hazelcast provide Distributed Caches -->
+      <groupId>com.hazelcast</groupId>
+      <artifactId>hazelcast-spring</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>io.micrometer</groupId>
+      <artifactId>micrometer-core</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>net.logstash.logback</groupId>
+      <artifactId>logstash-logback-encoder</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.codehaus.janino</groupId>
+      <artifactId>janino</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.onap.cps</groupId>
       <artifactId>cps-events</artifactId>
     </dependency>
     <dependency>
       <groupId>org.onap.cps</groupId>
       <artifactId>cps-events</artifactId>
     </dependency>
+    <dependency>
+      <groupId>org.onap.cps</groupId>
+      <artifactId>cps-path-parser</artifactId>
+    </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-model-api</artifactId>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
       <artifactId>yang-model-api</artifactId>
       <artifactId>yang-parser-impl</artifactId>
     </dependency>
     <dependency>
       <artifactId>yang-parser-impl</artifactId>
     </dependency>
     <dependency>
+      <!-- required for processing yang data in json format -->
       <groupId>org.opendaylight.yangtools</groupId>
       <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-model-util</artifactId>
+      <artifactId>yang-data-codec-gson</artifactId>
     </dependency>
     </dependency>
-    <!-- required for processing yang data in json format -->
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-data-codec-gson</artifactId>
+      <artifactId>yang-data-codec-xml</artifactId>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
     </dependency>
     <dependency>
       <groupId>org.opendaylight.yangtools</groupId>
-      <artifactId>yang-data-codec-xml</artifactId>
+      <artifactId>yang-model-util</artifactId>
     </dependency>
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
     </dependency>
     </dependency>
     <dependency>
       <groupId>org.projectlombok</groupId>
       <artifactId>lombok</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-starter-cache</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>com.github.ben-manes.caffeine</groupId>
-      <artifactId>caffeine</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework.kafka</groupId>
-      <artifactId>spring-kafka</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.springframework</groupId>
-      <artifactId>spring-messaging</artifactId>
-    </dependency>
     <dependency>
       <!-- For logging -->
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
     <dependency>
     <dependency>
       <!-- For logging -->
       <groupId>org.slf4j</groupId>
       <artifactId>slf4j-api</artifactId>
     </dependency>
     <dependency>
-      <groupId>org.springframework.boot</groupId>
-      <artifactId>spring-boot-starter-validation</artifactId>
+      <groupId>org.springframework</groupId>
+      <artifactId>spring-messaging</artifactId>
     </dependency>
     <dependency>
     </dependency>
     <dependency>
-      <!-- For parsing JSON object -->
-      <groupId>com.google.code.gson</groupId>
-      <artifactId>gson</artifactId>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-cache</artifactId>
     </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
     </dependency>
     <dependency>
     </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-aop</artifactId>
     </dependency>
     <dependency>
-      <groupId>net.logstash.logback</groupId>
-      <artifactId>logstash-logback-encoder</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.codehaus.janino</groupId>
-      <artifactId>janino</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.onap.cps</groupId>
-      <artifactId>cps-path-parser</artifactId>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-validation</artifactId>
     </dependency>
     <dependency>
     </dependency>
     <dependency>
-      <!-- Hazelcast provide Distributed Caches -->
-      <groupId>com.hazelcast</groupId>
-      <artifactId>hazelcast-spring</artifactId>
+      <groupId>org.springframework.kafka</groupId>
+      <artifactId>spring-kafka</artifactId>
     </dependency>
     <!-- T E S T   D E P E N D E N C I E S -->
     <dependency>
     </dependency>
     <!-- T E S T   D E P E N D E N C I E S -->
     <dependency>
index 38fa92a..53fab29 100755 (executable)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -28,6 +28,7 @@ import static org.onap.cps.notification.Operation.CREATE;
 import static org.onap.cps.notification.Operation.DELETE;
 import static org.onap.cps.notification.Operation.UPDATE;
 
 import static org.onap.cps.notification.Operation.DELETE;
 import static org.onap.cps.notification.Operation.UPDATE;
 
+import io.micrometer.core.annotation.Timed;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.time.OffsetDateTime;
 import java.util.ArrayList;
 import java.util.Collection;
@@ -48,7 +49,7 @@ import org.onap.cps.spi.model.DataNode;
 import org.onap.cps.spi.model.DataNodeBuilder;
 import org.onap.cps.spi.utils.CpsValidator;
 import org.onap.cps.utils.ContentType;
 import org.onap.cps.spi.model.DataNodeBuilder;
 import org.onap.cps.spi.utils.CpsValidator;
 import org.onap.cps.utils.ContentType;
-import org.onap.cps.utils.YangUtils;
+import org.onap.cps.utils.TimedYangParser;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.springframework.stereotype.Service;
 import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.springframework.stereotype.Service;
@@ -66,6 +67,7 @@ public class CpsDataServiceImpl implements CpsDataService {
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
     private final NotificationService notificationService;
     private final CpsValidator cpsValidator;
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
     private final NotificationService notificationService;
     private final CpsValidator cpsValidator;
+    private final TimedYangParser timedYangParser;
 
     @Override
     public void saveData(final String dataspaceName, final String anchorName, final String nodeData,
 
     @Override
     public void saveData(final String dataspaceName, final String anchorName, final String nodeData,
@@ -74,6 +76,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.root.save",
+        description = "Time taken to save a root data node")
     public void saveData(final String dataspaceName, final String anchorName, final String nodeData,
                          final OffsetDateTime observedTimestamp, final ContentType contentType) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void saveData(final String dataspaceName, final String anchorName, final String nodeData,
                          final OffsetDateTime observedTimestamp, final ContentType contentType) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -90,6 +94,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.child.save",
+        description = "Time taken to save a child data node")
     public void saveData(final String dataspaceName, final String anchorName, final String parentNodeXpath,
                          final String nodeData, final OffsetDateTime observedTimestamp,
                          final ContentType contentType) {
     public void saveData(final String dataspaceName, final String anchorName, final String parentNodeXpath,
                          final String nodeData, final OffsetDateTime observedTimestamp,
                          final ContentType contentType) {
@@ -101,6 +107,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.list.element.save",
+        description = "Time taken to save a list element")
     public void saveListElements(final String dataspaceName, final String anchorName,
         final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void saveListElements(final String dataspaceName, final String anchorName,
         final String parentNodeXpath, final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -112,6 +120,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.list.element.batch.save",
+        description = "Time taken to save a batch of list elements")
     public void saveListElementsBatch(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final Collection<String> jsonDataList, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void saveListElementsBatch(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final Collection<String> jsonDataList, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -123,6 +133,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.get",
+        description = "Time taken to get a data node")
     public DataNode getDataNode(final String dataspaceName, final String anchorName, final String xpath,
         final FetchDescendantsOption fetchDescendantsOption) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public DataNode getDataNode(final String dataspaceName, final String anchorName, final String xpath,
         final FetchDescendantsOption fetchDescendantsOption) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -130,6 +142,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.batch.get",
+        description = "Time taken to get a batch of data nodes")
     public Collection<DataNode> getDataNodes(final String dataspaceName, final String anchorName,
                                              final Collection<String> xpaths,
                                 final FetchDescendantsOption fetchDescendantsOption) {
     public Collection<DataNode> getDataNodes(final String dataspaceName, final String anchorName,
                                              final Collection<String> xpaths,
                                 final FetchDescendantsOption fetchDescendantsOption) {
@@ -138,6 +152,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.leaves.update",
+        description = "Time taken to get a batch of data nodes")
     public void updateNodeLeaves(final String dataspaceName, final String anchorName, final String parentNodeXpath,
         final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void updateNodeLeaves(final String dataspaceName, final String anchorName, final String parentNodeXpath,
         final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -148,6 +164,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.leaves.descendants.leaves.update",
+        description = "Time taken to update data node leaves and existing descendants leaves")
     public void updateNodeLeavesAndExistingDescendantLeaves(final String dataspaceName, final String anchorName,
         final String parentNodeXpath,
         final String dataNodeUpdatesAsJson,
     public void updateNodeLeavesAndExistingDescendantLeaves(final String dataspaceName, final String anchorName,
         final String parentNodeXpath,
         final String dataNodeUpdatesAsJson,
@@ -184,6 +202,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.descendants.update",
+        description = "Time taken to update a data node and descendants")
     public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName,
                                              final String parentNodeXpath, final String jsonData,
                                              final OffsetDateTime observedTimestamp) {
     public void updateDataNodeAndDescendants(final String dataspaceName, final String anchorName,
                                              final String parentNodeXpath, final String jsonData,
                                              final OffsetDateTime observedTimestamp) {
@@ -196,6 +216,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.descendants.batch.update",
+        description = "Time taken to update a batch of data nodes and descendants")
     public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName,
                                               final Map<String, String> nodesJsonData,
                                               final OffsetDateTime observedTimestamp) {
     public void updateDataNodesAndDescendants(final String dataspaceName, final String anchorName,
                                               final Map<String, String> nodesJsonData,
                                               final OffsetDateTime observedTimestamp) {
@@ -208,6 +230,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.list.update",
+        description = "Time taken to update a list")
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final String jsonData, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -217,6 +241,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.list.batch.update",
+        description = "Time taken to update a batch of lists")
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final Collection<DataNode> dataNodes, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void replaceListContent(final String dataspaceName, final String anchorName, final String parentNodeXpath,
             final Collection<DataNode> dataNodes, final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -225,6 +251,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.delete",
+        description = "Time taken to delete a datanode")
     public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath,
                                final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void deleteDataNode(final String dataspaceName, final String anchorName, final String dataNodeXpath,
                                final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -233,6 +261,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.datanode.batch.delete",
+        description = "Time taken to delete a batch of datanodes")
     public void deleteDataNodes(final String dataspaceName, final String anchorName,
         final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void deleteDataNodes(final String dataspaceName, final String anchorName,
         final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -241,6 +271,8 @@ public class CpsDataServiceImpl implements CpsDataService {
     }
 
     @Override
     }
 
     @Override
+    @Timed(value = "cps.data.service.list.delete",
+        description = "Time taken to delete a list or list element")
     public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
         final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
     public void deleteListOrListElement(final String dataspaceName, final String anchorName, final String listNodeXpath,
         final OffsetDateTime observedTimestamp) {
         cpsValidator.validateNameCharacters(dataspaceName, anchorName);
@@ -256,11 +288,12 @@ public class CpsDataServiceImpl implements CpsDataService {
         final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
 
         if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
         final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
 
         if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
-            final ContainerNode containerNode = YangUtils.parseData(contentType, nodeData, schemaContext);
+            final ContainerNode containerNode = timedYangParser.parseData(contentType, nodeData, schemaContext);
             return new DataNodeBuilder().withContainerNode(containerNode).build();
         }
 
             return new DataNodeBuilder().withContainerNode(containerNode).build();
         }
 
-        final ContainerNode containerNode = YangUtils.parseData(contentType, nodeData, schemaContext, parentNodeXpath);
+        final ContainerNode containerNode =
+            timedYangParser.parseData(contentType, nodeData, schemaContext, parentNodeXpath);
 
         return new DataNodeBuilder()
                 .withParentNodeXpath(parentNodeXpath)
 
         return new DataNodeBuilder()
                 .withParentNodeXpath(parentNodeXpath)
@@ -283,8 +316,9 @@ public class CpsDataServiceImpl implements CpsDataService {
 
         final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
         final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
 
         final Anchor anchor = cpsAdminService.getAnchor(dataspaceName, anchorName);
         final SchemaContext schemaContext = getSchemaContext(dataspaceName, anchor.getSchemaSetName());
+
         if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
         if (ROOT_NODE_XPATH.equals(parentNodeXpath)) {
-            final ContainerNode containerNode = YangUtils.parseData(contentType, nodeData, schemaContext);
+            final ContainerNode containerNode = timedYangParser.parseData(contentType, nodeData, schemaContext);
             final Collection<DataNode> dataNodes = new DataNodeBuilder()
                     .withContainerNode(containerNode)
                     .buildCollection();
             final Collection<DataNode> dataNodes = new DataNodeBuilder()
                     .withContainerNode(containerNode)
                     .buildCollection();
@@ -293,7 +327,8 @@ public class CpsDataServiceImpl implements CpsDataService {
             }
             return dataNodes;
         }
             }
             return dataNodes;
         }
-        final ContainerNode containerNode = YangUtils.parseData(contentType, nodeData, schemaContext, parentNodeXpath);
+        final ContainerNode containerNode =
+            timedYangParser.parseData(contentType, nodeData, schemaContext, parentNodeXpath);
         final Collection<DataNode> dataNodes = new DataNodeBuilder()
             .withParentNodeXpath(parentNodeXpath)
             .withContainerNode(containerNode)
         final Collection<DataNode> dataNodes = new DataNodeBuilder()
             .withParentNodeXpath(parentNodeXpath)
             .withContainerNode(containerNode)
@@ -302,7 +337,6 @@ public class CpsDataServiceImpl implements CpsDataService {
             throw new DataValidationException("Invalid data.", "No data nodes provided");
         }
         return dataNodes;
             throw new DataValidationException("Invalid data.", "No data nodes provided");
         }
         return dataNodes;
-
     }
 
     private Collection<Collection<DataNode>> buildDataNodes(final String dataspaceName, final String anchorName,
     }
 
     private Collection<Collection<DataNode>> buildDataNodes(final String dataspaceName, final String anchorName,
index a04dd2a..ccd0fcc 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2022 Nordix Foundation
+ *  Copyright (C) 2020-2023 Nordix Foundation
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 Bell Canada
  *  Modifications Copyright (C) 2022 TechMahindra Ltd
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 Bell Canada
  *  Modifications Copyright (C) 2022 TechMahindra Ltd
@@ -23,6 +23,7 @@
 
 package org.onap.cps.api.impl;
 
 
 package org.onap.cps.api.impl;
 
+import io.micrometer.core.annotation.Timed;
 import java.util.Collection;
 import java.util.Map;
 import lombok.RequiredArgsConstructor;
 import java.util.Collection;
 import java.util.Map;
 import lombok.RequiredArgsConstructor;
@@ -36,8 +37,8 @@ import org.onap.cps.spi.model.ModuleDefinition;
 import org.onap.cps.spi.model.ModuleReference;
 import org.onap.cps.spi.model.SchemaSet;
 import org.onap.cps.spi.utils.CpsValidator;
 import org.onap.cps.spi.model.ModuleReference;
 import org.onap.cps.spi.model.SchemaSet;
 import org.onap.cps.spi.utils.CpsValidator;
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder;
 import org.onap.cps.yang.YangTextSchemaSourceSet;
 import org.onap.cps.yang.YangTextSchemaSourceSet;
-import org.onap.cps.yang.YangTextSchemaSourceSetBuilder;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -49,13 +50,16 @@ public class CpsModuleServiceImpl implements CpsModuleService {
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
     private final CpsAdminService cpsAdminService;
     private final CpsValidator cpsValidator;
     private final YangTextSchemaSourceSetCache yangTextSchemaSourceSetCache;
     private final CpsAdminService cpsAdminService;
     private final CpsValidator cpsValidator;
+    private final TimedYangTextSchemaSourceSetBuilder timedYangTextSchemaSourceSetBuilder;
 
     @Override
 
     @Override
+    @Timed(value = "cps.module.service.schemaset.create",
+        description = "Time taken to create (and store) a schemaset")
     public void createSchemaSet(final String dataspaceName, final String schemaSetName,
         final Map<String, String> yangResourcesNameToContentMap) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
     public void createSchemaSet(final String dataspaceName, final String schemaSetName,
         final Map<String, String> yangResourcesNameToContentMap) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
-        final var yangTextSchemaSourceSet
-            = YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap);
+        final YangTextSchemaSourceSet yangTextSchemaSourceSet =
+            timedYangTextSchemaSourceSetBuilder.getYangTextSchemaSourceSet(yangResourcesNameToContentMap);
         cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
         yangTextSchemaSourceSetCache.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet);
     }
         cpsModulePersistenceService.storeSchemaSet(dataspaceName, schemaSetName, yangResourcesNameToContentMap);
         yangTextSchemaSourceSetCache.updateCache(dataspaceName, schemaSetName, yangTextSchemaSourceSet);
     }
index 0f620b0..4fdae5a 100644 (file)
@@ -2,7 +2,7 @@
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 Bell Canada
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 Bell Canada
- *  Modifications Copyright (C) 2022 Nordix Foundation
+ *  Modifications Copyright (C) 2022-2023 Nordix Foundation
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -23,7 +23,9 @@
 package org.onap.cps.api.impl;
 
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
 package org.onap.cps.api.impl;
 
 import com.google.errorprone.annotations.CanIgnoreReturnValue;
+import io.micrometer.core.instrument.Metrics;
 import java.util.Map;
 import java.util.Map;
+import java.util.concurrent.atomic.AtomicInteger;
 import lombok.RequiredArgsConstructor;
 import org.onap.cps.spi.CpsModulePersistenceService;
 import org.onap.cps.spi.utils.CpsValidator;
 import lombok.RequiredArgsConstructor;
 import org.onap.cps.spi.CpsModulePersistenceService;
 import org.onap.cps.spi.utils.CpsValidator;
@@ -46,6 +48,9 @@ public class YangTextSchemaSourceSetCache {
     private final CpsModulePersistenceService cpsModulePersistenceService;
     private final CpsValidator cpsValidator;
 
     private final CpsModulePersistenceService cpsModulePersistenceService;
     private final CpsValidator cpsValidator;
 
+    private final AtomicInteger yangSchemaCacheCounter = Metrics.gauge("cps.yangschema.cache.gauge",
+                                                                        new AtomicInteger(0));
+
     /**
      * Cache YangTextSchemaSourceSet.
      *
     /**
      * Cache YangTextSchemaSourceSet.
      *
@@ -74,10 +79,10 @@ public class YangTextSchemaSourceSetCache {
     public YangTextSchemaSourceSet updateCache(final String dataspaceName, final String schemaSetName,
             final YangTextSchemaSourceSet yangTextSchemaSourceSet) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
     public YangTextSchemaSourceSet updateCache(final String dataspaceName, final String schemaSetName,
             final YangTextSchemaSourceSet yangTextSchemaSourceSet) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+        yangSchemaCacheCounter.incrementAndGet();
         return yangTextSchemaSourceSet;
     }
 
         return yangTextSchemaSourceSet;
     }
 
-
     /**
      * Remove the cached value for the given dataspace and schema-set.
      *
     /**
      * Remove the cached value for the given dataspace and schema-set.
      *
@@ -87,6 +92,7 @@ public class YangTextSchemaSourceSetCache {
     @CacheEvict(key = "#p0.concat('-').concat(#p1)")
     public void removeFromCache(final String dataspaceName, final String schemaSetName) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
     @CacheEvict(key = "#p0.concat('-').concat(#p1)")
     public void removeFromCache(final String dataspaceName, final String schemaSetName) {
         cpsValidator.validateNameCharacters(dataspaceName, schemaSetName);
+        yangSchemaCacheCounter.decrementAndGet();
         // Spring provides implementation for removing object from cache
     }
 
         // Spring provides implementation for removing object from cache
     }
 
diff --git a/cps-service/src/main/java/org/onap/cps/utils/TimedYangParser.java b/cps-service/src/main/java/org/onap/cps/utils/TimedYangParser.java
new file mode 100644 (file)
index 0000000..4640593
--- /dev/null
@@ -0,0 +1,61 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.utils;
+
+import io.micrometer.core.annotation.Timed;
+import org.opendaylight.yangtools.yang.data.api.schema.ContainerNode;
+import org.opendaylight.yangtools.yang.model.api.SchemaContext;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TimedYangParser {
+
+    /**
+     * Parses data into Collection of NormalizedNode according to given schema context.
+     *
+     * @param nodeData      data string
+     * @param schemaContext schema context describing associated data model
+     * @return the NormalizedNode object
+     */
+    @Timed(value = "cps.utils.yangparser.nodedata.parse",
+        description = "Time taken to parse node data without a parent")
+    public ContainerNode parseData(final ContentType contentType,
+                                          final String nodeData,
+                                          final SchemaContext schemaContext) {
+        return YangUtils.parseData(contentType, nodeData, schemaContext);
+    }
+
+    /**
+     * Parses data into NormalizedNode according to given schema context.
+     *
+     * @param nodeData      data string
+     * @param schemaContext schema context describing associated data model
+     * @return the NormalizedNode object
+     */
+    @Timed(value = "cps.utils.yangparser.nodedata.with.parent.parse",
+        description = "Time taken to parse node data with a parent")
+    public ContainerNode parseData(final ContentType contentType,
+                                          final String nodeData,
+                                          final SchemaContext schemaContext,
+                                          final String parentNodeXpath) {
+        return YangUtils.parseData(contentType, nodeData, schemaContext, parentNodeXpath);
+    }
+}
index c0dfe52..7da4024 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2022 Nordix Foundation
+ *  Copyright (C) 2020-2023 Nordix Foundation
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2021 Bell Canada.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -87,7 +87,7 @@ public class YangUtils {
      * @param schemaContext schema context describing associated data model
      * @return the NormalizedNode object
      */
      * @param schemaContext schema context describing associated data model
      * @return the NormalizedNode object
      */
-    public static ContainerNode parseData(final ContentType contentType,
+    static ContainerNode parseData(final ContentType contentType,
                                           final String nodeData,
                                           final SchemaContext schemaContext) {
         if (contentType == ContentType.JSON) {
                                           final String nodeData,
                                           final SchemaContext schemaContext) {
         if (contentType == ContentType.JSON) {
@@ -103,7 +103,7 @@ public class YangUtils {
      * @param schemaContext schema context describing associated data model
      * @return the NormalizedNode object
      */
      * @param schemaContext schema context describing associated data model
      * @return the NormalizedNode object
      */
-    public static ContainerNode parseData(final ContentType contentType,
+    static ContainerNode parseData(final ContentType contentType,
                                           final String nodeData,
                                           final SchemaContext schemaContext,
                                           final String parentNodeXpath) {
                                           final String nodeData,
                                           final SchemaContext schemaContext,
                                           final String parentNodeXpath) {
diff --git a/cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java b/cps-service/src/main/java/org/onap/cps/yang/TimedYangTextSchemaSourceSetBuilder.java
new file mode 100644 (file)
index 0000000..013faff
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2023 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.yang;
+
+import io.micrometer.core.annotation.Timed;
+import java.util.Map;
+import org.springframework.stereotype.Service;
+
+@Service
+public class TimedYangTextSchemaSourceSetBuilder {
+
+    @Timed(value = "cps.yangtextschemasourceset.build",
+        description = "Time taken to build a yang text schema source set")
+    public YangTextSchemaSourceSet getYangTextSchemaSourceSet(
+        final Map<String, String> yangResourcesNameToContentMap) {
+        return YangTextSchemaSourceSetBuilder.of(yangResourcesNameToContentMap);
+    }
+
+}
index e0f24f3..deb5b05 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Pantheon.tech
 /*
  *  ============LICENSE_START=======================================================
  *  Copyright (C) 2020 Pantheon.tech
- *  Modifications Copyright (C) 2022 Nordix Foundation.
+ *  Modifications Copyright (C) 2022-2023 Nordix Foundation.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
  *  ================================================================================
  *  Licensed under the Apache License, Version 2.0 (the "License");
  *  you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableMap;
 
 import com.google.common.base.MoreObjects;
 import com.google.common.collect.ImmutableMap;
+import io.micrometer.core.annotation.Timed;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
@@ -58,16 +59,35 @@ public final class YangTextSchemaSourceSetBuilder {
 
     private final ImmutableMap.Builder<String, String> yangModelMap = new ImmutableMap.Builder<>();
 
 
     private final ImmutableMap.Builder<String, String> yangModelMap = new ImmutableMap.Builder<>();
 
+    /**
+     * Add Yang resource context.
+     *
+     * @param yangResourceNameToContent the resource content
+     * @return this builder
+     */
     public YangTextSchemaSourceSetBuilder putAll(final Map<String, String> yangResourceNameToContent) {
         this.yangModelMap.putAll(yangResourceNameToContent);
         return this;
     }
 
     public YangTextSchemaSourceSetBuilder putAll(final Map<String, String> yangResourceNameToContent) {
         this.yangModelMap.putAll(yangResourceNameToContent);
         return this;
     }
 
+    /**
+     * Build a YangTextSchemaSourceSet.
+     *
+     * @return the YangTextSchemaSourceSet
+     */
     public YangTextSchemaSourceSet build() {
         final var schemaContext = generateSchemaContext(yangModelMap.build());
         return new YangTextSchemaSourceSetImpl(schemaContext);
     }
 
     public YangTextSchemaSourceSet build() {
         final var schemaContext = generateSchemaContext(yangModelMap.build());
         return new YangTextSchemaSourceSetImpl(schemaContext);
     }
 
+    /**
+     * Add yangResourceNameToContent and build a YangTextSchemaSourceSet.
+     *
+     * @param yangResourceNameToContent the resource content
+     * @return the YangTextSchemaSourceSet
+     */
+
+    @Timed(value = "cps.yang.schemasourceset.build", description = "Time taken to build a ODL yang Model")
     public static YangTextSchemaSourceSet of(final Map<String, String> yangResourceNameToContent) {
         return new YangTextSchemaSourceSetBuilder().putAll(yangResourceNameToContent).build();
     }
     public static YangTextSchemaSourceSet of(final Map<String, String> yangResourceNameToContent) {
         return new YangTextSchemaSourceSetBuilder().putAll(yangResourceNameToContent).build();
     }
index c81a50e..01dc0bd 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2021-2022 Nordix Foundation
+ *  Copyright (C) 2021-2023 Nordix Foundation
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Bell Canada.
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2021 Pantheon.tech
  *  Modifications Copyright (C) 2021-2022 Bell Canada.
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -34,6 +34,7 @@ import org.onap.cps.spi.model.Anchor
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
 import org.onap.cps.utils.ContentType
 import org.onap.cps.spi.model.DataNode
 import org.onap.cps.spi.model.DataNodeBuilder
 import org.onap.cps.utils.ContentType
+import org.onap.cps.utils.TimedYangParser
 import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
 import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
@@ -48,9 +49,10 @@ class CpsDataServiceImplSpec extends Specification {
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
     def mockNotificationService = Mock(NotificationService)
     def mockCpsValidator = Mock(CpsValidator)
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
     def mockNotificationService = Mock(NotificationService)
     def mockCpsValidator = Mock(CpsValidator)
+    def timedYangParser = new TimedYangParser()
 
     def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockCpsAdminService,
 
     def objectUnderTest = new CpsDataServiceImpl(mockCpsDataPersistenceService, mockCpsAdminService,
-            mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator)
+            mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator, timedYangParser)
 
     def setup() {
         mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
 
     def setup() {
         mockCpsAdminService.getAnchor(dataspaceName, anchorName) >> anchor
index 358a6fb..2bb0e63 100644 (file)
@@ -1,6 +1,6 @@
 /*
  *  ============LICENSE_START=======================================================
 /*
  *  ============LICENSE_START=======================================================
- *  Copyright (C) 2020-2022 Nordix Foundation
+ *  Copyright (C) 2020-2023 Nordix Foundation
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
  *  Modifications Copyright (C) 2020-2021 Pantheon.tech
  *  Modifications Copyright (C) 2020-2022 Bell Canada.
  *  Modifications Copyright (C) 2022 TechMahindra Ltd.
@@ -32,6 +32,7 @@ import org.onap.cps.spi.utils.CpsValidator
 import org.onap.cps.spi.model.Anchor
 import org.onap.cps.spi.model.ModuleReference
 import org.onap.cps.spi.model.SchemaSet
 import org.onap.cps.spi.model.Anchor
 import org.onap.cps.spi.model.ModuleReference
 import org.onap.cps.spi.model.SchemaSet
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
 import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
 import org.onap.cps.yang.YangTextSchemaSourceSet
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder
 import spock.lang.Specification
@@ -44,8 +45,9 @@ class CpsModuleServiceImplSpec extends Specification {
     def mockCpsAdminService = Mock(CpsAdminService)
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
     def mockCpsValidator = Mock(CpsValidator)
     def mockCpsAdminService = Mock(CpsAdminService)
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)
     def mockCpsValidator = Mock(CpsValidator)
+    def timedYangTextSchemaSourceSetBuilder = new TimedYangTextSchemaSourceSetBuilder()
 
 
-    def objectUnderTest = new CpsModuleServiceImpl(mockCpsModulePersistenceService, mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator)
+    def objectUnderTest = new CpsModuleServiceImpl(mockCpsModulePersistenceService, mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)
 
     def 'Create schema set.'() {
         given: 'Valid yang resource as name-to-content map'
 
     def 'Create schema set.'() {
         given: 'Valid yang resource as name-to-content map'
index ccfb23b..8ed7aed 100755 (executable)
@@ -1,6 +1,6 @@
 /*\r
  * ============LICENSE_START=======================================================\r
 /*\r
  * ============LICENSE_START=======================================================\r
- * Copyright (C) 2021-2022 Nordix Foundation.\r
+ * Copyright (C) 2021-2023 Nordix Foundation.\r
  * Modifications Copyright (C) 2021-2022 Bell Canada.\r
  * Modifications Copyright (C) 2021 Pantheon.tech\r
  * Modifications Copyright (C) 2022 TechMahindra Ltd.\r
  * Modifications Copyright (C) 2021-2022 Bell Canada.\r
  * Modifications Copyright (C) 2021 Pantheon.tech\r
  * Modifications Copyright (C) 2022 TechMahindra Ltd.\r
@@ -30,7 +30,9 @@ import org.onap.cps.spi.CpsDataPersistenceService
 import org.onap.cps.spi.CpsModulePersistenceService\r
 import org.onap.cps.spi.model.Anchor\r
 import org.onap.cps.spi.utils.CpsValidator\r
 import org.onap.cps.spi.CpsModulePersistenceService\r
 import org.onap.cps.spi.model.Anchor\r
 import org.onap.cps.spi.utils.CpsValidator\r
+import org.onap.cps.utils.TimedYangParser\r
 import org.onap.cps.utils.YangUtils\r
 import org.onap.cps.utils.YangUtils\r
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder\r
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder\r
 import spock.lang.Specification\r
 \r
 import org.onap.cps.yang.YangTextSchemaSourceSetBuilder\r
 import spock.lang.Specification\r
 \r
@@ -41,10 +43,14 @@ class E2ENetworkSliceSpec extends Specification {
     def mockNotificationService = Mock(NotificationService)\r
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)\r
     def mockCpsValidator = Mock(CpsValidator)\r
     def mockNotificationService = Mock(NotificationService)\r
     def mockYangTextSchemaSourceSetCache = Mock(YangTextSchemaSourceSetCache)\r
     def mockCpsValidator = Mock(CpsValidator)\r
+    def timedYangTextSchemaSourceSetBuilder = new TimedYangTextSchemaSourceSetBuilder()\r
+    def timedYangParser = new TimedYangParser()\r
+\r
     def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,\r
     def cpsModuleServiceImpl = new CpsModuleServiceImpl(mockModuleStoreService,\r
-            mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator)\r
+            mockYangTextSchemaSourceSetCache, mockCpsAdminService, mockCpsValidator,timedYangTextSchemaSourceSetBuilder)\r
+\r
     def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAdminService,\r
     def cpsDataServiceImpl = new CpsDataServiceImpl(mockDataStoreService, mockCpsAdminService,\r
-            mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator)\r
+            mockYangTextSchemaSourceSetCache, mockNotificationService, mockCpsValidator, timedYangParser)\r
 \r
     def dataspaceName = 'someDataspace'\r
     def anchorName = 'someAnchor'\r
 \r
     def dataspaceName = 'someDataspace'\r
     def anchorName = 'someAnchor'\r
index fe41fc4..7d6379a 100644 (file)
@@ -119,4 +119,4 @@ services:
       - ../../../cps-ncmp-service/src/main/resources/model/:/model
     depends_on:
       cps-and-ncmp:
       - ../../../cps-ncmp-service/src/main/resources/model/:/model
     depends_on:
       cps-and-ncmp:
-        condition: service_started
\ No newline at end of file
+        condition: service_started
index 33283f1..0e04d62 100644 (file)
@@ -36,6 +36,8 @@ import org.onap.cps.spi.repository.SchemaSetRepository
 import org.onap.cps.spi.repository.YangResourceRepository
 import org.onap.cps.spi.utils.SessionManager
 import org.onap.cps.utils.JsonObjectMapper
 import org.onap.cps.spi.repository.YangResourceRepository
 import org.onap.cps.spi.utils.SessionManager
 import org.onap.cps.utils.JsonObjectMapper
+import org.onap.cps.utils.TimedYangParser
+import org.onap.cps.yang.TimedYangTextSchemaSourceSetBuilder
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
 import org.springframework.beans.factory.annotation.Autowired
 import org.springframework.context.annotation.Bean
 import org.springframework.context.annotation.Configuration
@@ -76,10 +78,6 @@ class TestConfig extends Specification{
     @Lazy
     JsonObjectMapper jsonObjectMapper
 
     @Lazy
     JsonObjectMapper jsonObjectMapper
 
-    @Autowired
-    @Lazy
-    NotificationService stubbedNotificationService
-
     @Autowired
     @Lazy
     SessionManager stubbedSessionManager
     @Autowired
     @Lazy
     SessionManager stubbedSessionManager
@@ -113,4 +111,15 @@ class TestConfig extends Specification{
     SessionManager sessionManager() {
         return Stub(SessionManager)
     }
     SessionManager sessionManager() {
         return Stub(SessionManager)
     }
-}
\ No newline at end of file
+
+    @Bean
+    TimedYangParser timedYangParser() {
+        return new TimedYangParser()
+    }
+
+    @Bean
+    TimedYangTextSchemaSourceSetBuilder textSchemaSourceSetBuilder() {
+        return new TimedYangTextSchemaSourceSetBuilder()
+    }
+
+}