You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by jo...@apache.org on 2016/04/08 19:39:57 UTC

ambari git commit: AMBARI-15745 - Create Alert For Reporting Potential Issues With Slow REST Responses (part2) (jonathanhurley)

Repository: ambari
Updated Branches:
  refs/heads/trunk bc17f9cf4 -> ddc656714


AMBARI-15745 - Create Alert For Reporting Potential Issues With Slow REST Responses (part2) (jonathanhurley)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/ddc65671
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/ddc65671
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/ddc65671

Branch: refs/heads/trunk
Commit: ddc656714914c34597eb4791920dd68f1430b242
Parents: bc17f9c
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Fri Apr 8 12:32:59 2016 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Fri Apr 8 13:39:50 2016 -0400

----------------------------------------------------------------------
 .../alerts/AmbariPerformanceRunnable.java       | 89 ++++++++++++--------
 .../server/orm/dao/HostRoleCommandDAO.java      |  9 +-
 ambari-server/src/main/resources/alerts.json    | 18 ++++
 .../alerts/AmbariPerformanceRunnableTest.java   | 70 ++++++++++++++-
 4 files changed, 147 insertions(+), 39 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/ddc65671/ambari-server/src/main/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnable.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnable.java b/ambari-server/src/main/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnable.java
index 63fa12d..a69abeb 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnable.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnable.java
@@ -20,25 +20,25 @@ package org.apache.ambari.server.alerts;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
-import java.util.HashSet;
+import java.util.HashMap;
 import java.util.List;
-import java.util.Set;
+import java.util.Map;
 
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.actionmanager.ActionManager;
 import org.apache.ambari.server.actionmanager.RequestStatus;
+import org.apache.ambari.server.api.query.Query;
+import org.apache.ambari.server.api.query.QueryImpl;
+import org.apache.ambari.server.api.query.render.DefaultRenderer;
+import org.apache.ambari.server.api.resources.ClusterResourceDefinition;
 import org.apache.ambari.server.api.services.BaseRequest;
-import org.apache.ambari.server.controller.AmbariManagementController;
-import org.apache.ambari.server.controller.internal.AbstractControllerResourceProvider;
-import org.apache.ambari.server.controller.internal.ClusterResourceProvider;
-import org.apache.ambari.server.controller.spi.Predicate;
-import org.apache.ambari.server.controller.spi.Request;
-import org.apache.ambari.server.controller.spi.Resource.Type;
-import org.apache.ambari.server.controller.spi.ResourceProvider;
-import org.apache.ambari.server.controller.utilities.PredicateBuilder;
-import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
+import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.security.authorization.internal.InternalAuthenticationToken;
 import org.apache.ambari.server.state.Alert;
 import org.apache.ambari.server.state.AlertState;
 import org.apache.ambari.server.state.Cluster;
@@ -51,9 +51,9 @@ import org.apache.commons.lang.StringUtils;
 import org.apache.commons.lang.math.NumberUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.security.core.context.SecurityContextHolder;
 
 import com.google.inject.Inject;
-import com.google.inject.Provider;
 
 /**
  * The {@link AmbariPerformanceRunnable} is used by the
@@ -104,7 +104,7 @@ public class AmbariPerformanceRunnable extends AlertRunnable {
    * The {@link PerformanceArea} enumeration represents logical areas of
    * functionality to test for performance.
    */
