/*****************************************************************************
*
* Copyright (C) Zenoss, Inc. 2010, 2014 all rights reserved.
*
* This content is made available according to terms specified in
* License.zenoss under the directory where your Zenoss product is installed.
*
****************************************************************************/
package org.zenoss.zep.index.impl;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexableField;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.AbstractTransactionalJUnit4SpringContextTests;
import org.springframework.test.util.ReflectionTestUtils;
import org.zenoss.protobufs.model.Model;
import org.zenoss.protobufs.zep.Zep;
import org.zenoss.protobufs.zep.Zep.Event;
import org.zenoss.protobufs.zep.Zep.EventDetail;
import org.zenoss.protobufs.zep.Zep.EventDetailFilter;
import org.zenoss.protobufs.zep.Zep.EventDetailSet;
import org.zenoss.protobufs.zep.Zep.EventFilter;
import org.zenoss.protobufs.zep.Zep.EventNote;
import org.zenoss.protobufs.zep.Zep.EventQuery;
import org.zenoss.protobufs.zep.Zep.EventSeverity;
import org.zenoss.protobufs.zep.Zep.EventSort;
import org.zenoss.protobufs.zep.Zep.EventSort.Direction;
import org.zenoss.protobufs.zep.Zep.EventSort.Field;
import org.zenoss.protobufs.zep.Zep.EventStatus;
import org.zenoss.protobufs.zep.Zep.EventSummary;
import org.zenoss.protobufs.zep.Zep.EventSummaryRequest;
import org.zenoss.protobufs.zep.Zep.EventSummaryResult;
import org.zenoss.protobufs.zep.Zep.EventTag;
import org.zenoss.protobufs.zep.Zep.EventTagFilter;
import org.zenoss.protobufs.zep.Zep.EventTagSeverities;
import org.zenoss.protobufs.zep.Zep.EventTagSeveritiesSet;
import org.zenoss.protobufs.zep.Zep.EventTagSeverity;
import org.zenoss.protobufs.zep.Zep.FilterOperator;
import org.zenoss.zep.ZepConstants;
import org.zenoss.zep.ZepException;
import org.zenoss.zep.ZepUtils;
import org.zenoss.zep.dao.EventArchiveDao;
import org.zenoss.zep.dao.EventBatch;
import org.zenoss.zep.dao.EventBatchParams;
import org.zenoss.zep.dao.EventSummaryDao;
import org.zenoss.zep.dao.impl.EventTestUtils;
import org.zenoss.zep.dao.impl.compat.DatabaseCompatibility;
import org.zenoss.zep.dao.impl.compat.TypeConverter;
import org.zenoss.zep.impl.EventPreCreateContextImpl;
import org.zenoss.zep.index.EventIndexDao;
import org.zenoss.zep.index.impl.lucene.LuceneEventIndexBackend;
import org.zenoss.zep.plugins.EventPreCreateContext;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
@ContextConfiguration({"classpath:zep-config.xml"})
public class EventIndexDaoImplIT extends AbstractTransactionalJUnit4SpringContextTests {
@Autowired
public EventSummaryDao eventSummaryDao;
@Autowired
@Qualifier("summary")
public EventIndexDao eventIndexDao;
@Autowired
@Qualifier("summary")
public LuceneEventIndexBackend eventSummaryLuceneIndexBackend;
@Autowired
public EventArchiveDao eventArchiveDao;
@Autowired
@Qualifier("archive")
public EventIndexDao eventArchiveIndexDao;
@Autowired
@Qualifier("archive")
public LuceneEventIndexBackend eventArchiveLuceneIndexBackend;
@Autowired
public DatabaseCompatibility databaseCompatibility;
@Before
public void setUp() throws ZepException {
((MultiBackendEventIndexDao)eventIndexDao).disableRebuilders();
((MultiBackendEventIndexDao)eventArchiveIndexDao).disableRebuilders();
((MultiBackendEventIndexDao)eventIndexDao).disableAsyncProcessing();
((MultiBackendEventIndexDao)eventArchiveIndexDao).disableAsyncProcessing();
eventIndexDao.clear();
eventArchiveIndexDao.clear();
eventSummaryLuceneIndexBackend.setReaderReopenInterval(0);
eventArchiveLuceneIndexBackend.setReaderReopenInterval(0);
}
@After
public void tearDown() throws ZepException {
eventIndexDao.clear();
eventArchiveIndexDao.clear();
}
private EventSummary createSummaryNew(Event event) throws ZepException {
return createSummary(event, EventStatus.STATUS_NEW);
}
private EventSummary createSummary(Event event, EventStatus status) throws ZepException {
Event changedStatus = Event.newBuilder(event).setStatus(status).build();
String uuid = eventSummaryDao.create(changedStatus, new EventPreCreateContextImpl());
return eventSummaryDao.findByUuid(uuid);
}
private EventSummary createArchiveClosed(Event event) throws ZepException {
return createArchive(event, EventStatus.STATUS_CLOSED);
}
private EventSummary createArchive(Event event, EventStatus status) throws ZepException {
Event changedStatus = Event.newBuilder(event).setStatus(status).build();
String uuid = eventArchiveDao.create(changedStatus, new EventPreCreateContextImpl());
return eventArchiveDao.findByUuid(uuid);
}
@Test
public void testList() throws ZepException {
eventIndexDao.commit();
EventSummaryResult emptyResult = eventIndexDao.list(EventSummaryRequest.newBuilder().setLimit(10).build());
assertEquals(0, emptyResult.getEventsCount());
Set<String> uuidsToSearch = new HashSet<String>();
EventSummary eventSummaryFromDb;
eventSummaryFromDb = createSummaryNew(EventTestUtils.createSampleEvent());
uuidsToSearch.add(eventSummaryFromDb.getUuid());
eventIndexDao.index(eventSummaryFromDb);
eventSummaryFromDb = createSummaryNew(EventTestUtils.createSampleEvent());
uuidsToSearch.add(eventSummaryFromDb.getUuid());
eventIndexDao.index(eventSummaryFromDb);
eventIndexDao.commit();
EventSummaryResult result = eventIndexDao.list(EventSummaryRequest.newBuilder().setLimit(10).build());
Set<String> uuidsFound = new HashSet<String>();
for (EventSummary e : result.getEventsList()) {
uuidsFound.add(e.getUuid());
}
assertEquals(uuidsToSearch, uuidsFound);
assertEquals(10, result.getLimit());
assertEquals(2, result.getEventsCount());
}
@Test
public void testIndex() throws ZepException {
Event event = EventTestUtils.createSampleEvent();
EventSummary eventSummaryFromDb = createSummaryNew(event);
eventIndexDao.index(eventSummaryFromDb);
}
@Test
public void testFindByUuid() throws AssertionError, ZepException {
Event event = EventTestUtils.createSampleEvent();
EventSummary eventSummaryFromDb = createSummaryNew(event);
eventIndexDao.index(eventSummaryFromDb);
assertNotNull(eventIndexDao.findByUuid(eventSummaryFromDb.getUuid()));
}
@Test
public void testDelete() throws AssertionError, ZepException {
Event event = EventTestUtils.createSampleEvent();
EventSummary eventSummaryFromDb = createSummaryNew(event);
eventIndexDao.index(eventSummaryFromDb);
assertNotNull(eventIndexDao.findByUuid(eventSummaryFromDb.getUuid()));
eventIndexDao.delete(eventSummaryFromDb.getUuid());
assertNull(eventIndexDao.findByUuid(eventSummaryFromDb.getUuid()));
}
@Test
public void testIndexMany() throws ZepException {
Event event = EventTestUtils.createSampleEvent();
EventSummary eventSummaryFromDb = createSummaryNew(event);
List<EventSummary> events = new ArrayList<EventSummary>();
events.add(eventSummaryFromDb);
events.add(eventSummaryFromDb);
eventIndexDao.indexMany(events);
}
private EventSummary createEventWithSeverity(EventSeverity severity,
EventStatus status, String... tags) throws ZepException {
final Event.Builder eventBuilder = Event.newBuilder(EventTestUtils.createSampleEvent());
eventBuilder.setSeverity(severity);
eventBuilder.clearTags();
for (String tag : tags) {
eventBuilder.addTags(EventTag.newBuilder().addUuid(tag).setType("zenoss.device").build());
}
final Event event = eventBuilder.build();
EventSummary summary = createSummary(event, status);
eventIndexDao.index(summary);
return summary;
}
@Test
public void testGetEventTagSeverities() throws ZepException {
String tag1 = UUID.randomUUID().toString();
String tag2 = UUID.randomUUID().toString();
String tag3 = UUID.randomUUID().toString();
EventTagFilter.Builder tagFilterBuilder = EventTagFilter.newBuilder();
tagFilterBuilder.addAllTagUuids(Arrays.asList(tag1, tag2, tag3));
EventFilter.Builder eventFilterBuilder = EventFilter.newBuilder();
eventFilterBuilder.addTagFilter(tagFilterBuilder.build());
eventFilterBuilder.addAllStatus(Arrays.asList(EventStatus.STATUS_NEW, EventStatus.STATUS_ACKNOWLEDGED));
EventFilter eventFilter = eventFilterBuilder.build();
/* Create error severity with two tags */
for (int i = 0; i < 5; i++) {
createEventWithSeverity(EventSeverity.SEVERITY_ERROR,
EventStatus.STATUS_NEW, tag1, tag2);
createEventWithSeverity(EventSeverity.SEVERITY_ERROR,
EventStatus.STATUS_ACKNOWLEDGED, tag1, tag2);
}
/* Create critical severity with one tag */
for (int i = 0; i < 3; i++) {
createEventWithSeverity(EventSeverity.SEVERITY_CRITICAL,
EventStatus.STATUS_NEW, tag2);
createEventWithSeverity(EventSeverity.SEVERITY_CRITICAL,
EventStatus.STATUS_ACKNOWLEDGED, tag2);
}
/* Create some closed events for all tags - these should be ignored. */
for (int i = 0; i < 2; i++) {
createEventWithSeverity(EventSeverity.SEVERITY_CRITICAL,
EventStatus.STATUS_CLOSED, tag1, tag2, tag3);
createEventWithSeverity(EventSeverity.SEVERITY_ERROR,
EventStatus.STATUS_CLOSED, tag1, tag2, tag3);
createEventWithSeverity(EventSeverity.SEVERITY_INFO,
EventStatus.STATUS_CLEARED, tag1, tag2, tag3);
}
EventTagSeveritiesSet tagSeveritiesSet = eventIndexDao.getEventTagSeverities(eventFilter);
Map<String, EventTagSeverities> tagSeveritiesMap = new HashMap<String, EventTagSeverities>();
for (EventTagSeverities tagSeverities : tagSeveritiesSet.getSeveritiesList()) {
tagSeveritiesMap.put(tagSeverities.getTagUuid(), tagSeverities);
}
EventTagSeverities tag1Severities = tagSeveritiesMap.get(tag1);
assertEquals(10, tag1Severities.getTotal());
assertEquals(1, tag1Severities.getSeveritiesCount());
for (EventTagSeverity tagSeverity : tag1Severities.getSeveritiesList()) {
assertEquals(EventSeverity.SEVERITY_ERROR, tagSeverity.getSeverity());
assertEquals(10, tagSeverity.getCount());
assertEquals(5, tagSeverity.getAcknowledgedCount());
}
EventTagSeverities tag2Severities = tagSeveritiesMap.get(tag2);
assertEquals(16, tag2Severities.getTotal());
assertEquals(2, tag2Severities.getSeveritiesCount());
for (EventTagSeverity tagSeverity : tag1Severities.getSeveritiesList()) {
switch (tagSeverity.getSeverity()) {
case SEVERITY_ERROR:
assertEquals(10, tagSeverity.getCount());
assertEquals(5, tagSeverity.getAcknowledgedCount());
break;
case SEVERITY_CRITICAL:
assertEquals(6, tagSeverity.getCount());
assertEquals(3, tagSeverity.getAcknowledgedCount());
break;
default:
throw new RuntimeException("Unexpected severity: " + tagSeverity.getSeverity());
}
}
EventTagSeverities tag3Severities = tagSeveritiesMap.get(tag3);
assertEquals(0, tag3Severities.getTotal());
assertEquals(0, tag3Severities.getSeveritiesCount());
}
private EventSummaryRequest createTagRequest(FilterOperator op,
String... tags) {
EventTagFilter.Builder tagBuilder = EventTagFilter.newBuilder();
tagBuilder.addAllTagUuids(Arrays.asList(tags));
tagBuilder.setOp(op);
EventFilter.Builder filterBuilder = EventFilter.newBuilder();
filterBuilder.addTagFilter(tagBuilder.build());
EventSummaryRequest.Builder reqBuilder = EventSummaryRequest.newBuilder();
reqBuilder.setEventFilter(filterBuilder.build());
return reqBuilder.build();
}
@Test
public void testTagFilterOp() throws ZepException {
String tag1 = UUID.randomUUID().toString();
String tag2 = UUID.randomUUID().toString();
EventSummary eventBothTags = createEventWithSeverity(
EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW, tag1,
tag2);
EventSummary eventTag1 = createEventWithSeverity(
EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW, tag1);
EventSummary eventTag2 = createEventWithSeverity(
EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW, tag2);
EventSummaryResult result = this.eventIndexDao.list(createTagRequest(
FilterOperator.OR, tag1, tag2));
assertEquals(3, result.getEventsCount());
Set<String> foundUuids = getUuidsFromResult(result);
assertTrue(foundUuids.contains(eventBothTags.getUuid()));
assertTrue(foundUuids.contains(eventTag1.getUuid()));
assertTrue(foundUuids.contains(eventTag2.getUuid()));
result = this.eventIndexDao.list(createTagRequest(FilterOperator.AND,
tag1, tag2));
assertEquals(1, result.getEventsCount());
assertEquals(eventBothTags.getUuid(), result.getEventsList().get(0)
.getUuid());
}
public static Zep.EventActor createSampleActor(String elementId, String elementSubId) {
Zep.EventActor.Builder actorBuilder = Zep.EventActor.newBuilder();
actorBuilder.setElementIdentifier(elementId);
actorBuilder.setElementTypeId(Model.ModelElementType.DEVICE);
actorBuilder.setElementUuid(UUID.randomUUID().toString());
actorBuilder.setElementSubIdentifier(elementSubId);
actorBuilder.setElementSubTypeId(Model.ModelElementType.COMPONENT);
actorBuilder.setElementSubUuid(UUID.randomUUID().toString());
return actorBuilder.build();
}
@Test
public void testIdentifierInsensitive() throws ZepException {
EventSummary summary = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
Event occurrence = Event.newBuilder(summary.getOccurrence(0)).setActor(
createSampleActor("MyHostName.zenoss.loc", "myCompName")).build();
summary = EventSummary.newBuilder(summary).clearOccurrence().addOccurrence(occurrence).build();
eventIndexDao.index(summary);
List<String> queries = Arrays.asList("myhostname", "ZENOSS", "loc");
for (String query : queries) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder();
filterBuilder.addElementIdentifier(query);
final EventFilter filter = filterBuilder.build();
EventSummaryRequest.Builder reqBuilder = EventSummaryRequest.newBuilder();
reqBuilder.setEventFilter(filter);
final EventSummaryRequest req = reqBuilder.build();
EventSummaryResult result = eventIndexDao.list(req);
assertEquals(1, result.getEventsCount());
assertEquals(summary, result.getEvents(0));
}
}
public static Zep.EventSummary createSampleSummary(EventSummary summary, String elementId) {
Event occurrence = Event.newBuilder(summary.getOccurrence(0)).setActor(
createSampleActor(elementId, "myCompName")).build();
return EventSummary.newBuilder(summary).clearOccurrence().addOccurrence(occurrence).build();
}
@Test
public void testIdentifierSortInsensitive() throws ZepException {
EventSummary summarya = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
summarya = createSampleSummary(summarya, "a_device.zenoss.loc");
eventIndexDao.index(summarya);
EventSummary summaryB = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
summaryB = createSampleSummary(summaryB, "B_device.zenoss.loc");
eventIndexDao.index(summaryB);
EventSummary summaryx = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
summaryx = createSampleSummary(summaryx, "x_device.zenoss.loc");
eventIndexDao.index(summaryx);
EventSummary summaryZ = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
summaryZ = createSampleSummary(summaryZ, "Z_device.zenoss.loc");
eventIndexDao.index(summaryZ);
EventSort.Builder sortBuilder = EventSort.newBuilder();
sortBuilder.setField(Field.ELEMENT_IDENTIFIER);
sortBuilder.setDirection(Direction.DESCENDING);
EventSummaryRequest.Builder reqBuilder = EventSummaryRequest.newBuilder();
reqBuilder.addSort(sortBuilder.build());
EventSummaryResult result = eventIndexDao.list(reqBuilder.build());
assertEquals(4, result.getEventsCount());
assertEquals(summaryZ, result.getEvents(0));
assertEquals(summaryx, result.getEvents(1));
assertEquals(summaryB, result.getEvents(2));
assertEquals(summarya, result.getEvents(3));
EventSort.Builder sortBuilderAsc = EventSort.newBuilder();
sortBuilderAsc.setField(Field.ELEMENT_IDENTIFIER);
sortBuilderAsc.setDirection(Direction.ASCENDING);
EventSummaryRequest.Builder reqBuilderAsc = EventSummaryRequest.newBuilder();
reqBuilderAsc.addSort(sortBuilderAsc.build());
EventSummaryResult resultAsc = eventIndexDao.list(reqBuilderAsc.build());
assertEquals(4, resultAsc.getEventsCount());
assertEquals(summarya, resultAsc.getEvents(0));
assertEquals(summaryB, resultAsc.getEvents(1));
assertEquals(summaryx, resultAsc.getEvents(2));
assertEquals(summaryZ, resultAsc.getEvents(3));
}
@Test
public void testIdentifier() throws ZepException {
EventSummary summary = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
Event occurrence = Event.newBuilder(summary.getOccurrence(0)).setActor(
createSampleActor("test-jboss.zenoss.loc", "myCompName")).build();
summary = EventSummary.newBuilder(summary).clearOccurrence().addOccurrence(occurrence).build();
eventIndexDao.index(summary);
List<String> queries = Arrays.asList("tes*", "test", "test-jboss*", "zenoss", "loc", "test-jboss*",
"test-jboss.zenoss.loc", "\"test-jboss.zenoss.loc\"", "noss", "\"TEST-jBoss.Zenoss.lOc\"",
"\"test-jboss*\"");
for (String query : queries) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder();
filterBuilder.addElementIdentifier(query);
final EventFilter filter = filterBuilder.build();
EventSummaryRequest.Builder reqBuilder = EventSummaryRequest.newBuilder();
reqBuilder.setEventFilter(filter);
final EventSummaryRequest req = reqBuilder.build();
EventSummaryResult result = eventIndexDao.list(req);
assertEquals(query, 1, result.getEventsCount());
assertEquals(query, summary, result.getEvents(0));
}
}
private static EventSummaryRequest createUuidRequest(Set<String> include, Set<String> exclude) {
EventSummaryRequest.Builder reqBuilder = EventSummaryRequest.newBuilder();
if (!include.isEmpty()) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder().addAllUuid(include);
reqBuilder.setEventFilter(filterBuilder.build());
}
if (!exclude.isEmpty()) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder().addAllUuid(exclude);
reqBuilder.setExclusionFilter(filterBuilder.build());
}
return reqBuilder.build();
}
private static Set<String> getUuidsFromResult(EventSummaryResult result) {
Set<String> uuids = new HashSet<String>(result.getEventsCount());
for (EventSummary summary : result.getEventsList()) {
uuids.add(summary.getUuid());
}
return uuids;
}
@Test
public void testExcludeUuids() throws ZepException {
EventSummary event1 = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
EventSummary event2 = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
EventSummary event3 = createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
Set<String> include = new HashSet<String>();
Set<String> exclude = new HashSet<String>();
// No filters should return all three events
Set<String> foundUuids = getUuidsFromResult(this.eventIndexDao.list(createUuidRequest(include, exclude)));
assertEquals(3, foundUuids.size());
assertTrue(foundUuids.contains(event1.getUuid()));
assertTrue(foundUuids.contains(event2.getUuid()));
assertTrue(foundUuids.contains(event3.getUuid()));
// Test filter excluding all events
exclude.add(event1.getUuid());
exclude.add(event2.getUuid());
exclude.add(event3.getUuid());
foundUuids = getUuidsFromResult(this.eventIndexDao.list(createUuidRequest(include, exclude)));
assertEquals(0, foundUuids.size());
// Test filter including 2 events
include.clear();
exclude.clear();
include.add(event1.getUuid());
include.add(event3.getUuid());
foundUuids = getUuidsFromResult(this.eventIndexDao.list(createUuidRequest(include, exclude)));
assertEquals(2, foundUuids.size());
assertTrue(foundUuids.contains(event1.getUuid()));
assertTrue(foundUuids.contains(event3.getUuid()));
// Test filter including all events of SEVERITY_ERROR but excluding a UUID
EventFilter filter = EventFilter.newBuilder().addSeverity(EventSeverity.SEVERITY_ERROR).build();
EventFilter exclusion = EventFilter.newBuilder().addUuid(event1.getUuid()).build();
EventSummaryRequest req = EventSummaryRequest.newBuilder().setEventFilter(filter)
.setExclusionFilter(exclusion).build();
foundUuids = getUuidsFromResult(this.eventIndexDao.list(req));
assertEquals(2, foundUuids.size());
assertTrue(foundUuids.contains(event2.getUuid()));
assertTrue(foundUuids.contains(event3.getUuid()));
}
private EventSummary createEventWithClass(String eventClass) throws ZepException {
final Event.Builder eventBuilder = Event.newBuilder(EventTestUtils.createSampleEvent());
eventBuilder.setEventClass(eventClass);
final Event event = eventBuilder.build();
EventSummary summary = createSummary(event, EventStatus.STATUS_NEW);
eventIndexDao.index(summary);
return summary;
}
private EventSummaryRequest createRequestForEventClass(String... eventClass) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder();
filterBuilder.addAllEventClass(Arrays.asList(eventClass));
final EventFilter filter = filterBuilder.build();
EventSummaryRequest.Builder reqBuilder = EventSummaryRequest.newBuilder();
reqBuilder.setEventFilter(filter);
return reqBuilder.build();
}
@Test
public void testListByEventClass() throws ZepException {
EventSummary event1 = createEventWithClass("/Status/Ping");
EventSummary event2 = createEventWithClass("/Status/Snmp");
createEventWithClass("/Perf");
EventSummary event4 = createEventWithClass("/App/Info/Status");
// Exact match if it doesn't end with a slash
EventSummaryResult res = this.eventIndexDao.list(createRequestForEventClass("/Status"));
assertEquals(0, res.getEventsCount());
// Matches this class and children
for (String query : Arrays.asList("/Status/", "/Status*", "/STATUS/", "/status/*")) {
res = this.eventIndexDao.list(createRequestForEventClass(query));
assertEquals(2, res.getEventsCount());
Set<String> uuids = getUuidsFromResult(res);
assertTrue(uuids.contains(event1.getUuid()));
assertTrue(uuids.contains(event2.getUuid()));
}
// Matches exact class
for (String query : Arrays.asList("/Status/Ping", "/status/ping", "/STATUS/ping")) {
res = this.eventIndexDao.list(createRequestForEventClass(query));
assertEquals(1, res.getEventsCount());
assertEquals(event1.getUuid(), res.getEvents(0).getUuid());
}
// Matches substring
for (String query : Arrays.asList("Ping", "ping", "PING", "PIN*")) {
res = this.eventIndexDao.list(createRequestForEventClass(query));
assertEquals(1, res.getEventsCount());
assertEquals(event1.getUuid(), res.getEvents(0).getUuid());
}
// Matches substring with slash
for (String query : Arrays.asList("app/info", "app/inf*", "app/i*", "ap*/inf*", "a*/info")) {
res = this.eventIndexDao.list(createRequestForEventClass(query));
assertEquals(1, res.getEventsCount());
assertEquals(event4.getUuid(), res.getEvents(0).getUuid());
}
// Ensure we don't match if substring order differs
for (String query : Arrays.asList("info/app", "inf*/app", "info/app*", "app/information", "inform*")) {
res = this.eventIndexDao.list(createRequestForEventClass(query));
assertEquals(0, res.getEventsCount());
}
}
@Test
public void testOnlyExclusion() throws ZepException {
EventSummary event1 = createEventWithSeverity(EventSeverity.SEVERITY_INFO, EventStatus.STATUS_NEW);
/* This event should be excluded from result. */
createEventWithSeverity(EventSeverity.SEVERITY_ERROR, EventStatus.STATUS_NEW);
EventFilter.Builder exclusion = EventFilter.newBuilder();
exclusion.addSeverity(EventSeverity.SEVERITY_ERROR);
EventSummaryRequest req = EventSummaryRequest.newBuilder().setExclusionFilter(exclusion.build()).build();
EventSummaryResult res = this.eventIndexDao.list(req);
assertEquals(1, res.getEventsCount());
assertEquals(event1, res.getEvents(0));
}
@Test
public void testEventFilterOperator() throws ZepException {
createEventWithSeverity(EventSeverity.SEVERITY_INFO, EventStatus.STATUS_NEW);
createEventWithSeverity(EventSeverity.SEVERITY_DEBUG, EventStatus.STATUS_CLOSED);
// First test OR query with INFO or CLOSED; should return both events
EventFilter.Builder or_filter = EventFilter.newBuilder()
.addSeverity(EventSeverity.SEVERITY_INFO)
.addStatus(EventStatus.STATUS_CLOSED)
.setOperator(FilterOperator.OR);
EventSummaryRequest or_req = EventSummaryRequest.newBuilder()
.setEventFilter(or_filter)
.build();
EventSummaryResult or_res = this.eventIndexDao.list(or_req);
assertEquals(2, or_res.getEventsCount());
// Now AND query with INFO and CLOSED; should return zero
EventFilter.Builder and_filter = EventFilter.newBuilder()
.addSeverity(EventSeverity.SEVERITY_INFO)
.addStatus(EventStatus.STATUS_CLOSED)
.setOperator(FilterOperator.AND);
EventSummaryRequest and_req = EventSummaryRequest.newBuilder()
.setEventFilter(and_filter)
.build();
EventSummaryResult and_res = this.eventIndexDao.list(and_req);
assertEquals(0, and_res.getEventsCount());
}
@Test
public void testDetailNumericFilter() throws ZepException {
// This detail is currently defined as an integer.
final String production_state_key = ZepConstants.DETAIL_DEVICE_PRODUCTION_STATE;
// Test to make sure this string value gets correctly parsed into numeric value.
final String test_value1 = "1234";
createEventWithDetail(production_state_key, test_value1);
final String low_value = "103";
createEventWithDetail(production_state_key, low_value);
final String high_value = "4154";
createEventWithDetail(production_state_key, high_value);
final EventSummaryResult result = findResultForDetail(production_state_key, test_value1);
assertEquals(1, result.getEventsCount());
final String test_value2 = "1234.0";
Exception expectedException = null;
try {
findResultForDetail(production_state_key, test_value2);
} catch (RuntimeException e) {
expectedException = e;
}
assertNotNull("Querying with a float value against an integer value should fail.", expectedException);
// find the low_value and the test_value1
final String test_value3 = ":1235";
final EventSummaryResult result3 = findResultForDetail(production_state_key, test_value3);
assertEquals(2, result3.getEventsCount());
// find the test_value1 and the high_value
final String test_value4 = "1233:";
final EventSummaryResult result4 = findResultForDetail(production_state_key, test_value4);
assertEquals(2, result4.getEventsCount());
// test that these filters get converted to ranges correctly and that the ranges find the value, 1234.
// expecting: 1233-1235, 1239
final List<String> test_value5 = new ArrayList<String>();
test_value5.add("1233");
test_value5.add("1234");
test_value5.add("1235");
test_value5.add("1239");
final EventSummaryResult result5 = findResultForDetails(production_state_key, test_value5);
assertEquals(1, result5.getEventsCount());
// test that this value gets converted to range correctly and that the range finds the value, 1234.
final List<String> test_value6 = new ArrayList<String>();
test_value6.add("1230:1239");
final EventSummaryResult result6 = findResultForDetails(production_state_key, test_value6);
assertEquals(1, result6.getEventsCount());
// test the edge of a range is inclusive.
final List<String> test_value7 = new ArrayList<String>();
test_value7.add("1230:1234");
final EventSummaryResult result7 = findResultForDetails(production_state_key, test_value7);
assertEquals(1, result7.getEventsCount());
// Just get ridiculous. Test out of order, numbers within a range, singles that span a range boundary
// Produces:
// queries=
// [
// details.zenoss.device.production_state:[4155 TO 2147483647],
// details.zenoss.device.production_state:[-2147483648 TO 1234],
// details.zenoss.device.production_state:[300 TO 300]
// details.zenoss.device.production_state:[1232 TO 1233]
// details.zenoss.device.production_state:[1235 TO 1236]
// details.zenoss.device.production_state:[3467 TO 3467]
// ]
// }
final List<String> test_value8 = new ArrayList<String>();
test_value8.add("300"); // low ball
test_value8.add("1232"); // start a sequence
test_value8.add("1233");
test_value8.add("3467"); // throw something in 'out of order'
test_value8.add("4155:"); // does not include the highest value.
test_value8.add(":1234"); // everything up to this int, counting the previous sequence
test_value8.add("1235"); // continue the sequence over the previous range.
test_value8.add("1236"); // continue the sequence over the previous range.
// should find all but the highest test event, 4154
final EventSummaryResult result8 = findResultForDetails(production_state_key, test_value8);
assertEquals(2, result8.getEventsCount());
}
@Test
@Ignore
public void testDetailStringFilter() throws ZepException {
// override the spring config to test a string detail
}
private EventSummary createEventWithDetail(String key, String val) throws ZepException {
final EventDetail.Builder detailBuilder = EventDetail.newBuilder();
detailBuilder.setName(key);
detailBuilder.addValue(val);
return createEventWithDetails(Collections.singletonList(detailBuilder.build()));
}
private EventSummary createEventWithDetails(List<EventDetail> details) throws ZepException {
final Event.Builder eventBuilder = Event.newBuilder(EventTestUtils.createSampleEvent());
eventBuilder.addAllDetails(details);
final Event event = eventBuilder.build();
EventSummary summary = createSummary(event, EventStatus.STATUS_NEW);
eventIndexDao.index(summary);
return summary;
}
private EventSummaryResult findResultForDetail(String key, String val) throws ZepException {
return findResultForDetails(key, Collections.singletonList(val));
}
private EventSummaryResult findResultForDetails(String key, List<String> vals) throws ZepException {
final EventDetailFilter.Builder edFilterBuilder = EventDetailFilter.newBuilder();
edFilterBuilder.setKey(key);
edFilterBuilder.addAllValue(vals);
final EventDetailFilter edf = edFilterBuilder.build();
final EventFilter.Builder filter = EventFilter.newBuilder().addAllDetails(Collections.singletonList(edf));
EventSummaryRequest request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
return this.eventIndexDao.list(request);
}
@Test
public void testSummaryPhrase() throws ZepException {
EventSummary event1 = createSummaryNew(Event.newBuilder(EventTestUtils.createSampleEvent())
.setSummary("Monkeys love to eat bananas").build());
EventSummary event2 = createSummaryNew(Event.newBuilder(EventTestUtils.createSampleEvent())
.setSummary("Bananas love to eat monkeys").build());
eventIndexDao.indexMany(Arrays.asList(event1, event2));
EventFilter filter = EventFilter.newBuilder().addEventSummary("\"eat bananas\"").build();
EventSummaryRequest request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
EventSummaryResult result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event1, result.getEvents(0));
filter = EventFilter.newBuilder().addEventSummary("\"eat monkeys\"").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
// Test unterminated phrase query (from live search, etc.)
filter = EventFilter.newBuilder().addEventSummary("\"eat monkeys").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
// Test wildcard multi-term
filter = EventFilter.newBuilder().addEventSummary("\"eat monkey?\"").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
// Test wildcard multi-term
filter = EventFilter.newBuilder().addEventSummary("\"eat mon*ys\"").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
// AND query where both match
filter = EventFilter.newBuilder().addEventSummary("\"eat monkeys\" bananas").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
// AND query where one doesn't match
filter = EventFilter.newBuilder().addEventSummary("\"eat monkeys\" not-here").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(0, result.getEventsCount());
// Test OR query where one doesn't match
filter = EventFilter.newBuilder().addEventSummary("\"eat monkeys\"").addEventSummary("not-here").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
filter = EventFilter.newBuilder().addEventSummary("\"eat mon*\" ban*").build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(1, result.getEventsCount());
assertEquals(event2, result.getEvents(0));
List<String> bothMatchQueries = Arrays.asList("\"bana*\"", "bananas monkeys", "bananas", "monkeys", "ban*", "mon*k*");
for (String bothMatchQuery : bothMatchQueries) {
filter = EventFilter.newBuilder().addEventSummary(bothMatchQuery).build();
request = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
result = this.eventIndexDao.list(request);
assertEquals(2, result.getEventsCount());
Map<String, EventSummary> expected = new HashMap<String, EventSummary>();
expected.put(event1.getUuid(), event1);
expected.put(event2.getUuid(), event2);
for (EventSummary resultSummary : result.getEventsList()) {
EventSummary e = expected.remove(resultSummary.getUuid());
assertNotNull(e);
assertEquals(e, resultSummary);
}
assertTrue(expected.isEmpty());
}
}
@Test
public void testSortNumericFilter() throws ZepException {
final String production_state_key = ZepConstants.DETAIL_DEVICE_PRODUCTION_STATE;
List<EventSummary> sorted = new ArrayList<EventSummary>();
sorted.add(createEventWithDetail(production_state_key, "5"));
sorted.add(createEventWithDetail(production_state_key, "10"));
sorted.add(createEventWithDetail(production_state_key, "25"));
sorted.add(createEventWithDetail(production_state_key, "500"));
sorted.add(createEventWithDetail(production_state_key, "1000"));
EventSort sort = EventSort.newBuilder().setField(Field.DETAIL).setDetailKey(production_state_key).build();
EventSummaryRequest request = EventSummaryRequest.newBuilder().addSort(sort).build();
EventSummaryResult result = this.eventIndexDao.list(request);
assertEquals(sorted, result.getEventsList());
sort = EventSort.newBuilder().setField(Field.DETAIL).setDetailKey(production_state_key)
.setDirection(Direction.DESCENDING).build();
request = EventSummaryRequest.newBuilder().addSort(sort).build();
result = this.eventIndexDao.list(request);
Collections.reverse(sorted);
assertEquals(sorted, result.getEventsList());
}
@Test
public void testListZeroLimit() throws ZepException {
/* Create one event */
EventSummary event = createSummaryNew(EventTestUtils.createSampleEvent());
this.eventIndexDao.index(event);
EventSummaryRequest request = EventSummaryRequest.newBuilder().setLimit(0).build();
EventSummaryResult result = this.eventIndexDao.list(request);
assertEquals(0, result.getEventsCount());
assertEquals(0, result.getLimit());
assertEquals(0, result.getNextOffset());
assertEquals(1, result.getTotal());
}
@Test
public void testIpv4Sort() throws ZepException {
List<EventSummary> sorted = new ArrayList<EventSummary>();
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.2"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.10"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.20"));
EventSort sort = EventSort.newBuilder().setField(Field.DETAIL)
.setDetailKey(ZepConstants.DETAIL_DEVICE_IP_ADDRESS).build();
EventSummaryRequest request = EventSummaryRequest.newBuilder().addSort(sort).build();
EventSummaryResult result = this.eventIndexDao.list(request);
assertEquals(sorted, result.getEventsList());
sort = EventSort.newBuilder(sort).setDirection(Direction.DESCENDING).build();
request = EventSummaryRequest.newBuilder().addSort(sort).build();
result = this.eventIndexDao.list(request);
Collections.reverse(sorted);
assertEquals(sorted, result.getEventsList());
}
@Test
public void testIpv6Sort() throws ZepException {
List<EventSummary> sorted = new ArrayList<EventSummary>();
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::20"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::1000"));
EventSort sort = EventSort.newBuilder().setField(Field.DETAIL)
.setDetailKey(ZepConstants.DETAIL_DEVICE_IP_ADDRESS).build();
EventSummaryRequest request = EventSummaryRequest.newBuilder().addSort(sort).build();
EventSummaryResult result = this.eventIndexDao.list(request);
assertEquals(sorted, result.getEventsList());
sort = EventSort.newBuilder(sort).setDirection(Direction.DESCENDING).build();
request = EventSummaryRequest.newBuilder().addSort(sort).build();
result = this.eventIndexDao.list(request);
Collections.reverse(sorted);
assertEquals(sorted, result.getEventsList());
}
@Test
public void testIpv4Before6Sort() throws ZepException {
List<EventSummary> sorted = new ArrayList<EventSummary>();
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "0.0.0.0"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.2"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::"));
sorted.add(createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192f::"));
EventSort sort = EventSort.newBuilder().setField(Field.DETAIL)
.setDetailKey(ZepConstants.DETAIL_DEVICE_IP_ADDRESS).build();
EventSummaryRequest request = EventSummaryRequest.newBuilder().addSort(sort).build();
EventSummaryResult result = this.eventIndexDao.list(request);
assertEquals(sorted, result.getEventsList());
sort = EventSort.newBuilder(sort).setDirection(Direction.DESCENDING).build();
request = EventSummaryRequest.newBuilder().addSort(sort).build();
result = this.eventIndexDao.list(request);
Collections.reverse(sorted);
assertEquals(sorted, result.getEventsList());
}
private EventFilter createFilterForIpAddress(String value) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder();
filterBuilder.addDetailsBuilder().setKey(ZepConstants.DETAIL_DEVICE_IP_ADDRESS).addValue(value);
return filterBuilder.build();
}
private void assertContainsEvents(EventSummaryResult result, EventSummary... summaries) {
final Map<String, EventSummary> summaryMap = Maps.newHashMap();
for (EventSummary summary : summaries) {
summaryMap.put(summary.getUuid(), summary);
}
for (EventSummary event : result.getEventsList()) {
EventSummary expected = summaryMap.remove(event.getUuid());
assertEquals("Unable to find event in expected map: " + event, expected, event);
}
assertTrue("Expected empty map, still contains: " + summaryMap, summaryMap.isEmpty());
}
private void assertContainsEvents(EventSummaryResult result, Collection<EventSummary> summaries) {
assertContainsEvents(result, summaries.toArray(new EventSummary[summaries.size()]));
}
@Test
public void testIpv4RangeQuery() throws ZepException {
EventSummary ev5 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.5");
EventSummary ev6 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.6");
EventSummary ev7 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.7");
EventSummary ev9 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.9");
EventSummaryRequest request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress("192.168.1.5-192.168.1.7")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev5, ev6, ev7);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("192.168.1.5-7"))
.build();
assertContainsEvents(this.eventIndexDao.list(request), ev5, ev6, ev7);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("192.168.1.5/24")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev5, ev6, ev7, ev9);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("192.168.1.5")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev5);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("192.168.1.7-10")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev7, ev9);
}
@Test
public void testIpv6RangeQuery() throws ZepException {
EventSummary ev1 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffa0");
EventSummary ev2 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffa7");
EventSummary ev3 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffb0");
EventSummary ev4 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffc0");
EventSummaryRequest request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress("::ffa0-::ffb0")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2, ev3);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("::ffa0-ffb0"))
.build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2, ev3);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("::ffa0/120")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2, ev3, ev4);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("::ffa7")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev2);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("::ffb0-ffc0")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev3, ev4);
}
@Test
public void testIpv4SubstringQuery() throws ZepException {
EventSummary ev1 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.2");
EventSummary ev2 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.200");
EventSummary ev3 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.168.1.3");
EventSummary ev4 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "192.1.2.3");
EventSummaryRequest request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress("1.2")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev4);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("1.?"))
.build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev3, ev4);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("1.2*")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2, ev4);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("1.*")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2, ev3, ev4);
}
@Test
public void testIpv6SubstringQuery() throws ZepException {
EventSummary ev1 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffa0:123");
EventSummary ev2 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffa1:123");
EventSummary ev3 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::ffa0:0");
EventSummaryRequest request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress("ffa?")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2, ev3);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("0123"))
.build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("123")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("ffa0:0*")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev3);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("ffa?:1*")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1, ev2);
}
@Test
public void testIpv6ExactMatch() throws ZepException {
EventSummary ev1 = createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::1");
EventSummaryRequest request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress("0:0:0:0:0:0:0:1")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1);
request = EventSummaryRequest.newBuilder().setEventFilter(createFilterForIpAddress("::1")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1);
request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress("0000:0000:0000:0000:0000:0000:0000:0001")).build();
assertContainsEvents(this.eventIndexDao.list(request), ev1);
}
@Test
public void testInvalidIpAddress() throws ZepException {
createEventWithDetail(ZepConstants.DETAIL_DEVICE_IP_ADDRESS, "::1");
List<String> invalid = Arrays.asList(":::", ":", "....", "not an ip");
for (String query : invalid) {
EventSummaryRequest request = EventSummaryRequest.newBuilder()
.setEventFilter(createFilterForIpAddress(query)).build();
assertEquals(0, this.eventIndexDao.list(request).getEventsCount());
}
}
@Test
public void testDetailOrganizerQueries() throws ZepException {
List<String> detailNames = Arrays.asList(ZepConstants.DETAIL_DEVICE_GROUPS, ZepConstants.DETAIL_DEVICE_LOCATION,
ZepConstants.DETAIL_DEVICE_SYSTEMS);
for (String detailName : detailNames) {
EventSummary ev1 = createEventWithDetail(detailName, "/Group1/Nested2");
List<String> matches = Arrays.asList("group*", "nested*", "/Group*", "Group1/Nes*", "Group1", "Nested2",
"/Group1/Nested2", "/Group1/Nested2/");
for (String query : matches) {
EventSummaryResult result = findResultForDetail(detailName, query);
assertEquals(1, result.getEventsCount());
assertEquals(ev1.getUuid(), result.getEventsList().get(0).getUuid());
}
List<String> noMatches = Arrays.asList("Nested*/Group*", "/Nested*");
for (String query : noMatches) {
EventSummaryResult result = findResultForDetail(detailName, query);
assertEquals(0, result.getEventsCount());
}
}
}
@Test
public void testSize() throws ZepException {
long size = eventIndexDao.getSize();
String msg = String.format("eventIndexDao.getSize(): %d > 0", size);
assertTrue(msg, size > 0);
}
@Test
public void testSearchMessage() throws ZepException {
EventSummary event1 = createSummaryNew(Event.newBuilder(EventTestUtils.createSampleEvent())
.setMessage("This is a Sample message").build());
this.eventIndexDao.index(event1);
EventFilter filter = EventFilter.newBuilder().addMessage("sampl? MESS*").build();
EventSummaryRequest req = EventSummaryRequest.newBuilder().setEventFilter(filter).build();
EventSummaryResult result = this.eventIndexDao.list(req);
assertContainsEvents(result, event1);
}
@Test
public void testArchive() throws ZepException {
List<EventSummary> created = Lists.newArrayList();
for (int i = 0; i < 55; i++) {
String summary = String.format("Event Archive %03d", i);
EventSummary event = createArchiveClosed(
Event.newBuilder(EventTestUtils.createSampleEvent()).setSummary(summary).build());
created.add(event);
}
this.eventArchiveIndexDao.indexMany(created);
EventSort sort = EventSort.newBuilder().setField(Field.EVENT_SUMMARY).build();
EventSummaryRequest req = EventSummaryRequest.newBuilder().addSort(sort).setOffset(30).setLimit(17).build();
EventSummaryResult result = this.eventArchiveIndexDao.list(req);
assertContainsEvents(result, created.subList(req.getOffset(), req.getOffset() + req.getLimit()));
}
@Test
public void testArchiveMissingInDb() throws ZepException {
List<EventSummary> created = Lists.newArrayList();
for (int i = 0; i < 10; i++) {
String summary = String.format("Event Archive %03d", i);
EventSummary event = createArchiveClosed(
Event.newBuilder(EventTestUtils.createSampleEvent()).setSummary(summary).build());
created.add(event);
}
this.eventArchiveIndexDao.indexMany(created);
// Delete the first 3 events from the database (but don't delete from index)
List<String> summariesToDelete = Lists.newArrayList();
for (int i = 0; i < 3; i++) {
summariesToDelete.add(created.get(i).getOccurrence(0).getSummary());
}
Map<String, List<String>> args = Collections.singletonMap("_summaries", summariesToDelete);
this.simpleJdbcTemplate.update("DELETE FROM event_archive WHERE summary IN (:_summaries)", args);
EventSort sort = EventSort.newBuilder().setField(Field.EVENT_SUMMARY).build();
EventSummaryRequest req = EventSummaryRequest.newBuilder().addSort(sort).build();
EventSummaryResult result = this.eventArchiveIndexDao.list(req);
assertContainsEvents(result, created.subList(3, 10));
// Test sorting descending by summary
sort = EventSort.newBuilder().setField(Field.EVENT_SUMMARY).setDirection(Direction.DESCENDING).build();
req = EventSummaryRequest.newBuilder().addSort(sort).build();
result = this.eventArchiveIndexDao.list(req);
List<EventSummary> subList = created.subList(3, 10);
assertContainsEvents(result, subList);
ListIterator<EventSummary> it = subList.listIterator(subList.size());
int i = 0;
while (it.hasPrevious()) {
assertEquals(result.getEvents(i), it.previous());
++i;
}
}
private Set<String> getFieldNames(LuceneEventIndexBackend backend, String eventUuid) throws IOException {
IndexWriter indexWriter = (IndexWriter) ReflectionTestUtils.getField(backend, "writer");
IndexReader reader = null;
try {
reader = IndexReader.open(indexWriter, true);
IndexSearcher searcher = new IndexSearcher(reader);
TopDocs docs = searcher.search(new TermQuery(new Term(IndexConstants.FIELD_UUID,
eventUuid)), null, 1);
assertEquals(1, docs.totalHits);
int docId = docs.scoreDocs[0].doc;
Document document = reader.document(docId);
Set<String> fieldNames = Sets.newHashSet();
for (IndexableField field : document.getFields()) {
fieldNames.add(field.name());
}
return fieldNames;
} finally {
ZepUtils.close(reader);
}
}
@Test
public void testSummaryStoredEvent() throws ZepException, IOException {
// Verify that the event summary index stores serialized versions of the events
EventSummary event = createSummaryNew(Event.newBuilder(EventTestUtils.createSampleEvent()).build());
this.eventIndexDao.index(event);
Set<String> fieldNames = getFieldNames(this.eventSummaryLuceneIndexBackend, event.getUuid());
assertEquals(Sets.newHashSet(IndexConstants.FIELD_UUID, IndexConstants.FIELD_LAST_SEEN_TIME,
IndexConstants.FIELD_STATUS, IndexConstants.FIELD_PROTOBUF, IndexConstants.FIELD_COUNT,
IndexConstants.FIELD_TAGS, IndexConstants.FIELD_SEVERITY), fieldNames);
}
@Test
public void testArchiveNoStoredEvent() throws ZepException, IOException {
// Verify that the event archive index doesn't store events in the index but gets them from the database
EventSummary event = createArchiveClosed(Event.newBuilder(EventTestUtils.createSampleEvent()).build());
this.eventArchiveIndexDao.index(event);
Set<String> fieldNames = getFieldNames(this.eventArchiveLuceneIndexBackend, event.getUuid());
assertEquals(Sets.newHashSet(IndexConstants.FIELD_UUID, IndexConstants.FIELD_LAST_SEEN_TIME,
IndexConstants.FIELD_STATUS, IndexConstants.FIELD_COUNT, IndexConstants.FIELD_TAGS,
IndexConstants.FIELD_SEVERITY), fieldNames);
}
@Test
public void testArchiveFindByUuid() throws ZepException, IOException {
EventSummary event = createArchiveClosed(Event.newBuilder(EventTestUtils.createSampleEvent()).build());
this.eventArchiveIndexDao.index(event);
assertEquals(this.eventArchiveIndexDao.findByUuid(event.getUuid()), event);
}
@Test
public void testArchiveFindByUuidNotInDb() throws ZepException {
TypeConverter<String> uuidConverter = databaseCompatibility.getUUIDConverter();
EventSummary event = createArchiveClosed(Event.newBuilder(EventTestUtils.createSampleEvent()).build());
this.eventArchiveIndexDao.index(event);
this.simpleJdbcTemplate.update("DELETE FROM event_archive WHERE uuid=:uuid",
Collections.singletonMap("uuid", uuidConverter.toDatabaseType(event.getUuid())));
assertNull(this.eventArchiveIndexDao.findByUuid(event.getUuid()));
}
@Test
public void testArchiveGetEventTagSeverities() throws ZepException {
String tag1 = UUID.randomUUID().toString();
String tag2 = UUID.randomUUID().toString();
String tag3 = UUID.randomUUID().toString();
EventTagFilter.Builder tagFilterBuilder = EventTagFilter.newBuilder();
tagFilterBuilder.addAllTagUuids(Arrays.asList(tag1, tag2, tag3));
EventFilter.Builder eventFilterBuilder = EventFilter.newBuilder();
eventFilterBuilder.addTagFilter(tagFilterBuilder.build());
eventFilterBuilder.addAllStatus(Arrays.asList(EventStatus.STATUS_CLOSED, EventStatus.STATUS_AGED));
EventFilter eventFilter = eventFilterBuilder.build();
/* Create error severity with two tags */
for (int i = 0; i < 5; i++) {
createEventWithSeverity(EventSeverity.SEVERITY_ERROR,
EventStatus.STATUS_CLOSED, tag1, tag2);
createEventWithSeverity(EventSeverity.SEVERITY_ERROR,
EventStatus.STATUS_AGED, tag1, tag2);
}
/* Create critical severity with one tag */
for (int i = 0; i < 3; i++) {
createEventWithSeverity(EventSeverity.SEVERITY_CRITICAL,
EventStatus.STATUS_CLOSED, tag2);
createEventWithSeverity(EventSeverity.SEVERITY_CRITICAL,
EventStatus.STATUS_AGED, tag2);
}
/* Create some cleared events for all tags - these should be ignored. */
for (int i = 0; i < 2; i++) {
createEventWithSeverity(EventSeverity.SEVERITY_CRITICAL,
EventStatus.STATUS_CLEARED, tag1, tag2, tag3);
createEventWithSeverity(EventSeverity.SEVERITY_ERROR,
EventStatus.STATUS_CLEARED, tag1, tag2, tag3);
createEventWithSeverity(EventSeverity.SEVERITY_INFO,
EventStatus.STATUS_CLEARED, tag1, tag2, tag3);
}
EventTagSeveritiesSet tagSeveritiesSet = eventIndexDao.getEventTagSeverities(eventFilter);
Map<String, EventTagSeverities> tagSeveritiesMap = new HashMap<String, EventTagSeverities>();
for (EventTagSeverities tagSeverities : tagSeveritiesSet.getSeveritiesList()) {
tagSeveritiesMap.put(tagSeverities.getTagUuid(), tagSeverities);
}
EventTagSeverities tag1Severities = tagSeveritiesMap.get(tag1);
assertEquals(10, tag1Severities.getTotal());
assertEquals(1, tag1Severities.getSeveritiesCount());
for (EventTagSeverity tagSeverity : tag1Severities.getSeveritiesList()) {
assertEquals(EventSeverity.SEVERITY_ERROR, tagSeverity.getSeverity());
assertEquals(10, tagSeverity.getCount());
assertEquals(0, tagSeverity.getAcknowledgedCount());
}
EventTagSeverities tag2Severities = tagSeveritiesMap.get(tag2);
assertEquals(16, tag2Severities.getTotal());
assertEquals(2, tag2Severities.getSeveritiesCount());
for (EventTagSeverity tagSeverity : tag1Severities.getSeveritiesList()) {
switch (tagSeverity.getSeverity()) {
case SEVERITY_ERROR:
assertEquals(10, tagSeverity.getCount());
assertEquals(0, tagSeverity.getAcknowledgedCount());
break;
case SEVERITY_CRITICAL:
assertEquals(6, tagSeverity.getCount());
assertEquals(0, tagSeverity.getAcknowledgedCount());
break;
default:
throw new RuntimeException("Unexpected severity: " + tagSeverity.getSeverity());
}
}
EventTagSeverities tag3Severities = tagSeveritiesMap.get(tag3);
assertEquals(0, tag3Severities.getTotal());
assertEquals(0, tag3Severities.getSeveritiesCount());
}
@Test
public void testIdentifierPrefixUppercase() throws ZepException {
EventSummary.Builder summaryBuilder = EventSummary.newBuilder(
createSummaryNew(EventTestUtils.createSampleEvent()));
summaryBuilder.getOccurrenceBuilder(0).getActorBuilder().setElementIdentifier("EC2Manager");
EventSummary summary = summaryBuilder.build();
eventIndexDao.index(summary);
List<String> queries = Arrays.asList("E", "EC", "EC2");
for (String query : queries) {
EventFilter.Builder filterBuilder = EventFilter.newBuilder().addElementIdentifier(query);
EventSummaryRequest req = EventSummaryRequest.newBuilder().setEventFilter(filterBuilder).build();
EventSummaryResult result = eventIndexDao.list(req);
assertEquals(1, result.getEventsCount());
assertEquals(summary, result.getEvents(0));
}
}
@Test
public void testSavedSearchTimeout() throws ZepException {
/*
* Verifies the behavior of a saved search to ensure it is not expired
* during a long database operation. This test creates a saved search
* with a short timeout of 1 second. Then it performs three queries on
* the saved search in quick succession with the database DAO mocked
* out to make the query take longer than 1 second on the first call.
* Previously, this would cause the saved search to time out before
* the second call could be issued. Now the behavior will disable the
* timeout of the saved search until after the query returns.
*/
EventSummary.Builder summaryBuilder = EventSummary.newBuilder(
createArchiveClosed(EventTestUtils.createSampleEvent()));
EventSummary summary = summaryBuilder.build();
eventArchiveIndexDao.index(summary);
final EventArchiveDao archiveDao = applicationContext.getBean(EventArchiveDao.class);
// Create a mock of the current archive dao (override findByUuids to take longer)
EventArchiveDao mockArchiveDao = new EventArchiveDao() {
private AtomicBoolean initialDelay = new AtomicBoolean();
@Override
public String create(Event event, EventPreCreateContext context) throws ZepException {
return archiveDao.create(event, context);
}
@Override
public EventSummary findByUuid(String uuid) throws ZepException {
return archiveDao.findByUuid(uuid);
}
@Override
public List<EventSummary> findByUuids(List<String> uuids) throws ZepException {
// Delay the first call to findByUuids
if (initialDelay.compareAndSet(false, true)) {
try {
Thread.sleep(1500L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ZepException(e.getLocalizedMessage(), e);
}
}
return archiveDao.findByUuids(uuids);
}
@Override
public List<EventSummary> findByKey(Collection<EventSummary> toLookup) throws ZepException {
// Delay the first call to findByUuids
if (initialDelay.compareAndSet(false, true)) {
try {
Thread.sleep(1500L);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new ZepException(e.getLocalizedMessage(), e);
}
}
return archiveDao.findByKey(toLookup);
}
@Override
public int addNote(String uuid, EventNote note) throws ZepException {
return archiveDao.addNote(uuid, note);
}
@Override
public int updateDetails(String uuid, EventDetailSet details) throws ZepException {
return archiveDao.updateDetails(uuid, details);
}
@Override
public EventBatch listBatch(EventBatchParams batchParams, long maxUpdateTime, int limit) throws ZepException {
return archiveDao.listBatch(batchParams, maxUpdateTime, limit);
}
@Override
public void importEvent(EventSummary eventSummary) throws ZepException {
archiveDao.importEvent(eventSummary);
}
@Override
public void initializePartitions() throws ZepException {
archiveDao.initializePartitions();
}
@Override
public long getPartitionIntervalInMs() {
return archiveDao.getPartitionIntervalInMs();
}
@Override
public void purge(int duration, TimeUnit unit) throws ZepException {
archiveDao.purge(duration, unit);
}
};
EventQuery.Builder queryBuilder = EventQuery.newBuilder();
queryBuilder.setTimeout(1);
EventQuery query = queryBuilder.build();
String searchUuid = this.eventArchiveIndexDao.createSavedSearch(query);
try {
ReflectionTestUtils.setField(this.eventArchiveLuceneIndexBackend, "eventSummaryBaseDao", mockArchiveDao);
for (int i = 0; i < 3; i++) {
EventSummaryResult result = this.eventArchiveIndexDao.savedSearch(searchUuid, 0, 1000);
assertEquals(1, result.getTotal());
assertEquals(summary.getUuid(), result.getEvents(0).getUuid());
}
} finally {
ReflectionTestUtils.setField(this.eventArchiveLuceneIndexBackend, "eventSummaryBaseDao", archiveDao);
this.eventArchiveIndexDao.deleteSavedSearch(searchUuid);
}
}
@Test
public void testFailMaxCountClauseParam() throws ZepException {
eventIndexDao.getEventTagSeverities(getEventFilterInst(2000));
}
@Test
public void testPassMaxCountClauseParam() throws ZepException {
// I really just want to see that an exception doesn't get thrown, so no asserts here
BooleanQuery.setMaxClauseCount(4096);
eventIndexDao.getEventTagSeverities(getEventFilterInst(2000));
}
private EventFilter getEventFilterInst(int numOfEventClasses) {
EventFilter.Builder myEventFilterBuilder = EventFilter.newBuilder();
for (int i = 0; i < 2000; i++) {
myEventFilterBuilder.addEventClass(UUID.randomUUID().toString());
}
EventFilter eventFilter = myEventFilterBuilder.build();
return eventFilter;
}
}