diff options
author | jhh <jorge.hernandez-herrero@att.com> | 2020-04-23 13:18:48 -0500 |
---|---|---|
committer | jhh <jorge.hernandez-herrero@att.com> | 2020-04-23 15:48:55 -0500 |
commit | e8401780120dc035b074d932b89445cfce228634 (patch) | |
tree | 36acfa1d5f6e1a522940fd3da2648b8d6f6ee450 | |
parent | 3dde9f0b68fae53c14f8fe89e58022381f1f17e0 (diff) |
transaction tracking improvements with telemetry
Issue-ID: POLICY-2456
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
Change-Id: I75b7e8e787d567cf120d7ae7d65d1bff12e8e24e
Signed-off-by: jhh <jorge.hernandez-herrero@att.com>
11 files changed, 726 insertions, 74 deletions
diff --git a/controlloop/common/feature-controlloop-trans/src/main/java/org/onap/policy/drools/apps/controlloop/feature/trans/CacheBasedControlLoopMetricsManager.java b/controlloop/common/feature-controlloop-trans/src/main/java/org/onap/policy/drools/apps/controlloop/feature/trans/CacheBasedControlLoopMetricsManager.java index f0d8eb0ad..75e0f1f4d 100644 --- a/controlloop/common/feature-controlloop-trans/src/main/java/org/onap/policy/drools/apps/controlloop/feature/trans/CacheBasedControlLoopMetricsManager.java +++ b/controlloop/common/feature-controlloop-trans/src/main/java/org/onap/policy/drools/apps/controlloop/feature/trans/CacheBasedControlLoopMetricsManager.java @@ -31,6 +31,7 @@ import java.util.List; import java.util.Properties; import java.util.UUID; import java.util.concurrent.TimeUnit; +import org.apache.commons.collections4.CollectionUtils; import org.onap.policy.controlloop.ControlLoopOperation; import org.onap.policy.controlloop.VirtualControlLoopNotification; import org.onap.policy.drools.persistence.SystemPersistenceConstants; @@ -88,11 +89,10 @@ class CacheBasedControlLoopMetricsManager implements ControlLoopMetrics { this.cacheSize = cacheSize; this.transactionTimeout = transactionTimeout; - CacheLoader<UUID, VirtualControlLoopNotification> loader = - new CacheLoader<UUID, VirtualControlLoopNotification>() { + CacheLoader<UUID, VirtualControlLoopNotification> loader = new CacheLoader<>() { @Override - public VirtualControlLoopNotification load(UUID key) throws Exception { + public VirtualControlLoopNotification load(UUID key) { return null; } }; @@ -176,7 +176,8 @@ class CacheBasedControlLoopMetricsManager implements ControlLoopMetrics { notification.setNotificationTime(ZonedDateTime.now()); } - notification.setFrom(notification.getFrom() + ":" + controller.getName()); + notification.setFrom(notification.getFrom() + ":" + controller.getName() + + ":" + controller.getDrools().getCanonicalSessionNames()); } @Override @@ -218,7 +219,7 @@ class CacheBasedControlLoopMetricsManager implements ControlLoopMetrics { this.transaction(notification, startTime); if (startNotification != null) { - cache.invalidate(startNotification); + removeTransaction(startNotification.getRequestId()); } } @@ -256,28 +257,20 @@ class CacheBasedControlLoopMetricsManager implements ControlLoopMetrics { } protected void metric(VirtualControlLoopNotification notification) { - MdcTransaction trans = MdcTransaction - .newTransaction(notification.getRequestId().toString(), notification.getFrom()) - .setServiceName(notification.getClosedLoopControlName()).setTargetEntity(notification.getTarget()); - + MdcTransaction trans = getMdcTransaction(notification); List<ControlLoopOperation> operations = notification.getHistory(); switch (notification.getNotification()) { case ACTIVE: - trans.setStatusCode(true); - trans.metric().resetTransaction(); + trans.setStatusCode(true).metric().resetTransaction(); break; case OPERATION: - metricOperation(trans, operations); + operation(trans.setStatusCode(true), operations).metric().resetTransaction(); break; case OPERATION_SUCCESS: - trans.setStatusCode(true); - operation(trans, operations); - trans.transaction().resetTransaction(); + operation(trans.setStatusCode(true), operations).metric().transaction().resetTransaction(); break; case OPERATION_FAILURE: - trans.setStatusCode(false); - operation(trans, operations); - trans.transaction().resetTransaction(); + operation(trans.setStatusCode(false), operations).metric().transaction().resetTransaction(); break; default: /* unexpected */ @@ -287,65 +280,66 @@ class CacheBasedControlLoopMetricsManager implements ControlLoopMetrics { } } - private void metricOperation(MdcTransaction trans, List<ControlLoopOperation> operations) { - trans.setStatusCode(true); - if (!operations.isEmpty()) { - ControlLoopOperation operation = operations.get(operations.size() - 1); - trans.setTargetEntity(operation.getTarget()); - trans.setTargetServiceName(operation.getActor()); - } - trans.metric().resetTransaction(); + private MdcTransaction getMdcTransaction(VirtualControlLoopNotification notification) { + return MdcTransaction + .newTransaction(notification.getRequestId().toString(), notification.getFrom()) + .setServiceName(notification.getClosedLoopControlName()) + .setServiceInstanceId(notification.getPolicyScope() + + ":" + notification.getPolicyName() + ":" + notification.getPolicyVersion()) + .setProcessKey("" + notification.getAai()) + .setTargetEntity(notification.getTargetType() + "." + notification.getTarget()) + .setResponseCode((notification.getNotification() != null) ? notification.getNotification().name() : "-") + .setResponseDescription(notification.getMessage()) + .setClientIpAddress(notification.getClosedLoopEventClient()); } - protected void operation(MdcTransaction trans, List<ControlLoopOperation> operations) { - if (!operations.isEmpty()) { - ControlLoopOperation operation = operations.get(operations.size() - 1); + protected MdcTransaction operation(MdcTransaction trans, List<ControlLoopOperation> operations) { + if (CollectionUtils.isEmpty(operations)) { + return trans; + } - if (operation.getTarget() != null) { - trans.setTargetEntity(operation.getTarget()); - } + ControlLoopOperation operation = operations.get(operations.size() - 1); - if (operation.getActor() != null) { - trans.setTargetServiceName(operation.getActor()); - } + if (operation.getActor() != null) { + trans.setTargetServiceName(operation.getActor() + "." + operation.getOperation()); + } - if (operation.getMessage() != null) { - trans.setResponseDescription(operation.getMessage()); - } + if (operation.getTarget() != null) { + trans.setTargetVirtualEntity(operation.getTarget()); + } + if (operation.getSubRequestId() != null) { trans.setInvocationId(operation.getSubRequestId()); + } - if (operation.getOutcome() != null) { - trans.setResponseCode(operation.getOutcome()); - } + if (operation.getOutcome() != null) { + trans.setResponseDescription(operation.getOutcome() + ":" + operation.getMessage()); + } - if (operation.getStart() != null) { - trans.setStartTime(operation.getStart()); - } + if (operation.getStart() != null) { + trans.setStartTime(operation.getStart()); + } - if (operation.getEnd() != null) { - trans.setEndTime(operation.getEnd()); - } + if (operation.getEnd() != null) { + trans.setEndTime(operation.getEnd()); } + + return trans; } protected void transaction(VirtualControlLoopNotification notification, ZonedDateTime startTime) { - MdcTransaction trans = MdcTransaction - .newTransaction(notification.getRequestId().toString(), notification.getFrom()) - .setServiceName(notification.getClosedLoopControlName()).setTargetEntity(notification.getTarget()) - .setStartTime(startTime.toInstant()).setEndTime(notification.getNotificationTime().toInstant()) - .setResponseDescription(notification.getMessage()); + MdcTransaction trans = getMdcTransaction(notification) + .setStartTime(startTime.toInstant()) + .setEndTime(notification.getNotificationTime().toInstant()); switch (notification.getNotification()) { case FINAL_OPENLOOP: - trans.setStatusCode(true); - break; + /* fall through */ case FINAL_SUCCESS: trans.setStatusCode(true); break; case FINAL_FAILURE: - trans.setStatusCode(false); - break; + /* fall through */ case REJECTED: trans.setStatusCode(false); break; @@ -361,11 +355,11 @@ class CacheBasedControlLoopMetricsManager implements ControlLoopMetrics { @Override public String toString() { - final StringBuilder sb = new StringBuilder(); - sb.append("CacheBasedControlLoopMetricsManager{"); - sb.append("cacheSize=").append(cacheSize); - sb.append(", transactionTimeout=").append(transactionTimeout); - sb.append('}'); - return sb.toString(); + return "CacheBasedControlLoopMetricsManager{" + "cacheSize=" + cacheSize + + ",transactionTimeout=" + + transactionTimeout + + ",cacheOccupancy=" + + getCacheOccupancy() + + "}"; } } diff --git a/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/apps/controlloop/feature/trans/ControlLoopMetricsFeatureTest.java b/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/apps/controlloop/feature/trans/ControlLoopMetricsFeatureTest.java index b713e8e8f..eeb382ae1 100644 --- a/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/apps/controlloop/feature/trans/ControlLoopMetricsFeatureTest.java +++ b/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/apps/controlloop/feature/trans/ControlLoopMetricsFeatureTest.java @@ -23,6 +23,7 @@ package org.onap.policy.drools.apps.controlloop.feature.trans; import static org.awaitility.Awaitility.await; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -34,8 +35,10 @@ import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; +import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.controlloop.ControlLoopNotificationType; import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.util.Serialization; import org.onap.policy.drools.persistence.SystemPersistenceConstants; import org.onap.policy.drools.system.PolicyController; import org.onap.policy.drools.system.PolicyEngineConstants; @@ -87,7 +90,7 @@ public class ControlLoopMetricsFeatureTest { } @Test - public void testValidActiveNotification() throws InterruptedException { + public void testValidActiveNotification() { ControlLoopMetricsFeature feature = new ControlLoopMetricsFeature(); VirtualControlLoopNotification notification = new VirtualControlLoopNotification(); UUID requestId = UUID.randomUUID(); @@ -99,7 +102,7 @@ public class ControlLoopMetricsFeatureTest { assertTrue(ControlLoopMetricsManager.getManager().getTransaction(requestId).getFrom() .contains(testController.getName())); assertNotNull(ControlLoopMetricsManager.getManager().getTransaction(requestId).getNotificationTime()); - assertTrue(ControlLoopMetricsManager.getManager().getCacheOccupancy() == 1); + assertEquals(1, ControlLoopMetricsManager.getManager().getCacheOccupancy()); /* wait for the entries to expire */ await().atMost(ControlLoopMetricsManager.getManager().getTransactionTimeout() + 1, TimeUnit.SECONDS) @@ -135,7 +138,7 @@ public class ControlLoopMetricsFeatureTest { } @Test - public void testEviction() throws InterruptedException { + public void testEviction() { ControlLoopMetricsFeature feature = new ControlLoopMetricsFeature(); for (int i = 0; i < ControlLoopMetricsManager.getManager().getCacheSize(); i++) { VirtualControlLoopNotification notification = generateNotification(); @@ -151,10 +154,10 @@ public class ControlLoopMetricsFeatureTest { assertEquals(ControlLoopMetricsManager.getManager().getCacheOccupancy(), ControlLoopMetricsManager.getManager().getCacheOccupancy()); assertNotNull(ControlLoopMetricsManager.getManager().getTransaction(overflowNotification.getRequestId())); - assertTrue(ControlLoopMetricsManager.getManager().getTransactionIds().size() == ControlLoopMetricsManager - .getManager().getCacheSize()); - assertTrue(ControlLoopMetricsManager.getManager().getCacheOccupancy() == ControlLoopMetricsManager.getManager() - .getCacheSize()); + assertEquals(ControlLoopMetricsManager.getManager().getTransactionIds().size(), + ControlLoopMetricsManager.getManager().getCacheSize()); + assertEquals(ControlLoopMetricsManager.getManager().getCacheOccupancy(), + ControlLoopMetricsManager.getManager().getCacheSize()); assertFalse(ControlLoopMetricsManager.getManager().getTransactionIds().isEmpty()); assertFalse(ControlLoopMetricsManager.getManager().getTransactions().isEmpty()); @@ -163,10 +166,10 @@ public class ControlLoopMetricsFeatureTest { .until(() -> ControlLoopMetricsManager.getManager().getTransactions().isEmpty()); ControlLoopMetricsManager.getManager().refresh(); - assertTrue(ControlLoopMetricsManager.getManager().getTransactionIds().size() == ControlLoopMetricsManager - .getManager().getCacheOccupancy()); - assertFalse(ControlLoopMetricsManager.getManager().getCacheOccupancy() == ControlLoopMetricsManager.getManager() - .getCacheSize()); + assertEquals(ControlLoopMetricsManager.getManager().getTransactionIds().size(), + ControlLoopMetricsManager.getManager().getCacheOccupancy()); + assertNotEquals(ControlLoopMetricsManager.getManager().getCacheOccupancy(), + ControlLoopMetricsManager.getManager().getCacheSize()); assertTrue(ControlLoopMetricsManager.getManager().getTransactionIds().isEmpty()); assertTrue(ControlLoopMetricsManager.getManager().getTransactions().isEmpty()); @@ -184,6 +187,72 @@ public class ControlLoopMetricsFeatureTest { @Test public void getSequenceNumber() { ControlLoopMetricsFeature feature = new ControlLoopMetricsFeature(); - assertTrue(feature.getSequenceNumber() == ControlLoopMetricsFeature.FEATURE_SEQUENCE_PRIORITY); + assertEquals(feature.getSequenceNumber(), ControlLoopMetricsFeature.FEATURE_SEQUENCE_PRIORITY); + } + + @Test + public void testSuccessControlLoop() { + ControlLoopMetricsFeature feature = new ControlLoopMetricsFeature(); + + String activeNotification = ResourceUtils.getResourceAsString("policy-cl-mgt-active.json"); + VirtualControlLoopNotification active = + Serialization.gsonPretty.fromJson(activeNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, active); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + String opStartNotification = ResourceUtils.getResourceAsString("policy-cl-mgt-operation.json"); + VirtualControlLoopNotification opStart = + Serialization.gsonPretty.fromJson(opStartNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, opStart); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + String permitNotification = ResourceUtils.getResourceAsString("policy-cl-mgt-permit.json"); + VirtualControlLoopNotification permit = + Serialization.gsonPretty.fromJson(permitNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, permit); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + String restartNotification = ResourceUtils.getResourceAsString("policy-cl-mgt-restart.json"); + VirtualControlLoopNotification restart = + Serialization.gsonPretty.fromJson(restartNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, restart); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + String restartSuccessNotification = + ResourceUtils.getResourceAsString("policy-cl-mgt-restart-success.json"); + VirtualControlLoopNotification restartSuccess = + Serialization.gsonPretty.fromJson(restartSuccessNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, restartSuccess); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + String finalSuccessNotification = + ResourceUtils.getResourceAsString("policy-cl-mgt-final-success.json"); + VirtualControlLoopNotification finalSuccess = + Serialization.gsonPretty.fromJson(finalSuccessNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, finalSuccess); + assertEquals(0, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + } + + @Test + public void testUntrackedNotifications() throws InterruptedException { + ControlLoopMetricsFeature feature = new ControlLoopMetricsFeature(); + + String finalSuccessNotification = + ResourceUtils.getResourceAsString("policy-cl-mgt-final-success.json"); + VirtualControlLoopNotification finalSuccess = + Serialization.gsonPretty.fromJson(finalSuccessNotification, VirtualControlLoopNotification.class); + finalSuccess.setRequestId(UUID.randomUUID()); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, finalSuccess); + assertEquals(0, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + String opStartNotification = + ResourceUtils.getResourceAsString("policy-cl-mgt-operation.json"); + VirtualControlLoopNotification opStart = + Serialization.gsonPretty.fromJson(opStartNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, CommInfrastructure.DMAAP, POLICY_CL_MGT, opStart); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + Thread.sleep((ControlLoopMetricsManager.getManager().getTransactionTimeout() + 1) * 1000L); // NOSONAR + assertEquals(0, ControlLoopMetricsManager.getManager().getTransactionIds().size()); } } diff --git a/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/server/restful/RestTransactionTracker.java b/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/server/restful/RestTransactionTracker.java new file mode 100644 index 000000000..b954167ee --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/server/restful/RestTransactionTracker.java @@ -0,0 +1,129 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.server.restful; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import java.util.UUID; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.onap.policy.common.endpoints.http.server.YamlMessageBodyHandler; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.drools.apps.controlloop.feature.trans.ControlLoopMetricsManager; + +/** + * REST Transaction Tracker. + */ + +@Path("/policy/pdp/engine/controllers") +@Produces({MediaType.APPLICATION_JSON, YamlMessageBodyHandler.APPLICATION_YAML}) +@Consumes({MediaType.APPLICATION_JSON, YamlMessageBodyHandler.APPLICATION_YAML}) +@Api +public class RestTransactionTracker { + + /** + * GET transactions. + */ + + @GET + @Path("transactions") + @ApiOperation(value = "Retrieve in-progress transactions", responseContainer = "List") + public Response transactions() { + return Response.status(Response.Status.OK) + .entity(ControlLoopMetricsManager.getManager().getTransactions()).build(); + } + + /** + * GET one transaction. + */ + + @GET + @Path("transactions/{transactionId}") + @ApiOperation(value = "Retrieve an in-progress transaction", response = VirtualControlLoopNotification.class) + public Response transactionId( + @ApiParam(value = "UUID", required = true) @PathParam("transactionId") String transactionId) { + VirtualControlLoopNotification notification = + ControlLoopMetricsManager.getManager().getTransaction(UUID.fromString(transactionId)); + return Response.status((notification != null) ? Response.Status.OK : Response.Status.NOT_FOUND) + .entity(notification).build(); + } + + /** + * Resets the cache with a new cache size. + */ + + @PUT + @Path("transactions/cacheSize/{cacheSize}") + @ApiOperation(value = "Sets the cache size", response = Integer.class) + public Response cacheSize( + @ApiParam(value = "cache size", required = true) @PathParam("cacheSize") int cacheSize) { + ControlLoopMetricsManager.getManager().resetCache(cacheSize, + ControlLoopMetricsManager.getManager().getTransactionTimeout()); + return Response.status(Response.Status.OK) + .entity(ControlLoopMetricsManager.getManager().getCacheSize()).build(); + } + + /** + * GET the cache size. + */ + + @GET + @Path("transactions/cacheSize") + @ApiOperation(value = "Gets the cache size", response = Integer.class) + public Response cacheSize() { + return Response.status(Response.Status.OK) + .entity(ControlLoopMetricsManager.getManager().getCacheSize()).build(); + } + + /** + * Resets the cache with a new transaction timeout in seconds. + */ + + @PUT + @Path("transactions/timeout/{timeoutSecs}") + @ApiOperation(value = "Sets the timeout in seconds", response = Integer.class) + public Response timeout( + @ApiParam(value = "timeout", required = true) @PathParam("timeoutSecs") long timeoutSecs) { + ControlLoopMetricsManager.getManager().resetCache( + ControlLoopMetricsManager.getManager().getCacheSize(), timeoutSecs); + return Response.status(Response.Status.OK) + .entity(ControlLoopMetricsManager.getManager().getTransactionTimeout()).build(); + } + + /** + * GET the cache timeout. + */ + + @GET + @Path("transactions/timeout") + @ApiOperation(value = "Gets the cache timeout", response = Long.class) + public Response timeout() { + return Response.status(Response.Status.OK) + .entity(ControlLoopMetricsManager.getManager().getTransactionTimeout()).build(); + } +} diff --git a/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/server/restful/RestTransactionTrackerTest.java b/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/server/restful/RestTransactionTrackerTest.java new file mode 100644 index 000000000..2fa4ed532 --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/java/org/onap/policy/drools/server/restful/RestTransactionTrackerTest.java @@ -0,0 +1,160 @@ +/* + * ============LICENSE_START======================================================= + * ONAP + * ================================================================================ + * Copyright (C) 2020 AT&T Intellectual Property. All rights reserved. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.drools.server.restful; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.List; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Response; +import org.jetbrains.annotations.NotNull; +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; +import org.onap.policy.common.endpoints.event.comm.Topic; +import org.onap.policy.common.endpoints.event.comm.bus.internal.BusTopicParams; +import org.onap.policy.common.endpoints.http.client.HttpClient; +import org.onap.policy.common.endpoints.http.client.HttpClientFactoryInstance; +import org.onap.policy.common.endpoints.http.server.HttpServletServer; +import org.onap.policy.common.endpoints.http.server.HttpServletServerFactoryInstance; +import org.onap.policy.common.utils.network.NetworkUtil; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.controlloop.VirtualControlLoopNotification; +import org.onap.policy.controlloop.util.Serialization; +import org.onap.policy.drools.apps.controlloop.feature.trans.ControlLoopMetricsFeature; +import org.onap.policy.drools.apps.controlloop.feature.trans.ControlLoopMetricsManager; +import org.onap.policy.drools.persistence.SystemPersistenceConstants; +import org.onap.policy.drools.system.PolicyController; +import org.onap.policy.drools.system.PolicyEngineConstants; + +public class RestTransactionTrackerTest { + + private static PolicyController testController; + private static HttpClient client; + + @BeforeClass + public static void testBeforeClass() throws Exception { + SystemPersistenceConstants.getManager().setConfigurationDir("target/test-classes"); + + HttpServletServerFactoryInstance.getServerFactory().destroy(); + HttpClientFactoryInstance.getClientFactory().destroy(); + + HttpClientFactoryInstance.getClientFactory().build( + BusTopicParams.builder() + .clientName("trans") + .hostname("localhost") + .port(8769) + .basePath("policy/pdp/engine/controllers/transactions") + .managed(true) + .build()); + + HttpServletServer server = + HttpServletServerFactoryInstance + .getServerFactory() + .build("trans", "localhost", 8769, "/", true, true); + server.addServletClass("/*", RestTransactionTracker.class.getName()); + server.waitedStart(5000L); + assertTrue(NetworkUtil.isTcpPortOpen("localhost", 8769, 5, 10000L)); + + testController = PolicyEngineConstants.getManager().createPolicyController("metrics", + SystemPersistenceConstants.getManager().getControllerProperties("metrics")); + + client = HttpClientFactoryInstance.getClientFactory().get("trans"); + } + + @AfterClass + public static void testAfterClass() { + HttpClientFactoryInstance.getClientFactory().destroy(); + HttpServletServerFactoryInstance.getServerFactory().destroy(); + + SystemPersistenceConstants.getManager().setConfigurationDir(null); + } + + @Test + public void testConfiguration() { + equals(get("cacheSize", Response.Status.OK.getStatusCode()), Integer.class, 3); + equals(get("timeout", Response.Status.OK.getStatusCode()), Integer.class, 2); + + put("cacheSize/10", "", Response.Status.OK.getStatusCode()); + put("timeout/20", "", Response.Status.OK.getStatusCode()); + + equals(get("cacheSize", Response.Status.OK.getStatusCode()), Integer.class, 10); + equals(get("timeout", Response.Status.OK.getStatusCode()), Integer.class, 20); + + put("cacheSize/3", "", Response.Status.OK.getStatusCode()); + put("timeout/2", "", Response.Status.OK.getStatusCode()); + + equals(get("cacheSize", Response.Status.OK.getStatusCode()), Integer.class, 3); + equals(get("timeout", Response.Status.OK.getStatusCode()), Integer.class, 2); + } + + @Test + public void testTransactions() { + equals(get("/", Response.Status.OK.getStatusCode()), List.class, Collections.emptyList()); + + ControlLoopMetricsFeature feature = new ControlLoopMetricsFeature(); + + assertTrue(HttpClient.getBody(get("/", Response.Status.OK.getStatusCode()), List.class).isEmpty()); + get("/664be3d2-6c12-4f4b-a3e7-c349acced200", Response.Status.NOT_FOUND.getStatusCode()); + + String activeNotification = ResourceUtils.getResourceAsString("policy-cl-mgt-active.json"); + VirtualControlLoopNotification active = + Serialization.gsonPretty.fromJson(activeNotification, VirtualControlLoopNotification.class); + feature.beforeDeliver(testController, Topic.CommInfrastructure.DMAAP, "POLICY-CL-MGT", active); + assertEquals(1, ControlLoopMetricsManager.getManager().getTransactionIds().size()); + + assertFalse(HttpClient.getBody(get("/", Response.Status.OK.getStatusCode()), List.class).isEmpty()); + notNull(get("/664be3d2-6c12-4f4b-a3e7-c349acced200", Response.Status.OK.getStatusCode()), String.class); + } + + private Response get(String contextPath, int statusCode) { + Response response = client.get(contextPath); + return checkResponse(statusCode, response); + } + + private Response put(String contextPath, String body, int statusCode) { + Response response = client.put(contextPath, Entity.json(body), Collections.emptyMap()); + return checkResponse(statusCode, response); + } + + private <T, Y> void equals(Response response, Class<T> clazz, Y expected) { + assertEquals(expected, HttpClient.getBody(response, clazz)); + } + + private <T> void notNull(Response response, Class<T> clazz) { + assertNotNull(HttpClient.getBody(response, clazz)); + } + + private <T> void empty(Response response, Class<T> clazz) { + assertNull(HttpClient.getBody(response, clazz)); + } + + @NotNull + private Response checkResponse(int statusCode, Response response) { + assertEquals(statusCode, response.getStatus()); + return response; + } +}
\ No newline at end of file diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/logback.xml b/controlloop/common/feature-controlloop-trans/src/test/resources/logback.xml new file mode 100644 index 000000000..6a25769e3 --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/logback.xml @@ -0,0 +1,148 @@ +<!-- + ============LICENSE_START======================================================= + policy-management + ================================================================================ + Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved. + ================================================================================ + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + ============LICENSE_END========================================================= + --> + +<configuration scan="true" scanPeriod="30 seconds" debug="false"> + + <property name="logDir" value="target/test-classes" /> + + <property name="errorLog" value="error" /> + <property name="debugLog" value="debug" /> + <property name="networkLog" value="network" /> + + <property name="metricLog" value="metric" /> + <property name="transactionLog" value="audit" /> + + <property name="debugPattern" + value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%level|%logger{0}|%thread] %msg%n" /> + <property name="errorPattern" value="${debugPattern}" /> + <property name="networkPattern" value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}|%t]%m%n" /> + <property name="abstractNetworkPattern" + value="[%d{yyyy-MM-dd'T'HH:mm:ss.SSS+00:00, UTC}] [%X{networkEventType:-NULL}|%X{networkProtocol:-NULL}|%X{networkTopic:-NULL}|%X{requestID:-NULL}]%n" /> + + <property name="metricPattern" + value="%X{RequestID}|%X{InvocationID}|%X{ServiceName}|%X{PartnerName}|%X{BeginTimestamp}|%X{EndTimestamp}|%X{ElapsedTime}|%X{ServiceInstanceID}|%X{VirtualServerName}|%X{StatusCode}|%X{ResponseCode}|%X{ResponseDescription}|%X{InstanceUUID}|%X{Severity}|%X{TargetEntity}|%X{TargetServiceName}|%X{Server}|%X{ServerIPAddress}|%X{ServerFQDN}|%X{ClientIPAddress}|%X{ProcessKey}|%X{RemoteHost}||%X{TargetVirtualEntity}|%level|%thread| %msg%n" /> + <property name="transactionPattern" value="${metricPattern}" /> + + <appender name="ErrorOut" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDir}/${errorLog}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDir}/${errorLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> + <level>WARN</level> + </filter> + <encoder> + <pattern>${errorPattern}</pattern> + </encoder> + </appender> + + <appender name="AsyncErrorOut" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="ErrorOut" /> + </appender> + + <appender name="DebugOut" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDir}/${debugLog}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDir}/${debugLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>${debugPattern}</pattern> + </encoder> + </appender> + + <appender name="AsyncDebugOut" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="DebugOut" /> + </appender> + + <appender name="NetworkOut" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDir}/${networkLog}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDir}/${networkLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + <encoder> + <pattern>${networkPattern}</pattern> + </encoder> + </appender> + + <appender name="AsyncNetworkOut" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="NetworkOut" /> + </appender> + + <appender name="MetricOut" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDir}/${metricLog}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDir}/${metricLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + <filter class="org.onap.policy.drools.utils.logging.LoggerMarkerFilter$MetricLoggerMarkerFilter" /> + <encoder> + <pattern>${metricPattern}</pattern> + </encoder> + </appender> + + <appender name="AsyncMetricOut" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="MetricOut" /> + </appender> + + <appender name="TransactionOut" class="ch.qos.logback.core.rolling.RollingFileAppender"> + <file>${logDir}/${transactionLog}.log</file> + <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy"> + <fileNamePattern>${logDir}/${transactionLog}.%d{yyyy-MM-dd}.%i.log.zip</fileNamePattern> + <maxFileSize>50MB</maxFileSize> + <maxHistory>30</maxHistory> + <totalSizeCap>10GB</totalSizeCap> + </rollingPolicy> + <filter class="org.onap.policy.drools.utils.logging.LoggerMarkerFilter$TransactionLoggerMarkerFilter" /> + <encoder> + <pattern>${transactionPattern}</pattern> + </encoder> + </appender> + + <appender name="AsyncTransactionOut" class="ch.qos.logback.classic.AsyncAppender"> + <appender-ref ref="TransactionOut" /> + </appender> + + <logger name="network" level="INFO" additivity="false"> + <appender-ref ref="AsyncNetworkOut" /> + </logger> + + <logger name="org.eclipse.jetty.server.RequestLog" level="info" additivity="false"> + <appender-ref ref="AsyncNetworkOut" /> + </logger> + + <root level="INFO"> + <appender-ref ref="AsyncDebugOut" /> + <appender-ref ref="AsyncErrorOut" /> + <appender-ref ref="AsyncMetricOut" /> + <appender-ref ref="AsyncTransactionOut" /> + </root> + +</configuration> diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-active.json b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-active.json new file mode 100644 index 000000000..9430327c3 --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-active.json @@ -0,0 +1,21 @@ +{ + "AAI": { + "vserver.prov-status": "ACTIVE", + "vserver.is-closed-loop-disabled": "false", + "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app" + }, + "closedLoopAlarmStart": 1463679805324, + "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e", + "version": "1.0.2", + "requestId": "664be3d2-6c12-4f4b-a3e7-c349acced200", + "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca", + "targetType": "VNF", + "target": "generic-vnf.vnf-id", + "from": "policy", + "policyScope": "onap.policies.controlloop.operational.common.Drools:1.0.0", + "policyName": "operational.restart.EVENT", + "policyVersion": "1.0.0", + "notification": "ACTIVE", + "notificationTime": "2020-04-20 19:12:17.223175+00:00", + "history": [] +} diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-final-success.json b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-final-success.json new file mode 100644 index 000000000..e1f98de28 --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-final-success.json @@ -0,0 +1,32 @@ +{ + "AAI": { + "vserver.prov-status": "ACTIVE", + "vserver.is-closed-loop-disabled": "false", + "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app" + }, + "closedLoopAlarmStart": 1463679805324, + "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e", + "version": "1.0.2", + "requestId": "664be3d2-6c12-4f4b-a3e7-c349acced200", + "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca", + "targetType": "VNF", + "target": "generic-vnf.vnf-id", + "from": "policy", + "policyScope": "onap.policies.controlloop.operational.common.Drools:1.0.0", + "policyName": "operational.restart.EVENT.MANAGER.FINAL", + "policyVersion": "1.0.0", + "notification": "FINAL: SUCCESS", + "notificationTime": "2020-04-20 19:12:17.684718+00:00", + "history": [ + { + "actor": "APPC", + "operation": "Restart", + "target": "Target [type=VM, resourceId=null]", + "start": 1587409937614, + "end": 1587409937679, + "subRequestId": "38ce5fcb-f16a-4cfc-abc6-8d8b78e2f959", + "outcome": "Success", + "message": "Restart Successful" + } + ] +} diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-operation.json b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-operation.json new file mode 100644 index 000000000..567af4893 --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-operation.json @@ -0,0 +1,22 @@ +{ + "AAI": { + "vserver.prov-status": "ACTIVE", + "vserver.is-closed-loop-disabled": "false", + "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app" + }, + "closedLoopAlarmStart": 1463679805324, + "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e", + "version": "1.0.2", + "requestId": "664be3d2-6c12-4f4b-a3e7-c349acced200", + "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca", + "targetType": "VNF", + "target": "generic-vnf.vnf-id", + "from": "policy", + "policyScope": "onap.policies.controlloop.operational.common.Drools:1.0.0", + "policyName": "operational.restart.EVENT.MANAGER.PROCESSING", + "policyVersion": "1.0.0", + "notification": "OPERATION", + "message": "Sending guard query for APPC Restart", + "notificationTime": "2020-04-20 19:12:17.244277+00:00", + "history": [] +} diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-permit.json b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-permit.json new file mode 100644 index 000000000..d8c28be61 --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-permit.json @@ -0,0 +1,22 @@ +{ + "AAI": { + "vserver.prov-status": "ACTIVE", + "vserver.is-closed-loop-disabled": "false", + "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app" + }, + "closedLoopAlarmStart": 1463679805324, + "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e", + "version": "1.0.2", + "requestId": "664be3d2-6c12-4f4b-a3e7-c349acced200", + "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca", + "targetType": "VNF", + "target": "generic-vnf.vnf-id", + "from": "policy", + "policyScope": "onap.policies.controlloop.operational.common.Drools:1.0.0", + "policyName": "operational.restart.EVENT.MANAGER.PROCESSING", + "policyVersion": "1.0.0", + "notification": "OPERATION", + "message": "Guard result for APPC Restart is Permit", + "notificationTime": "2020-04-20 19:12:17.608770+00:00", + "history": [] +} diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-restart-success.json b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-restart-success.json new file mode 100644 index 000000000..80686452d --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-restart-success.json @@ -0,0 +1,33 @@ +{ + "AAI": { + "vserver.prov-status": "ACTIVE", + "vserver.is-closed-loop-disabled": "false", + "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app" + }, + "closedLoopAlarmStart": 1463679805324, + "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e", + "version": "1.0.2", + "requestId": "664be3d2-6c12-4f4b-a3e7-c349acced200", + "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca", + "targetType": "VNF", + "target": "generic-vnf.vnf-id", + "from": "policy", + "policyScope": "onap.policies.controlloop.operational.common.Drools:1.0.0", + "policyName": "operational.restart.EVENT.MANAGER.PROCESSING", + "policyVersion": "1.0.0", + "notification": "OPERATION: SUCCESS", + "message": "actor=APPC,operation=Restart,target=Target [type=VM, resourceId=null],start=2020-04-20T19:12:17.614106Z,end=2020-04-20T19:12:17.679500Z,subRequestId=38ce5fcb-f16a-4cfc-abc6-8d8b78e2f959,outcome=Success,message=Restart Successful", + "notificationTime": "2020-04-20 19:12:17.680716+00:00", + "history": [ + { + "actor": "APPC", + "operation": "Restart", + "target": "Target [type=VM, resourceId=null]", + "start": 1587409937614, + "end": 1587409937679, + "subRequestId": "38ce5fcb-f16a-4cfc-abc6-8d8b78e2f959", + "outcome": "Success", + "message": "Restart Successful" + } + ] +} diff --git a/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-restart.json b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-restart.json new file mode 100644 index 000000000..1825a02be --- /dev/null +++ b/controlloop/common/feature-controlloop-trans/src/test/resources/policy-cl-mgt-restart.json @@ -0,0 +1,22 @@ +{ + "AAI": { + "vserver.prov-status": "ACTIVE", + "vserver.is-closed-loop-disabled": "false", + "generic-vnf.vnf-id": "vCPE_Infrastructure_vGMUX_demo_app" + }, + "closedLoopAlarmStart": 1463679805324, + "closedLoopControlName": "ControlLoop-vCPE-48f0c2c3-a172-4192-9ae3-052274181b6e", + "version": "1.0.2", + "requestId": "664be3d2-6c12-4f4b-a3e7-c349acced200", + "closedLoopEventClient": "DCAE_INSTANCE_ID.dcae-tca", + "targetType": "VNF", + "target": "generic-vnf.vnf-id", + "from": "policy", + "policyScope": "onap.policies.controlloop.operational.common.Drools:1.0.0", + "policyName": "operational.restart.EVENT.MANAGER.PROCESSING", + "policyVersion": "1.0.0", + "notification": "OPERATION", + "message": "actor=APPC,operation=Restart,target=Target [type=VM, resourceId=null],subRequestId=38ce5fcb-f16a-4cfc-abc6-8d8b78e2f959", + "notificationTime": "2020-04-20 19:12:17.614625+00:00", + "history": [] +} |