This adds metadata to alerts that are copied to the action entries for this alert.

Original commit: elastic/x-pack-elasticsearch@0abfc22421
This commit is contained in:
Brian Murphy 2014-11-27 14:00:28 +00:00
parent b54aea7c14
commit fbec93d941
9 changed files with 123 additions and 3 deletions

View File

@ -16,6 +16,7 @@ import org.elasticsearch.common.xcontent.XContentBuilder;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class Alert implements ToXContent {
@ -29,6 +30,7 @@ public class Alert implements ToXContent {
private TimeValue throttlePeriod = new TimeValue(0);
private DateTime timeLastActionExecuted = null;
private AlertAckState ackState = AlertAckState.NOT_ACKABLE;
private Map<String,Object> metadata = null;
public Alert() {
actions = new ArrayList<>();
@ -79,6 +81,9 @@ public class Alert implements ToXContent {
trigger.toXContent(builder, params);
builder.endObject();
}
if (metadata != null) {
builder.field(AlertsStore.META_FIELD.getPreferredName(), metadata);
}
builder.endObject();
return builder;
}
@ -193,6 +198,18 @@ public class Alert implements ToXContent {
this.ackState = ackState;
}
/**
* @return The metadata that was associated with the alert
*/
public Map<String, Object> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;

View File

@ -56,6 +56,7 @@ public class AlertsStore extends AbstractComponent {
public static final ParseField THROTTLE_PERIOD_FIELD = new ParseField("throttle_period");
public static final ParseField LAST_ACTION_EXECUTED_FIELD = new ParseField("last_action_executed");
public static final ParseField ACK_STATE_FIELD = new ParseField("ack_state");
public static final ParseField META_FIELD = new ParseField("meta");
private final Client client;
private final TriggerManager triggerManager;
@ -249,6 +250,8 @@ public class AlertsStore extends AbstractComponent {
alert.actions(actions);
} else if (REQUEST_FIELD.match(currentFieldName)) {
alert.setSearchRequest(AlertUtils.readSearchRequest(parser));
} else if (META_FIELD.match(currentFieldName)) {
alert.setMetadata(parser.map());
} else {
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
}

View File

@ -37,6 +37,7 @@ public class AlertActionEntry implements ToXContent {
private Map<String, Object> searchResponse;
private boolean triggered;
private String errorMsg;
private Map<String,Object> metadata;
AlertActionEntry() {
}
@ -182,6 +183,19 @@ public class AlertActionEntry implements ToXContent {
this.errorMsg = errorMsg;
}
/**
* @return The metadata that was associated with the alert when this entry was created
*/
public Map<String, Object> getMetadata() {
return metadata;
}
public void setMetadata(Map<String, Object> metadata) {
this.metadata = metadata;
}
@Override
public XContentBuilder toXContent(XContentBuilder historyEntry, Params params) throws IOException {
historyEntry.startObject();
@ -210,8 +224,12 @@ public class AlertActionEntry implements ToXContent {
if (errorMsg != null) {
historyEntry.field("error_msg", errorMsg);
}
historyEntry.endObject();
if (metadata != null) {
historyEntry.field("meta", metadata);
}
historyEntry.endObject();
return historyEntry;
}

View File

@ -56,6 +56,7 @@ public class AlertActionManager extends AbstractComponent {
public static final String RESPONSE = "response";
public static final String ACTIONS_FIELD = "actions";
public static final String STATE = "state";
public static final String METADATA = "meta";
public static final String ALERT_HISTORY_INDEX_PREFIX = ".alert_history_";
public static final DateTimeFormatter alertHistoryIndexTimeFormat = DateTimeFormat.forPattern("YYYY-MM-dd");
@ -217,6 +218,8 @@ public class AlertActionManager extends AbstractComponent {
case RESPONSE:
entry.setSearchResponse(parser.map());
break;
case METADATA:
entry.setMetadata(parser.map());
default:
throw new ElasticsearchIllegalArgumentException("Unexpected field [" + currentFieldName + "]");
}
@ -258,6 +261,9 @@ public class AlertActionManager extends AbstractComponent {
logger.debug("Adding alert action for alert [{}]", alert.alertName());
String alertHistoryIndex = getAlertHistoryIndexNameForTime(scheduledFireTime);
AlertActionEntry entry = new AlertActionEntry(alert, scheduledFireTime, fireTime, AlertActionState.SEARCH_NEEDED);
if (alert.getMetadata() != null) {
entry.setMetadata(alert.getMetadata());
}
IndexResponse response = client.prepareIndex(alertHistoryIndex, ALERT_HISTORY_TYPE, entry.getId())
.setSource(XContentFactory.jsonBuilder().value(entry))
.setOpType(IndexRequest.OpType.CREATE)

View File

@ -49,6 +49,10 @@
"type" : "object",
"enabled" : false,
"dynamic" : true
},
"meta" : {
"type" : "object",
"dynamic": true
}
}
}

View File

@ -42,6 +42,10 @@
"type" : "object",
"enabled" : false,
"dynamic" : true
},
"meta" : {
"type" : "object",
"dynamic": true
}
}
}

View File

@ -90,11 +90,19 @@ public abstract class AbstractAlertingTests extends ElasticsearchIntegrationTest
}
protected BytesReference createAlertSource(String cron, SearchRequest request, String scriptTrigger) throws IOException {
return createAlertSource(cron, request, scriptTrigger, null);
}
protected BytesReference createAlertSource(String cron, SearchRequest request, String scriptTrigger, Map<String,Object> metadata) throws IOException {
XContentBuilder builder = jsonBuilder().startObject();
builder.field("schedule", cron);
builder.field("request");
AlertUtils.writeSearchRequest(request, builder, ToXContent.EMPTY_PARAMS);
if (metadata != null) {
builder.field("meta", metadata);
}
builder.startObject("trigger");
builder.startObject("script");
builder.field("script", scriptTrigger);
@ -106,6 +114,7 @@ public abstract class AbstractAlertingTests extends ElasticsearchIntegrationTest
builder.field("index", "my-index");
builder.field("type", "trail");
builder.endObject();
builder.endObject();
return builder.endObject().bytes();

View File

@ -0,0 +1,52 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
package org.elasticsearch.alerts;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.alerts.actions.AlertActionManager;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.search.builder.SearchSourceBuilder.searchSource;
import static org.hamcrest.Matchers.greaterThan;
/**
*/
public class AlertMetadataTest extends AbstractAlertingTests {
@Test
public void testAlertMetadata() throws Exception {
Map<String, Object> metadata = new HashMap<>();
metadata.put("foo", "bar");
List<String> metaList = new ArrayList<>();
metaList.add("this");
metaList.add("is");
metaList.add("a");
metaList.add("test");
metadata.put("baz", metaList);
SearchRequest searchRequest = createTriggerSearchRequest("my-index").source(searchSource().query(matchAllQuery()));
alertClient().preparePutAlert("1")
.setAlertSource(createAlertSource("0/5 * * * * ? *", searchRequest, "hits.total == 1", metadata))
.get();
assertAlertTriggered("1", 0, false);
searchRequest = client()
.prepareSearch(AlertActionManager.ALERT_HISTORY_INDEX_PREFIX+"*").request();
searchRequest.source(searchSource().query(termQuery("meta.foo", "bar")));
SearchResponse searchResponse = client().search(searchRequest).actionGet();
assertThat(searchResponse.getHits().getTotalHits(), greaterThan(0L));
}
}

View File

@ -19,7 +19,9 @@ import org.elasticsearch.test.ElasticsearchIntegrationTest;
import org.junit.Test;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class AlertSerializationTest extends ElasticsearchIntegrationTest {
@ -40,6 +42,10 @@ public class AlertSerializationTest extends ElasticsearchIntegrationTest {
new TimeValue(0),
AlertAckState.NOT_TRIGGERED);
Map<String, Object> metadata = new HashMap<>();
metadata.put("foo","bar");
metadata.put("list", "baz");
alert.setMetadata(metadata);
XContentBuilder jsonBuilder = XContentFactory.jsonBuilder();
alert.toXContent(jsonBuilder, ToXContent.EMPTY_PARAMS);
@ -58,7 +64,8 @@ public class AlertSerializationTest extends ElasticsearchIntegrationTest {
if (parsedAlert.getTimeLastActionExecuted() == null) {
assertNull(alert.getTimeLastActionExecuted());
}
assertEquals(parsedAlert.getAckState(), parsedAlert.getAckState());
assertEquals(parsedAlert.getAckState(), alert.getAckState());
assertEquals(parsedAlert.getMetadata(), alert.getMetadata());
}