浏览代码

AMBARI-8623 - Alert Host Count Summary Exposed Via Cluster Endpoint (jonathanhurley)

Jonathan Hurley 10 年之前
父节点
当前提交
a51afbe54e

+ 41 - 5
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertSummaryPropertyProvider.java

@@ -17,7 +17,6 @@
  */
 package org.apache.ambari.server.controller.internal;
 
-import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
@@ -30,6 +29,7 @@ import org.apache.ambari.server.controller.spi.PropertyProvider;
 import org.apache.ambari.server.controller.spi.Request;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.orm.dao.AlertHostSummaryDTO;
 import org.apache.ambari.server.orm.dao.AlertSummaryDTO;
 import org.apache.ambari.server.orm.dao.AlertsDAO;
 import org.apache.ambari.server.state.AlertState;
@@ -38,6 +38,7 @@ import org.apache.ambari.server.state.Clusters;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import com.google.common.collect.ImmutableSet;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -49,6 +50,17 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
 
   private final static Logger LOG = LoggerFactory.getLogger(AlertSummaryPropertyProvider.class);
 
+  /**
+   * The property ID for a summary of all cluster-wide alerts.
+   */
+  private final static String ALERTS_SUMMARY = "alerts_summary";
+
+  /**
+   * The property ID for a summary of all cluster-wide alerts that have a host
+   * associated with them.
+   */
+  private final static String ALERTS_SUMMARY_HOSTS = "alerts_summary_hosts";
+
   @Inject
   private static Provider<Clusters> s_clusters = null;
 
