private AlertStreamEvent mockAlertEvent (String policyId) { AlertStreamEvent event = new AlertStreamEvent(); event.setSiteId("test"); event.setCreatedBy("junit"); event.setCreatedTime(1480491075923L); event.setPolicyId(policyId); event.setStreamId("ALERT_STREAM"); event.setSchema(mockAlertStreamDefinition("ALERT_STREAM")); event.setMetaVersion("SAMPLE_META_VERSION"); event.setTimestamp(1480491075923L); event.setData(new Object[]{"test_cluster", "cpu.usage", "localhost", "hadoop", 0.98}); event.ensureAlertId(); return event; }
public static AlertPublishEvent createAlertPublishEvent(AlertStreamEvent event) { Preconditions.checkNotNull(event.getAlertId(), "alertId is not initialized before being published: " + event.toString()); AlertPublishEvent alertEvent = new AlertPublishEvent(); alertEvent.setAlertId(event.getAlertId()); alertEvent.setPolicyId(event.getPolicyId()); alertEvent.setAlertTimestamp(event.getCreatedTime()); alertEvent.setStreamId(event.getStreamId()); alertEvent.setCreatedBy(event.getCreatedBy()); alertEvent.setCreatedTime(event.getCreatedTime()); alertEvent.setAlertSubject(event.getSubject()); alertEvent.setAlertBody(event.getBody()); if (event.getContext() != null && !event.getContext().isEmpty()) { if (event.getContext().containsKey(SITE_ID_KEY)) { alertEvent.setSiteId(event.getContext().get(SITE_ID_KEY).toString()); } if (event.getContext().containsKey(POLICY_VALUE_KEY)) { alertEvent.setPolicyValue(event.getContext().get(POLICY_VALUE_KEY).toString()); } if (event.getContext().containsKey(APP_IDS_KEY)) { alertEvent.setAppIds((List<String>) event.getContext().get(APP_IDS_KEY)); } } alertEvent.setAlertData(event.getDataMap()); return alertEvent; }
public AlertStreamEvent(AlertStreamEvent event) { this.siteId = event.getSiteId(); this.alertId = event.getAlertId(); this.policyId = event.policyId; this.schema = event.schema; this.createdBy = event.createdBy; this.createdTime = event.createdTime; this.setTimestamp(event.getTimestamp()); this.setData(new Object[event.data.length]); System.arraycopy(event.data, 0, this.data, 0, event.data.length); this.setStreamId(event.getStreamId()); this.setMetaVersion(event.getMetaVersion()); }
private String getAlertBody(AlertStreamEvent event) { if (event.getBody() == null) { return String.format("Alert policy \"%s\" was triggered: %s", event.getPolicyId(), generateAlertDataDesc(event)); } else { return event.getBody(); } }
@Override public String toString() { List<String> dataStrings = new ArrayList<>(this.getData().length); for (Object obj : this.getData()) { if (obj != null) { dataStrings.add(obj.toString()); } else { dataStrings.add(null); } } return String.format("Alert {site=%s, stream=%s,timestamp=%s,data=%s, policyId=%s, createdBy=%s, metaVersion=%s}", this.getSiteId(), this.getStreamId(), DateTimeUtil.millisecondsToHumanDateWithMilliseconds(this.getTimestamp()), this.getDataMap(), this.getPolicyId(), this.getCreatedBy(), this.getMetaVersion()); }
private AlertStreamEvent mergeEventWithDedupValue(AlertStreamEvent originalEvent, DedupValue dedupValue, String dedupStateField) { AlertStreamEvent event = new AlertStreamEvent(); Object[] newdata = new Object[originalEvent.getData().length]; for (int i = 0; i < originalEvent.getData().length; i++) { newdata[i] = originalEvent.getData()[i]; event.setData(newdata); event.setStreamId(originalEvent.getStreamId()); event.setSchema(originalEvent.getSchema()); event.setPolicyId(originalEvent.getPolicyId()); event.setCreatedTime(originalEvent.getCreatedTime()); event.setCreatedBy(originalEvent.getCreatedBy()); event.setTimestamp(originalEvent.getTimestamp()); StreamDefinition streamDefinition = event.getSchema(); for (int i = 0; i < event.getData().length; i++) { String colName = streamDefinition.getColumns().get(i).getName(); if (Objects.equal(colName, dedupStateField)) { event.getData()[i] = dedupValue.getStateFieldValue(); event.getData()[i] = dedupValue.getCount(); event.getData()[i] = dedupValue.getFirstOccurrence(); event.getData()[i] = dedupValue.getDocId();
public static AlertStreamEvent createEvent(StreamDefinition stream, PolicyDefinition policy, Object[] data) { AlertStreamEvent event = new AlertStreamEvent(); event.setPolicyId(policy.getName()); event.setSchema(stream); event.setStreamId(stream.getStreamId()); event.setTimestamp(System.currentTimeMillis()); event.setCreatedTime(System.currentTimeMillis()); event.setSubject("Namenode Disk Used 98%"); event.setBody("Disk Usage of Test cluster's name node (<a href=\"#\">namenode.hostname.domain</a>) is <strong style=\"color: red\">98%</strong> at <strong>2016-11-30 12:30:45</strong>, exceeding alert threshold <strong>90</strong>%"); event.setData(data); event.ensureAlertId(); event.setSeverity(AlertSeverity.CRITICAL); event.setCategory("HDFS"); event.setContext(new HashMap<String,Object>(){{ put(AlertPublishEvent.SITE_ID_KEY,"TestCluster"); }}); Assert.assertNotNull(event.getAlertId()); return event; }
if (event.getContext() != null) { for (Map.Entry<String, Object> entry : event.getContext().entrySet()) { if (entry.getValue() == null) { alertContext.put(entry.getKey(), "N/A"); alertContext.put(PublishConstants.ALERT_EMAIL_SUBJECT, event.getSubject()); alertContext.put(PublishConstants.ALERT_EMAIL_BODY, getAlertBody(event)); alertContext.put(PublishConstants.ALERT_EMAIL_POLICY_ID, event.getPolicyId()); alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_ID, event.getAlertId()); alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_DATA, event.getDataMap().toString()); alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_DATA_DESC, generateAlertDataDesc(event)); alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_CATEGORY, event.getCategory()); alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_SEVERITY, event.getSeverity().toString()); alertContext.put(PublishConstants.ALERT_EMAIL_TIME, String.format("%s %s", DateTimeUtil.millisecondsToHumanDateWithSeconds(event.getCreatedTime()), DateTimeUtil.CURRENT_TIME_ZONE.getID())); alertContext.put(PublishConstants.ALERT_EMAIL_STREAM_ID, event.getStreamId()); alertContext.put(PublishConstants.ALERT_EMAIL_CREATOR, event.getCreatedBy()); alertContext.put(PublishConstants.ALERT_EMAIL_VERSION, Version.version); try { alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_DETAIL_URL, String.format("%s/#/site/%s/alert/detail/%s?timestamp=%s", rootUrl, event.getSiteId(), URIUtil.encodeQuery(event.getAlertId(), "UTF-8"), event.getTimestamp())); alertContext.put(PublishConstants.ALERT_EMAIL_POLICY_DETAIL_URL, String.format("%s/#/site/%s/policy/detail/%s", rootUrl, event.getSiteId(), URIUtil.encodeQuery(event.getPolicyId(), "UTF-8"))); } catch (URIException e) { LOG.warn(e.getMessage(), e); alertContext.put(PublishConstants.ALERT_EMAIL_ALERT_DETAIL_URL, String.format("%s/#/site/%s/alert/detail/%s?timestamp=%s", rootUrl, event.getSiteId(), event.getAlertId(), event.getTimestamp()));
public AlertEntity convertAlertEvent(AlertStreamEvent event) { Preconditions.checkNotNull(event.getAlertId(), "alertId is not initialized before being published: " + event.toString()); AlertEntity alertEvent = new AlertEntity(); Map<String, String> tags = new HashMap<>(); tags.put(POLICY_ID_KEY, event.getPolicyId()); tags.put(ALERT_ID_KEY, event.getAlertId()); tags.put(ALERT_CATEGORY, event.getCategory()); tags.put(ALERT_SEVERITY, event.getSeverity().toString()); String host = event.getDataMap().getOrDefault("host", "null").toString(); String hostname = event.getDataMap().getOrDefault("hostname", "null").toString(); if (host != "null") { tags.put(ALERT_HOST, host); } else { tags.put(ALERT_HOST, hostname); } if (event.getContext() != null && !event.getContext().isEmpty()) { tags.put(SITE_ID_KEY, event.getContext().get(SITE_ID_KEY).toString()); alertEvent.setPolicyValue(event.getContext().get(POLICY_VALUE_KEY).toString()); alertEvent.setAppIds((List<String>) event.getContext().get(APP_IDS_KEY)); } alertEvent.setTimestamp(event.getCreatedTime()); alertEvent.setAlertData(event.getDataMap()); alertEvent.setAlertSubject(event.getSubject()); alertEvent.setAlertBody(event.getBody()); alertEvent.setTags(tags); return alertEvent; }
public String streamEventToJson(AlertStreamEvent event) { Map<String, Object> jsonMap = new HashMap<String, Object>(); jsonMap.put("policyId", event.getPolicyId()); jsonMap.put("streamId", event.getStreamId()); jsonMap.put("createBy", event.getCreatedBy()); jsonMap.put("createTime", event.getCreatedTime()); // data int size = event.getData().length; List<StreamColumn> columns = event.getSchema().getColumns(); for (int i = 0; i < size; i++) { if (columns.size() < i) { // redundant check to log inconsistency LOG.error(" stream event data have different lenght compare to column definition! "); } else { jsonMap.put(columns.get(i).getName(), event.getData()[i]); } } return JsonUtils.writeValueAsString(jsonMap); }
private static VelocityContext buildAlertContext(PolicyDefinition policyDefinition, AlertStreamEvent event) { VelocityContext context = new VelocityContext(); context.put(AlertContextFields.SITE_ID, event.getSiteId()); context.put(AlertContextFields.STREAM_ID, event.getStreamId()); context.put(AlertContextFields.ALERT_ID, event.getAlertId()); context.put(AlertContextFields.CREATED_BY, event.getCreatedBy()); context.put(AlertContextFields.CREATED_TIMESTAMP, event.getCreatedTime()); context.put(AlertContextFields.CREATED_TIME, String.format("%s %s", DateTimeUtil.millisecondsToHumanDateWithSeconds(event.getCreatedTime()), DateTimeUtil.CURRENT_TIME_ZONE.getID())); context.put(AlertContextFields.ALERT_TIMESTAMP, event.getTimestamp()); context.put(AlertContextFields.ALERT_TIME, String.format("%s %s", DateTimeUtil.millisecondsToHumanDateWithSeconds(event.getTimestamp()), DateTimeUtil.CURRENT_TIME_ZONE.getID())); context.put(AlertContextFields.ALERT_SCHEMA, event.getSchema()); context.put(AlertContextFields.ALERT_EVENT, event); context.put(AlertContextFields.POLICY_ID, policyDefinition.getName()); context.put(AlertContextFields.POLICY_DESC, policyDefinition.getDescription()); context.put(AlertContextFields.POLICY_TYPE, policyDefinition.getDefinition().getType()); context.put(AlertContextFields.POLICY_DEFINITION, policyDefinition.getDefinition().getValue()); context.put(AlertContextFields.POLICY_HANDLER, policyDefinition.getDefinition().getHandlerClass()); for (Map.Entry<String, Object> entry : event.getDataMap().entrySet()) { context.put(entry.getKey(), entry.getValue()); } return context; } }
AlertStreamEvent alertStreamEvent = new AlertStreamEvent(); alertStreamEvent.setData(new Object[]{"namevalue", "hostvalue", "1", 10, 0.1, -0.2, "{\"name\":\"heap.COMMITTED\", \"Value\":\"175636480\"}", 1}); alertStreamEvent.setSchema(streamDefinition); alertStreamEvent.setPolicyId("setPolicyId"); alertStreamEvent.setCreatedTime(1234); alertStreamEvent.ensureAlertId(); AlertPublishEvent alertPublishEvent = AlertPublishEvent.createAlertPublishEvent(alertStreamEvent); Assert.assertEquals(null, alertPublishEvent.getSiteId()); extraData.put(AlertPublishEvent.POLICY_VALUE_KEY, "POLICY_VALUE_KEY"); extraData.put(AlertPublishEvent.APP_IDS_KEY, Arrays.asList("appId1", "appId2")); alertStreamEvent.setContext(extraData);
/** * TODO: Refactor wrapAlertPublishEvent into alertTemplateEngine and remove extraData from AlertStreamEvent. */ @Override public AlertStreamEvent filter(AlertStreamEvent event) { event.ensureAlertId(); Map<String, Object> extraData = new HashMap<>(); List<String> appIds = new ArrayList<>(); if (alertPublisherBolt.policyDefinitionMap == null || alertPublisherBolt.streamDefinitionMap == null) { LOG.warn("policyDefinitions or streamDefinitions in publisher bolt have not been initialized"); } else { PolicyDefinition policyDefinition = alertPublisherBolt.policyDefinitionMap.get(event.getPolicyId()); if (alertPublisherBolt.policyDefinitionMap != null && policyDefinition != null) { for (String inputStreamId : policyDefinition.getInputStreams()) { StreamDefinition sd = alertPublisherBolt.streamDefinitionMap.get(inputStreamId); if (sd != null) { extraData.put(AlertPublishEvent.SITE_ID_KEY, sd.getSiteId()); appIds.add(sd.getStreamSource()); } } extraData.put(AlertPublishEvent.APP_IDS_KEY, appIds); extraData.put(AlertPublishEvent.POLICY_VALUE_KEY, policyDefinition.getDefinition().getValue()); event.setSeverity(policyDefinition.getAlertSeverity()); event.setCategory(policyDefinition.getAlertCategory()); } event.setContext(extraData); } return event; } }
@Override public void send(StreamEvent event) throws Exception { AlertStreamEvent alert = new AlertStreamEvent(); alert.setPolicyId(context.getPolicyDefinition().getName()); alert.setSchema(sds.get(event.getStreamId())); this.collector.emit(alert); }
@Override public void emit(AlertStreamEvent event) { if (event == null) { return; } event.ensureAlertId(); Set<PublishPartition> clonedPublishPartitions = new HashSet<>(publishPartitions); for (PublishPartition publishPartition : clonedPublishPartitions) { // skip the publish partition which is not belong to this policy and also check streamId PublishPartition cloned = publishPartition.clone(); Optional.ofNullable(event) .filter(x -> x != null && x.getSchema() != null && cloned.getPolicyId().equalsIgnoreCase(x.getPolicyId()) && (cloned.getStreamId().equalsIgnoreCase(x.getSchema().getStreamId()) || cloned.getStreamId().equalsIgnoreCase(Publishment.STREAM_NAME_DEFAULT))) .ifPresent(x -> { cloned.getColumns().stream() .filter(y -> event.getSchema().getColumnIndex(y) >= 0 && event.getSchema().getColumnIndex(y) < event.getSchema().getColumns().size()) .map(y -> event.getData()[event.getSchema().getColumnIndex(y)]) .filter(y -> y != null) .forEach(y -> cloned.getColumnValues().add(y)); synchronized (outputLock) { streamContext.counter().incr("alert_count"); delegate.emit(Arrays.asList(cloned, event)); } }); } }
@Test public void testAlertStreamEvent() { List<StreamColumn> streamColumns = new ArrayList<>(); streamColumns.add(new StreamColumn.Builder().name("name").type(StreamColumn.Type.STRING).build()); streamColumns.add(new StreamColumn.Builder().name("host").type(StreamColumn.Type.STRING).build()); streamColumns.add(new StreamColumn.Builder().name("flag").type(StreamColumn.Type.BOOL).build()); streamColumns.add(new StreamColumn.Builder().name("value").type(StreamColumn.Type.DOUBLE).build()); streamColumns.add(new StreamColumn.Builder().name("data").type(StreamColumn.Type.LONG).build()); streamColumns.add(new StreamColumn.Builder().name("salary").type(StreamColumn.Type.FLOAT).build()); streamColumns.add(new StreamColumn.Builder().name("object").type(StreamColumn.Type.OBJECT).build()); streamColumns.add(new StreamColumn.Builder().name("int").type(StreamColumn.Type.INT).build()); StreamDefinition streamDefinition = new StreamDefinition(); streamDefinition.setColumns(streamColumns); AlertStreamEvent alertStreamEvent = new AlertStreamEvent(); alertStreamEvent.setSchema(streamDefinition); alertStreamEvent.setData(new Object[]{"namevalue", "hostvalue", "1", 10, 0.1, -0.2, "{\"name\":\"heap.COMMITTED\", \"Value\":\"175636480\"}", 1}); AlertStreamEvent alertStreamEvent1 = new AlertStreamEvent(alertStreamEvent); Assert.assertFalse(alertStreamEvent1 == alertStreamEvent); Assert.assertTrue(alertStreamEvent1.equals(alertStreamEvent)); Assert.assertTrue(alertStreamEvent1.hashCode() == alertStreamEvent.hashCode()); } }
@Test public void testVelocityAlertTemplateWithoutTemplate () { AlertTemplateEngine templateEngine = new VelocityAlertTemplateEngine(); templateEngine.init(ConfigFactory.load()); templateEngine.register(mockPolicyWithoutTemplate("testPolicyName")); AlertStreamEvent event = templateEngine.filter(mockAlertEvent("testPolicyName")); Assert.assertEquals("Message: Alert {site=test, stream=ALERT_STREAM,timestamp=2016-11-30 07:31:15,923," + "data={site=test_cluster, role=hadoop, metric=cpu.usage, host=localhost, value=0.98}, " + "policyId=testPolicyName, createdBy=junit, metaVersion=SAMPLE_META_VERSION} " + "(Auto-generated alert message as template not defined in policy testPolicyName)", event.getBody()); Assert.assertEquals("testPolicyName", event.getSubject()); }
@Test public void testSlackPublishment() throws Exception { Config config = ConfigFactory.load("application-test.conf"); AlertPublisher publisher = new AlertPublisherImpl("alertPublishBolt"); publisher.init(config, new HashMap()); List<Publishment> pubs = loadEntities("/router/publishments-slack.json", Publishment.class); publisher.onPublishChange(pubs, null, null, null); AlertStreamEvent event1 = createSeverityWithStreamDef("switch1", "testapp1", "Memory 1 inconsistency detected", "WARNING", "docId1", "ed01", "distribution switch", "us"); AlertStreamEvent event2 = createSeverityWithStreamDef("switch2", "testapp2", "Memory 2 inconsistency detected", "CRITICAL", "docId2", "ed02", "distribution switch", "us"); AlertStreamEvent event3 = createSeverityWithStreamDef("switch2", "testapp2", "Memory 3 inconsistency detected", "WARNING", "docId3", "ed02", "distribution switch", "us"); publisher.nextEvent(new PublishPartition(event1.getStreamId(), event1.getPolicyId(), pubs.get(0).getName(), pubs.get(0).getPartitionColumns()), event1); publisher.nextEvent(new PublishPartition(event2.getStreamId(), event2.getPolicyId(), pubs.get(0).getName(), pubs.get(0).getPartitionColumns()), event2); publisher.nextEvent(new PublishPartition(event3.getStreamId(), event3.getPolicyId(), pubs.get(0).getName(), pubs.get(0).getPartitionColumns()), event3); }
@Override public synchronized AlertStreamEvent filter(AlertStreamEvent event) { Preconditions.checkArgument(this.policyDefinitionRepository.containsKey(event.getPolicyId()), "Unknown policyId " + event.getPolicyId()); PolicyDefinition policyDefinition = this.policyDefinitionRepository.get(event.getPolicyId()); StringWriter bodyWriter = new StringWriter(); StringWriter subjectWriter = new StringWriter(); try { VelocityContext alertContext = buildAlertContext(policyDefinition, event); Template template = engine.getTemplate(getAlertBodyTemplateName(event.getPolicyId())); template.merge(alertContext, bodyWriter); event.setBody(bodyWriter.toString()); template = engine.getTemplate(getAlertSubjectTemplateName(event.getPolicyId())); template.merge(alertContext, subjectWriter); event.setSubject(subjectWriter.toString()); } finally { try { bodyWriter.close(); } catch (IOException e) { LOG.warn(e.getMessage(), e); } try { subjectWriter.close(); } catch (IOException e) { LOG.warn(e.getMessage(), e); } } return event; }