Skip to content

Commit

Permalink
Merge pull request #154 from jshaughn/hwkalerts-126
Browse files Browse the repository at this point in the history
Hwkalerts 126 - Add/Remove tags for alerts and events
  • Loading branch information
lucasponce committed Jan 21, 2016
2 parents a7a55d4 + a67f3da commit 1e81d40
Show file tree
Hide file tree
Showing 10 changed files with 703 additions and 48 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates
* Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -51,6 +51,8 @@
@Type(name = "ALERT", value = Alert.class) })
public class Event implements Comparable<Event>, Serializable {

private static final long serialVersionUID = 1L;

// This field will be controlled vi fasterxml. We need to make this an explicit field because we ship the
// serialized json to clients via rest. Since we serialize via fasterxml the field will be added to the json.
// Using "visible=false" in JsonTypeInfo only works if we control the deserialization.
Expand Down Expand Up @@ -259,6 +261,13 @@ public void addTag(String name, String value) {
getTags().put(name, value);
}

public void removeTag(String name) {
if (null == name) {
throw new IllegalArgumentException("Tag must have non-null name");
}
getTags().remove(name);
}

public Map<String, String> getContext() {
if (null == context) {
context = new HashMap<>();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates
* Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand All @@ -18,6 +18,7 @@

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.hawkular.alerts.api.model.condition.ConditionEval;
Expand Down Expand Up @@ -54,12 +55,30 @@ public interface AlertsService {
void addAlerts(Collection<Alert> alerts) throws Exception;

/**
* Persist the provided events and sent to the engine for alerts evaluation.
* Add the provided tags to the specified alerts.
* @param tenantId Tenant where alerts are stored
* @param alertIds Alerts to be tagged
* @param tags the tags to add
* @throws Exception any problem
*/
void addAlertTags(String tenantId, Collection<String> alertIds, Map<String, String> tags) throws Exception;

/**
* Persist the provided events and send to the engine for alerts evaluation.
* @param events Set of unpersisted Events.
* @throws Exception any problem
*/
void addEvents(Collection<Event> events) throws Exception;

/**
* Add the provided tags to the specified events.
* @param tenantId Tenant where alerts are stored
* @param eventIds Events to be tagged.
* @param tags the tags to add
* @throws Exception any problem
*/
void addEventTags(String tenantId, Collection<String> eventIds, Map<String, String> tags) throws Exception;

/**
* Only persist the provided events.
* @param events Set of unpersisted Events.
Expand Down Expand Up @@ -89,7 +108,7 @@ public interface AlertsService {

/**
* Delete the requested Events, as described by the provided criteria.
* @param tenantId Tenant where alerts are stored
* @param tenantId Tenant where events are stored
* @param criteria specifying the Events to be deleted. Not null.
* @returns the number of events deleted
* @throws Exception any problem
Expand Down Expand Up @@ -132,6 +151,24 @@ public interface AlertsService {
*/
Page<Event> getEvents(String tenantId, EventsCriteria criteria, Pager pager) throws Exception;

/**
* Remove the provided tags from the specified alerts.
* @param tenantId Tenant where alerts are stored
* @param alertIds Alerts from which to remove the tags
* @param tags the tag names to remove.
* @throws Exception any problem
*/
void removeAlertTags(String tenantId, Collection<String> alertIds, Collection<String> tags) throws Exception;

/**
* Remove the provided tags from the specified events.
* @param tenantId Tenant where events are stored
* @param eventIds Events from which to remove the tags
* @param tags the tag names to remove
* @throws Exception any problem
*/
void removeEventTags(String tenantId, Collection<String> eventIds, Collection<String> tags) throws Exception;

/**
* The alerts must already have been added. Set the alerts to RESOLVED status. The resolvedTime will be set to the
* system time. If the call leaves the trigger with no unresolved alerts then:<br>
Expand Down
38 changes: 0 additions & 38 deletions hawkular-alerts-engine/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -206,44 +206,6 @@
</dependencies>
</profile>

<profile>
<id>clustering-eap64</id>
<activation>
<property>
<name>env</name>
<value>eap64</value>
</property>
</activation>
<dependencies>
<dependency>
<groupId>org.infinispan</groupId>
<artifactId>infinispan-core</artifactId>
<scope>provided</scope>
<version>${version.org.infinispan.eap64}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<systemProperties>
<property>
<name>testOutput</name>
<value>${project.build.testOutputDirectory}</value>
</property>
</systemProperties>
<excludes>
<exclude>**/*/PerfRulesEngineTest.java</exclude>
<exclude>**/*/CassPersistenceTest.java</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</profile>

<!-- Profiles to control test scenarios -->
<profile>
<id>default-tests</id>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,180 @@ public void addNote(String tenantId, String alertId, String user, String text) t
}
}

@Override
public void addAlertTags(String tenantId, Collection<String> alertIds, Map<String, String> tags) throws Exception {
if (isEmpty(tenantId)) {
throw new IllegalArgumentException("TenantId must be not null");
}
if (isEmpty(alertIds)) {
throw new IllegalArgumentException("AlertIds must be not null");
}
if (isEmpty(tags)) {
throw new IllegalArgumentException("Tags must be not null");
}

// Only tag existing alerts
AlertsCriteria criteria = new AlertsCriteria();
criteria.setAlertIds(alertIds);
Page<Alert> existingAlerts = getAlerts(tenantId, criteria, null);

Session session = CassCluster.getSession();
PreparedStatement updateAlert = CassStatement.get(session, CassStatement.UPDATE_ALERT);
PreparedStatement insertTag = CassStatement.get(session, CassStatement.INSERT_TAG);

try {
List<ResultSetFuture> futures = new ArrayList<>();
existingAlerts.stream().forEach(a -> {
tags.entrySet().stream().forEach(tag -> {
a.addTag(tag.getKey(), tag.getValue());
futures.add(session.executeAsync(insertTag.bind(tenantId, TagType.ALERT.name(),
tag.getKey(), tag.getValue(), a.getId())));
});
futures.add(session.executeAsync(updateAlert.bind(JsonUtil.toJson(a), tenantId, a.getAlertId())));
});
/*
main method is synchronous so we need to wait until futures are completed
*/
Futures.allAsList(futures).get();

} catch (Exception e) {
msgLog.errorDatabaseException(e.getMessage());
throw e;
}
}

@Override
public void addEventTags(String tenantId, Collection<String> eventIds, Map<String, String> tags) throws Exception {
if (isEmpty(tenantId)) {
throw new IllegalArgumentException("TenantId must be not null");
}
if (isEmpty(eventIds)) {
throw new IllegalArgumentException("EventIds must be not null");
}
if (isEmpty(tags)) {
throw new IllegalArgumentException("Tags must be not null");
}

// Only tag existing events
EventsCriteria criteria = new EventsCriteria();
criteria.setEventIds(eventIds);
Page<Event> existingEvents = getEvents(tenantId, criteria, null);

Session session = CassCluster.getSession();
PreparedStatement updateEvent = CassStatement.get(session, CassStatement.UPDATE_EVENT);
PreparedStatement insertTag = CassStatement.get(session, CassStatement.INSERT_TAG);

try {
List<ResultSetFuture> futures = new ArrayList<>();
existingEvents.stream().forEach(a -> {
tags.entrySet().stream().forEach(tag -> {
a.addTag(tag.getKey(), tag.getValue());
futures.add(session.executeAsync(insertTag.bind(tenantId, TagType.EVENT.name(),
tag.getKey(), tag.getValue(), a.getId())));
});
futures.add(session.executeAsync(updateEvent.bind(JsonUtil.toJson(a), tenantId, a.getId())));
});
/*
main method is synchronous so we need to wait until futures are completed
*/
Futures.allAsList(futures).get();

} catch (Exception e) {
msgLog.errorDatabaseException(e.getMessage());
throw e;
}
}

@Override
public void removeAlertTags(String tenantId, Collection<String> alertIds, Collection<String> tags)
throws Exception {
if (isEmpty(tenantId)) {
throw new IllegalArgumentException("TenantId must be not null");
}
if (isEmpty(alertIds)) {
throw new IllegalArgumentException("AlertIds must be not null");
}
if (isEmpty(tags)) {
throw new IllegalArgumentException("Tags must be not null");
}

// Only untag existing alerts
AlertsCriteria criteria = new AlertsCriteria();
criteria.setAlertIds(alertIds);
Page<Alert> existingAlerts = getAlerts(tenantId, criteria, null);

Session session = CassCluster.getSession();
PreparedStatement updateAlert = CassStatement.get(session, CassStatement.UPDATE_ALERT);
PreparedStatement deleteTag = CassStatement.get(session, CassStatement.DELETE_TAG);

try {
List<ResultSetFuture> futures = new ArrayList<>();
existingAlerts.stream().forEach(a -> {
tags.stream().forEach(tag -> {
if (a.getTags().containsKey(tag)) {
futures.add(session.executeAsync(deleteTag.bind(tenantId, TagType.ALERT.name(),
tag, a.getTags().get(tag), a.getId())));
a.removeTag(tag);
}
});
futures.add(session.executeAsync(updateAlert.bind(JsonUtil.toJson(a), tenantId, a.getAlertId())));
});
/*
main method is synchronous so we need to wait until futures are completed
*/
Futures.allAsList(futures).get();

} catch (Exception e) {
msgLog.errorDatabaseException(e.getMessage());
throw e;
}
}

@Override
public void removeEventTags(String tenantId, Collection<String> eventIds, Collection<String> tags)
throws Exception {
if (isEmpty(tenantId)) {
throw new IllegalArgumentException("TenantId must be not null");
}
if (isEmpty(eventIds)) {
throw new IllegalArgumentException("EventIds must be not null");
}
if (isEmpty(tags)) {
throw new IllegalArgumentException("Tags must be not null");
}

// Only untag existing events
EventsCriteria criteria = new EventsCriteria();
criteria.setEventIds(eventIds);
Page<Event> existingEvents = getEvents(tenantId, criteria, null);

Session session = CassCluster.getSession();
PreparedStatement updateEvent = CassStatement.get(session, CassStatement.UPDATE_EVENT);
PreparedStatement deleteTag = CassStatement.get(session, CassStatement.DELETE_TAG);

try {
List<ResultSetFuture> futures = new ArrayList<>();
existingEvents.stream().forEach(e -> {
tags.stream().forEach(tag -> {
if (e.getTags().containsKey(tag)) {
futures.add(session.executeAsync(deleteTag.bind(tenantId, TagType.EVENT.name(),
tag, e.getTags().get(tag), e.getId())));
e.removeTag(tag);
}
});
futures.add(session.executeAsync(updateEvent.bind(JsonUtil.toJson(e), tenantId, e.getId())));
});
/*
main method is synchronous so we need to wait until futures are completed
*/
Futures.allAsList(futures).get();

} catch (Exception e) {
msgLog.errorDatabaseException(e.getMessage());
throw e;
}
}

@Override
public Alert getAlert(String tenantId, String alertId, boolean thin) throws Exception {
if (isEmpty(tenantId)) {
Expand Down Expand Up @@ -1337,6 +1511,10 @@ private void sendAction(Alert a) {
}
}

private boolean isEmpty(Map<?, ?> m) {
return null == m || m.isEmpty();
}

private boolean isEmpty(Collection<?> c) {
return null == c || c.isEmpty();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2015 Red Hat, Inc. and/or its affiliates
* Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
Expand Down Expand Up @@ -147,6 +147,7 @@ public class CassStatement {
public static final String UPDATE_ACTION_PLUGIN_DEFAULT_PROPERTIES;
public static final String UPDATE_ALERT;
public static final String UPDATE_DAMPENING_ID;
public static final String UPDATE_EVENT;
public static final String UPDATE_TRIGGER;

static {
Expand Down Expand Up @@ -525,6 +526,8 @@ public class CassStatement {
+ "SET type = ?, evalTrueSetting = ?, evalTotalSetting = ?, evalTimeSetting = ? "
+ "WHERE tenantId = ? AND triggerId = ? AND triggerMode = ? AND dampeningId = ? ";

UPDATE_EVENT = "UPDATE " + keyspace + ".events SET payload = ? WHERE tenantId = ? AND id = ? ";

UPDATE_TRIGGER = "UPDATE " + keyspace + ".triggers "
+ "SET autoDisable = ?, autoEnable = ?, autoResolve = ?, autoResolveAlerts = ?, autoResolveMatch = ?, "
+ "context = ?, description = ?, enabled = ?, eventCategory = ?, eventText = ?, firingMatch = ?, "
Expand Down

0 comments on commit 1e81d40

Please sign in to comment.