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 2014/11/10 17:00:19 UTC
ambari git commit: AMBARI-8237 - Alerts: Provide Summary Structure On
Alerts Endpoint (jonathanhurley)
Repository: ambari
Updated Branches:
refs/heads/trunk de1f8ff64 -> f088f55e4
AMBARI-8237 - Alerts: Provide Summary Structure On Alerts Endpoint (jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/f088f55e
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/f088f55e
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/f088f55e
Branch: refs/heads/trunk
Commit: f088f55e4d9853ec0f671e1d095abb349d9d8a20
Parents: de1f8ff
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Sun Nov 9 09:08:15 2014 -0500
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Mon Nov 10 11:00:14 2014 -0500
----------------------------------------------------------------------
.../api/query/render/AlertSummaryRenderer.java | 227 +++++++++++++++++++
.../api/resources/AlertResourceDefinition.java | 31 ++-
.../internal/AlertResourceProvider.java | 42 ++--
.../internal/AlertResourceProviderTest.java | 176 +++++++++++---
4 files changed, 426 insertions(+), 50 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/f088f55e/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryRenderer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryRenderer.java b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryRenderer.java
new file mode 100644
index 0000000..afe9798
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/query/render/AlertSummaryRenderer.java
@@ -0,0 +1,227 @@
+/**
+ * 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.api.query.render;
+
+import java.util.Set;
+
+import org.apache.ambari.server.api.query.QueryInfo;
+import org.apache.ambari.server.api.services.Request;
+import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.services.ResultPostProcessor;
+import org.apache.ambari.server.api.services.ResultPostProcessorImpl;
+import org.apache.ambari.server.api.util.TreeNode;
+import org.apache.ambari.server.api.util.TreeNodeImpl;
+import org.apache.ambari.server.controller.internal.AlertResourceProvider;
+import org.apache.ambari.server.controller.internal.ResourceImpl;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.state.AlertState;
+
+/**
+ * The {@link AlertSummaryRenderer} is used to format the results of queries to
+ * the alerts endpoint. Each item returned from the query represents an
+ * individual current alert which is then aggregated into a summary structure
+ * based on the alert state.
+ * <p/>
+ * The finalized structure is:
+ *
+ * <pre>
+ * {
+ * "href" : "http://localhost:8080/api/v1/clusters/c1/alerts?format=summary",
+ * "alerts_summary" : {
+ * "CRITICAL" : {
+ * "count" : 3,
+ * "original_timestamp" : 1415372828182
+ * },
+ * "OK" : {
+ * "count" : 37,
+ * "original_timestamp" : 1415375364937
+ * },
+ * "UNKNOWN" : {
+ * "count" : 1,
+ * "original_timestamp" : 1415372632261
+ * },
+ * "WARN" : {
+ * "count" : 0,
+ * "original_timestamp" : 0
+ * }
+ * }
+ * }
+ * </pre>
+ * <p/>
+ * The nature of a {@link Renderer} is that it manipulates the dataset returned
+ * by a query. In the case of alert data, the query could potentially return
+ * thousands of results if there are thousands of nodes in the cluster. This
+ * could present a performance issue that can only be addressed by altering the
+ * incoming query and modifying it to instruct the backend to return a JPA SUM
+ * instead of a collection of entities.
+ */
+public class AlertSummaryRenderer extends BaseRenderer implements Renderer {
+
+ private static final String OK_COUNT_PROPERTY = "alerts_summary/OK/count";
+ private static final String OK_TIMESTAMP_PROPERTY = "alerts_summary/OK/original_timestamp";
+
+ private static final String WARN_COUNT_PROPERTY = "alerts_summary/WARNING/count";
+ private static final String WARN_TIMESTAMP_PROPERTY = "alerts_summary/WARNING/original_timestamp";
+
+ private static final String CRITICAL_COUNT_PROPERTY = "alerts_summary/CRITICAL/count";
+ private static final String CRITICAL_TIMESTAMP_PROPERTY = "alerts_summary/CRITICAL/original_timestamp";
+
+ private static final String UNKNOWN_COUNT_PROPERTY = "alerts_summary/UNKNOWN/count";
+ private static final String UNKNOWN_TIMESTAMP_PROPERTY = "alerts_summary/UNKNOWN/original_timestamp";
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public TreeNode<Set<String>> finalizeProperties(
+ TreeNode<QueryInfo> queryTree, boolean isCollection) {
+
+ QueryInfo queryInfo = queryTree.getObject();
+ TreeNode<Set<String>> resultTree = new TreeNodeImpl<Set<String>>(
+ null, queryInfo.getProperties(), queryTree.getName());
+
+ copyPropertiesToResult(queryTree, resultTree);
+
+ boolean addKeysToEmptyResource = true;
+ if (!isCollection && isRequestWithNoProperties(queryTree)) {
+ addSubResources(queryTree, resultTree);
+ addKeysToEmptyResource = false;
+ }
+
+ ensureRequiredProperties(resultTree, addKeysToEmptyResource);
+
+ // ensure that state and original_timestamp are on the request since these
+ // are required by the finalization process of this renderer
+ Set<String> properties = resultTree.getObject();
+ properties.add(AlertResourceProvider.ALERT_STATE);
+ properties.add(AlertResourceProvider.ALERT_ORIGINAL_TIMESTAMP);
+
+ return resultTree;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public ResultPostProcessor getResultPostProcessor(Request request) {
+ // simply return the native rendering
+ return new ResultPostProcessorImpl(request);
+ }
+
+ /**
+ * {@inheritDoc}
+ * <p/>
+ * This will iterate over all of the nodes in the result tree and combine
+ * their {@link AlertResourceProvider#ALERT_STATE} into a single summary
+ * structure.
+ */
+ @Override
+ public Result finalizeResult(Result queryResult) {
+ TreeNode<Resource> resultTree = queryResult.getResultTree();
+ Result summary = new ResultImpl(true);
+
+ // counts
+ int ok = 0;
+ int warning = 0;
+ int critical = 0;
+ int unknown = 0;
+
+ // keeps track of the most recent state change
+ // (not the most recent alert received)
+ long mostRecentOK = 0;
+ long mostRecentWarning = 0;
+ long mostRecentCritical = 0;
+ long mostRecentUnknown = 0;
+
+ // iterate over all returned flattened alerts and build the summary info
+ for (TreeNode<Resource> node : resultTree.getChildren()) {
+ Resource resource = node.getObject();
+ AlertState state = (AlertState) resource.getPropertyValue(AlertResourceProvider.ALERT_STATE);
+ Long originalTimestampObject = (Long) resource.getPropertyValue(AlertResourceProvider.ALERT_ORIGINAL_TIMESTAMP);
+
+ // NPE sanity
+ if (null == state) {
+ state = AlertState.UNKNOWN;
+ }
+
+ // NPE sanity
+ long originalTimestamp = 0;
+ if (null != originalTimestampObject) {
+ originalTimestamp = originalTimestampObject.longValue();
+ }
+
+ switch (state) {
+ case CRITICAL: {
+ critical++;
+
+ if (originalTimestamp > mostRecentCritical) {
+ mostRecentCritical = originalTimestamp;
+ }
+
+ break;
+ }
+ case OK: {
+ ok++;
+
+ if (originalTimestamp > mostRecentOK) {
+ mostRecentOK = originalTimestamp;
+ }
+
+ break;
+ }
+ case WARNING: {
+ warning++;
+
+ if (originalTimestamp > mostRecentWarning) {
+ mostRecentWarning = originalTimestamp;
+ }
+
+ break;
+ }
+ default:
+ case UNKNOWN: {
+ unknown++;
+
+ if (originalTimestamp > mostRecentUnknown) {
+ mostRecentUnknown = originalTimestamp;
+ }
+
+ break;
+ }
+ }
+ }
+
+ Resource resource = new ResourceImpl(Resource.Type.Alert);
+ resource.setProperty(OK_COUNT_PROPERTY, ok);
+ resource.setProperty(WARN_COUNT_PROPERTY, warning);
+ resource.setProperty(CRITICAL_COUNT_PROPERTY, critical);
+ resource.setProperty(UNKNOWN_COUNT_PROPERTY, unknown);
+
+ resource.setProperty(OK_TIMESTAMP_PROPERTY, mostRecentOK);
+ resource.setProperty(WARN_TIMESTAMP_PROPERTY, mostRecentWarning);
+ resource.setProperty(CRITICAL_TIMESTAMP_PROPERTY, mostRecentCritical);
+ resource.setProperty(UNKNOWN_TIMESTAMP_PROPERTY, mostRecentUnknown);
+
+ TreeNode<Resource> summaryTree = summary.getResultTree();
+ summaryTree.addChild(resource, "alerts_summary");
+
+ return summary;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f088f55e/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertResourceDefinition.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertResourceDefinition.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertResourceDefinition.java
index d7aca22..18f206e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertResourceDefinition.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/AlertResourceDefinition.java
@@ -17,25 +17,48 @@
*/
package org.apache.ambari.server.api.resources;
+import org.apache.ambari.server.api.query.render.AlertSummaryRenderer;
+import org.apache.ambari.server.api.query.render.Renderer;
import org.apache.ambari.server.controller.spi.Resource;
/**
* Definition for alert resources.
*/
public class AlertResourceDefinition extends BaseResourceDefinition {
-
+
+ /**
+ * Constructor.
+ *
+ */
public AlertResourceDefinition() {
super(Resource.Type.Alert);
}
-
+
+ /**
+ * {@inheritDoc}
+ */
@Override
public String getPluralName() {
return "alerts";
}
-
+
+ /**
+ * {@inheritDoc}
+ */
@Override
public String getSingularName() {
return "alert";
}
-
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Renderer getRenderer(String name) {
+ if (name != null && name.equals("summary")) {
+ return new AlertSummaryRenderer();
+ } else {
+ return super.getRenderer(name);
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/f088f55e/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
index 715d017..3430f8d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/AlertResourceProvider.java
@@ -47,21 +47,22 @@ import com.google.inject.Injector;
*/
public class AlertResourceProvider extends ReadOnlyResourceProvider {
+ public static final String ALERT_STATE = "Alert/state";
+ public static final String ALERT_ORIGINAL_TIMESTAMP = "Alert/original_timestamp";
+
protected static final String ALERT_CLUSTER_NAME = "Alert/cluster_name";
protected static final String ALERT_ID = "Alert/id";
protected static final String ALERT_NAME = "Alert/name";
protected static final String ALERT_LATEST_TIMESTAMP = "Alert/latest_timestamp";
protected static final String ALERT_MAINTENANCE_STATE = "Alert/maintenance_state";
- protected static final String ALERT_ORIGINAL_TIMESTAMP = "Alert/original_timestamp";
protected static final String ALERT_INSTANCE = "Alert/instance";
protected static final String ALERT_LABEL = "Alert/label";
- protected static final String ALERT_STATE = "Alert/state";
protected static final String ALERT_TEXT = "Alert/text";
protected static final String ALERT_COMPONENT = "Alert/component_name";
protected static final String ALERT_HOST = "Alert/host_name";
protected static final String ALERT_SERVICE = "Alert/service_name";
protected static final String ALERT_SCOPE = "Alert/scope";
-
+
private static Set<String> pkPropertyIds = new HashSet<String>(
Arrays.asList(ALERT_ID, ALERT_NAME));
@@ -78,7 +79,7 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
AlertResourceProvider(Set<String> propertyIds,
Map<Resource.Type, String> keyPropertyIds,
AmbariManagementController managementController) {
-
+
super(propertyIds, keyPropertyIds, managementController);
}
@@ -94,11 +95,11 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
NoSuchResourceException, NoSuchParentResourceException {
Set<String> requestPropertyIds = getRequestPropertyIds(request, predicate);
-
+
Set<Resource> results = new HashSet<Resource>();
for (Map<String, Object> propertyMap : getPropertyMaps(predicate)) {
-
+
String clusterName = (String) propertyMap.get(ALERT_CLUSTER_NAME);
if (null == clusterName || clusterName.isEmpty()) {
@@ -108,25 +109,25 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
String id = (String) propertyMap.get(ALERT_ID);
if (null != id) {
AlertCurrentEntity entity = alertsDAO.findCurrentById(Long.parseLong(id));
-
+
if (null != entity) {
results.add(toResource(false, clusterName, entity, requestPropertyIds));
}
-
+
} else {
Cluster cluster = null;
-
+
try {
cluster = getManagementController().getClusters().getCluster(clusterName);
} catch (AmbariException e) {
throw new NoSuchResourceException("Parent Cluster resource doesn't exist", e);
}
-
+
String serviceName = (String) propertyMap.get(ALERT_SERVICE);
String hostName = (String) propertyMap.get(ALERT_HOST);
-
+
List<AlertCurrentEntity> entities = null;
-
+
if (null != hostName) {
entities = alertsDAO.findCurrentByHost(cluster.getClusterId(),
hostName);
@@ -134,12 +135,13 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
entities = alertsDAO.findCurrentByService(cluster.getClusterId(),
serviceName);
} else {
- entities = alertsDAO.findCurrentByCluster(cluster.getClusterId());
+ entities = alertsDAO.findCurrentByCluster(cluster.getClusterId());
}
-
- if (null == entities)
+
+ if (null == entities) {
entities = Collections.emptyList();
-
+ }
+
for (AlertCurrentEntity entity : entities) {
results.add(toResource(true, clusterName, entity, requestPropertyIds));
}
@@ -151,7 +153,7 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
/**
* Converts an entity to a resource.
- *
+ *
* @param isCollection {@code true} if the response is for a collection
* @param clusterName the cluster name
* @param entity the entity
@@ -168,7 +170,7 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
setResourceProperty(resource, ALERT_MAINTENANCE_STATE, entity.getMaintenanceState(), requestedIds);
setResourceProperty(resource, ALERT_ORIGINAL_TIMESTAMP, entity.getOriginalTimestamp(), requestedIds);
setResourceProperty(resource, ALERT_TEXT, entity.getLatestText(), requestedIds);
-
+
AlertHistoryEntity history = entity.getAlertHistory();
setResourceProperty(resource, ALERT_INSTANCE, history.getAlertInstance(), requestedIds);
setResourceProperty(resource, ALERT_LABEL, history.getAlertLabel(), requestedIds);
@@ -176,11 +178,11 @@ public class AlertResourceProvider extends ReadOnlyResourceProvider {
setResourceProperty(resource, ALERT_COMPONENT, history.getComponentName(), requestedIds);
setResourceProperty(resource, ALERT_HOST, history.getHostName(), requestedIds);
setResourceProperty(resource, ALERT_SERVICE, history.getServiceName(), requestedIds);
-
+
AlertDefinitionEntity definition = history.getAlertDefinition();
setResourceProperty(resource, ALERT_NAME, definition.getDefinitionName(), requestedIds);
setResourceProperty(resource, ALERT_SCOPE, definition.getScope(), requestedIds);
-
+
if (isCollection) {
// !!! want name to be populated as if it were a PK when requesting the collection
resource.setProperty(ALERT_NAME, definition.getDefinitionName());
http://git-wip-us.apache.org/repos/asf/ambari/blob/f088f55e/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java
index ef014a9..2bac86a 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/AlertResourceProviderTest.java
@@ -27,12 +27,19 @@ import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.junit.Assert.assertEquals;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
import javax.persistence.EntityManager;
+import org.apache.ambari.server.api.query.render.AlertSummaryRenderer;
+import org.apache.ambari.server.api.services.Result;
+import org.apache.ambari.server.api.services.ResultImpl;
+import org.apache.ambari.server.api.util.TreeNode;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.spi.Predicate;
@@ -51,6 +58,7 @@ import org.apache.ambari.server.state.Cluster;
import org.apache.ambari.server.state.Clusters;
import org.easymock.Capture;
import org.easymock.EasyMock;
+import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -77,7 +85,7 @@ public class AlertResourceProviderTest {
private AmbariManagementController m_amc;
@Before
- @SuppressWarnings("boxing")
+ @SuppressWarnings("boxing")
public void before() throws Exception {
Injector m_injector = Guice.createInjector(new MockModule());
@@ -91,9 +99,9 @@ public class AlertResourceProviderTest {
expect(cluster.getClusterId()).andReturn(Long.valueOf(1L));
replay(m_amc, clusters, cluster);
-
+
m_dao = m_injector.getInstance(AlertsDAO.class);
-
+
AlertResourceProvider.init(m_injector);
}
@@ -105,17 +113,17 @@ public class AlertResourceProviderTest {
public void testGetCluster() throws Exception {
expect(m_dao.findCurrentByCluster(
captureLong(new Capture<Long>()))).andReturn(getClusterMockEntities()).anyTimes();
-
+
replay(m_dao);
Request request = PropertyHelper.getReadRequest(
AlertResourceProvider.ALERT_ID,
AlertResourceProvider.ALERT_NAME,
AlertResourceProvider.ALERT_LABEL);
-
+
Predicate predicate = new PredicateBuilder().property(
AlertResourceProvider.ALERT_CLUSTER_NAME).equals("c1").toPredicate();
-
+
AlertResourceProvider provider = createProvider();
Set<Resource> results = provider.getResources(request, predicate);
@@ -123,10 +131,10 @@ public class AlertResourceProviderTest {
Resource r = results.iterator().next();
assertEquals("c1", r.getPropertyValue(AlertResourceProvider.ALERT_CLUSTER_NAME));
-
+
verify(m_dao);
}
-
+
/**
* Test for service
*/
@@ -134,18 +142,18 @@ public class AlertResourceProviderTest {
public void testGetService() throws Exception {
expect(m_dao.findCurrentByService(captureLong(new Capture<Long>()),
capture(new Capture<String>()))).andReturn(getClusterMockEntities()).anyTimes();
-
+
replay(m_dao);
Request request = PropertyHelper.getReadRequest(
AlertResourceProvider.ALERT_ID,
AlertResourceProvider.ALERT_NAME,
AlertResourceProvider.ALERT_LABEL);
-
+
Predicate predicate = new PredicateBuilder().property(
AlertResourceProvider.ALERT_CLUSTER_NAME).equals("c1").and()
.property(AlertResourceProvider.ALERT_SERVICE).equals(ALERT_VALUE_SERVICE).toPredicate();
-
+
AlertResourceProvider provider = createProvider();
Set<Resource> results = provider.getResources(request, predicate);
@@ -154,9 +162,9 @@ public class AlertResourceProviderTest {
Resource r = results.iterator().next();
assertEquals("c1", r.getPropertyValue(AlertResourceProvider.ALERT_CLUSTER_NAME));
assertEquals(ALERT_VALUE_SERVICE, r.getPropertyValue(AlertResourceProvider.ALERT_SERVICE));
-
+
verify(m_dao);
- }
+ }
/**
* Test for service
@@ -165,18 +173,18 @@ public class AlertResourceProviderTest {
public void testGetHost() throws Exception {
expect(m_dao.findCurrentByHost(captureLong(new Capture<Long>()),
capture(new Capture<String>()))).andReturn(getClusterMockEntities()).anyTimes();
-
+
replay(m_dao);
Request request = PropertyHelper.getReadRequest(
AlertResourceProvider.ALERT_ID,
AlertResourceProvider.ALERT_NAME,
AlertResourceProvider.ALERT_LABEL);
-
+
Predicate predicate = new PredicateBuilder().property(
AlertResourceProvider.ALERT_CLUSTER_NAME).equals("c1").and()
.property(AlertResourceProvider.ALERT_HOST).equals(ALERT_VALUE_HOSTNAME).toPredicate();
-
+
AlertResourceProvider provider = createProvider();
Set<Resource> results = provider.getResources(request, predicate);
@@ -185,12 +193,65 @@ public class AlertResourceProviderTest {
Resource r = results.iterator().next();
assertEquals("c1", r.getPropertyValue(AlertResourceProvider.ALERT_CLUSTER_NAME));
assertEquals(ALERT_VALUE_HOSTNAME, r.getPropertyValue(AlertResourceProvider.ALERT_HOST));
-
+
verify(m_dao);
- }
+ }
+
+ /**
+ * Tests that the {@link AlertSummaryRenderer} correctly transforms the alert
+ * data.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testGetClusterSummary() throws Exception {
+ expect(m_dao.findCurrentByCluster(captureLong(new Capture<Long>()))).andReturn(
+ getMockEntitiesManyStates()).anyTimes();
+
+ replay(m_dao);
+
+ Request request = PropertyHelper.getReadRequest(
+ AlertResourceProvider.ALERT_ID, AlertResourceProvider.ALERT_NAME,
+ AlertResourceProvider.ALERT_LABEL, AlertResourceProvider.ALERT_STATE,
+ AlertResourceProvider.ALERT_ORIGINAL_TIMESTAMP);
+
+ Predicate predicate = new PredicateBuilder().property(
+ AlertResourceProvider.ALERT_CLUSTER_NAME).equals("c1").toPredicate();
+
+ AlertResourceProvider provider = createProvider();
+ Set<Resource> results = provider.getResources(request, predicate);
+
+ verify(m_dao);
+
+ AlertSummaryRenderer renderer = new AlertSummaryRenderer();
+ ResultImpl result = new ResultImpl(true);
+ TreeNode<Resource> resources = result.getResultTree();
+
+ AtomicInteger alertResourceId = new AtomicInteger(1);
+ for (Resource resource : results) {
+ resources.addChild(resource, "Alert " + alertResourceId.getAndIncrement());
+ }
+
+ Result summary = renderer.finalizeResult(result);
+ Assert.assertNotNull(summary);
+
+ // pull out the alerts_summary child set by the renderer
+ TreeNode<Resource> summaryResultTree = summary.getResultTree();
+ TreeNode<Resource> summaryResources = summaryResultTree.getChild("alerts_summary");
+
+ Resource summaryResource = summaryResources.getObject();
+
+ Integer okCount = (Integer) summaryResource.getPropertyValue("alerts_summary/OK/count");
+ Integer warningCount = (Integer) summaryResource.getPropertyValue("alerts_summary/WARNING/count");
+ Integer criticalCount = (Integer) summaryResource.getPropertyValue("alerts_summary/CRITICAL/count");
+ Integer unknownCount = (Integer) summaryResource.getPropertyValue("alerts_summary/UNKNOWN/count");
+
+ Assert.assertEquals(10, okCount.intValue());
+ Assert.assertEquals(2, warningCount.intValue());
+ Assert.assertEquals(1, criticalCount.intValue());
+ Assert.assertEquals(3, unknownCount.intValue());
+ }
-
-
private AlertResourceProvider createProvider() {
return new AlertResourceProvider(
PropertyHelper.getPropertyIds(Resource.Type.Alert),
@@ -206,7 +267,7 @@ public class AlertResourceProviderTest {
current.setAlertId(Long.valueOf(1000L));
current.setLatestTimestamp(Long.valueOf(1L));
current.setOriginalTimestamp(Long.valueOf(2L));
-
+
AlertHistoryEntity history = new AlertHistoryEntity();
history.setAlertId(ALERT_VALUE_ID);
history.setAlertInstance(null);
@@ -218,15 +279,78 @@ public class AlertResourceProviderTest {
history.setComponentName(ALERT_VALUE_COMPONENT);
history.setHostName(ALERT_VALUE_HOSTNAME);
history.setServiceName(ALERT_VALUE_SERVICE);
-
+
AlertDefinitionEntity definition = new AlertDefinitionEntity();
-
+
history.setAlertDefinition(definition);
current.setAlertHistory(history);
-
+
return Arrays.asList(current);
}
+ /**
+ * Gets a bunch of alerts with various values for state and timestamp.
+ *
+ * @return
+ */
+ private List<AlertCurrentEntity> getMockEntitiesManyStates() throws Exception {
+ // yesterday
+ AtomicLong timestamp = new AtomicLong(System.currentTimeMillis() - 86400000);
+ AtomicLong alertId = new AtomicLong(1);
+
+ int ok = 10;
+ int warning = 2;
+ int critical = 1;
+ int unknown = 3;
+ int total = ok + warning + critical + unknown;
+
+ List<AlertCurrentEntity> currents = new ArrayList<AlertCurrentEntity>(total);
+
+ for (int i = 0; i < total; i++) {
+ AlertState state = AlertState.OK;
+ String service = "HDFS";
+ String component = "NAMENODE";
+
+ if (i >= ok && i < ok + warning) {
+ state = AlertState.WARNING;
+ service = "YARN";
+ component = "RESOURCEMANAGER";
+ } else if (i >= ok + warning & i < ok + warning + critical) {
+ state = AlertState.CRITICAL;
+ service = "HIVE";
+ component = "HIVE_SERVER";
+ } else if (i >= ok + warning + critical) {
+ state = AlertState.UNKNOWN;
+ service = "FLUME";
+ component = "FLUME_HANDLER";
+ }
+
+ AlertCurrentEntity current = new AlertCurrentEntity();
+ current.setAlertId(alertId.getAndIncrement());
+ current.setOriginalTimestamp(timestamp.getAndAdd(10000));
+ current.setLatestTimestamp(timestamp.getAndAdd(10000));
+
+ AlertHistoryEntity history = new AlertHistoryEntity();
+ history.setAlertId(alertId.getAndIncrement());
+ history.setAlertInstance(null);
+ history.setAlertLabel(ALERT_VALUE_LABEL);
+ history.setAlertState(state);
+ history.setAlertText(ALERT_VALUE_TEXT);
+ history.setAlertTimestamp(current.getOriginalTimestamp());
+ history.setClusterId(Long.valueOf(1L));
+ history.setComponentName(component);
+ history.setHostName(ALERT_VALUE_HOSTNAME);
+ history.setServiceName(service);
+
+ AlertDefinitionEntity definition = new AlertDefinitionEntity();
+ history.setAlertDefinition(definition);
+ current.setAlertHistory(history);
+ currents.add(current);
+ }
+
+ return currents;
+ }
+
/**
*
@@ -238,10 +362,10 @@ public class AlertResourceProviderTest {
binder.bind(AlertsDAO.class).toInstance(EasyMock.createMock(AlertsDAO.class));
binder.bind(AmbariManagementController.class).toInstance(createMock(AmbariManagementController.class));
binder.bind(DBAccessor.class).to(DBAccessorImpl.class);
-
+
Clusters clusters = EasyMock.createNiceMock(Clusters.class);
Configuration configuration = EasyMock.createMock(Configuration.class);
-
+
binder.bind(Clusters.class).toInstance(clusters);
binder.bind(Configuration.class).toInstance(configuration);