Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Backport main] Fix get alerts api to also return chained alerts with default params. and skip audit state alerts #1056

Merged
merged 1 commit into from
Jul 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ object MonitorMetadataService :
monitor: Monitor,
createWithRunContext: Boolean = true,
skipIndex: Boolean = false,
workflowMetadataId: String? = null,
workflowMetadataId: String? = null
): Pair<MonitorMetadata, Boolean> {
try {
val created = true
Expand Down Expand Up @@ -152,7 +152,7 @@ object MonitorMetadataService :
getResponse.sourceAsBytesRef, XContentType.JSON
)
XContentParserUtils.ensureExpectedToken(XContentParser.Token.START_OBJECT, xcp.nextToken(), xcp)
MonitorMetadata.parse(xcp)
MonitorMetadata.parse(xcp, getResponse.id, getResponse.seqNo, getResponse.primaryTerm)
} else {
null
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ class TransportGetAlertsAction @Inject constructor(
clusterService: ClusterService,
actionFilters: ActionFilters,
val settings: Settings,
val xContentRegistry: NamedXContentRegistry
val xContentRegistry: NamedXContentRegistry,
) : HandledTransportAction<ActionRequest, GetAlertsResponse>(
AlertingActions.GET_ALERTS_ACTION_NAME,
transportService,
Expand All @@ -78,7 +78,7 @@ class TransportGetAlertsAction @Inject constructor(
override fun doExecute(
task: Task,
request: ActionRequest,
actionListener: ActionListener<GetAlertsResponse>
actionListener: ActionListener<GetAlertsResponse>,
) {
val getAlertsRequest = request as? GetAlertsRequest
?: recreateObject(request) { GetAlertsRequest(it) }
Expand All @@ -98,7 +98,15 @@ class TransportGetAlertsAction @Inject constructor(
queryBuilder.filter(QueryBuilders.termQuery("severity", getAlertsRequest.severityLevel))
}

if (getAlertsRequest.alertState != "ALL") {
if (getAlertsRequest.alertState == "ALL") {
// alerting dashboards expects chained alerts and individually executed monitors' alerts to be returned from this api
// when invoked with state=ALL. They require that audit alerts are NOT returned in this page
// and only be shown in "associated alerts" field under get workflow_alerts API.
// But if the API is called with query_params: state=AUDIT,monitor_id=<123>,workflow_id=<abc>, this api
// will return audit alerts generated by delegate monitor <123> in workflow <abc>
QueryBuilders.boolQuery()
.filter(QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(Alert.STATE_FIELD, Alert.State.AUDIT.name)))
} else {
queryBuilder.filter(QueryBuilders.termQuery("state", getAlertsRequest.alertState))
}

Expand All @@ -108,16 +116,23 @@ class TransportGetAlertsAction @Inject constructor(

if (getAlertsRequest.monitorId != null) {
queryBuilder.filter(QueryBuilders.termQuery("monitor_id", getAlertsRequest.monitorId))
if (getAlertsRequest.workflowIds.isNullOrEmpty()) {
val noWorkflowIdQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(Alert.WORKFLOW_ID_FIELD)))
.should(QueryBuilders.termsQuery(Alert.WORKFLOW_ID_FIELD, ""))
queryBuilder.must(noWorkflowIdQuery)
}
} else if (getAlertsRequest.monitorIds.isNullOrEmpty() == false) {
queryBuilder.filter(QueryBuilders.termsQuery("monitor_id", getAlertsRequest.monitorIds))
if (getAlertsRequest.workflowIds.isNullOrEmpty()) {
val noWorkflowIdQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(Alert.WORKFLOW_ID_FIELD)))
.should(QueryBuilders.termsQuery(Alert.WORKFLOW_ID_FIELD, ""))
queryBuilder.must(noWorkflowIdQuery)
}
}
if (getAlertsRequest.workflowIds.isNullOrEmpty() == false) {
queryBuilder.must(QueryBuilders.termsQuery("workflow_id", getAlertsRequest.workflowIds))
} else {
val noWorklfowIdQuery = QueryBuilders.boolQuery()
.should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(Alert.WORKFLOW_ID_FIELD)))
.should(QueryBuilders.termsQuery(Alert.WORKFLOW_ID_FIELD, ""))
queryBuilder.must(noWorklfowIdQuery)
}
if (!tableProp.searchString.isNullOrBlank()) {
queryBuilder
Expand Down Expand Up @@ -197,7 +212,7 @@ class TransportGetAlertsAction @Inject constructor(
alertIndex: String,
searchSourceBuilder: SearchSourceBuilder,
actionListener: ActionListener<GetAlertsResponse>,
user: User?
user: User?,
) {
// user is null when: 1/ security is disabled. 2/when user is super-admin.
if (user == null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,11 @@ class TransportGetWorkflowAlertsAction @Inject constructor(
queryBuilder.filter(QueryBuilders.termQuery("severity", getWorkflowAlertsRequest.severityLevel))
}

if (getWorkflowAlertsRequest.alertState != "ALL") {
queryBuilder.filter(QueryBuilders.termQuery("state", getWorkflowAlertsRequest.alertState))
if (getWorkflowAlertsRequest.alertState == "ALL") {
QueryBuilders.boolQuery()
.filter(QueryBuilders.boolQuery().mustNot(QueryBuilders.termsQuery(Alert.STATE_FIELD, Alert.State.AUDIT.name)))
} else {
queryBuilder.filter(QueryBuilders.termQuery(Alert.STATE_FIELD, getWorkflowAlertsRequest.alertState))
}

if (getWorkflowAlertsRequest.alertIds.isNullOrEmpty() == false) {
Expand Down Expand Up @@ -149,7 +152,7 @@ class TransportGetWorkflowAlertsAction @Inject constructor(
}

fun resolveAlertsIndexName(getAlertsRequest: GetWorkflowAlertsRequest): String {
return if (getAlertsRequest.alertIndex.isNullOrEmpty()) AlertIndices.ALL_ALERT_INDEX_PATTERN
return if (getAlertsRequest.alertIndex.isNullOrEmpty()) AlertIndices.ALERT_INDEX
else getAlertsRequest.alertIndex!!
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -310,7 +310,7 @@ object CompositeWorkflowRunner : WorkflowRunner() {
.should(boolQuery().mustNot(existsQuery(Alert.ERROR_MESSAGE_FIELD)))
.should(termsQuery(Alert.ERROR_MESSAGE_FIELD, ""))
queryBuilder.must(noErrorQuery)
searchRequest.source().query(queryBuilder)
searchRequest.source().query(queryBuilder).size(9999)
val searchResponse: SearchResponse = monitorCtx.client!!.suspendUntil { monitorCtx.client!!.search(searchRequest, it) }
val alerts = searchResponse.hits.map { hit ->
val xcp = XContentHelper.createParser(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4071,6 +4071,23 @@ class MonitorDataSourcesIT : AlertingSingleNodeTestCase() {
)
var chainedAlerts = res.alerts
Assert.assertTrue(chainedAlerts.size == 1)

// verify get alerts api with defaults set in query params returns only chained alerts and not audit alerts
val table = Table("asc", "id", null, 1, 0, "")
val getAlertsDefaultParamsResponse = client().execute(
AlertingActions.GET_ALERTS_ACTION_TYPE,
GetAlertsRequest(
table = table,
severityLevel = "ALL",
alertState = "ALL",
monitorId = null,
alertIndex = null,
monitorIds = null,
workflowIds = null,
alertIds = null
)
).get()
Assert.assertEquals(getAlertsDefaultParamsResponse.alerts.size, 1)
Assert.assertTrue(res.associatedAlerts.isEmpty())
verifyAcknowledgeChainedAlerts(chainedAlerts, workflowId, 1)
Assert.assertTrue(chainedAlerts[0].executionId == executeWorkflowResponse.workflowRunResult.executionId)
Expand Down Expand Up @@ -4114,6 +4131,20 @@ class MonitorDataSourcesIT : AlertingSingleNodeTestCase() {
notTriggerResult = triggerResults[notTrigger.id]
Assert.assertFalse(notTriggerResult!!.triggered)
Assert.assertTrue(andTriggerResult!!.triggered)
val getAuditAlertsForMonitor1 = client().execute(
AlertingActions.GET_ALERTS_ACTION_TYPE,
GetAlertsRequest(
table = table,
severityLevel = "ALL",
alertState = "AUDIT",
monitorId = monitorResponse.id,
alertIndex = null,
monitorIds = null,
workflowIds = listOf(workflowId),
alertIds = null
)
).get()
Assert.assertEquals(getAuditAlertsForMonitor1.alerts.size, 1)
res = getWorkflowAlerts(workflowId)
chainedAlerts = res.alerts
Assert.assertTrue(chainedAlerts.size == 1)
Expand Down Expand Up @@ -4151,6 +4182,10 @@ class MonitorDataSourcesIT : AlertingSingleNodeTestCase() {
assertAuditStateAlerts(monitorResponse2.id, alerts1)
assertFindings(monitorResponse2.id, customFindingsIndex2, 1, 1, listOf("2"))
verifyAcknowledgeChainedAlerts(chainedAlerts, workflowId, 1)
// test redundant executions of workflow dont query old data again to verify metadata updation works fine
val redundantExec = executeWorkflow(workflow)
Assert.assertFalse(redundantExec?.workflowRunResult!!.triggerResults[andTrigger.id]!!.triggered)
Assert.assertTrue(redundantExec.workflowRunResult.triggerResults[notTrigger.id]!!.triggered)
}

private fun getDelegateMonitorMetadataId(
Expand Down
Loading