-
Notifications
You must be signed in to change notification settings - Fork 8.3k
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
[ML] Alerts as data integration for Anomaly Detection rule type #166349
[ML] Alerts as data integration for Anomaly Detection rule type #166349
Conversation
x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts
Show resolved
Hide resolved
packages/kbn-alerts-as-data-utils/src/schemas/generated/ml_anomaly_detection_schema.ts
Outdated
Show resolved
Hide resolved
…ts-as-data' into ml-165958-anomaly-detection-alerts-as-data
…ection-alerts-as-data
x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts
Outdated
Show resolved
Hide resolved
x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts
Outdated
Show resolved
Hide resolved
context: ANOMALY_DETECTION_AAD_INDEX_NAME, | ||
mappings: { | ||
fieldMap: { | ||
[ALERT_ANOMALY_DETECTION_JOB_ID]: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@droberts195 could you please review the mappings for alert-as-data index? only additive changes will be allowed after release so I want to double-check it's correct.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some comments on the details but I don't understand enough about how these alerts will be searched to say with certainty what the correct answers are. There are very complicated tradeoffs to be made. Whatever is done, it's important that some comments are added to say why we've decided on those tradeoffs, as it's inevitable that somebody will complain about our decision in the future whichever way we go.
The decision on the mappings here needs to go with a best practice guide on how to search the resulting alerts.
x-pack/plugins/ml/server/lib/alerts/register_anomaly_detection_alert_type.ts
Show resolved
Hide resolved
[ALERT_ANOMALY_IS_INTERIM]: { type: ES_FIELD_TYPES.BOOLEAN, array: false, required: false }, | ||
[ALERT_ANOMALY_TIMESTAMP]: { type: ES_FIELD_TYPES.DATE, array: false, required: false }, | ||
[ALERT_TOP_RECORDS]: { | ||
type: ES_FIELD_TYPES.NESTED, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nested
is a very complex type to allow the sub-objects to be searched individually. It results in secret documents being indexed for each element of the array.
The other alternative here would be object
. Whether nested
is really needed here is probably the most important decision to make about these mappings before merging the PR. I don't know enough about how these alerts will be searched to know the answer.
There are more details in the "Arrays of objects" note on https://www.elastic.co/guide/en/elasticsearch/reference/current/array.html and the linked docs for the nested
type.
The same question applies to influencers
below.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We discussed it with @peteharverson and agreed it might be useful to fetch alerts with certain influencers, e.g.
GET .alerts-ml.anomaly-detection.alerts-default/_search
{
"query": {
"nested": {
"path": "kibana.alert.top_influencers",
"query": {
"bool": {
"must": [
{
"match": {
"kibana.alert.top_influencers.influencer_field_name": "key"
}
}
]
}
}
}
}
}
If I'm not mistaken it's only possible with the nested type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree with @droberts195 that we need to be especially cautious with using the nested
type. There are tons of pitfalls with the nested field type per the official docs: https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html. Additionally, Kibana does not handle nested fields well, so this will make consuming the data stored in these nested field types complicated as well.
If we use the object
type, we'd still be able to perform the query to match the influencers. The biggest limitation is that we can't query for multiple fields that appear within the array because of the way ES flattens arrays: https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html#nested-arrays-flattening-objects
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're running into general limitations of Elasticsearch and Kibana functionality.
"Show me ML alerts where one of the influencer fields was airline
" will be possible with an object
mapping.
But, "Show me ML alerts where one of the influencer fields was airline
and its influencer score was greater than 90" will not be reliable with object
. This is because influence_field_name: airline
and influencer_score > 90
might match on different array elements. So it might be that destination_airport
was the influencer with the score above 90, not airline
.
Given the difficulties of working with nested
in Kibana, and other drawbacks with flattened
, it sounds like object
is the mapping to go for here. But this will restrict the search functionality that can be built on top of these alerts to some extent. If these limitations are likely to cause problems then we need to hold this functionality back for a later release and think through a more major redesign of the document structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Many thanks for the feedback and suggestions @droberts195, @kobelb. Updated to the object
type in 33d037c.
Support for queries like this should be sufficient, cc @peteharverson
GET .alerts-ml.anomaly-detection.alerts-default/_search
{
"query": {
"term": {
"kibana.alert.top_influencers.influencer_field_name": {
"value": "key"
}
}
}
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Dima. We discussed this a bit and came to the conclusion that object
was the best option of the 3, even though none of the options are perfect. So what you've done tallies with the conclusion we came to.
type: ES_FIELD_TYPES.NESTED, | ||
array: true, | ||
required: false, | ||
dynamic: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One thing to understand here is that when we write anomalies to the anomaly results indices we added the partition/by/over fields twice:
- We add them as
partition_field_name
/partition_field_value
etc. - We add them using their original field names, for example
airline
/AAL
In the anomaly results indices we try to map the original field names as well as the predictable ones. This means that you can search anomaly results with a terms search on the airline
field and get hits.
Setting dynamic: false
here means that these sub-objects won't be searchable by original field names. If the values have been populated by copying the _source
of the original anomalies in full then the original fields will be visible in the _source
of the alerts, but the alerts won't be searchable by these original field names.
Unfortunately, trying to create the original field names in the mappings in the anomaly results indices has turned out to be a very difficult problem, and has resulted in a lot of complicated code and support cases when things go wrong.
Therefore I think it would be best not to try and do the same for alerts. (In other words leave this part of the mappings as it is now.) But it's important to realise that, as a result, it won't be possible to search for alerts for airline
/AAL
, but instead it will be necessary to search for partition_field_name
/airline
and partition_field_value
/AAL
. This then ties back to the object
vs nested
decision, because you can only search for two fields together in arrays of objects if you use the nested
type.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point regarding searching by the original field names and allowing dynamic mappings. It only affects .alerts-ml.anomaly-detection.alerts-default
indices so it shouldn't be an issue.
To clarify, will we be able to query for airline:AAL
with the object
type?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it be possible to use the flattened
mapping to be able to search for airline:AAL
inside the copy of the original _source
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's important to know the actual field name. With the flattened
mapping we can end up with similar field values coming from completely different fields if I understand it correctly. WDYT @droberts195?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To clarify, will we be able to query for
airline:AAL
with theobject
type?
No, only if there was an explicit mapping for airline
within the object
. And getting those explicit mappings in is extremely hard for fields that vary by job.
Would it be possible to use the
flattened
mapping
flattened
might be ideal if alert_top_records
was a single object rather than an array. I am not sure how flattened
will behave with an array of objects though - that would need some experimentation.
One more thing about flattened
is that it treats all sub-values as keywords. So then it definitely won't be possible to do a search like, "Give me all alerts where one of the top records has a record score greater than 90."
It all comes back to how we expect users to be searching these alerts. If we have a feel for how people will want to search, filter and sort then it will be easier to create mappings that support those use cases (or at least say with certainty that it's impossible to support all of them and document the use cases we do support).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Updated type to object
in 33d037c
context: ANOMALY_DETECTION_AAD_INDEX_NAME, | ||
mappings: { | ||
fieldMap: { | ||
[ALERT_ANOMALY_DETECTION_JOB_ID]: { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I left some comments on the details but I don't understand enough about how these alerts will be searched to say with certainty what the correct answers are. There are very complicated tradeoffs to be made. Whatever is done, it's important that some comments are added to say why we've decided on those tradeoffs, as it's inevitable that somebody will complain about our decision in the future whichever way we go.
The decision on the mappings here needs to go with a best practice guide on how to search the resulting alerts.
}, | ||
}, | ||
[ALERT_TOP_INFLUENCERS]: { | ||
type: ES_FIELD_TYPES.NESTED, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@XavierM Does the alerts table support KQL queries against nested fields? I don't believe we have any other nested fields in the AAD indices as of now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The index mappings LGTM.
(I haven't reviewed the rest of the PR, only the index mappings.)
@elasticmachine merge upstream |
…ection-alerts-as-data # Conflicts: # x-pack/plugins/ml/tsconfig.json
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Code LGTM
💚 Build Succeeded
Metrics [docs]Public APIs missing comments
Public APIs missing exports
Page load bundle
Unknown metric groupsAPI count
References to deprecated APIs
History
To update your PR or re-run it, just comment with: cc @darnautov |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM.
Tested against some anomaly detection rules and inspected index mapping and docs.
…tened alerts docs (#167439) Resolves #166946 ## Summary The rule registry has traditionally written out AAD docs with flattened keys, like ``` { "kibana.alert.rule.name": "test" } ``` The framework alerts client has been writing out AAD docs as objects, like ``` { "kibana": { "alert": { "rule": { "name": "test" } } } } ``` We've identified a few places where we're updating the docs where having this divergence makes things more difficult, so this is to switch the framework to writing flattened alert docs before onboarding more rule types. This PR is targeted for 8.11, which is also when we onboarded the index threshold rule type to FAAD. The only other rule type using FAAD to write docs is ES query, which landed in 8.10 so there will be a followup issue to handle the case of updating unflattened ES query AAD docs from 8.10 ## To Verify ### ES Query and Index Threshold AaD Create these rules that trigger alerts and verify that their AaD docs are written out as flattened. For the ES Query rule type, select a Metrics/Logs consumer and verify that they appear on the O11y alerts table. ### ML alerts ML alerts added in #166349 looked like: <details> <summary>Unflattened</summary> ``` { "kibana": { "alert": { "url": "/app/ml/explorer/?_g=(ml%3A(jobIds%3A!(rt-anomaly-mean-value))%2Ctime%3A(from%3A'2023-09-28T14%3A57%3A00.000Z'%2Cmode%3Aabsolute%2Cto%3A'2023-09-28T15%3A17%3A00.000Z'))&_a=(explorer%3A(mlExplorerFilter%3A(filterActive%3A!t%2CfilteredFields%3A!(key%2Cthird-key)%2CinfluencersFilterQuery%3A(bool%3A(minimum_should_match%3A1%2Cshould%3A!((match_phrase%3A(key%3Athird-key)))))%2CqueryString%3A'key%3A%22third-key%22')%2CmlExplorerSwimlane%3A()))", "reason": "Alerts are raised based on real-time scores. Remember that scores may be adjusted over time as data continues to be analyzed.", "job_id": "rt-anomaly-mean-value", "anomaly_score": 73.63508175828011, "is_interim": false, "anomaly_timestamp": 1695913620000, "top_records": [{ "job_id": "rt-anomaly-mean-value", "record_score": 73.63516446528412, "initial_record_score": 73.63516446528412, "detector_index": 0, "is_interim": false, "timestamp": 1695913620000, "partition_field_name": "key", "partition_field_value": "third-key", "function": "mean", "actual": [ 3 ], "typical": [ 4.187715468532429 ] }], "top_influencers": [{ "job_id": "rt-anomaly-mean-value", "influencer_field_name": "key", "influencer_field_value": "third-key", "influencer_score": 73.63508175828011, "initial_influencer_score": 73.63508175828011, "is_interim": false, "timestamp": 1695913620000 }], "action_group": "anomaly_score_match", "flapping": false, "flapping_history": [ true, false, false, false ], "instance": { "id": "rt-anomaly-mean-value" }, "maintenance_window_ids": [], "rule": { "category": "Anomaly detection alert", "consumer": "alerts", "execution": { "uuid": "e9e681d4-c8e4-43eb-82e5-a58bdf7ffe12" }, "name": "rt-ad-alert-influencer", "parameters": { "severity": 5, "resultType": "influencer", "includeInterim": false, "jobSelection": { "jobIds": [ "rt-anomaly-mean-value" ], "groupIds": [] }, "lookbackInterval": null, "topNBuckets": null }, "producer": "ml", "revision": 0, "rule_type_id": "xpack.ml.anomaly_detection_alert", "tags": [], "uuid": "9e1d6bc0-5e10-11ee-8416-3bf48cca0922" }, "status": "active", "uuid": "c9c1f075-9985-4c55-8ff8-22349cb30269", "workflow_status": "open", "duration": { "us": "99021000000" }, "start": "2023-09-28T15:07:12.868Z", "time_range": { "gte": "2023-09-28T15:07:12.868Z" } }, "space_ids": [ "default" ], "version": "8.11.0" }, "@timestamp": "2023-09-28T15:08:51.889Z", "event": { "action": "active", "kind": "signal" }, "tags": [] } ``` </details> Now they look like: <details> <summary>Flattened</summary> ``` { "kibana.alert.url": "/app/ml/explorer/?_g=(ml%3A(jobIds%3A!(rt-anomaly-mean-value))%2Ctime%3A(from%3A'2023-09-28T15%3A03%3A00.000Z'%2Cmode%3Aabsolute%2Cto%3A'2023-09-28T15%3A23%3A00.000Z'))&_a=(explorer%3A(mlExplorerFilter%3A(filterActive%3A!t%2CfilteredFields%3A!(key%2Cthird-key)%2CinfluencersFilterQuery%3A(bool%3A(minimum_should_match%3A1%2Cshould%3A!((match_phrase%3A(key%3Athird-key)))))%2CqueryString%3A'key%3A%22third-key%22')%2CmlExplorerSwimlane%3A()))", "kibana.alert.reason": "Alerts are raised based on real-time scores. Remember that scores may be adjusted over time as data continues to be analyzed.", "kibana.alert.job_id": "rt-anomaly-mean-value", "kibana.alert.anomaly_score": 72.75515452061356, "kibana.alert.is_interim": false, "kibana.alert.anomaly_timestamp": 1695913980000, "kibana.alert.top_records": [{ "job_id": "rt-anomaly-mean-value", "record_score": 72.75515452061356, "initial_record_score": 72.75515452061356, "detector_index": 0, "is_interim": false, "timestamp": 1695913980000, "partition_field_name": "key", "partition_field_value": "third-key", "function": "mean", "actual": [ 0.5 ], "typical": [ 4.138745343296527 ] }], "kibana.alert.top_influencers": [{ "job_id": "rt-anomaly-mean-value", "influencer_field_name": "key", "influencer_field_value": "third-key", "influencer_score": 72.75515452061356, "initial_influencer_score": 72.75515452061356, "is_interim": false, "timestamp": 1695913980000 }], "kibana.alert.rule.category": "Anomaly detection alert", "kibana.alert.rule.consumer": "alerts", "kibana.alert.rule.execution.uuid": "17fef3d3-d595-4362-837e-b2a73650169e", "kibana.alert.rule.name": "rt-ad-alert-influencer", "kibana.alert.rule.parameters": { "severity": 5, "resultType": "influencer", "includeInterim": false, "jobSelection": { "jobIds": [ "rt-anomaly-mean-value" ], "groupIds": [] }, "lookbackInterval": null, "topNBuckets": null }, "kibana.alert.rule.producer": "ml", "kibana.alert.rule.revision": 0, "kibana.alert.rule.rule_type_id": "xpack.ml.anomaly_detection_alert", "kibana.alert.rule.tags": [], "kibana.alert.rule.uuid": "757c7610-5e11-11ee-8bc6-a95c3ced4757", "kibana.space_ids": [ "default" ], "@timestamp": "2023-09-28T15:14:52.057Z", "event.action": "active", "event.kind": "signal", "kibana.alert.action_group": "anomaly_score_match", "kibana.alert.flapping": false, "kibana.alert.flapping_history": [ true, false, false, false ], "kibana.alert.instance.id": "rt-anomaly-mean-value", "kibana.alert.maintenance_window_ids": [], "kibana.alert.status": "active", "kibana.alert.uuid": "ac1f0d7c-461b-4fc6-b4c3-04416ac876d3", "kibana.alert.workflow_status": "open", "kibana.alert.duration.us": "99028000000", "kibana.alert.start": "2023-09-28T15:13:13.028Z", "kibana.alert.time_range": { "gte": "2023-09-28T15:13:13.028Z" }, "kibana.version": "8.11.0", "tags": [] } ``` </details>
…tened alerts docs (#167691) Resolves #166946 ## PRs to this feature branch * #167439 * #167583 ## Summary The rule registry has traditionally written out AAD docs with flattened keys, like ``` { "kibana.alert.rule.name": "test" } ``` The framework alerts client has been writing out AAD docs as objects, like ``` { "kibana": { "alert": { "rule": { "name": "test" } } } } ``` We've identified a few places where we're updating the docs where having this divergence makes things more difficult, so this is to switch the framework to writing flattened alert docs before onboarding more rule types. This PR is targeted for 8.11, which is also when we onboarded the index threshold rule type and the ML anomaly detection rule type to FAAD. For the ES query rule, which started writing unflattened AaD docs in 8.10, this PR adds special handling to ensure that those unflattened docs are correctly updated with flattened fields. ## To Verify ### ES Query and Index Threshold AaD Create these rules that trigger alerts and verify that their AaD docs are written out as flattened. For the ES Query rule type, select a Metrics/Logs consumer and verify that they appear on the O11y alerts table. ### ML alerts ML alerts added in #166349 looked like: <details> <summary>Unflattened</summary> ``` { "kibana": { "alert": { "url": "/app/ml/explorer/?_g=(ml%3A(jobIds%3A!(rt-anomaly-mean-value))%2Ctime%3A(from%3A'2023-09-28T14%3A57%3A00.000Z'%2Cmode%3Aabsolute%2Cto%3A'2023-09-28T15%3A17%3A00.000Z'))&_a=(explorer%3A(mlExplorerFilter%3A(filterActive%3A!t%2CfilteredFields%3A!(key%2Cthird-key)%2CinfluencersFilterQuery%3A(bool%3A(minimum_should_match%3A1%2Cshould%3A!((match_phrase%3A(key%3Athird-key)))))%2CqueryString%3A'key%3A%22third-key%22')%2CmlExplorerSwimlane%3A()))", "reason": "Alerts are raised based on real-time scores. Remember that scores may be adjusted over time as data continues to be analyzed.", "job_id": "rt-anomaly-mean-value", "anomaly_score": 73.63508175828011, "is_interim": false, "anomaly_timestamp": 1695913620000, "top_records": [{ "job_id": "rt-anomaly-mean-value", "record_score": 73.63516446528412, "initial_record_score": 73.63516446528412, "detector_index": 0, "is_interim": false, "timestamp": 1695913620000, "partition_field_name": "key", "partition_field_value": "third-key", "function": "mean", "actual": [ 3 ], "typical": [ 4.187715468532429 ] }], "top_influencers": [{ "job_id": "rt-anomaly-mean-value", "influencer_field_name": "key", "influencer_field_value": "third-key", "influencer_score": 73.63508175828011, "initial_influencer_score": 73.63508175828011, "is_interim": false, "timestamp": 1695913620000 }], "action_group": "anomaly_score_match", "flapping": false, "flapping_history": [ true, false, false, false ], "instance": { "id": "rt-anomaly-mean-value" }, "maintenance_window_ids": [], "rule": { "category": "Anomaly detection alert", "consumer": "alerts", "execution": { "uuid": "e9e681d4-c8e4-43eb-82e5-a58bdf7ffe12" }, "name": "rt-ad-alert-influencer", "parameters": { "severity": 5, "resultType": "influencer", "includeInterim": false, "jobSelection": { "jobIds": [ "rt-anomaly-mean-value" ], "groupIds": [] }, "lookbackInterval": null, "topNBuckets": null }, "producer": "ml", "revision": 0, "rule_type_id": "xpack.ml.anomaly_detection_alert", "tags": [], "uuid": "9e1d6bc0-5e10-11ee-8416-3bf48cca0922" }, "status": "active", "uuid": "c9c1f075-9985-4c55-8ff8-22349cb30269", "workflow_status": "open", "duration": { "us": "99021000000" }, "start": "2023-09-28T15:07:12.868Z", "time_range": { "gte": "2023-09-28T15:07:12.868Z" } }, "space_ids": [ "default" ], "version": "8.11.0" }, "@timestamp": "2023-09-28T15:08:51.889Z", "event": { "action": "active", "kind": "signal" }, "tags": [] } ``` </details> Now they look like: <details> <summary>Flattened</summary> ``` { "kibana.alert.url": "/app/ml/explorer/?_g=(ml%3A(jobIds%3A!(rt-anomaly-mean-value))%2Ctime%3A(from%3A'2023-09-28T15%3A03%3A00.000Z'%2Cmode%3Aabsolute%2Cto%3A'2023-09-28T15%3A23%3A00.000Z'))&_a=(explorer%3A(mlExplorerFilter%3A(filterActive%3A!t%2CfilteredFields%3A!(key%2Cthird-key)%2CinfluencersFilterQuery%3A(bool%3A(minimum_should_match%3A1%2Cshould%3A!((match_phrase%3A(key%3Athird-key)))))%2CqueryString%3A'key%3A%22third-key%22')%2CmlExplorerSwimlane%3A()))", "kibana.alert.reason": "Alerts are raised based on real-time scores. Remember that scores may be adjusted over time as data continues to be analyzed.", "kibana.alert.job_id": "rt-anomaly-mean-value", "kibana.alert.anomaly_score": 72.75515452061356, "kibana.alert.is_interim": false, "kibana.alert.anomaly_timestamp": 1695913980000, "kibana.alert.top_records": [{ "job_id": "rt-anomaly-mean-value", "record_score": 72.75515452061356, "initial_record_score": 72.75515452061356, "detector_index": 0, "is_interim": false, "timestamp": 1695913980000, "partition_field_name": "key", "partition_field_value": "third-key", "function": "mean", "actual": [ 0.5 ], "typical": [ 4.138745343296527 ] }], "kibana.alert.top_influencers": [{ "job_id": "rt-anomaly-mean-value", "influencer_field_name": "key", "influencer_field_value": "third-key", "influencer_score": 72.75515452061356, "initial_influencer_score": 72.75515452061356, "is_interim": false, "timestamp": 1695913980000 }], "kibana.alert.rule.category": "Anomaly detection alert", "kibana.alert.rule.consumer": "alerts", "kibana.alert.rule.execution.uuid": "17fef3d3-d595-4362-837e-b2a73650169e", "kibana.alert.rule.name": "rt-ad-alert-influencer", "kibana.alert.rule.parameters": { "severity": 5, "resultType": "influencer", "includeInterim": false, "jobSelection": { "jobIds": [ "rt-anomaly-mean-value" ], "groupIds": [] }, "lookbackInterval": null, "topNBuckets": null }, "kibana.alert.rule.producer": "ml", "kibana.alert.rule.revision": 0, "kibana.alert.rule.rule_type_id": "xpack.ml.anomaly_detection_alert", "kibana.alert.rule.tags": [], "kibana.alert.rule.uuid": "757c7610-5e11-11ee-8bc6-a95c3ced4757", "kibana.space_ids": [ "default" ], "@timestamp": "2023-09-28T15:14:52.057Z", "event.action": "active", "event.kind": "signal", "kibana.alert.action_group": "anomaly_score_match", "kibana.alert.flapping": false, "kibana.alert.flapping_history": [ true, false, false, false ], "kibana.alert.instance.id": "rt-anomaly-mean-value", "kibana.alert.maintenance_window_ids": [], "kibana.alert.status": "active", "kibana.alert.uuid": "ac1f0d7c-461b-4fc6-b4c3-04416ac876d3", "kibana.alert.workflow_status": "open", "kibana.alert.duration.us": "99028000000", "kibana.alert.start": "2023-09-28T15:13:13.028Z", "kibana.alert.time_range": { "gte": "2023-09-28T15:13:13.028Z" }, "kibana.version": "8.11.0", "tags": [] } ``` </details> --------- Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
## Summary With alerts-as-data integration added in #166349, we're enabled to incorporate alerts historical data into views in the ML UI to see how it correlates with the anomaly results. This PR add alerts data to the Anomaly Explorer page. If selected anomaly detection jobs have associated alerting rules, we show a new "Alerts" panel. It contains: <img width="1675" alt="image" src="https://github.com/elastic/kibana/assets/5236598/1945d1f1-7f12-4a03-8ebd-e0b36c8fce68"> #### A line chart with alerts count over time using the Lens embeddable It support sync cursor with the Anomaly swim lane making it easier to align anomalous buckets with alerts spikes. <img width="1189" alt="image" src="https://github.com/elastic/kibana/assets/5236598/343b9bcf-bfa4-479d-bf8f-c1572402aa42"> #### Summary of the alerting rules Shows an aggregated information for each alerting rule associated with the current job selection: - An indicator if alerting rule is active - Total number of alerts - Duration of the latest alerts - Start time for active rules and Recovery time for recovered Rules summary has a descending order based on the following criteria: - Number of active alerts in rule - Total number of alerts in rule - Duration of the most recent alert in rule <img width="1032" alt="image" src="https://github.com/elastic/kibana/assets/5236598/899f37f3-dd8c-4cb6-b7f6-263ed86d20ee"> #### Alert details It contains an alerts table provided by `triggersActionsUI` plugin. For each alert the user can: - Open alerts details page - Attach an alert to a new case - Attach n alert to an existing case <img width="1177" alt="image" src="https://github.com/elastic/kibana/assets/5236598/d3b7768a-bae2-404f-b364-ff7d7493cb9b"> #### Alert context menu When an anomaly swim lane cells are selected, and there are alerts within the chosen time range, a context menu displaying alert details is shown. <img width="1202" alt="image" src="https://github.com/elastic/kibana/assets/5236598/2b684c51-db5a-4f8c-bda9-c3e9aabde0d4"> ### Checklist - [x] Any text added follows [EUI's writing guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses sentence case text and includes [i18n support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md) - [ ] [Documentation](https://www.elastic.co/guide/en/kibana/master/development-documentation.html) was added for features that require explanation or tutorials - [x] [Unit or functional tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html) were updated or added to match the most common scenarios - [x] Any UI touched in this PR is usable by keyboard only (learn more about [keyboard accessibility](https://webaim.org/techniques/keyboard/)) - [x] Any UI touched in this PR does not create any new axe failures (run axe in browser: [FF](https://addons.mozilla.org/en-US/firefox/addon/axe-devtools/), [Chrome](https://chrome.google.com/webstore/detail/axe-web-accessibility-tes/lhdoppojpmngadmnindnejefpokejbdd?hl=en-US)) - [x] This renders correctly on smaller devices using a responsive layout. (You can test this [in your browser](https://www.browserstack.com/guide/responsive-testing-on-local-server)) - [x] This was checked for [cross-browser compatibility](https://www.elastic.co/support/matrix#matrix_browsers)
Summary
Part of #165958
Replaces usage of the deprecated
alertFactory
with the new alerts client and adds alerts-as-data integration for Anomaly Detection alerting rule type.Alert instances are stored in
.alerts-ml.anomaly-detection.alerts-default
index and extends the commonAlertSchema
.Result mappings
Checklist