This is an automated email from the ASF dual-hosted git repository.

rmerriman pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/metron.git


The following commit(s) were added to refs/heads/master by this push:
     new 373ac51  METRON-2109 Add option to use Metron GUID as the id in 
Elasticsearch (merrimanr) closes apache/metron#1403
373ac51 is described below

commit 373ac513b0779c9399fce299094560a0261a6590
Author: merrimanr <[email protected]>
AuthorDate: Wed May 22 14:30:48 2019 -0500

    METRON-2109 Add option to use Metron GUID as the id in Elasticsearch 
(merrimanr) closes apache/metron#1403
---
 metron-platform/metron-common/README.md            |  1 +
 .../configuration/IndexingConfigurations.java      | 17 +++++
 .../writer/IndexingWriterConfiguration.java        |  5 ++
 .../configuration/writer/WriterConfiguration.java  |  9 +++
 .../configuration/IndexingConfigurationsTest.java  | 82 ++++++++++++++++++++++
 .../bulk/ElasticsearchBulkDocumentWriter.java      |  2 +-
 .../elasticsearch/writer/ElasticsearchWriter.java  | 13 ++--
 .../ElasticsearchSearchIntegrationTest.java        |  6 +-
 .../components/ElasticSearchComponent.java         | 18 +++--
 .../writer/ElasticsearchWriterTest.java            | 62 +++++++++++++++-
 metron-platform/metron-indexing/README.md          | 18 ++++-
 11 files changed, 220 insertions(+), 13 deletions(-)

