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/09/16 14:46:55 UTC
git commit: AMBARI-7316 - Alerts: Create Alert Notices For Incoming
Alert State Changes (jonathanhurley)
Repository: ambari
Updated Branches:
refs/heads/branch-alerts-dev aaf051357 -> 760bedfe3
AMBARI-7316 - Alerts: Create Alert Notices For Incoming Alert State Changes (jonathanhurley)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/760bedfe
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/760bedfe
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/760bedfe
Branch: refs/heads/branch-alerts-dev
Commit: 760bedfe32f2a673a14cc14e7f2d41794ca3db98
Parents: aaf0513
Author: Jonathan Hurley <jh...@hortonworks.com>
Authored: Mon Sep 15 14:04:42 2014 -0400
Committer: Jonathan Hurley <jh...@hortonworks.com>
Committed: Mon Sep 15 14:04:42 2014 -0400
----------------------------------------------------------------------
.../ambari/server/agent/HeartBeatHandler.java | 20 ++-
.../server/controller/ControllerModule.java | 15 ++
.../apache/ambari/server/events/AlertEvent.java | 58 +++++++
.../server/events/AlertReceivedEvent.java | 50 +++++++
.../server/events/AlertStateChangeEvent.java | 85 +++++++++++
.../events/listeners/AlertReceivedListener.java | 150 +++++++++++++++++++
.../listeners/AlertStateChangedListener.java | 98 ++++++++++++
.../events/publishers/AlertEventPublisher.java | 100 +++++++++++++
.../ambari/server/orm/dao/AlertDispatchDAO.java | 22 +++
.../server/orm/entities/AlertGroupEntity.java | 7 +-
.../org/apache/ambari/server/state/Alert.java | 55 ++++---
.../server/state/cluster/AlertDataManager.java | 111 --------------
.../server/orm/dao/AlertDispatchDAOTest.java | 29 ++++
.../state/cluster/AlertDataManagerTest.java | 129 ++++++++++++----
14 files changed, 753 insertions(+), 176 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
index 492d832..a366301 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/agent/HeartBeatHandler.java
@@ -39,6 +39,9 @@ import org.apache.ambari.server.actionmanager.HostRoleStatus;
import org.apache.ambari.server.api.services.AmbariMetaInfo;
import org.apache.ambari.server.configuration.Configuration;
import org.apache.ambari.server.controller.MaintenanceStateHelper;
+import org.apache.ambari.server.events.AlertEvent;
+import org.apache.ambari.server.events.AlertReceivedEvent;
+import org.apache.ambari.server.events.publishers.AlertEventPublisher;
import org.apache.ambari.server.metadata.ActionMetadata;
import org.apache.ambari.server.state.AgentVersion;
import org.apache.ambari.server.state.Alert;
@@ -60,7 +63,6 @@ import org.apache.ambari.server.state.StackInfo;
import org.apache.ambari.server.state.State;
import org.apache.ambari.server.state.alert.AlertDefinition;
import org.apache.ambari.server.state.alert.AlertDefinitionHash;
-import org.apache.ambari.server.state.cluster.AlertDataManager;
import org.apache.ambari.server.state.fsm.InvalidStateTransitionException;
import org.apache.ambari.server.state.host.HostHealthyHeartbeatEvent;
import org.apache.ambari.server.state.host.HostRegistrationRequestEvent;
@@ -115,9 +117,12 @@ public class HeartBeatHandler {
@Inject
private AlertDefinitionHash alertDefinitionHash;
-
+
+ /**
+ * Publishes {@link AlertEvent} instances.
+ */
@Inject
- private AlertDataManager alertManager;
+ private AlertEventPublisher alertEventPublisher;
private Map<String, Long> hostResponseIds = new ConcurrentHashMap<String, Long>();
@@ -236,13 +241,16 @@ public class HeartBeatHandler {
if (null == hostname || null == heartbeat) {
return;
}
-
+
if (null != heartbeat.getAlerts()) {
for (Alert alert : heartbeat.getAlerts()) {
- if (null == alert.getHost())
+ if (null == alert.getHost()) {
alert.setHost(hostname);
+ }
+
Cluster cluster = clusterFsm.getCluster(alert.getCluster());
- alertManager.add(cluster.getClusterId(), alert);
+ AlertEvent event = new AlertReceivedEvent(cluster.getClusterId(), alert);
+ alertEventPublisher.publish(event);
}
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
index c395df6..8413762 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ControllerModule.java
@@ -51,6 +51,8 @@ import org.apache.ambari.server.controller.internal.HostResourceProvider;
import org.apache.ambari.server.controller.internal.MemberResourceProvider;
import org.apache.ambari.server.controller.internal.ServiceResourceProvider;
import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.events.listeners.AlertReceivedListener;
+import org.apache.ambari.server.events.listeners.AlertStateChangedListener;
import org.apache.ambari.server.orm.DBAccessor;
import org.apache.ambari.server.orm.DBAccessorImpl;
import org.apache.ambari.server.orm.PersistenceType;
@@ -222,6 +224,8 @@ public class ControllerModule extends AbstractModule {
bind(ViewInstanceHandlerList.class).to(AmbariHandlerList.class);
requestStaticInjection(ExecutionCommandWrapper.class);
+
+ bindEagerSingletons();
}
@@ -299,4 +303,15 @@ public class ControllerModule extends AbstractModule {
bind(HostRoleCommandFactory.class).to(HostRoleCommandFactoryImpl.class);
bind(SecurityHelper.class).toInstance(SecurityHelperImpl.getInstance());
}
+
+ /**
+ * Initializes all eager singletons that should be instantiated as soon as
+ * possible and not wait for injection.
+ */
+ private void bindEagerSingletons() {
+ // alert subscribers are "headless" and have no guice references; created
+ // them as eager singletons to have them register with the eventbus
+ bind(AlertReceivedListener.class).asEagerSingleton();
+ bind(AlertStateChangedListener.class).asEagerSingleton();
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
new file mode 100644
index 0000000..a75477d
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertEvent.java
@@ -0,0 +1,58 @@
+/**
+ * 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.events;
+
+import org.apache.ambari.server.state.Alert;
+
+/**
+ * The {@link AlertEvent} class the base for all events related to alerts.
+ */
+public abstract class AlertEvent {
+
+ protected long m_clusterId;
+ protected Alert m_alert;
+
+ /**
+ * Constructor.
+ *
+ * @param clusterId
+ * @param alert
+ */
+ public AlertEvent(long clusterId, Alert alert) {
+ m_clusterId = clusterId;
+ m_alert = alert;
+ }
+
+ /**
+ * Gets the cluster ID that the alert belongs to.
+ *
+ * @return the ID of the cluster.
+ */
+ public long getClusterId() {
+ return m_clusterId;
+ }
+
+ /**
+ * Gets the alert that this event is created for.
+ *
+ * @return the alert (never {@code null}).
+ */
+ public Alert getAlert(){
+ return m_alert;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
new file mode 100644
index 0000000..558c9da
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertReceivedEvent.java
@@ -0,0 +1,50 @@
+/**
+ * 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.events;
+
+import org.apache.ambari.server.state.Alert;
+
+/**
+ * The {@link AlertReceivedEvent} is fired when an {@link Alert} is received or
+ * generated.
+ */
+public final class AlertReceivedEvent extends AlertEvent {
+
+ /**
+ * Constructor.
+ *
+ * @param clusterId
+ * @param alert
+ */
+ public AlertReceivedEvent(long clusterId, Alert alert) {
+ super(clusterId, alert);
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ StringBuilder buffer = new StringBuilder("AlertReceivedEvent{ ");
+ buffer.append("cluserId=").append(m_clusterId);
+ buffer.append(", alert=").append(m_alert);
+
+ buffer.append("}");
+ return buffer.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/events/AlertStateChangeEvent.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/AlertStateChangeEvent.java b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertStateChangeEvent.java
new file mode 100644
index 0000000..ab2c3dd
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/AlertStateChangeEvent.java
@@ -0,0 +1,85 @@
+/**
+ * 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.events;
+
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.state.Alert;
+import org.apache.ambari.server.state.AlertState;
+
+/**
+ * The {@link AlertStateChangeEvent} is fired when an {@link Alert} instance has
+ * its {@link AlertState} changed.
+ */
+public final class AlertStateChangeEvent extends AlertEvent {
+
+ /**
+ * The prior alert state.
+ */
+ private final AlertState m_fromState;
+
+ /**
+ * The newly created historical entry.
+ */
+ private final AlertHistoryEntity m_newEntity;
+
+ /**
+ * Constructor.
+ *
+ * @param clusterId
+ * @param alert
+ */
+ public AlertStateChangeEvent(long clusterId, Alert alert,
+ AlertHistoryEntity newEntity, AlertState fromState) {
+ super(clusterId, alert);
+
+ m_newEntity = newEntity;
+ m_fromState = fromState;
+ }
+
+ /**
+ * Gets the newly created item in alert history.
+ *
+ * @return the newly created historical item.
+ */
+ public AlertHistoryEntity getNewHistoricalEntry() {
+ return m_newEntity;
+ }
+
+ /**
+ * Gets the prior state of the alert.
+ *
+ * @return the prior state of the alert.
+ */
+ public AlertState getFromState() {
+ return m_fromState;
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public String toString() {
+ StringBuilder buffer = new StringBuilder("AlertStateChangeEvent{ ");
+ buffer.append("cluserId=").append(m_clusterId);
+ buffer.append(", fromState=").append(m_fromState);
+ buffer.append(", alert=").append(m_alert);
+
+ buffer.append("}");
+ return buffer.toString();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertReceivedListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertReceivedListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertReceivedListener.java
new file mode 100644
index 0000000..1bdd7e2
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertReceivedListener.java
@@ -0,0 +1,150 @@
+/**
+ * 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.events.listeners;
+
+import org.apache.ambari.server.events.AlertEvent;
+import org.apache.ambari.server.events.AlertReceivedEvent;
+import org.apache.ambari.server.events.AlertStateChangeEvent;
+import org.apache.ambari.server.events.publishers.AlertEventPublisher;
+import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
+import org.apache.ambari.server.orm.dao.AlertsDAO;
+import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.state.Alert;
+import org.apache.ambari.server.state.AlertState;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.eventbus.AllowConcurrentEvents;
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * The {@link AlertReceivedListener} class handles {@link AlertReceivedEvent}
+ * and updates the appropirate DAOs. It may also fire new
+ * {@link AlertStateChangeEvent} when an {@link AlertState} change is detected.
+ */
+@Singleton
+public class AlertReceivedListener {
+ /**
+ * Logger.
+ */
+ private static Log LOG = LogFactory.getLog(AlertReceivedListener.class);
+
+ @Inject
+ private AlertsDAO m_alertsDao;
+
+ @Inject
+ private AlertDefinitionDAO m_definitionDao;
+
+ /**
+ * Receives and publishes {@link AlertEvent} instances.
+ */
+ private AlertEventPublisher m_alertEventPublisher;
+
+ /**
+ * Constructor.
+ *
+ * @param publisher
+ */
+ @Inject
+ public AlertReceivedListener(AlertEventPublisher publisher) {
+ m_alertEventPublisher = publisher;
+ m_alertEventPublisher.register(this);
+ }
+
+
+ /**
+ * Adds an alert. Checks for a new state before creating a new history record.
+ *
+ * @param clusterId the id for the cluster
+ * @param alert the alert to add
+ */
+ @Subscribe
+ @AllowConcurrentEvents
+ public void onAlertEvent(AlertReceivedEvent event) {
+ long clusterId = event.getClusterId();
+ Alert alert = event.getAlert();
+
+ AlertCurrentEntity current = m_alertsDao.findCurrentByHostAndName(clusterId,
+ alert.getHost(), alert.getName());
+
+ if (null == current) {
+ AlertDefinitionEntity definition = m_definitionDao.findByName(clusterId,
+ alert.getName());
+
+ AlertHistoryEntity history = createHistory(clusterId, definition, alert);
+
+ current = new AlertCurrentEntity();
+ current.setAlertHistory(history);
+ current.setLatestTimestamp(Long.valueOf(alert.getTimestamp()));
+ current.setOriginalTimestamp(Long.valueOf(alert.getTimestamp()));
+
+ m_alertsDao.create(current);
+
+ } else if (alert.getState() == current.getAlertHistory().getAlertState()) {
+ current.setLatestTimestamp(Long.valueOf(alert.getTimestamp()));
+ current.setLatestText(alert.getText());
+
+ m_alertsDao.merge(current);
+ } else {
+ AlertState oldState = current.getAlertHistory().getAlertState();
+
+ // insert history, update current
+ AlertHistoryEntity history = createHistory(clusterId,
+ current.getAlertHistory().getAlertDefinition(), alert);
+
+ current.setAlertHistory(history);
+ current.setLatestTimestamp(Long.valueOf(alert.getTimestamp()));
+ current.setOriginalTimestamp(Long.valueOf(alert.getTimestamp()));
+
+ m_alertsDao.merge(current);
+
+ // broadcast the alert changed event for other subscribers
+ AlertStateChangeEvent alertChangedEvent = new AlertStateChangeEvent(
+ event.getClusterId(), event.getAlert(), history, oldState);
+
+ m_alertEventPublisher.publish(alertChangedEvent);
+ }
+ }
+
+ /**
+ * Convenience to create a new alert.
+ * @param clusterId the cluster id
+ * @param definition the definition
+ * @param alert the alert data
+ * @return the new history record
+ */
+ private AlertHistoryEntity createHistory(long clusterId, AlertDefinitionEntity definition, Alert alert) {
+ AlertHistoryEntity history = new AlertHistoryEntity();
+ history.setAlertDefinition(definition);
+ history.setAlertInstance(alert.getInstance());
+ history.setAlertLabel(alert.getLabel());
+ history.setAlertState(alert.getState());
+ history.setAlertText(alert.getText());
+ history.setAlertTimestamp(Long.valueOf(alert.getTimestamp()));
+ history.setClusterId(Long.valueOf(clusterId));
+ history.setComponentName(alert.getComponent());
+ history.setHostName(alert.getHost());
+ history.setServiceName(alert.getService());
+
+ return history;
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertStateChangedListener.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertStateChangedListener.java b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertStateChangedListener.java
new file mode 100644
index 0000000..a327110
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/listeners/AlertStateChangedListener.java
@@ -0,0 +1,98 @@
+/**
+ * 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.events.listeners;
+
+import java.util.List;
+import java.util.Set;
+
+import org.apache.ambari.server.events.AlertStateChangeEvent;
+import org.apache.ambari.server.events.publishers.AlertEventPublisher;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
+import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.NotificationState;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import com.google.common.eventbus.AllowConcurrentEvents;
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+
+/**
+ * The {@link AlertStateChangedListener} class response to
+ * {@link AlertStateChangeEvent} and updates {@link AlertNoticeEntity} instances
+ * in the database.
+ */
+@Singleton
+public class AlertStateChangedListener {
+
+ /**
+ * Logger.
+ */
+ private static Log LOG = LogFactory.getLog(AlertStateChangedListener.class);
+
+ /**
+ * Used for looking up groups and targets.
+ */
+ @Inject
+ private AlertDispatchDAO m_alertsDispatchDao;
+
+ /**
+ * Constructor.
+ *
+ * @param publisher
+ */
+ @Inject
+ public AlertStateChangedListener(AlertEventPublisher publisher) {
+ publisher.register(this);
+ }
+
+ /**
+ * Listens for when an alert's state has changed.
+ */
+ @Subscribe
+ @AllowConcurrentEvents
+ public void onAlertEvent(AlertStateChangeEvent event) {
+ AlertHistoryEntity history = event.getNewHistoricalEntry();
+ AlertDefinitionEntity definition = history.getAlertDefinition();
+
+ List<AlertGroupEntity> groups = m_alertsDispatchDao.findGroupsByDefinition(definition);
+
+ // for each group, determine if there are any targets that need to receive
+ // a notification about the alert state change event
+ for (AlertGroupEntity group : groups) {
+ Set<AlertTargetEntity> targets = group.getAlertTargets();
+ if (null == targets || targets.size() == 0) {
+ continue;
+ }
+
+ for (AlertTargetEntity target : targets) {
+ AlertNoticeEntity notice = new AlertNoticeEntity();
+ notice.setAlertTarget(target);
+ notice.setAlertHistory(event.getNewHistoricalEntry());
+ notice.setNotifyState(NotificationState.PENDING);
+
+ m_alertsDispatchDao.merge(notice);
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AlertEventPublisher.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AlertEventPublisher.java b/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AlertEventPublisher.java
new file mode 100644
index 0000000..e42e317
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/events/publishers/AlertEventPublisher.java
@@ -0,0 +1,100 @@
+/**
+ * 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.events.publishers;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.ambari.server.events.AlertEvent;
+
+import com.google.common.eventbus.AsyncEventBus;
+import com.google.common.eventbus.EventBus;
+import com.google.common.eventbus.Subscribe;
+import com.google.inject.Singleton;
+
+/**
+ * The {@link AlertEventPublisher} is used to wrap a customized instance of an
+ * {@link AsyncEventBus} that is only used for alerts. In general, Ambari should
+ * have its own application-wide event bus for application events (session
+ * information, state changes, etc), but since alerts can contain many events
+ * being published concurrently, it makes sense to encapsulate a specific alert
+ * bus in this publisher.
+ */
+@Singleton
+public final class AlertEventPublisher {
+
+ /**
+ * A multi-threaded event bus that can handle dispatching {@link AlertEvent}s.
+ */
+ private final EventBus s_eventBus;
+
+ /**
+ * Constructor.
+ */
+ public AlertEventPublisher() {
+ s_eventBus = new AsyncEventBus(Executors.newFixedThreadPool(2,
+ new AlertEventBusThreadFactory()));
+ }
+
+ /**
+ * Publishes the specified event to all registered listeners that
+ * {@link Subscribe} to any of the {@link AlertEvent} instances.
+ *
+ * @param event
+ */
+ public void publish(AlertEvent event) {
+ s_eventBus.post(event);
+ }
+
+ /**
+ * Register a listener to receive events. The listener should use the
+ * {@link Subscribe} annotation.
+ *
+ * @param object
+ * the listener to receive events.
+ */
+ public void register(Object object) {
+ s_eventBus.register(object);
+ }
+
+ /**
+ * A custom {@link ThreadFactory} for the threads that will handle published
+ * {@link AlertEvent}. Threads created will have slightly reduced priority
+ * since {@link AlertEvent} instances are not critical to the system.
+ */
+ private static final class AlertEventBusThreadFactory implements
+ ThreadFactory {
+
+ private static final AtomicInteger s_threadIdPool = new AtomicInteger(1);
+
+ /**
+ * {@inheritDoc}
+ */
+ @Override
+ public Thread newThread(Runnable r) {
+ Thread thread = new Thread(r, "alert-event-bus-"
+ + s_threadIdPool.getAndIncrement());
+
+ thread.setDaemon(false);
+ thread.setPriority(Thread.NORM_PRIORITY - 1);
+
+ return thread;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
index e08c948..6d4d19b 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/dao/AlertDispatchDAO.java
@@ -22,9 +22,11 @@ import java.util.List;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
+import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
import org.apache.ambari.server.orm.entities.AlertGroupEntity;
import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
import org.apache.ambari.server.orm.entities.AlertTargetEntity;
+import org.apache.ambari.server.state.alert.AlertGroup;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -192,6 +194,26 @@ public class AlertDispatchDAO {
}
/**
+ * Gets all of the {@link AlertGroup} instances that include the specified
+ * alert definition.
+ *
+ * @param definitionEntity
+ * the definition that the group must include (not {@code null}).
+ * @return all alert groups that have an association with the specified
+ * definition or empty list if none exist (never {@code null}).
+ */
+ public List<AlertGroupEntity> findGroupsByDefinition(
+ AlertDefinitionEntity definitionEntity) {
+
+ TypedQuery<AlertGroupEntity> query = entityManagerProvider.get().createNamedQuery(
+ "AlertGroupEntity.findByAssociatedDefinition", AlertGroupEntity.class);
+
+ query.setParameter("alertDefinition", definitionEntity);
+
+ return daoUtils.selectList(query);
+ }
+
+ /**
* Gets all alert notifications stored in the database.
*
* @return all alert notifications or empty list if none exist (never
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
index f97a0eb..e7fa9c6 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/AlertGroupEntity.java
@@ -48,7 +48,8 @@ import javax.persistence.UniqueConstraint;
@NamedQuery(name = "AlertGroupEntity.findAll", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup"),
@NamedQuery(name = "AlertGroupEntity.findAllInCluster", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.clusterId = :clusterId"),
@NamedQuery(name = "AlertGroupEntity.findByName", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.groupName = :groupName"),
- @NamedQuery(name = "AlertGroupEntity.findByNameInCluster", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.groupName = :groupName AND alertGroup.clusterId = :clusterId"), })
+ @NamedQuery(name = "AlertGroupEntity.findByNameInCluster", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE alertGroup.groupName = :groupName AND alertGroup.clusterId = :clusterId"),
+ @NamedQuery(name = "AlertGroupEntity.findByAssociatedDefinition", query = "SELECT alertGroup FROM AlertGroupEntity alertGroup WHERE :alertDefinition MEMBER OF alertGroup.alertDefinitions"), })
public class AlertGroupEntity {
@Id
@@ -224,7 +225,7 @@ public class AlertGroupEntity {
/**
* Adds the specified definition to the definitions that this group will
* dispatch to.
- *
+ *
* @param definition
* the definition to add (not {@code null}).
*/
@@ -240,7 +241,7 @@ public class AlertGroupEntity {
/**
* Removes the specified definition from the definitions that this group will
* dispatch to.
- *
+ *
* @param definition
* the definition to remove (not {@code null}).
*/
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java b/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
index 7b8aabd..3675f87 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/Alert.java
@@ -32,8 +32,8 @@ public class Alert {
private String label = null;
private String text = null;
private long timestamp = 0L;
-
-
+
+
/**
* Constructor.
* @param alertName the name of the alert
@@ -56,32 +56,32 @@ public class Alert {
public Alert() {
}
-
+
/**
* @return the name
*/
- @JsonProperty("name")
+ @JsonProperty("name")
public String getName() {
return name;
}
-
+
/**
* @return the service
*/
- @JsonProperty("service")
+ @JsonProperty("service")
public String getService() {
return service;
}
-
+
/**
* @return the component
*/
- @JsonProperty("component")
+ @JsonProperty("component")
public String getComponent() {
return component;
}
-
+
/**
* @return the host
*/
@@ -89,7 +89,7 @@ public class Alert {
public String getHost() {
return host;
}
-
+
/**
* @return the state
*/
@@ -101,7 +101,7 @@ public class Alert {
/**
* @return a short descriptive label for the alert
*/
- @JsonProperty("label")
+ @JsonProperty("label")
public String getLabel() {
return label;
}
@@ -109,32 +109,32 @@ public class Alert {
/**
* @param alertLabel a short descriptive label for the alert
*/
- @JsonProperty("label")
+ @JsonProperty("label")
public void setLabel(String alertLabel) {
label = alertLabel;
}
-
+
/**
* @return detail text about the alert
*/
- @JsonProperty("text")
+ @JsonProperty("text")
public String getText() {
return text;
}
-
+
/**
* @param alertText detail text about the alert
*/
- @JsonProperty("text")
+ @JsonProperty("text")
public void setText(String alertText) {
text = alertText;
}
- @JsonProperty("instance")
+ @JsonProperty("instance")
public String getInstance() {
return instance;
}
-
+
@JsonProperty("instance")
public void setInstance(String instance) {
this.instance = instance;
@@ -164,24 +164,24 @@ public class Alert {
public void setState(AlertState state) {
this.state = state;
}
-
+
@JsonProperty("timestamp")
public void setTimestamp(long ts) {
timestamp = ts;
}
-
+
@JsonProperty("timestamp")
public long getTimestamp() {
return timestamp;
}
-
+
/**
* @return
*/
public String getCluster() {
return cluster;
}
-
+
@Override
public int hashCode() {
int result = alertHashCode();
@@ -197,8 +197,9 @@ public class Alert {
*/
@Override
public boolean equals(Object o) {
- if (null == o || !Alert.class.isInstance(o))
+ if (null == o || !Alert.class.isInstance(o)) {
return false;
+ }
return hashCode() == o.hashCode();
}
@@ -217,7 +218,7 @@ public class Alert {
/**
* Checks equality with another alert, not taking into account instance info
- *
+ *
* @param that
* the other alert to compare against
* @return <code>true</code> when the alert is equal in every way except the
@@ -226,8 +227,7 @@ public class Alert {
public boolean almostEquals(Alert that) {
return alertHashCode() == that.alertHashCode();
}
-
-
+
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
@@ -242,7 +242,4 @@ public class Alert {
sb.append('}');
return sb.toString();
}
-
-
-
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/AlertDataManager.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/AlertDataManager.java b/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/AlertDataManager.java
deleted file mode 100644
index 4a65d5a..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/cluster/AlertDataManager.java
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
- * 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.state.cluster;
-
-import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
-import org.apache.ambari.server.orm.dao.AlertsDAO;
-import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
-import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
-import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
-import org.apache.ambari.server.state.Alert;
-
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-
-/**
- * The AlertManager is reponsible for tracking all alerts generated for a cluster.
- */
-@Singleton
-public class AlertDataManager {
-
- @Inject
- private AlertsDAO m_alertsDao;
- @Inject
- private AlertDefinitionDAO m_definitionDao;
-
-
- AlertDataManager() {
- }
-
- /**
- * Adds an alert. Checks for a new state before creating a new history record.
- *
- * @param clusterId the id for the cluster
- * @param alert the alert to add
- */
- public void add(long clusterId, Alert alert) {
-
- AlertCurrentEntity current = m_alertsDao.findCurrentByHostAndName(clusterId,
- alert.getHost(), alert.getName());
-
- if (null == current) {
- AlertDefinitionEntity definition = m_definitionDao.findByName(clusterId,
- alert.getName());
-
- AlertHistoryEntity history = createHistory(clusterId, definition, alert);
-
- current = new AlertCurrentEntity();
- current.setAlertHistory(history);
- current.setLatestTimestamp(Long.valueOf(alert.getTimestamp()));
- current.setOriginalTimestamp(Long.valueOf(alert.getTimestamp()));
-
- m_alertsDao.create(current);
-
- } else if (alert.getState() == current.getAlertHistory().getAlertState()) {
- current.setLatestTimestamp(Long.valueOf(alert.getTimestamp()));
- current.setLatestText(alert.getText());
-
- m_alertsDao.merge(current);
- } else {
- // insert history, update current
- AlertHistoryEntity history = createHistory(clusterId,
- current.getAlertHistory().getAlertDefinition(), alert);
-
- current.setAlertHistory(history);
- current.setLatestTimestamp(Long.valueOf(alert.getTimestamp()));
- current.setOriginalTimestamp(Long.valueOf(alert.getTimestamp()));
-
- m_alertsDao.merge(current);
- }
-
- }
- /**
- * Convenience to create a new alert.
- * @param clusterId the cluster id
- * @param definition the definition
- * @param alert the alert data
- * @return the new history record
- */
- private AlertHistoryEntity createHistory(long clusterId, AlertDefinitionEntity definition, Alert alert) {
- AlertHistoryEntity history = new AlertHistoryEntity();
- history.setAlertDefinition(definition);
- history.setAlertInstance(alert.getInstance());
- history.setAlertLabel(alert.getLabel());
- history.setAlertState(alert.getState());
- history.setAlertText(alert.getText());
- history.setAlertTimestamp(Long.valueOf(alert.getTimestamp()));
- history.setClusterId(Long.valueOf(clusterId));
- history.setComponentName(alert.getComponent());
- history.setHostName(alert.getHost());
- history.setServiceName(alert.getService());
-
- return history;
- }
-
-
-}
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
index 8451c9b..1103961 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/dao/AlertDispatchDAOTest.java
@@ -351,6 +351,35 @@ public class AlertDispatchDAOTest {
}
/**
+ * Tests finding groups by a definition ID that they are associatd with.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testFindGroupsByDefinition() throws Exception {
+ List<AlertDefinitionEntity> definitions = createDefinitions();
+ AlertGroupEntity group = helper.createAlertGroup(clusterId, null);
+
+ group = dao.findGroupById(group.getGroupId());
+ assertNotNull(group);
+
+ for (AlertDefinitionEntity definition : definitions) {
+ group.addAlertDefinition(definition);
+ }
+
+ dao.merge(group);
+
+ group = dao.findGroupByName(group.getGroupName());
+ assertEquals(definitions.size(), group.getAlertDefinitions().size());
+
+ for (AlertDefinitionEntity definition : definitions) {
+ List<AlertGroupEntity> groups = dao.findGroupsByDefinition(definition);
+ assertEquals(1, groups.size());
+ assertEquals(group.getGroupId(), groups.get(0).getGroupId());
+ }
+ }
+
+ /**
* @return
*/
private List<AlertDefinitionEntity> createDefinitions() throws Exception {
http://git-wip-us.apache.org/repos/asf/ambari/blob/760bedfe/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
index eae1de6..bbf7774 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/cluster/AlertDataManagerTest.java
@@ -21,17 +21,28 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import java.util.UUID;
+import org.apache.ambari.server.events.AlertEvent;
+import org.apache.ambari.server.events.AlertReceivedEvent;
+import org.apache.ambari.server.events.AlertStateChangeEvent;
+import org.apache.ambari.server.events.listeners.AlertReceivedListener;
+import org.apache.ambari.server.events.listeners.AlertStateChangedListener;
import org.apache.ambari.server.orm.GuiceJpaInitializer;
import org.apache.ambari.server.orm.InMemoryDefaultTestModule;
import org.apache.ambari.server.orm.OrmTestHelper;
import org.apache.ambari.server.orm.dao.AlertDefinitionDAO;
+import org.apache.ambari.server.orm.dao.AlertDispatchDAO;
import org.apache.ambari.server.orm.dao.AlertsDAO;
import org.apache.ambari.server.orm.entities.AlertCurrentEntity;
import org.apache.ambari.server.orm.entities.AlertDefinitionEntity;
+import org.apache.ambari.server.orm.entities.AlertGroupEntity;
import org.apache.ambari.server.orm.entities.AlertHistoryEntity;
+import org.apache.ambari.server.orm.entities.AlertNoticeEntity;
+import org.apache.ambari.server.orm.entities.AlertTargetEntity;
import org.apache.ambari.server.state.Alert;
import org.apache.ambari.server.state.AlertState;
import org.apache.ambari.server.state.alert.Scope;
@@ -44,22 +55,24 @@ import com.google.inject.Injector;
import com.google.inject.persist.PersistService;
/**
- * Tests the alert manager.
+ * Tests the management of {@link AlertEvent}s in the system.
*/
public class AlertDataManagerTest {
-
+
private static final String ALERT_DEFINITION = "Alert Definition 1";
private static final String SERVICE = "service1";
private static final String COMPONENT = "component1";
private static final String HOST1 = "h1";
private static final String HOST2 = "h2";
private static final String ALERT_LABEL = "My Label";
-
+
private Long clusterId;
private Injector injector;
private OrmTestHelper helper;
private AlertsDAO dao;
-
+ private AlertDispatchDAO dispatchDao;
+ private AlertDefinitionDAO definitionDao;
+
@Before
public void setup() throws Exception {
injector = Guice.createInjector(new InMemoryDefaultTestModule());
@@ -67,7 +80,8 @@ public class AlertDataManagerTest {
helper = injector.getInstance(OrmTestHelper.class);
clusterId = helper.createCluster();
dao = injector.getInstance(AlertsDAO.class);
- AlertDefinitionDAO definitionDao = injector.getInstance(AlertDefinitionDAO.class);
+ dispatchDao = injector.getInstance(AlertDispatchDAO.class);
+ definitionDao = injector.getInstance(AlertDefinitionDAO.class);
// create 5 definitions
for (int i = 0; i < 5; i++) {
@@ -83,18 +97,16 @@ public class AlertDataManagerTest {
definition.setSourceType("SCRIPT");
definitionDao.create(definition);
}
-
}
-
+
@After
public void teardown() {
injector.getInstance(PersistService.class).stop();
injector = null;
}
-
+
@Test
public void testAlertRecords() {
-
Alert alert1 = new Alert(ALERT_DEFINITION, null, SERVICE, COMPONENT, HOST1, AlertState.OK);
alert1.setLabel(ALERT_LABEL);
alert1.setText("Component component1 is OK");
@@ -103,18 +115,24 @@ public class AlertDataManagerTest {
Alert alert2 = new Alert(ALERT_DEFINITION, null, SERVICE, COMPONENT, HOST2, AlertState.CRITICAL);
alert2.setLabel(ALERT_LABEL);
alert2.setText("Component component2 is not OK");
-
- AlertDataManager am = injector.getInstance(AlertDataManager.class);
-
- am.add(clusterId.longValue(), alert1);
- am.add(clusterId.longValue(), alert2);
-
+
+ AlertReceivedListener listener = injector.getInstance(AlertReceivedListener.class);
+
+ AlertReceivedEvent event1 = new AlertReceivedEvent(clusterId.longValue(),
+ alert1);
+
+ AlertReceivedEvent event2 = new AlertReceivedEvent(clusterId.longValue(),
+ alert2);
+
+ listener.onAlertEvent(event1);
+ listener.onAlertEvent(event2);
+
List<AlertCurrentEntity> allCurrent = dao.findCurrentByService(clusterId.longValue(), SERVICE);
assertEquals(2, allCurrent.size());
-
+
List<AlertHistoryEntity> allHistory = dao.findAll(clusterId.longValue());
assertEquals(2, allHistory.size());
-
+
AlertCurrentEntity current = dao.findCurrentByHostAndName(clusterId.longValue(), HOST1, ALERT_DEFINITION);
assertNotNull(current);
assertEquals(HOST1, current.getAlertHistory().getHostName());
@@ -124,17 +142,21 @@ public class AlertDataManagerTest {
assertEquals(current.getAlertHistory().getAlertState(), AlertState.OK);
assertEquals(1L, current.getOriginalTimestamp().longValue());
assertEquals(1L, current.getLatestTimestamp().longValue());
-
+
Long currentId = current.getAlertId();
Long historyId = current.getAlertHistory().getAlertId();
-
+
// no new history since the state is the same
Alert alert3 = new Alert(ALERT_DEFINITION, null, SERVICE, COMPONENT, HOST1, AlertState.OK);
alert3.setLabel(ALERT_LABEL);
alert3.setText("Component component1 is OK");
alert3.setTimestamp(2L);
- am.add(clusterId.longValue(), alert3);
-
+
+ AlertReceivedEvent event3 = new AlertReceivedEvent(clusterId.longValue(),
+ alert3);
+
+ listener.onAlertEvent(event3);
+
current = dao.findCurrentByHostAndName(clusterId.longValue(), HOST1, ALERT_DEFINITION);
assertNotNull(current);
assertEquals(currentId, current.getAlertId());
@@ -146,24 +168,28 @@ public class AlertDataManagerTest {
assertEquals(current.getAlertHistory().getAlertState(), AlertState.OK);
assertEquals(1L, current.getOriginalTimestamp().longValue());
assertEquals(2L, current.getLatestTimestamp().longValue());
-
+
allCurrent = dao.findCurrentByService(clusterId.longValue(), SERVICE);
assertEquals(2, allCurrent.size());
-
+
allHistory = dao.findAll(clusterId.longValue());
assertEquals(2, allHistory.size());
-
+
// change to warning
Alert alert4 = new Alert(ALERT_DEFINITION, null, SERVICE, COMPONENT, HOST1, AlertState.WARNING);
alert4.setLabel(ALERT_LABEL);
alert4.setText("Component component1 is about to go down");
alert4.setTimestamp(3L);
- am.add(clusterId.longValue(), alert4);
+
+ AlertReceivedEvent event4 = new AlertReceivedEvent(clusterId.longValue(),
+ alert4);
+
+ listener.onAlertEvent(event4);
current = dao.findCurrentByHostAndName(clusterId.longValue(), HOST1, ALERT_DEFINITION);
assertNotNull(current);
assertEquals(current.getAlertId(), currentId);
- assertFalse(historyId.equals(current.getAlertHistory().getAlertId()));
+ assertFalse(historyId.equals(current.getAlertHistory().getAlertId()));
assertEquals(HOST1, current.getAlertHistory().getHostName());
assertEquals(ALERT_DEFINITION, current.getAlertHistory().getAlertDefinition().getDefinitionName());
assertEquals(ALERT_LABEL, current.getAlertHistory().getAlertLabel());
@@ -174,8 +200,57 @@ public class AlertDataManagerTest {
allCurrent = dao.findCurrentByService(clusterId.longValue(), SERVICE);
assertEquals(2, allCurrent.size());
-
+
allHistory = dao.findAll(clusterId.longValue());
assertEquals(3, allHistory.size());
}
+
+ /**
+ * Tests that {@link AlertStateChangeEvent} cause an {@link AlertNoticeEntity}
+ * entry.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testAlertNotices() throws Exception {
+ List<AlertNoticeEntity> notices = dispatchDao.findAllNotices();
+ assertEquals( 0, notices.size() );
+
+ List<AlertDefinitionEntity> definitions = definitionDao.findAll(clusterId);
+ AlertDefinitionEntity definition = definitions.get(0);
+
+ AlertHistoryEntity history = new AlertHistoryEntity();
+ history.setServiceName(definition.getServiceName());
+ history.setClusterId(clusterId);
+ history.setAlertDefinition(definition);
+ history.setAlertLabel(definition.getDefinitionName());
+ history.setAlertText(definition.getDefinitionName());
+ history.setAlertTimestamp(System.currentTimeMillis());
+ history.setHostName(HOST1);
+ history.setAlertState(AlertState.OK);
+ dao.create(history);
+
+ List<AlertHistoryEntity> histories = dao.findAll(clusterId);
+ assertEquals(1, histories.size());
+
+ AlertTargetEntity target = helper.createAlertTarget();
+ Set<AlertTargetEntity> targets = new HashSet<AlertTargetEntity>();
+ targets.add(target);
+
+ AlertGroupEntity group = helper.createAlertGroup(clusterId, targets);
+ group.addAlertDefinition( definitions.get(0) );
+ dispatchDao.merge(group);
+
+ Alert alert1 = new Alert(ALERT_DEFINITION, null, SERVICE, COMPONENT, HOST1,
+ AlertState.OK);
+
+ AlertStateChangeEvent event = new AlertStateChangeEvent(clusterId, alert1,
+ histories.get(0), AlertState.CRITICAL);
+
+ AlertStateChangedListener listener = injector.getInstance(AlertStateChangedListener.class);
+ listener.onAlertEvent(event);
+
+ notices = dispatchDao.findAllNotices();
+ assertEquals(1, notices.size());
+ }
}