Skip to content

Commit 8c033b9

Browse files
authored
Fixed a bug that prevented alerts from being generated for doc level monitors that use wildcard characters in index names. (#894)
Signed-off-by: AWSHurneyt <[email protected]>
1 parent 4ba7d42 commit 8c033b9

File tree

3 files changed

+58
-9
lines changed

3 files changed

+58
-9
lines changed

alerting/src/main/kotlin/org/opensearch/alerting/DocumentLevelMonitorRunner.kt

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ import org.opensearch.commons.alerting.util.string
4949
import org.opensearch.core.xcontent.ToXContent
5050
import org.opensearch.core.xcontent.XContentBuilder
5151
import org.opensearch.index.query.BoolQueryBuilder
52+
import org.opensearch.index.query.Operator
5253
import org.opensearch.index.query.QueryBuilders
5354
import org.opensearch.percolator.PercolateQueryBuilderExt
5455
import org.opensearch.rest.RestStatus
@@ -553,11 +554,11 @@ object DocumentLevelMonitorRunner : MonitorRunner() {
553554
monitorMetadata: MonitorMetadata,
554555
index: String
555556
): SearchHits {
556-
val boolQueryBuilder = BoolQueryBuilder().filter(QueryBuilders.matchQuery("index", index))
557+
val boolQueryBuilder = BoolQueryBuilder().must(QueryBuilders.matchQuery("index", index).operator(Operator.AND))
557558

558559
val percolateQueryBuilder = PercolateQueryBuilderExt("query", docs, XContentType.JSON)
559560
if (monitor.id.isNotEmpty()) {
560-
boolQueryBuilder.filter(QueryBuilders.matchQuery("monitor_id", monitor.id))
561+
boolQueryBuilder.must(QueryBuilders.matchQuery("monitor_id", monitor.id).operator(Operator.AND))
561562
}
562563
boolQueryBuilder.filter(percolateQueryBuilder)
563564

alerting/src/main/kotlin/org/opensearch/alerting/MonitorMetadataService.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ object MonitorMetadataService :
212212

213213
indices.forEach { indexName ->
214214
if (!lastRunContext.containsKey(indexName)) {
215-
lastRunContext[indexName] = createRunContextForIndex(index)
215+
lastRunContext[indexName] = createRunContextForIndex(indexName)
216216
}
217217
}
218218
} catch (e: RemoteTransportException) {

alerting/src/test/kotlin/org/opensearch/alerting/DocumentMonitorRunnerIT.kt

Lines changed: 54 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import org.opensearch.script.Script
2121
import java.time.ZonedDateTime
2222
import java.time.format.DateTimeFormatter
2323
import java.time.temporal.ChronoUnit.MILLIS
24+
import java.util.Locale
2425

2526
class DocumentMonitorRunnerIT : AlertingRestTestCase() {
2627

@@ -343,20 +344,67 @@ class DocumentMonitorRunnerIT : AlertingRestTestCase() {
343344
assertTrue("Findings saved for test monitor", findings[1].relatedDocIds.contains("5"))
344345
}
345346

346-
fun `test execute monitor with wildcard index that generates alerts and findings`() {
347-
val testIndex = createTestIndex("test1")
348-
val testIndex2 = createTestIndex("test2")
347+
fun `test execute monitor with wildcard index that generates alerts and findings for EQUALS query operator`() {
348+
val testIndexPrefix = "test-index-${randomAlphaOfLength(10).lowercase(Locale.ROOT)}"
349+
val testQueryName = "wildcard-test-query"
350+
val testIndex = createTestIndex("${testIndexPrefix}1")
351+
val testIndex2 = createTestIndex("${testIndexPrefix}2")
352+
349353
val testTime = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now().truncatedTo(MILLIS))
350354
val testDoc = """{
351355
"message" : "This is an error from IAD region",
352356
"test_strict_date_time" : "$testTime",
353357
"test_field" : "us-west-2"
354358
}"""
355359

356-
val docQuery = DocLevelQuery(query = "test_field:\"us-west-2\"", name = "3")
357-
val docLevelInput = DocLevelMonitorInput("description", listOf("test*"), listOf(docQuery))
360+
val docQuery = DocLevelQuery(query = "test_field:\"us-west-2\"", name = testQueryName)
361+
val docLevelInput = DocLevelMonitorInput("description", listOf("$testIndexPrefix*"), listOf(docQuery))
358362

359-
val trigger = randomDocumentLevelTrigger(condition = ALWAYS_RUN)
363+
val trigger = randomDocumentLevelTrigger(condition = Script("query[name=$testQueryName]"))
364+
val monitor = createMonitor(randomDocumentLevelMonitor(inputs = listOf(docLevelInput), triggers = listOf(trigger)))
365+
assertNotNull(monitor.id)
366+
367+
indexDoc(testIndex, "1", testDoc)
368+
indexDoc(testIndex2, "5", testDoc)
369+
370+
val response = executeMonitor(monitor.id)
371+
372+
val output = entityAsMap(response)
373+
374+
assertEquals(monitor.name, output["monitor_name"])
375+
@Suppress("UNCHECKED_CAST")
376+
val searchResult = (output.objectMap("input_results")["results"] as List<Map<String, Any>>).first()
377+
@Suppress("UNCHECKED_CAST")
378+
val matchingDocsToQuery = searchResult[docQuery.id] as List<String>
379+
assertEquals("Incorrect search result", 2, matchingDocsToQuery.size)
380+
assertTrue("Incorrect search result", matchingDocsToQuery.containsAll(listOf("1|$testIndex", "5|$testIndex2")))
381+
382+
val alerts = searchAlertsWithFilter(monitor)
383+
assertEquals("Alert saved for test monitor", 2, alerts.size)
384+
385+
val findings = searchFindings(monitor)
386+
assertEquals("Findings saved for test monitor", 2, findings.size)
387+
val foundFindings = findings.filter { it.relatedDocIds.contains("1") || it.relatedDocIds.contains("5") }
388+
assertEquals("Didn't find findings for docs 1 and 5", 2, foundFindings.size)
389+
}
390+
391+
fun `test execute monitor with wildcard index that generates alerts and findings for NOT EQUALS query operator`() {
392+
val testIndexPrefix = "test-index-${randomAlphaOfLength(10).lowercase(Locale.ROOT)}"
393+
val testQueryName = "wildcard-test-query"
394+
val testIndex = createTestIndex("${testIndexPrefix}1")
395+
val testIndex2 = createTestIndex("${testIndexPrefix}2")
396+
397+
val testTime = DateTimeFormatter.ISO_OFFSET_DATE_TIME.format(ZonedDateTime.now().truncatedTo(MILLIS))
398+
val testDoc = """{
399+
"message" : "This is an error from IAD region",
400+
"test_strict_date_time" : "$testTime",
401+
"test_field" : "us-west-2"
402+
}"""
403+
404+
val docQuery = DocLevelQuery(query = "NOT (test_field:\"us-west-1\")", name = testQueryName)
405+
val docLevelInput = DocLevelMonitorInput("description", listOf("$testIndexPrefix*"), listOf(docQuery))
406+
407+
val trigger = randomDocumentLevelTrigger(condition = Script("query[name=$testQueryName]"))
360408
val monitor = createMonitor(randomDocumentLevelMonitor(inputs = listOf(docLevelInput), triggers = listOf(trigger)))
361409
assertNotNull(monitor.id)
362410

0 commit comments

Comments
 (0)