diff --git a/metron-platform/metron-common/README.md 
b/metron-platform/metron-common/README.md
index 5144be7..4d19769 100644
--- a/metron-platform/metron-common/README.md
+++ b/metron-platform/metron-common/README.md
@@ -87,6 +87,7 @@ but a convenient index is provided here:
 | [`es.port`](../metron-elasticsearch#esport)                                  
                                         | Indexing      | String     | N/A     
                                |
 | [`es.date.format`](../metron-elasticsearch#esdateformat)                     
                                         | Indexing      | String     | 
`es_date_format`                        |
 | [`es.client.settings`](../metron-elasticsearch#esclientsettings)             
                                         | Indexing      | Object     | N/A     
                                |
+| 
[`indexing.writer.elasticsearch.setDocumentId`](../metron-indexing#elasticsearch)
                                                        | Indexing      | 
Boolean    | N/A                                     |
 | [`solr.zookeeper`](../metron-solr#configuration)                             
                                         | Indexing      | String     | 
`solr_zookeeper_url`                    |
 | [`solr.commitPerBatch`](../metron-solr#configuration)                        
                                         | Indexing      | String     | N/A     
                                |
 | [`solr.commit.soft`](../metron-solr#configuration)                           
                                         | Indexing      | String     | N/A     
                                |
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/IndexingConfigurations.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/IndexingConfigurations.java
index 584bed1..5001767 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/IndexingConfigurations.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/IndexingConfigurations.java
@@ -36,6 +36,8 @@ public class IndexingConfigurations extends Configurations {
   public static final String INDEX_CONF = "index";
   public static final String OUTPUT_PATH_FUNCTION_CONF = "outputPathFunction";
   public static final String FIELD_NAME_CONVERTER_CONF = "fieldNameConverter";
+  public static final String SET_DOCUMENT_ID_CONF = "setDocumentId";
+  public static final String GLOBAL_ELASTICSEARCH_SET_DOCUMENT_ID_CONF = 
"indexing.writer.elasticsearch.setDocumentId";
 
   /**
    * Gets the indexing config for a specific sensor.
@@ -184,6 +186,10 @@ public class IndexingConfigurations extends Configurations 
{
     return getFieldNameConverter(getSensorIndexingConfig(sensorName, 
writerName), sensorName);
   }
 
+  public boolean isSetDocumentId(String sensorName, String writerName) {
+    return isSetDocumentId(getGlobalConfig(true), 
getSensorIndexingConfig(sensorName, writerName));
+  }
+
   /**
    *  Retrieves the enabled value from the config.
    *
@@ -268,6 +274,17 @@ public class IndexingConfigurations extends Configurations 
{
   }
 
   /**
+   * Determines if the Metron generated id should be used when indexing
+   *
+   * @param globalConf The global config
+   * @param sensorConf The indexing config for a given sensor
+   * @return True if the Metron generated id should be used as the id, False 
otherwise
+   */
+  public static boolean isSetDocumentId(Map<String, Object> globalConf, 
Map<String, Object> sensorConf) {
+    return getAs(SET_DOCUMENT_ID_CONF, sensorConf, 
getAs(GLOBAL_ELASTICSEARCH_SET_DOCUMENT_ID_CONF, globalConf, false, 
Boolean.class), Boolean.class);
+  }
+
+  /**
    * Sets the enabled flag in the config.
    *
    * @param conf The configuration map to set enabled in. If null replaced 
with empty map.
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/IndexingWriterConfiguration.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/IndexingWriterConfiguration.java
index ab25a80..fbd1178 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/IndexingWriterConfiguration.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/IndexingWriterConfiguration.java
@@ -77,4 +77,9 @@ public class IndexingWriterConfiguration implements 
WriterConfiguration{
   public String getFieldNameConverter(String sensorName) {
     return config.orElse(new 
IndexingConfigurations()).getFieldNameConverter(sensorName, writerName);
   }
+
+  @Override
+  public boolean isSetDocumentId(String sensorName) {
+    return config.orElse(new 
IndexingConfigurations()).isSetDocumentId(sensorName, writerName);
+  }
 }
diff --git 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/WriterConfiguration.java
 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/WriterConfiguration.java
index e75a65d..5c932da 100644
--- 
a/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/WriterConfiguration.java
+++ 
b/metron-platform/metron-common/src/main/java/org/apache/metron/common/configuration/writer/WriterConfiguration.java
@@ -103,4 +103,13 @@ public interface WriterConfiguration extends Serializable {
    * @return The {@link FieldNameConverter}
    */
   String getFieldNameConverter(String sensorName);
+
+  /**
+   * Returns true, if the current writer configuration is set to use the GUID 
generated by Metron as the id
+   * @param sensorName The name of the sensor.
+   * @return True, if writer is configured to use GUID generated by Metron, 
false otherwise (and by default)
+   */
+  default boolean isSetDocumentId(String sensorName) {
+    return false;
+  }
 }
diff --git 
a/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/IndexingConfigurationsTest.java
 
b/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/IndexingConfigurationsTest.java
new file mode 100644
index 0000000..f561423
--- /dev/null
+++ 
b/metron-platform/metron-common/src/test/java/org/apache/metron/common/configuration/IndexingConfigurationsTest.java
@@ -0,0 +1,82 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.metron.common.configuration;
+
+import org.adrianwalker.multilinestring.Multiline;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.nio.charset.StandardCharsets;
+import java.util.HashMap;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+public class IndexingConfigurationsTest {
+
+  /**
+   * {
+   *  "indexing.writer.elasticsearch.setDocumentId" : "true"
+   * }
+   */
+  @Multiline
+  private static String globalConfig;
+
+  /**
+   * {
+   *  "writer" : {
+   *    "setDocumentId": true
+   *  }
+   * }
+   */
+  @Multiline
+  private static String sensorConfig;
+
+  private IndexingConfigurations configurations;
+
+  @Before
+  public void setup() {
+    configurations = new IndexingConfigurations();
+  }
+
+  @Test
+  public void shouldReturnDefaultSetDocumentId() throws Exception {
+    // verify false by default
+    assertFalse(configurations.isSetDocumentId("sensor", "writer"));
+  }
+
+  @Test
+  public void shouldReturnGlobalSetDocumentId() throws Exception {
+    // verify global config setting applies to any sensor
+    
configurations.updateGlobalConfig(globalConfig.getBytes(StandardCharsets.UTF_8));
+
+    assertTrue(configurations.isSetDocumentId("sensor", "writer"));
+    assertTrue(configurations.isSetDocumentId("anySensor", "writer"));
+  }
+
+  @Test
+  public void shouldReturnSensorSetDocumentId() throws Exception {
+    // verify sensor config only applies to that sensor
+    configurations.updateGlobalConfig(new HashMap<>());
+    configurations.updateSensorIndexingConfig("sensor", 
sensorConfig.getBytes(StandardCharsets.UTF_8));
+
+    assertTrue(configurations.isSetDocumentId("sensor", "writer"));
+    assertFalse(configurations.isSetDocumentId("anySensor", "writer"));
+  }
+}
diff --git 
a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/bulk/ElasticsearchBulkDocumentWriter.java
 
b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/bulk/ElasticsearchBulkDocumentWriter.java
index bde5664..e753711 100644
--- 
a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/bulk/ElasticsearchBulkDocumentWriter.java
+++ 
b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/bulk/ElasticsearchBulkDocumentWriter.java
@@ -130,7 +130,7 @@ public class ElasticsearchBulkDocumentWriter<D extends 
Document> implements Bulk
         // if creating a new document, set the doc ID to null to allow 
Elasticsearch to generate one.
         String docId = document.getDocumentID().orElse(null);
         if(LOG.isDebugEnabled() && document.getDocumentID().isPresent()) {
-            LOG.debug("Updating existing document with known doc ID; docID={}, 
guid={}, sensorType={}",
+            LOG.debug("Creating/Updating a document with known doc ID; 
docID={}, guid={}, sensorType={}",
                     docId, document.getGuid(), document.getSensorType());
         } else if(LOG.isDebugEnabled()) {
             LOG.debug("Creating a new document, doc ID not yet known; guid={}, 
sensorType={}",
diff --git 
a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriter.java
 
b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriter.java
index b7814b6..ef6577f 100644
--- 
a/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriter.java
+++ 
b/metron-platform/metron-elasticsearch/src/main/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriter.java
@@ -97,7 +97,7 @@ public class ElasticsearchWriter implements 
BulkMessageWriter<JSONObject>, Seria
 
     // create a document from each message
     for(BulkMessage<JSONObject> bulkWriterMessage: messages) {
-      MessageIdBasedDocument document = createDocument(bulkWriterMessage, 
sensorType, fieldNameConverter);
+      MessageIdBasedDocument document = createDocument(bulkWriterMessage, 
sensorType, fieldNameConverter, configurations.isSetDocumentId(sensorType));
       documentWriter.addDocument(document, indexName);
     }
 
@@ -117,7 +117,8 @@ public class ElasticsearchWriter implements 
BulkMessageWriter<JSONObject>, Seria
 
   private MessageIdBasedDocument createDocument(BulkMessage<JSONObject> 
bulkWriterMessage,
                                                 String sensorType,
-                                                FieldNameConverter 
fieldNameConverter) {
+                                                FieldNameConverter 
fieldNameConverter,
+                                                boolean setDocumentId) {
     // transform the message fields to the source fields of the indexed 
document
     JSONObject source = new JSONObject();
     JSONObject message = bulkWriterMessage.getMessage();
@@ -139,8 +140,12 @@ public class ElasticsearchWriter implements 
BulkMessageWriter<JSONObject>, Seria
     } else {
       LOG.warn("Missing '{}' field; timestamp will be set to system time.", 
TIMESTAMP.getName());
     }
-
-    return new MessageIdBasedDocument(source, guid, sensorType, timestamp, 
bulkWriterMessage.getId());
+    MessageIdBasedDocument messageIdBasedDocument = new 
MessageIdBasedDocument(source, guid, sensorType, timestamp, 
bulkWriterMessage.getId());
+    if (setDocumentId) {
+      // Use the metron-generated GUID instead of letting Elasticsearch set 
the id
+      messageIdBasedDocument.setDocumentID(guid);
+    }
+    return messageIdBasedDocument;
   }
 
   @Override
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
index 7036078..705beda 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/ElasticsearchSearchIntegrationTest.java
@@ -145,7 +145,11 @@ public class ElasticsearchSearchIntegrationTest extends 
SearchIntegrationTest {
     for (Object broObject: (JSONArray) new JSONParser().parse(broData)) {
       broDocuments.add(((JSONObject) broObject).toJSONString());
     }
-    es.add(BRO_INDEX, "bro", broDocuments);
+    // add documents using Metron GUID
+    es.add(BRO_INDEX, "bro", broDocuments.subList(0, 4), true);
+
+    // add a document to the same index but with an Elasticsearch id
+    es.add(BRO_INDEX, "bro", broDocuments.subList(4, 5), false);
 
     // write the test documents for Snort
     List<String> snortDocuments = new ArrayList<>();
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
index dfdf88e..18d947d 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/integration/components/ElasticSearchComponent.java
@@ -217,10 +217,14 @@ public class ElasticSearchComponent implements 
InMemoryComponent {
           throws IOException, ParseException {
     List<String> d = new ArrayList<>();
     Collections.addAll(d, docs);
-    add(indexName, sensorType, d);
+    add(indexName, sensorType, d, false);
   }
 
-  public void add(String indexName, String sensorType, Iterable<String> docs)
+  public void add(String indexName, String sensorType, Iterable<String> docs) 
throws IOException, ParseException {
+    add(indexName, sensorType, docs, false);
+  }
+
+  public void add(String indexName, String sensorType, Iterable<String> docs, 
boolean setDocumentId)
           throws IOException, ParseException {
 
     // create a collection of indexable documents
@@ -228,7 +232,7 @@ public class ElasticSearchComponent implements 
InMemoryComponent {
     Map<Document, Optional<String>> documents = new HashMap<>();
     for(String json: docs) {
       JSONObject message = (JSONObject) parser.parse(json);
-      documents.put(createDocument(message, sensorType), 
Optional.of(indexName));
+      documents.put(createDocument(message, sensorType, setDocumentId), 
Optional.of(indexName));
     }
 
     // write the documents
@@ -243,11 +247,15 @@ public class ElasticSearchComponent implements 
InMemoryComponent {
    * @return The {@link Document} that was written.
    * @throws IOException
    */
-  private static Document createDocument(JSONObject message, String docType) 
throws IOException {
+  private static Document createDocument(JSONObject message, String docType, 
boolean setDocumentId) throws IOException {
     Long timestamp = ConversionUtils.convert(message.get("timestamp"), 
Long.class);
     String source = message.toJSONString();
     String guid = (String) message.get("guid");
-    return new Document(source, guid, docType, timestamp);
+    Document document = new Document(source, guid, docType, timestamp);
+    if (setDocumentId) {
+      document.setDocumentID(guid);
+    }
+    return document;
   }
 
   public void createIndexWithMapping(String indexName, String mappingType, 
String mappingSource)
diff --git 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriterTest.java
 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriterTest.java
index ba5cfe0..2d5fd2a 100644
--- 
a/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriterTest.java
+++ 
b/metron-platform/metron-elasticsearch/src/test/java/org/apache/metron/elasticsearch/writer/ElasticsearchWriterTest.java
@@ -25,10 +25,15 @@ import org.apache.metron.common.writer.BulkWriterResponse;
 import org.apache.metron.common.writer.MessageId;
 import org.apache.metron.elasticsearch.bulk.BulkDocumentWriter;
 import org.apache.metron.elasticsearch.bulk.BulkDocumentWriterResults;
+import org.apache.metron.elasticsearch.utils.ElasticsearchUtils;
 import org.json.simple.JSONObject;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
+import java.text.SimpleDateFormat;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashMap;
@@ -40,9 +45,16 @@ import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertTrue;
+import static org.mockito.Matchers.any;
+import static org.mockito.Matchers.eq;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.when;
+import static org.powermock.api.mockito.PowerMockito.mockStatic;
 
+@RunWith(PowerMockRunner.class)
+@PrepareForTest({ElasticsearchWriter.class, ElasticsearchUtils.class})
 public class ElasticsearchWriterTest {
 
     Map stormConf;
@@ -243,6 +255,54 @@ public class ElasticsearchWriterTest {
         assertTrue(response.getSuccesses().contains(new 
MessageId("message1")));
     }
 
+    @Test
+    public void shouldWriteManySuccessfullyWithSetDocumentId() {
+        when(writerConfiguration.isSetDocumentId("bro")).thenReturn(true);
+        
when(writerConfiguration.getFieldNameConverter("bro")).thenReturn("NOOP");
+
+        mockStatic(ElasticsearchUtils.class);
+        when(ElasticsearchUtils.getIndexFormat(globals())).thenReturn(new 
SimpleDateFormat());
+        when(ElasticsearchUtils.getIndexName(eq("bro"), any(), 
eq(writerConfiguration))).thenReturn("bro_index");
+
+        // create a few message ids and the messages associated with the ids
+        List<BulkMessage<JSONObject>> messages = createMessages(3);
+
+        // documents should have field converted
+        MessageIdBasedDocument document1 = createDocument(messages.get(0));
+        MessageIdBasedDocument document2 = createDocument(messages.get(1));
+        MessageIdBasedDocument document3 = createDocument(messages.get(2));
+
+        // documents should have guid as documentID
+        document1.setDocumentID(document1.getGuid());
+        document2.setDocumentID(document1.getGuid());
+        document3.setDocumentID(document1.getGuid());
+
+        // create a document writer which will successfully write all
+        BulkDocumentWriterResults<MessageIdBasedDocument> results = new 
BulkDocumentWriterResults<>();
+        results.addSuccess(document1);
+        results.addSuccess(document2);
+        results.addSuccess(document3);
+        BulkDocumentWriter<MessageIdBasedDocument> docWriter = 
mock(BulkDocumentWriter.class);
+        when(docWriter.write()).thenReturn(results);
+
+        // attempt to write
+        ElasticsearchWriter esWriter = new ElasticsearchWriter();
+        esWriter.setDocumentWriter(docWriter);
+        esWriter.init(stormConf, writerConfiguration);
+        BulkWriterResponse response = esWriter.write("bro", 
writerConfiguration, messages);
+
+        // documents should have metron guid as documentID
+        verify(docWriter, times(1)).addDocument(document1, "bro_index");
+        verify(docWriter, times(1)).addDocument(document1, "bro_index");
+        verify(docWriter, times(1)).addDocument(document1, "bro_index");
+
+        // response should only contain successes
+        assertFalse(response.hasErrors());
+        assertTrue(response.getSuccesses().contains(new 
MessageId("message1")));
+        assertTrue(response.getSuccesses().contains(new 
MessageId("message2")));
+        assertTrue(response.getSuccesses().contains(new 
MessageId("message3")));
+    }
+
     private MessageIdBasedDocument createDocument(BulkMessage<JSONObject> 
bulkWriterMessage) {
         MessageId messageId = bulkWriterMessage.getId();
         JSONObject message = bulkWriterMessage.getMessage();
@@ -257,7 +317,7 @@ public class ElasticsearchWriterTest {
         message.put(Constants.GUID, UUID.randomUUID().toString());
         message.put(Constants.Fields.TIMESTAMP.getName(), 
System.currentTimeMillis());
         message.put(Constants.Fields.SRC_ADDR.getName(), "192.168.1.1");
-        message.put(Constants.SENSOR_TYPE, "sensor");
+        message.put(Constants.SENSOR_TYPE, "bro");
         return message;
     }
 
diff --git a/metron-platform/metron-indexing/README.md 
b/metron-platform/metron-indexing/README.md
index 46e511b..990a5a1 100644
--- a/metron-platform/metron-indexing/README.md
+++ b/metron-platform/metron-indexing/README.md
@@ -69,13 +69,29 @@ Depending on how you start the indexing topology, it will 
have either Elasticsea
 | `batchTimeout`       | The timeout after which a batch will be flushed even 
if `batchSize` has not been met. | Defaults to a duration which is a fraction 
of the Storm parameter `topology.message.timeout.secs`, if left undefined or 
set to 0.  Ignored if batchSize is `1`, since this disables batching.|
 | `enabled`            | A boolean indicating whether the writer is enabled.   
                                | Defaults to `true`                            
                                                                                
                        |
 | `fieldNameConverter` | Defines how field names are transformed before being 
written to the index.  Only applicable to `elasticsearch`.          | Defaults 
to `DEDOT`.  Acceptable values are `DEDOT` that replaces all '.' with ':' or 
`NOOP` that does not change the field names . |
+| `setDocumentId`      | A boolean indicating whether the writer should use 
the document id generated by Metron| Defaults to `false`.  This setting only 
applies to Elasticsearch, the id used with Solr is configured in the Solr 
schemas.
 
 
 ### Meta Alerts
 Alerts can be grouped, after appropriate searching, into a set of alerts 
called a meta alert.  A meta alert is useful for maintaining the context of 
searching and grouping during further investigations. Standard searches can 
return meta alerts, but grouping and other aggregation or sorting requests will 
not, because there's not a clear way to aggregate in many cases if there are 
multiple alerts contained in the meta alert. All meta alerts will have the 
source type of metaalert, regardles [...]
 
 ### Elasticsearch
-Metron comes with built-in templates for the default sensors for 
Elasticsearch. When adding a new sensor, it will be necessary to add a new 
template defining the output fields appropriately. In addition, there is a 
requirement for a field `alert` of type `nested` for Elasticsearch 2.x 
installs.  This is detailed at [Using Metron with Elasticsearch 
2.x](../metron-elasticsearch/README.md#using-metron-with-elasticsearch-2x)
+Metron comes with built-in templates for the default sensors for 
Elasticsearch. When adding a new sensor, it will be necessary to add a new 
template defining the output fields appropriately. In addition, there is a 
requirement for a field `alert` of type `nested` for Elasticsearch 2.x 
installs.  This is detailed at [Using Metron with Elasticsearch 
2.x](../metron-elasticsearch/README.md#using-metron-with-elasticsearch-2x).
+
+Metron is configured by default to let Elasticsearch [use auto-generated 
ids](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/tune-for-indexing-speed.html#_use_auto_generated_ids)
 for performance reasons.  However, due to Storm's at least once processing 
guarantee, it is possible for duplicate messages to be indexed when messages 
are replayed for whatever reason.  If this scenario is less desirable, the 
Metron generated id stored in the `guid` field of the message can be used [...]
+```
+{
+  "elasticsearch": {
+    "enabled": true,
+    "index": "bro",
+    "setDocumentId": true
+  }
+}
+```
+This can also be set for all sensors in the [Global 
Configuration](../metron-common#global-configuration) by setting the 
`indexing.writer.elasticsearch.setDocumentId` setting to true.  These settings 
are applied in this order of precedence (highest to lowest):
+1. Sensor indexing configuration
+2. Global configuration
+3. False by default
 
 ### Solr
 

Reply via email to