@@ -68,7 +80,7 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
    */
   AlertSummaryPropertyProvider(Resource.Type type,
       String clusterPropertyId, String typeIdPropertyId) {
-    super(Collections.singleton("alerts_summary"));
+    super(ImmutableSet.<String> of(ALERTS_SUMMARY, ALERTS_SUMMARY_HOSTS));
     m_resourceType = type;
     m_clusterPropertyId = clusterPropertyId;
     m_typeIdPropertyId = typeIdPropertyId;
@@ -95,6 +107,7 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
   private void populateResource(Resource resource, Set<String> requestedIds) throws AmbariException {
 
     AlertSummaryDTO summary = null;
+    AlertHostSummaryDTO hostSummary = null;
 
     String clusterName = (String) resource.getPropertyValue(m_clusterPropertyId);
 
@@ -107,7 +120,19 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
 
     switch (m_resourceType.getInternalType()) {
       case Cluster:
-        summary = s_dao.findCurrentCounts(cluster.getClusterId(), null, null);
+        long clusterId = cluster.getClusterId();
+
+        // only make the calculation of asked
+        if (BaseProvider.isPropertyRequested(ALERTS_SUMMARY, requestedIds)) {
+          summary = s_dao.findCurrentCounts(cluster.getClusterId(), null, null);
+        }
+
+        // only make the calculation of asked
+        if (BaseProvider.isPropertyRequested(ALERTS_SUMMARY_HOSTS,
+            requestedIds)) {
+          hostSummary = s_dao.findCurrentHostCounts(clusterId);
+        }
+
         break;
       case Service:
         summary = s_dao.findCurrentCounts(cluster.getClusterId(), typeId, null);
@@ -119,6 +144,7 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
         break;
     }
 
+    // all alerts in the cluster, in summary count form
     if (null != summary) {
       Map<AlertState, Integer> map = new HashMap<AlertState, Integer>();
       map.put(AlertState.OK, Integer.valueOf(summary.getOkCount()));
@@ -126,7 +152,17 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
       map.put(AlertState.CRITICAL, Integer.valueOf(summary.getCriticalCount()));
       map.put(AlertState.UNKNOWN, Integer.valueOf(summary.getUnknownCount()));
 
-      setResourceProperty(resource, "alerts_summary", map, requestedIds);
+      setResourceProperty(resource, ALERTS_SUMMARY, map, requestedIds);
+    }
+
+    // the summary of hosts with warning or critical alerts
+    if (null != hostSummary) {
+      Map<AlertState, Integer> map = new HashMap<AlertState, Integer>();
+      map.put(AlertState.OK, Integer.valueOf(hostSummary.getOkCount()));
+      map.put(AlertState.WARNING, Integer.valueOf(hostSummary.getWarningCount()));
+      map.put(AlertState.CRITICAL, Integer.valueOf(hostSummary.getCriticalCount()));
+      map.put(AlertState.UNKNOWN, Integer.valueOf(hostSummary.getUnknownCount()));
+      setResourceProperty(resource, ALERTS_SUMMARY_HOSTS, map, requestedIds);
     }
 
   }
@@ -136,7 +172,7 @@ public class AlertSummaryPropertyProvider extends BaseProvider implements Proper
     Set<String> rejects = new HashSet<String>();
 
     for (String id : propertyIds) {
-      if (!id.startsWith("alerts_summary")) {
+      if (!id.startsWith(ALERTS_SUMMARY)) {
         rejects.add(id);
       }
     }

+ 7 - 4
ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertTargetResourceProvider.java

@@ -275,10 +275,13 @@ public class AlertTargetResourceProvider extends
 
       // groups are not required on creation
       if (requestMap.containsKey(ALERT_TARGET_GROUPS)) {
-        List<Long> groupIds = (List<Long>) requestMap.get(ALERT_TARGET_GROUPS);
-        Set<AlertGroupEntity> groups = new HashSet<AlertGroupEntity>();
-        groups.addAll(s_dao.findGroupsById(groupIds));
-        entity.setAlertGroups(groups);
+        Collection<Long> groupIds = (Collection<Long>) requestMap.get(ALERT_TARGET_GROUPS);
+        if( !groupIds.isEmpty() ){
+          Set<AlertGroupEntity> groups = new HashSet<AlertGroupEntity>();
+          List<Long> ids = new ArrayList<Long>(groupIds);
+          groups.addAll(s_dao.findGroupsById(ids));
+          entity.setAlertGroups(groups);
+        }
       }
 
       entity.setDescription(description);

+ 95 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertHostSummaryDTO.java

@@ -0,0 +1,95 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.ambari.server.orm.dao;
+
+
+/**
+ * The {@link AlertHostSummaryDTO} is used to return a summary of the alerts
+ * affecting the hosts of the cluster. This will contain an aggregate of the
+ * number of hosts that have alerts in various alert states.
+ * <p/>
+ * The sum of all of the values of this DTO should equal the total number of
+ * hosts.
+ */
+public class AlertHostSummaryDTO {
+
+  /**
+   * The number of hosts whose most critical alert is a WARNING.
+   */
+  private final int m_warningCount;
+
+  /**
+   * The number of hosts whose most critical alert is a CRITICAL.
+   */
+  private final int m_criticalCount;
+
+  /**
+   * The number of hosts whose most critical alert is a UNKNOWN.
+   */
+  private final int m_unknownCount;
+
+  /**
+   * The number of hosts with all OK.
+   */
+  private final int m_okCount;
+
+  /**
+   * Constructor.
+   *
+   * @param okCount
+   * @param unknownCount
+   * @param warningCount
+   * @param criticalCount
+   */
+  public AlertHostSummaryDTO(int okCount, int unknownCount, int warningCount,
+      int criticalCount) {
+
+    m_okCount = okCount;
+    m_unknownCount = unknownCount;
+    m_warningCount = warningCount;
+    m_criticalCount = criticalCount;
+  }
+
+  /**
+   * @return the warningCount
+   */
+  public int getWarningCount() {
+    return m_warningCount;
+  }
+
+  /**
+   * @return the criticalCount
+   */
+  public int getCriticalCount() {
+    return m_criticalCount;
+  }
+
+  /**
+   * @return the unknownCount
+   */
+  public int getUnknownCount() {
+    return m_unknownCount;
+  }
+
+  /**
+   * @return the okCount
+   */
+  public int getOkCount() {
+    return m_okCount;
+  }
+}

+ 59 - 0
ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertsDAO.java

@@ -339,6 +339,65 @@ public class AlertsDAO {
     return daoUtils.selectSingle(query);
   }
 
+  /**
+   * Retrieve the summary alert information for all hosts. This is different
+   * from {@link #findCurrentCounts(long, String, String)} since this will not
+   * return alerts that are not related to a particular host, such as aggregate
+   * alerts. In general, {@link #findCurrentCounts(long, String, String)} and
+   * this method will return very similar counts.
+   *
+   * @param clusterId
+   *          the cluster id
+   * @return the summary DTO for host alerts.
+   */
+  @RequiresSession
+  public AlertHostSummaryDTO findCurrentHostCounts(long clusterId) {
+    StringBuilder sb = new StringBuilder();
+    sb.append("SELECT MAX(CASE WHEN history.alertState = :criticalState THEN 3 WHEN history.alertState = :warningState THEN 2 WHEN history.alertState = :unknownState THEN 1 ELSE 0 END) ");
+    sb.append("FROM AlertCurrentEntity alert JOIN alert.alertHistory history ");
+    sb.append("WHERE history.clusterId = :clusterId AND history.hostName IS NOT NULL GROUP BY history.hostName");
+
+    TypedQuery<Integer> query = entityManagerProvider.get().createQuery(
+        sb.toString(), Integer.class);
+
+    query.setParameter("clusterId", Long.valueOf(clusterId));
+    query.setParameter("criticalState", AlertState.CRITICAL);
+    query.setParameter("warningState", AlertState.WARNING);
+    query.setParameter("unknownState", AlertState.UNKNOWN);
+
+    int okCount = 0;
+    int warningCount = 0;
+    int criticalCount = 0;
+    int unknownCount = 0;
+
+    List<Integer> hostStateValues = daoUtils.selectList(query);
+    for (Integer hostStateValue : hostStateValues) {
+      if (null == hostStateValue) {
+        continue;
+      }
+
+      switch (hostStateValue) {
+        case 0:
+          okCount++;
+          break;
+        case 1:
+          unknownCount++;
+          break;
+        case 2:
+          warningCount++;
+          break;
+        case 3:
+          criticalCount++;
+          break;
+      }
+    }
+
+    AlertHostSummaryDTO hostSummary = new AlertHostSummaryDTO(okCount,
+        unknownCount, warningCount, criticalCount);
+
+    return hostSummary;
+  }
+
   /**
    * Gets the current alerts for a given service.
    *

+ 80 - 0
ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertsDAOTest.java

@@ -467,6 +467,86 @@ public class AlertsDAOTest {
     assertEquals(0, summary.getCriticalCount());
   }
 
+  /**
+   *
+   */
+  @Test
+  public void testFindCurrentHostSummary() throws Exception {
+    // start out with 1 since all alerts are for a single host and are OK
+    AlertHostSummaryDTO summary = m_dao.findCurrentHostCounts(m_cluster.getClusterId());
+    assertEquals(0, summary.getWarningCount());
+    assertEquals(0, summary.getCriticalCount());
+    assertEquals(0, summary.getUnknownCount());
+    assertEquals(1, summary.getOkCount());
+
+    // grab 1 and change it to warning
+    AlertHistoryEntity h1 = m_dao.findCurrentByCluster(m_cluster.getClusterId()).get(
+        1).getAlertHistory();
+
+    h1.setAlertState(AlertState.WARNING);
+    m_dao.merge(h1);
+
+    // verify host changed to warning
+    summary = m_dao.findCurrentHostCounts(m_cluster.getClusterId());
+    assertEquals(1, summary.getWarningCount());
+    assertEquals(0, summary.getCriticalCount());
+    assertEquals(0, summary.getUnknownCount());
+    assertEquals(0, summary.getOkCount());
+
+    h1.setAlertState(AlertState.CRITICAL);
+    m_dao.merge(h1);
+
+    // verify host changed to critical
+    summary = m_dao.findCurrentHostCounts(m_cluster.getClusterId());
+    assertEquals(0, summary.getWarningCount());
+    assertEquals(1, summary.getCriticalCount());
+    assertEquals(0, summary.getUnknownCount());
+    assertEquals(0, summary.getOkCount());
+
+    // grab another and change the host so that an OK shows up
+    AlertHistoryEntity h2 = m_dao.findCurrentByCluster(m_cluster.getClusterId()).get(
+        2).getAlertHistory();
+
+    h2.setHostName(h2.getHostName() + "-foo");
+    m_dao.merge(h2);
+
+    summary = m_dao.findCurrentHostCounts(m_cluster.getClusterId());
+    assertEquals(0, summary.getWarningCount());
+    assertEquals(1, summary.getCriticalCount());
+    assertEquals(0, summary.getUnknownCount());
+    assertEquals(1, summary.getOkCount());
+
+    // grab another and change that host name as well
+    AlertHistoryEntity h3 = m_dao.findCurrentByCluster(m_cluster.getClusterId()).get(
+        3).getAlertHistory();
+
+    // change the name to simulate a 3rd host
+    h3.setHostName(h3.getHostName() + "-bar");
+    m_dao.merge(h3);
+
+    // verify 2 hosts report OK
+    summary = m_dao.findCurrentHostCounts(m_cluster.getClusterId());
+    assertEquals(0, summary.getWarningCount());
+    assertEquals(1, summary.getCriticalCount());
+    assertEquals(0, summary.getUnknownCount());
+    assertEquals(2, summary.getOkCount());
+
+    // grab another and change that host name and the state to UNKNOWN
+    AlertHistoryEntity h4 = m_dao.findCurrentByCluster(m_cluster.getClusterId()).get(
+        4).getAlertHistory();
+
+    h4.setHostName(h4.getHostName() + "-baz");
+    h4.setAlertState(AlertState.UNKNOWN);
+    m_dao.merge(h3);
+
+    // verify a new host shows up with UNKNOWN status hosts report OK
+    summary = m_dao.findCurrentHostCounts(m_cluster.getClusterId());
+    assertEquals(0, summary.getWarningCount());
+    assertEquals(1, summary.getCriticalCount());
+    assertEquals(1, summary.getUnknownCount());
+    assertEquals(2, summary.getOkCount());
+  }
+
   @Test
   public void testFindAggregates() throws Exception {
     // definition