Adding support for custom application metrics in Xacml-PDP. 32/129332/6
authorisaac <isaac.adorno@att.com>
Thu, 19 May 2022 20:12:05 +0000 (15:12 -0500)
committerisaac <isaac.adorno@att.com>
Tue, 21 Jun 2022 23:22:34 +0000 (18:22 -0500)
Issue-ID: POLICY-3762
Signed-off-by: isaac <isaac.adorno@att.com>
Change-Id: I84b43ae3a61702ceaf9f526a1c537caa77802af6

main/src/main/java/org/onap/policy/pdpx/main/rest/XacmlPdpStatisticsManager.java
main/src/main/java/org/onap/policy/pdpx/main/rest/model/StatisticsReport.java
main/src/main/java/org/onap/policy/pdpx/main/rest/provider/DecisionProvider.java
main/src/main/java/org/onap/policy/pdpx/main/rest/provider/StatisticsProvider.java
main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpRestServer.java
main/src/test/java/org/onap/policy/pdpx/main/rest/TestXacmlPdpStatistics.java

index 26ccfd3..253a009 100644 (file)
@@ -21,6 +21,8 @@
 package org.onap.policy.pdpx.main.rest;
 
 import io.prometheus.client.Counter;
+import java.util.HashMap;
+import java.util.Map;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.Synchronized;
@@ -42,6 +44,7 @@ public class XacmlPdpStatisticsManager {
     public static final String DENY_OPERATION = "deny";
     public static final String INDETERMINANT_OPERATION = "indeterminant";
     public static final String NOT_APPLICABLE_OPERATION = "not_applicable";
+    public static final String APPLICATION = "application";
 
     protected static final Counter deploymentsCounter =
         Counter.build().namespace(PROMETHEUS_NAMESPACE).name(PrometheusUtils.POLICY_DEPLOYMENTS_METRIC)
@@ -52,7 +55,7 @@ public class XacmlPdpStatisticsManager {
 
     protected static final Counter decisionsCounter =
         Counter.build().namespace(PROMETHEUS_NAMESPACE).name(POLICY_DECISIONS_METRIC)
-            .labelNames(PrometheusUtils.STATUS_METRIC_LABEL)
+            .labelNames(APPLICATION, PrometheusUtils.STATUS_METRIC_LABEL)
             .help(POLICY_DECISIONS_HELP)
             .register();
 
@@ -67,133 +70,142 @@ public class XacmlPdpStatisticsManager {
     private long undeployFailureCount;
     private long indeterminantDecisionsCount;
     private long notApplicableDecisionsCount;
+    private Map<String, Map<String, Integer>> applicationMetrics = new HashMap<>();
+
+    /**
+     * Used to update our Map of ApplicationNames to statistics.
+     * A typical applicationsMetric map could look something like this:
+     * {
+     *     "app_1_name": {
+     *         "permit_decisions_count": 1,
+     *         "deny_decisions_count": 1
+     *     },
+     *     "app_2_name": {
+     *         "indeterminant_decisions_count": 1,
+     *         "not_applicable_decisions_count": 1
+     *     }
+     * }
+     * @param appName - the current app we are updating decisions for
+     * @param updateMethod - the kind of decision we made for our app
+     */
+    @Synchronized
+    public void updateApplicationMetrics(String appName, String updateMethod) {
+        if (!applicationMetrics.containsKey(appName)) {
+            Map<String, Integer> appMap = new HashMap<>();
+            appMap.put(updateMethod, 1);
+            applicationMetrics.put(appName, appMap);
+        } else {
+            int newTotal = applicationMetrics.get(appName).getOrDefault(updateMethod, 0) + 1;
+            applicationMetrics.get(appName).put(updateMethod, newTotal);
+        }
+    }
 
     /**
      * Method to set the xacml pdp total policy types count. This
      * doesn't really increment, it depends on the applications
      * that are loaded. Which can be dynamic.
-     *
-     * @return the total
      */
     @Synchronized
-    public long setTotalPolicyTypesCount(long newCount) {
+    public void setTotalPolicyTypesCount(long newCount) {
         totalPolicyTypesCount = newCount;
-        return totalPolicyTypesCount;
     }
 
     /**
      * Method to set the xacml pdp total policies count. This
      * doesn't really increment, it depends on the applications
      * that are loaded. Which can be dynamic.
-     *
-     * @return the total
      */
     @Synchronized
-    public long setTotalPolicyCount(long newCount) {
+    public void setTotalPolicyCount(long newCount) {
         totalPoliciesCount = newCount;
-        return totalPoliciesCount;
     }
 
     /**
      * Method to update the number of error decisions.
-     *
-     * @return the errorDecisionsCount
      */
     @Synchronized
-    public long updateErrorCount() {
-        return ++errorCount;
+    public void updateErrorCount() {
+        ++errorCount;
     }
 
     /**
      * Method to update the number of permit decisions.
-     *
-     * @return the permitDecisionsCount
      */
     @Synchronized
-    public long updatePermitDecisionsCount() {
-        decisionsCounter.labels(PERMIT_OPERATION).inc();
-        return ++permitDecisionsCount;
+    public void updatePermitDecisionsCount(String appName) {
+        decisionsCounter.labels(appName, PERMIT_OPERATION).inc();
+        updateApplicationMetrics(appName, "permit_decisions_count");
+        ++permitDecisionsCount;
     }
 
     /**
      * Method to update the number of deny decisions.
-     *
-     * @return the denyDecisionsCount
      */
     @Synchronized
-    public long updateDenyDecisionsCount() {
-        decisionsCounter.labels(DENY_OPERATION).inc();
-        return ++denyDecisionsCount;
+    public void updateDenyDecisionsCount(String appName) {
+        decisionsCounter.labels(appName, DENY_OPERATION).inc();
+        updateApplicationMetrics(appName, "deny_decisions_count");
+        ++denyDecisionsCount;
     }
 
     /**
-     * Method to update the number of successful deploys.
-     *
-     * @return the deploySuccessCount
+     * Method to update the number of indeterminant decisions.
      */
     @Synchronized
-    public long updateDeploySuccessCount() {
-        deploymentsCounter.labels(PrometheusUtils.DEPLOY_OPERATION,
-            PdpResponseStatus.SUCCESS.name()).inc();
-        return ++deploySuccessCount;
+    public void updateIndeterminantDecisionsCount(String appName) {
+        decisionsCounter.labels(appName, INDETERMINANT_OPERATION).inc();
+        updateApplicationMetrics(appName, "indeterminant_decisions_count");
+        ++indeterminantDecisionsCount;
     }
 
     /**
-     * Method to update the number of failed deploys.
-     *
-     * @return the deployFailureCount
+     * Method to update the number of not applicable decisions.
      */
     @Synchronized
-    public long updateDeployFailureCount() {
-        deploymentsCounter.labels(PrometheusUtils.DEPLOY_OPERATION,
-            PdpResponseStatus.FAIL.name()).inc();
-        return ++deployFailureCount;
+    public void updateNotApplicableDecisionsCount(String appName) {
+        decisionsCounter.labels(appName, NOT_APPLICABLE_OPERATION).inc();
+        updateApplicationMetrics(appName, "not_applicable_decisions_count");
+        ++notApplicableDecisionsCount;
     }
 
     /**
-     * Method to update the number of successful undeploys.
-     *
-     * @return the undeploySuccessCount
+     * Method to update the number of successful deploys.
      */
     @Synchronized
-    public long updateUndeploySuccessCount() {
-        deploymentsCounter.labels(PrometheusUtils.UNDEPLOY_OPERATION,
+    public void updateDeploySuccessCount() {
+        deploymentsCounter.labels(PrometheusUtils.DEPLOY_OPERATION,
             PdpResponseStatus.SUCCESS.name()).inc();
-        return ++undeploySuccessCount;
+        ++deploySuccessCount;
     }
 
     /**
-     * Method to update the number of failed undeploys.
-     *
-     * @return the undeployFailureCount
+     * Method to update the number of failed deploys.
      */
     @Synchronized
-    public long updateUndeployFailureCount() {
-        deploymentsCounter.labels(PrometheusUtils.UNDEPLOY_OPERATION,
+    public void updateDeployFailureCount() {
+        deploymentsCounter.labels(PrometheusUtils.DEPLOY_OPERATION,
             PdpResponseStatus.FAIL.name()).inc();
-        return ++undeployFailureCount;
+        ++deployFailureCount;
     }
 
     /**
-     * Method to update the number of indeterminant decisions.
-     *
-     * @return the indeterminantDecisionsCount
+     * Method to update the number of successful undeploys.
      */
     @Synchronized
-    public long updateIndeterminantDecisionsCount() {
-        decisionsCounter.labels(INDETERMINANT_OPERATION).inc();
-        return ++indeterminantDecisionsCount;
+    public void updateUndeploySuccessCount() {
+        deploymentsCounter.labels(PrometheusUtils.UNDEPLOY_OPERATION,
+            PdpResponseStatus.SUCCESS.name()).inc();
+        ++undeploySuccessCount;
     }
 
     /**
-     * Method to update the number of not applicable decisions.
-     *
-     * @return the notApplicableDecisionsCount
+     * Method to update the number of failed undeploys.
      */
     @Synchronized
-    public long updateNotApplicableDecisionsCount() {
-        decisionsCounter.labels(NOT_APPLICABLE_OPERATION).inc();
-        return ++notApplicableDecisionsCount;
+    public void updateUndeployFailureCount() {
+        deploymentsCounter.labels(PrometheusUtils.UNDEPLOY_OPERATION,
+            PdpResponseStatus.FAIL.name()).inc();
+        ++undeployFailureCount;
     }
 
     /**
@@ -212,5 +224,6 @@ public class XacmlPdpStatisticsManager {
         undeployFailureCount = 0L;
         indeterminantDecisionsCount = 0L;
         notApplicableDecisionsCount = 0L;
+        applicationMetrics.clear();
     }
 }
index d122449..2ddb9c7 100644 (file)
@@ -20,6 +20,7 @@
 
 package org.onap.policy.pdpx.main.rest.model;
 
+import java.util.Map;
 import lombok.Getter;
 import lombok.Setter;
 import lombok.ToString;
@@ -45,4 +46,5 @@ public class StatisticsReport {
     private long undeployFailureCount;
     private long indeterminantDecisionsCount;
     private long notApplicableDecisionsCount;
+    private Map<String, Map<String, Integer>> applicationMetrics;
 }
index 24d0328..98340b2 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2019-2020 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019-2020, 2022 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.
@@ -59,7 +59,7 @@ public class DecisionProvider {
         //
         // Calculate statistics
         //
-        this.calculateStatistic(decision.getValue());
+        this.calculateStatistic(decision.getValue(), application.applicationName());
         //
         // Return the decision
         //
@@ -86,7 +86,7 @@ public class DecisionProvider {
         //
         // Calculate statistics
         //
-        this.calculateStatistic(decision);
+        this.calculateStatistic(decision, nativeApp.applicationName());
         //
         // Return the string decision
         //
@@ -111,7 +111,7 @@ public class DecisionProvider {
                 "Native PDP application cannot be found");
     }
 
-    private void calculateStatistic(Response xacmlResponse) {
+    private void calculateStatistic(Response xacmlResponse, String appName) {
         if (xacmlResponse == null) {
             XacmlPdpStatisticsManager.getCurrent().updateErrorCount();
             return;
@@ -119,22 +119,22 @@ public class DecisionProvider {
         for (Result result : xacmlResponse.getResults()) {
             switch (result.getDecision()) {
                 case PERMIT:
-                    XacmlPdpStatisticsManager.getCurrent().updatePermitDecisionsCount();
+                    XacmlPdpStatisticsManager.getCurrent().updatePermitDecisionsCount(appName);
                     break;
 
                 case DENY:
-                    XacmlPdpStatisticsManager.getCurrent().updateDenyDecisionsCount();
+                    XacmlPdpStatisticsManager.getCurrent().updateDenyDecisionsCount(appName);
                     break;
 
                 case INDETERMINATE:
                 case INDETERMINATE_DENY:
                 case INDETERMINATE_DENYPERMIT:
                 case INDETERMINATE_PERMIT:
-                    XacmlPdpStatisticsManager.getCurrent().updateIndeterminantDecisionsCount();
+                    XacmlPdpStatisticsManager.getCurrent().updateIndeterminantDecisionsCount(appName);
                     break;
 
                 case NOTAPPLICABLE:
-                    XacmlPdpStatisticsManager.getCurrent().updateNotApplicableDecisionsCount();
+                    XacmlPdpStatisticsManager.getCurrent().updateNotApplicableDecisionsCount(appName);
                     break;
 
                 default:
index 73d7436..5089d6e 100644 (file)
@@ -51,6 +51,7 @@ public class StatisticsProvider {
         report.setUndeployFailureCount(stats.getUndeployFailureCount());
         report.setIndeterminantDecisionsCount(stats.getIndeterminantDecisionsCount());
         report.setNotApplicableDecisionsCount(stats.getNotApplicableDecisionsCount());
+        report.setApplicationMetrics(stats.getApplicationMetrics());
         return report;
     }
 }
index a8a7b84..b626142 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2019, 2021 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2021-2022 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.
@@ -22,6 +22,8 @@ package org.onap.policy.pdpx.main.rest;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.HashMap;
+import java.util.Map;
 import javax.ws.rs.client.Invocation;
 import org.junit.Test;
 import org.onap.policy.common.endpoints.report.HealthCheckReport;
@@ -83,12 +85,12 @@ public class TestXacmlPdpRestServer extends CommonRest {
         Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT);
         StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
         LOGGER.info("testStatistics_200 health report {}", report);
-        validateStatisticsReport(report, 0, 200);
+        validateStatisticsReport(report, 0, 200, new HashMap<>());
         updateXacmlPdpStatistics();
         invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT);
         report = invocationBuilder.get(StatisticsReport.class);
         LOGGER.info("testStatistics_200 health report {}", report);
-        validateStatisticsReport(report, 1, 200);
+        validateStatisticsReport(report, 1, 200, returnStatisticsMap());
     }
 
     @Test
@@ -100,7 +102,7 @@ public class TestXacmlPdpRestServer extends CommonRest {
         final Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT);
         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
         LOGGER.info("testStatistics_500 health report {}", report);
-        validateStatisticsReport(report, 0, 500);
+        validateStatisticsReport(report, 0, 500, new HashMap<>());
     }
 
     @Test
@@ -109,7 +111,20 @@ public class TestXacmlPdpRestServer extends CommonRest {
         final Invocation.Builder invocationBuilder = sendHttpsRequest(STATISTICS_ENDPOINT);
         final StatisticsReport report = invocationBuilder.get(StatisticsReport.class);
         LOGGER.info("testHttpsStatistic health report {}", report);
-        validateStatisticsReport(report, 0, 200);
+        validateStatisticsReport(report, 0, 200, new HashMap<>());
+    }
+
+    private Map<String, Map<String, Integer>> returnStatisticsMap() {
+        Map<String, Integer> testAppMetrics1 = new HashMap<>();
+        Map<String, Integer> testAppMetrics2 = new HashMap<>();
+        testAppMetrics1.put("permit_decisions_count", 1);
+        testAppMetrics1.put("deny_decisions_count", 1);
+        testAppMetrics2.put("indeterminant_decisions_count", 1);
+        testAppMetrics2.put("not_applicable_decisions_count", 1);
+        Map<String, Map<String, Integer>> statisticsMap = new HashMap<>();
+        statisticsMap.put("testApp1", testAppMetrics1);
+        statisticsMap.put("testApp2", testAppMetrics2);
+        return statisticsMap;
     }
 
     private void updateXacmlPdpStatistics() {
@@ -117,13 +132,14 @@ public class TestXacmlPdpRestServer extends CommonRest {
         ++nupdates;
         stats.setTotalPolicyCount(nupdates);
         stats.setTotalPolicyTypesCount(nupdates);
-        stats.updatePermitDecisionsCount();
-        stats.updateDenyDecisionsCount();
-        stats.updateIndeterminantDecisionsCount();
-        stats.updateNotApplicableDecisionsCount();
+        stats.updatePermitDecisionsCount("testApp1");
+        stats.updateDenyDecisionsCount("testApp1");
+        stats.updateIndeterminantDecisionsCount("testApp2");
+        stats.updateNotApplicableDecisionsCount("testApp2");
     }
 
-    private void validateStatisticsReport(final StatisticsReport report, final int count, final int code) {
+    private void validateStatisticsReport(final StatisticsReport report, final int count,
+                                          final int code, final Map<String, Map<String, Integer>> decisionsMap) {
         assertEquals(code, report.getCode());
         assertEquals(count, report.getTotalPoliciesCount());
         assertEquals(count, report.getTotalPolicyTypesCount());
@@ -131,6 +147,7 @@ public class TestXacmlPdpRestServer extends CommonRest {
         assertEquals(count, report.getDenyDecisionsCount());
         assertEquals(count, report.getIndeterminantDecisionsCount());
         assertEquals(count, report.getNotApplicableDecisionsCount());
+        assertEquals(decisionsMap, report.getApplicationMetrics());
     }
 
     private void validateHealthCheckReport(final String name, final String url, final boolean healthy, final int code,
index 030b907..856a29a 100644 (file)
@@ -1,6 +1,6 @@
 /*-
  * ============LICENSE_START=======================================================
- * Copyright (C) 2019 AT&T Intellectual Property. All rights reserved.
+ * Copyright (C) 2019, 2022 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.
@@ -23,6 +23,8 @@ package org.onap.policy.pdpx.main.rest;
 
 import static org.junit.Assert.assertEquals;
 
+import java.util.HashMap;
+import java.util.Map;
 import org.junit.Test;
 import org.onap.policy.pdpx.main.CommonRest;
 import org.onap.policy.pdpx.main.rest.model.StatisticsReport;
@@ -43,20 +45,31 @@ public class TestXacmlPdpStatistics extends CommonRest {
     public void testXacmlPdpStatistics_200() throws Exception {
         LOGGER.info("*************************** Running testXacmlPdpStatistics_200 ***************************");
         StatisticsReport report = getXacmlPdpStatistics();
-        validateReport(report, 0, 200);
+        validateReport(report, 0, 200, new HashMap<>());
         updateXacmlPdpStatistics();
         report = getXacmlPdpStatistics();
-        validateReport(report, 1, 200);
+        validateReport(report, 1, 200, returnStatisticsMap());
     }
 
     @Test
     public void testXacmlPdpStatistics_500() throws Exception {
         LOGGER.info("***************************** Running testXacmlPdpStatistics_500 *****************************");
-
         markActivatorDead();
-
         final StatisticsReport report = getXacmlPdpStatistics();
-        validateReport(report, 0, 500);
+        validateReport(report, 0, 500, new HashMap<>());
+    }
+
+    private Map<String, Map<String, Integer>> returnStatisticsMap() {
+        Map<String, Integer> testAppMetrics1 = new HashMap<>();
+        Map<String, Integer> testAppMetrics2 = new HashMap<>();
+        testAppMetrics1.put("permit_decisions_count", 1);
+        testAppMetrics1.put("deny_decisions_count", 1);
+        testAppMetrics2.put("indeterminant_decisions_count", 1);
+        testAppMetrics2.put("not_applicable_decisions_count", 1);
+        Map<String, Map<String, Integer>> statisticsMap = new HashMap<>();
+        statisticsMap.put("testApp1", testAppMetrics1);
+        statisticsMap.put("testApp2", testAppMetrics2);
+        return statisticsMap;
     }
 
     private StatisticsReport getXacmlPdpStatistics() throws Exception {
@@ -69,13 +82,14 @@ public class TestXacmlPdpStatistics extends CommonRest {
         ++nupdates;
         stats.setTotalPolicyCount(nupdates);
         stats.setTotalPolicyTypesCount(nupdates);
-        stats.updatePermitDecisionsCount();
-        stats.updateDenyDecisionsCount();
-        stats.updateIndeterminantDecisionsCount();
-        stats.updateNotApplicableDecisionsCount();
+        stats.updatePermitDecisionsCount("testApp1");
+        stats.updateDenyDecisionsCount("testApp1");
+        stats.updateIndeterminantDecisionsCount("testApp2");
+        stats.updateNotApplicableDecisionsCount("testApp2");
     }
 
-    private void validateReport(final StatisticsReport report, final int count, final int code) {
+    private void validateReport(final StatisticsReport report, final int count,
+                                final int code, final Map<String, Map<String, Integer>> decisionsMap) {
         assertEquals(code, report.getCode());
         assertEquals(count, report.getTotalPoliciesCount());
         assertEquals(count, report.getTotalPolicyTypesCount());
@@ -83,5 +97,6 @@ public class TestXacmlPdpStatistics extends CommonRest {
         assertEquals(count, report.getDenyDecisionsCount());
         assertEquals(count, report.getIndeterminantDecisionsCount());
         assertEquals(count, report.getNotApplicableDecisionsCount());
+        assertEquals(decisionsMap, report.getApplicationMetrics());
     }
 }