-  private enum PerformanceArea {
+   enum PerformanceArea {
 
     /**
      * Query for requests by {@link RequestStatus#IN_PROGRESS}.
@@ -116,12 +116,32 @@ public class AmbariPerformanceRunnable extends AlertRunnable {
        */
       @Override
       void execute(AmbariPerformanceRunnable runnable, Cluster cluster) throws Exception {
-        runnable.m_actionManager.get().getRequestsByStatus(RequestStatus.IN_PROGRESS,
+        runnable.m_actionManager.getRequestsByStatus(RequestStatus.IN_PROGRESS,
             BaseRequest.DEFAULT_PAGE_SIZE, false);
       }
     },
 
     /**
+     * Query for requests by {@link RequestStatus#IN_PROGRESS}.
+     */
+    HRC_SUMMARY_STATUS("Database Access (Task Status Aggregation)",
+        "task.status.aggregation.warning.threshold", 3000,
+        "task.status.aggregation.critical.threshold", 5000) {
+      /**
+       * {@inheritDoc}
+       */
+      @Override
+      void execute(AmbariPerformanceRunnable runnable, Cluster cluster) throws Exception {
+        List<Long> requestIds = runnable.m_requestDAO.findAllRequestIds(
+            BaseRequest.DEFAULT_PAGE_SIZE, false);
+
+        for (long requestId : requestIds) {
+          runnable.m_hostRoleCommandDAO.findAggregateCounts(requestId);
+        }
+      }
+    },
+
+    /**
      * Query through the REST API framework for a cluster.
      */
     REST_API_GET_CLUSTER("REST API (Cluster)",
@@ -132,25 +152,19 @@ public class AmbariPerformanceRunnable extends AlertRunnable {
        */
       @Override
       void execute(AmbariPerformanceRunnable runnable, Cluster cluster) throws Exception {
-        Type type = Type.Cluster;
-        ResourceProvider provider = AbstractControllerResourceProvider.getResourceProvider(
-            type, PropertyHelper.getPropertyIds(type), PropertyHelper.getKeyPropertyIds(type),
-            runnable.m_amc.get());
-
-        Set<String> propertyIds = new HashSet<String>();
-
-        propertyIds.add(ClusterResourceProvider.CLUSTER_ID_PROPERTY_ID);
-        propertyIds.add(ClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID);
+        // Set authenticated user so that authorization checks will pass
+        InternalAuthenticationToken authenticationToken = new InternalAuthenticationToken("admin");
+        authenticationToken.setAuthenticated(true);
+        SecurityContextHolder.getContext().setAuthentication(authenticationToken);
 
         // create the request
-        Request request = PropertyHelper.getReadRequest(propertyIds);
+        Map<Resource.Type, String> mapIds = new HashMap<Resource.Type, String>();
+        mapIds.put(Resource.Type.Cluster, cluster.getClusterName());
 
-        // build the predicate for this cluster
-        Predicate predicate = new PredicateBuilder().property(
-            ClusterResourceProvider.CLUSTER_NAME_PROPERTY_ID).equals(
-                cluster.getClusterName()).toPredicate();
-
-        provider.getResources(request, predicate);
+        ClusterController clusterController = ClusterControllerHelper.getClusterController();
+        Query query = new QueryImpl(mapIds, new ClusterResourceDefinition(), clusterController);
+        query.setRenderer(new DefaultRenderer());
+        query.execute();
       }
     };
 
@@ -222,13 +236,22 @@ public class AmbariPerformanceRunnable extends AlertRunnable {
   }
 
   /**
-   * Used for querying for requests by status.
+   * Used for getting the most recent requests.
+   */
+  @Inject
+  private RequestDAO m_requestDAO;
+
+  /**
+   * Used for executing queries which are known to potentially take a long time.
    */
   @Inject
-  private Provider<ActionManager> m_actionManager;
+  private HostRoleCommandDAO m_hostRoleCommandDAO;
 
+  /**
+   * Used for querying for requests by status.
+   */
   @Inject
-  private Provider<AmbariManagementController> m_amc;
+  private ActionManager m_actionManager;
 
   /**
    * Constructor.

http://git-wip-us.apache.org/repos/asf/ambari/blob/ddc65671/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
index 2e35001..1768f21 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/HostRoleCommandDAO.java
@@ -23,7 +23,6 @@ import static org.apache.ambari.server.orm.dao.DaoUtils.ORACLE_LIST_LIMIT;
 
 import java.text.MessageFormat;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
@@ -318,7 +317,7 @@ public class HostRoleCommandDAO {
         "HostRoleCommandEntity.findByRequestIdAndStatuses", HostRoleCommandEntity.class);
     query.setParameter("requestId", requestId);
     query.setParameter("statuses", statuses);
-    List results = query.getResultList();
+    List<HostRoleCommandEntity> results = query.getResultList();
     return results;
   }
 
@@ -675,6 +674,7 @@ public class HostRoleCommandDAO {
    *          the request id
    * @return the map of stage-to-summary objects
    */
+  @RequiresSession
   public Map<Long, HostRoleCommandStatusSummaryDTO> findAggregateCounts(Long requestId) {
     if (!hostRoleCommandStatusSummaryCacheEnabled) {
       return loadAggregateCounts(requestId);
@@ -706,16 +706,17 @@ public class HostRoleCommandDAO {
    * @param requestId upgrade request id
    * @return Most recent task failure during stack upgrade, or null if one doesn't exist.
    */
+  @RequiresSession
   public HostRoleCommandEntity findMostRecentFailure(Long requestId) {
     TypedQuery<HostRoleCommandEntity> query = entityManagerProvider.get().createNamedQuery(
         "HostRoleCommandEntity.findTasksByStatusesOrderByIdDesc", HostRoleCommandEntity.class);
 
     query.setParameter("requestId", requestId);
     query.setParameter("statuses", HostRoleStatus.STACK_UPGRADE_FAILED_STATUSES);
-    List results = query.getResultList();
+    List<HostRoleCommandEntity> results = query.getResultList();
 
     if (!results.isEmpty()) {
-      HostRoleCommandEntity candidate = (HostRoleCommandEntity) results.get(0);
+      HostRoleCommandEntity candidate = results.get(0);
 
       // Ensure that there are no other completed tasks in a future stage to avoid returning an old error.
       // During Express Upgrade, we can run multiple commands in the same stage, so it's possible to have

http://git-wip-us.apache.org/repos/asf/ambari/blob/ddc65671/ambari-server/src/main/resources/alerts.json
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/resources/alerts.json b/ambari-server/src/main/resources/alerts.json
index 27ae76d..3b6ebbb 100644
--- a/ambari-server/src/main/resources/alerts.json
+++ b/ambari-server/src/main/resources/alerts.json
@@ -57,6 +57,24 @@
               "threshold": "CRITICAL"
             },
             {
+              "name": "task.status.aggregation.warning.threshold",
+              "display_name": "Warning",
+              "value": 3000,
+              "type": "NUMERIC",
+              "description": "The time to calculate a request's status from its tasks before a warning alert is triggered.",
+              "units": "ms",
+              "threshold": "WARNING"
+            },
+            {
+              "name": "task.status.aggregation.critical.threshold",
+              "display_name": "Critical",
+              "value": 5000,
+              "type": "NUMERIC",
+              "description": "The time to calculate a request's status from its tasks before a critical alert is triggered.",
+              "units": "ms",
+              "threshold": "CRITICAL"
+            },
+            {
               "name": "rest.api.cluster.warning.threshold",
               "display_name": "Warning",
               "value": 5000,

http://git-wip-us.apache.org/repos/asf/ambari/blob/ddc65671/ambari-server/src/test/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnableTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnableTest.java b/ambari-server/src/test/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnableTest.java
index 31ed745..7b1a5a2 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnableTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/alerts/AmbariPerformanceRunnableTest.java
@@ -19,6 +19,7 @@
 package org.apache.ambari.server.alerts;
 
 import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
 import static org.easymock.EasyMock.createNiceMock;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
@@ -33,8 +34,11 @@ import java.util.Map;
 import javax.persistence.EntityManager;
 
 import org.apache.ambari.server.actionmanager.ActionManager;
+import org.apache.ambari.server.alerts.AmbariPerformanceRunnable.PerformanceArea;
 import org.apache.ambari.server.controller.AmbariManagementController;
 import org.apache.ambari.server.controller.internal.ClusterResourceProvider;
+import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
 import org.apache.ambari.server.events.AlertEvent;
 import org.apache.ambari.server.events.AlertReceivedEvent;
 import org.apache.ambari.server.events.MockEventListener;
@@ -43,6 +47,7 @@ import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
 import org.apache.ambari.server.orm.dao.AlertsDAO;
 import org.apache.ambari.server.orm.dao.HostRoleCommandDAO;
+import org.apache.ambari.server.orm.dao.RequestDAO;
 import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
 import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
 import org.apache.ambari.server.state.Alert;
@@ -57,6 +62,10 @@ import org.easymock.EasyMock;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.api.easymock.PowerMock;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
 import com.google.common.eventbus.EventBus;
 import com.google.inject.Binder;
@@ -67,6 +76,9 @@ import com.google.inject.Module;
 /**
  * Tests {@link AmbariPerformanceRunnable}.
  */
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ ClusterControllerHelper.class, AmbariPerformanceRunnable.class,
+    PerformanceArea.class })
 public class AmbariPerformanceRunnableTest {
 
   private final static long CLUSTER_ID = 1;
@@ -148,7 +160,13 @@ public class AmbariPerformanceRunnableTest {
     AlertDefinitionFactory factory = m_injector.getInstance(AlertDefinitionFactory.class);
     expect(factory.coerce(EasyMock.anyObject(AlertDefinitionEntity.class))).andReturn(definition).atLeastOnce();
 
-    replay(m_definition, m_cluster, m_clusters, m_definitionDao, m_alertsDao, factory);
+    ClusterController clusterController = m_injector.getInstance(ClusterController.class);
+    PowerMock.mockStatic(ClusterControllerHelper.class);
+    expect(ClusterControllerHelper.getClusterController()).andReturn(clusterController);
+    PowerMock.replay(ClusterControllerHelper.class);
+
+    replay(m_definition, m_cluster, m_clusters, m_definitionDao, m_alertsDao, factory,
+        clusterController);
     }
 
   /**
@@ -159,10 +177,52 @@ public class AmbariPerformanceRunnableTest {
   }
 
   /**
+   * Tests that the event is triggerd with a status of OK if all performance
+   * areas pass.
+   */
+  @Test
+  public void testAlertFiresOKEvent() {
+    // mock the entire enum so that no problems are reported
+    PowerMock.mockStatic(PerformanceArea.class);
+    expect(PerformanceArea.values()).andReturn(new PerformanceArea[0]);
+    PowerMock.replay(PerformanceArea.class);
+
+    // instantiate and inject mocks
+    AmbariPerformanceRunnable runnable = new AmbariPerformanceRunnable(
+        m_definition.getDefinitionName());
+
+    m_injector.injectMembers(runnable);
+
+    // run the alert
+    runnable.run();
+
+    assertEquals(1, m_listener.getAlertEventReceivedCount(AlertReceivedEvent.class));
+
+    List<AlertEvent> events = m_listener.getAlertEventInstances(AlertReceivedEvent.class);
+    assertEquals(1, events.size());
+
+    AlertReceivedEvent event = (AlertReceivedEvent) events.get(0);
+    Alert alert = event.getAlert();
+    assertEquals("AMBARI", alert.getService());
+    assertEquals("AMBARI_SERVER", alert.getComponent());
+    assertEquals(AlertState.OK, alert.getState());
+    assertEquals(DEFINITION_NAME, alert.getName());
+
+    verify(m_cluster, m_clusters, m_definitionDao);
+  }
+
+  /**
    * Tests that the event is triggerd with a status of UNKNOWN.
    */
   @Test
-  public void testAlertFiresEvents() {
+  public void testAlertFiresUnknownEvent() {
+    // mock one area, leaving others to fail
+    RequestDAO requestDAO = m_injector.getInstance(RequestDAO.class);
+    expect(requestDAO.findAllRequestIds(EasyMock.anyInt(), EasyMock.anyBoolean())).andReturn(
+        new ArrayList<Long>());
+
+    replay(requestDAO);
+
     // instantiate and inject mocks
     AmbariPerformanceRunnable runnable = new AmbariPerformanceRunnable(
         m_definition.getDefinitionName());
@@ -185,6 +245,10 @@ public class AmbariPerformanceRunnableTest {
     assertEquals(AlertState.UNKNOWN, alert.getState());
     assertEquals(DEFINITION_NAME, alert.getName());
 
+    // verify that even though there is 1 UNKNOWN, there should also be 1 OK as
+    // well
+    assertTrue(alert.getText().contains("(OK)"));
+
     verify(m_cluster, m_clusters, m_definitionDao);
   }
 
@@ -227,6 +291,8 @@ public class AmbariPerformanceRunnableTest {
       binder.bind(AmbariManagementController.class).toInstance(createNiceMock(AmbariManagementController.class));
       binder.bind(AlertDefinitionFactory.class).toInstance(createNiceMock(AlertDefinitionFactory.class));
       binder.bind(ClusterResourceProvider.class).toInstance(createNiceMock(ClusterResourceProvider.class));
+      binder.bind(ClusterController.class).toInstance(createNiceMock(ClusterController.class));
+      binder.bind(RequestDAO.class).toInstance(createNiceMock(RequestDAO.class));
     }
   }
 }