Skip to content

Commit

Permalink
HWKALERTS-162 Allow to not store external events (#207)
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasponce authored and jshaughn committed Sep 19, 2016
1 parent 845d4e1 commit b2474ed
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ public interface AlertsService {
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.
* Send events to the engine for alerts evaluation.
* Persist the provided events.
*
* @param events Set of unpersisted Events.
* @throws Exception any problem
*/
Expand Down Expand Up @@ -214,4 +216,22 @@ void resolveAlertsForTrigger(String tenantId, String triggerId, String resolvedB
* @throws Exception any problem.
*/
void sendData(Collection<Data> data) throws Exception;

/**
* Send event to the engine for alerts evaluation.
* The event sent is not persisted into the alerts engine.
*
* @param event Not Null. The event to be evaluated by the alerting engine.
* @throws Exception any problem
*/
void sendEvent(Event event) throws Exception;

/**
* Send events to the engine for alerts evaluation.
* The event sent are not persisted into the alerts engine.
*
* @param events Not null. The events to be evaluated by the alerting engine.
* @throws Exception
*/
void sendEvents(Collection<Event> events) throws Exception;
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.hawkular.alerts.engine.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
Expand Down Expand Up @@ -1521,6 +1522,22 @@ public void addEvents(Collection<Event> events) throws Exception {
alertsEngine.sendEvents(events);
}

@Override
public void sendEvent(Event event) throws Exception {
if (null == event) {
return;
}
alertsEngine.sendEvents(Arrays.asList(event));
}

@Override
public void sendEvents(Collection<Event> events) throws Exception {
if (null == events || events.isEmpty()) {
return;
}
alertsEngine.sendEvents(events);
}

private void sendAction(Alert a) {
if (actionsService != null && a != null && a.getTrigger() != null && a.getTrigger().getActions() != null) {
a.getTrigger().getActions().stream().forEach(triggerAction -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,4 +146,22 @@ class EventsITest extends AbstractITestBase {
assert resp.status == 404 : resp.status
}

@Test
void sendAndNoPersistEvents() {
String now = String.valueOf(System.currentTimeMillis());

Event event = new Event("test-tenant", "test-event-id", System.currentTimeMillis(), "test-event-data-id",
"test-category", "test event text");
Collection<Event> events = Arrays.asList(event);

def resp = client.post(path: "events/data", body: events )
assertEquals(200, resp.status)

resp = client.get(path: "events/event/test-event-id" )
assert resp.status == 404 : resp.status

resp = client.get(path: "events", query: [startTime:now] )
assertEquals(200, resp.status)
assertEquals(0, resp.data.size())
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,142 @@ class EventsLifecycleITest extends AbstractITestBase {
assertEquals(1, resp.data.size())
}

@Test
void t03_eventsChainedWithoutPersistingInputEventsTest() {
logger.info( "Running t03_eventsChainedWithoutPersistingInputEventsTest" )

String start = String.valueOf(System.currentTimeMillis())

// Clean previous tests
def resp = client.delete(path: "triggers/test-events-t03-app1")
assert(200 == resp.status || 404 == resp.status)

resp = client.delete(path: "triggers/test-events-t03-app2")
assert(200 == resp.status || 404 == resp.status)

resp = client.delete(path: "triggers/test-events-t03-combined")
assert(200 == resp.status || 404 == resp.status)

// Triggers to fire events
Trigger t03app1 = new Trigger("test-events-t03-app1", "Check if app1 is down");
t03app1.setEventType(EventType.EVENT);

resp = client.post(path: "triggers", body: t03app1)
assertEquals(200, resp.status)

// Add a condition over events
EventCondition firingCond1 = new EventCondition("test-events-t03-app1", Mode.FIRING, "app1-03.war",
"text == 'DOWN'");
Collection<Condition> conditions1 = new ArrayList<>(1);
conditions1.add( firingCond1 );

resp = client.put(path: "triggers/test-events-t03-app1/conditions/firing", body: conditions1)
assertEquals(200, resp.status)
assertEquals(1, resp.data.size())

// Enable trigger
t03app1.setEnabled(true);

resp = client.put(path: "triggers/test-events-t03-app1", body: t03app1)
assertEquals(200, resp.status)

// Triggers to fire events
Trigger t03app2 = new Trigger("test-events-t03-app2", "Check if app2 is down");
t03app2.setEventType(EventType.EVENT);

resp = client.post(path: "triggers", body: t03app2)
assertEquals(200, resp.status)

// Add a condition over events
EventCondition firingCond2 = new EventCondition("test-events-t03-app2", Mode.FIRING, "app2-03.war",
"text == 'DOWN'");
Collection<Condition> conditions2 = new ArrayList<>(1);
conditions2.add( firingCond2 );

resp = client.put(path: "triggers/test-events-t03-app2/conditions/firing", body: conditions2)
assertEquals(200, resp.status)
assertEquals(1, resp.data.size())

// Enable trigger
t03app2.setEnabled(true);

resp = client.put(path: "triggers/test-events-t03-app2", body: t03app2)
assertEquals(200, resp.status)

// Trigger to fire alerts
Trigger t03combined = new Trigger("test-events-t03-combined", "App1 and App2 are down");

resp = client.post(path: "triggers", body: t03combined)
assertEquals(200, resp.status)

// Add a condition over events
EventCondition firingCond3 = new EventCondition("test-events-t03-combined", Mode.FIRING,
"test-events-t03-app1", null);
EventCondition firingCond4 = new EventCondition("test-events-t03-combined", Mode.FIRING,
"test-events-t03-app2", null);

Collection<Condition> conditions3 = new ArrayList<>(2);
conditions3.add( firingCond3 );
conditions3.add( firingCond4 );

resp = client.put(path: "triggers/test-events-t03-combined/conditions/firing", body: conditions3)
assertEquals(200, resp.status)
assertEquals(2, resp.data.size())

// Enable trigger
t03combined.setEnabled(true);

resp = client.put(path: "triggers/test-events-t03-combined/", body: t03combined)
assertEquals(200, resp.status)

String jsonEventApp1DownId = UUID.randomUUID().toString();
String jsonEventApp1Down = "[{" +
"\"id\":\"" + jsonEventApp1DownId + "\"," +
"\"ctime\":" + System.currentTimeMillis() + "," +
"\"category\":\"" + EventCategory.DEPLOYMENT.toString() + "\"," +
"\"dataId\":\"app1-03.war\"," +
"\"text\":\"DOWN\"" +
"}]";

resp = client.post(path: "events/data", body: jsonEventApp1Down);
assertEquals(200, resp.status)

resp = client.get(path: "events/event/" + jsonEventApp1DownId);
assertEquals(404, resp.status)

String jsonEventApp2DownId = UUID.randomUUID().toString();
String jsonEventApp2Down = "[{" +
"\"id\":\"" + jsonEventApp2DownId + "\"," +
"\"ctime\":" + System.currentTimeMillis() + "," +
"\"category\":\"" + EventCategory.DEPLOYMENT.toString() + "\"," +
"\"dataId\":\"app2-03.war\"," +
"\"text\":\"DOWN\"" +
"}]";

resp = client.post(path: "events/data", body: jsonEventApp2Down);
assertEquals(200, resp.status)

resp = client.get(path: "events/event/" + jsonEventApp2DownId);
assertEquals(404, resp.status)

// The alert processing happens async, so give it a little time before failing...
for ( int i=0; i < 100; ++i ) {
Thread.sleep(100);

// FETCH recent alerts for trigger, there should be 1
resp = client.get(path: "", query: [startTime:start,triggerIds:"test-events-t03-combined"] )
if ( resp.status == 200 && resp.data != null && resp.data.size > 0) {
if ( i > 50 ) {
logger.info( "Perf: passing but sleep iterations high [" + i + "]" );
}
break;
}
assertEquals(200, resp.status)
}
assertEquals(200, resp.status)
assertEquals(1, resp.data.size())
}

@Test
void t100_eventsCleanup() {
logger.info("Running t100_eventsCleanup")
Expand All @@ -250,6 +386,15 @@ class EventsLifecycleITest extends AbstractITestBase {
resp = client.delete(path: "triggers/test-events-t02-combined")
assert(200 == resp.status || 404 == resp.status)

resp = client.delete(path: "triggers/test-events-t03-app1")
assert(200 == resp.status || 404 == resp.status)

resp = client.delete(path: "triggers/test-events-t03-app2")
assert(200 == resp.status || 404 == resp.status)

resp = client.delete(path: "triggers/test-events-t03-combined")
assert(200 == resp.status || 404 == resp.status)

// clean up alerts
resp = client.put(path: "delete", query: [triggerIds:"test-events-t01"])
assertEquals(200, resp.status)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ public EventsHandler() {
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@ApiOperation(
value = "Create a new Event.",
value = "Create a new Event. " +
"Persist the new event and send it to the engine for processing/condition evaluation.",
notes = "Returns created Event.",
response = Event.class)
@ApiResponses(value = {
Expand Down Expand Up @@ -126,6 +127,42 @@ public Response createEvent(
}
}

@POST
@Path("/data")
@Consumes(APPLICATION_JSON)
@Produces(APPLICATION_JSON)
@ApiOperation(
value = "Send events to the engine for processing/condition evaluation. " +
"Only events generated by the engine are persisted." +
"Input events are treated as external data and those are not persisted into the system.")
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Success, Event Created."),
@ApiResponse(code = 500, message = "Internal server error.", response = ApiError.class),
@ApiResponse(code = 400, message = "Bad Request/Invalid Parameters.", response = ApiError.class)
})
public Response sendEvents(
@ApiParam(required = true, name = "datums", value = "Data to be processed by alerting.")
final Collection<Event> events) {
try {
if (isEmpty(events)) {
return ResponseUtil.badRequest("Events are empty");
} else {
events.stream().forEach(e -> e.setTenantId(tenantId));
alertsService.sendEvents(events);
if (log.isDebugEnabled()) {
log.debugf("Sent Events: %s", events);
}
return ResponseUtil.ok();
}
} catch (Exception e) {
log.debug(e.getMessage(), e);
if (e.getCause() != null && e.getCause() instanceof IllegalArgumentException) {
return ResponseUtil.badRequest("Bad arguments: " + e.getMessage());
}
return ResponseUtil.internalError(e);
}
}

@PUT
@Path("/tags")
@Consumes(APPLICATION_JSON)
Expand Down

0 comments on commit b2474ed

Please sign in to comment.