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

[Response Ops][Cases] Fetch alerts within observability #123883

Merged
merged 21 commits into from
Feb 11, 2022

Conversation

jonathan-buttner
Copy link
Contributor

@jonathan-buttner jonathan-buttner commented Jan 26, 2022

Fixes: #123755

This PR adds functionality to cases within observability to retrieve the alerts data so the rules links can be built in the event that the case comments does not have the information.

If the alert can't be found it will still mark the rule as Unknown.

image

Example working in observability

working obersvability rule details

Note

The alerts client returns the alert data in the form of collapsed fields "a.b.c" instead of it being nested. I removed the requirement for the useFetchAlertData to return Ecs because that will be misleading. Security solution has functionality that transforms the collapsed fields into nested fields by recursively iterating over the results. I'm open to doing that as well but we'd need to include those helper functions and I don't think it buys us much since we can just use lodash's get to access it as a collapsed field.

Example ES response
{
  "took": 2,
  "timed_out": false,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  },
  "hits": {
    "max_score": null,
    "hits": [
      {
        "_index": ".internal.alerts-observability.metrics.alerts-default-000001",
        "_id": "662aba44-d24f-47f9-8933-0e0f81cae6df",
        "_seq_no": 696,
        "_primary_term": 1,
        "_score": null,
        "_source": {
          "kibana.alert.rule.category": "Metric threshold",
          "kibana.alert.rule.consumer": "infrastructure",
          "kibana.alert.rule.execution.uuid": "40cc6f59-1101-45b1-81df-fdb47f87fcc4",
          "kibana.alert.rule.name": "Jon rule",
          "kibana.alert.rule.producer": "infrastructure",
          "kibana.alert.rule.rule_type_id": "metrics.alert.threshold",
          "kibana.alert.rule.uuid": "325830a0-7eba-11ec-a3b9-350ed5c64d7e",
          "kibana.space_ids": [
            "default"
          ],
          "kibana.alert.rule.tags": [],
          "@timestamp": "2022-01-26T22:37:20.409Z",
          "kibana.alert.reason": "Document count has reported no data over the past 1m for *",
          "kibana.alert.duration.us": 26767233000,
          "kibana.alert.instance.id": "*",
          "kibana.alert.start": "2022-01-26T15:11:13.176Z",
          "kibana.alert.uuid": "662aba44-d24f-47f9-8933-0e0f81cae6df",
          "kibana.alert.status": "active",
          "kibana.alert.workflow_status": "open",
          "event.kind": "signal",
          "event.action": "active",
          "kibana.version": "8.1.0",
          "tags": []
        },
        "fields": {
          "kibana.alert.rule.rule_type_id": [
            "metrics.alert.threshold"
          ],
          "kibana.alert.workflow_status": [
            "open"
          ],
          "kibana.space_ids": [
            "default"
          ],
          "kibana.alert.rule.consumer": [
            "infrastructure"
          ]
        },
        "sort": [
          1643236640409
        ]
      }
    ]
  }
}

Testing

To get an alert to show up in observability I typically navigate to the Metrics section in observability. Then at the top where it says Alerts -> Create -> Metrics and then use a Document Count is above 0. Then all you need to do is add some data and the rule should be active and show up under the Alerts tab.

Once you have that, grab the alert ID out of the comment and make a postman request with this body:

POST api/cases/<case id>/comments

{
    "alertId": [<add a valid alertId here>],
    "index": [".internal.alerts-observability.metrics.alerts-default-000001"],
    "rule": { "id": null, "name": null },
    "type": "alert",
    "owner": "observability"
}

The case should show two alerts that both have the rule name link created. Following the link should take you to the appropriate rule.

Release Notes

This fixes an issue where the rule's link in Cases within Observability were displayed as Unknown rule even when we could retrieve the correct rule name.

Before:
image

After:
image

@jonathan-buttner jonathan-buttner added release_note:fix Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) Feature:Cases Cases feature v8.1.0 v8.0.1 labels Jan 26, 2022
setAlert(parsedAlert);
setLoading(false);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we want to set loading to false when we're done, not only when we successfully get data?

}
};

if (!isEmpty(alertId) && loading === false && alert === null) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was running into rerender issues here as well when I added the abort signal, but removing these dependencies seemed to fix it. I don't think we want to rely on loading here because it'll change during the fetch.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you still want to check that is not loading or you can end up loading the same data twice.

@@ -6,3 +6,5 @@
*/

export type { CaseActionConnector } from '../../common/ui/types';

export type FetchAlertDataFunction = (alertIds: string[]) => [boolean, Record<string, unknown>];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be in common/ui instead?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeap it makes more sense to me. Also, I think it is better if we renamed it to UseFetchAlertData so we can understand that the type is about a React hook.

@jonathan-buttner jonathan-buttner marked this pull request as ready for review January 27, 2022 17:23
@jonathan-buttner jonathan-buttner requested a review from a team as a code owner January 27, 2022 17:23
@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops (Team:ResponseOps)

@elasticmachine
Copy link
Contributor

Pinging @elastic/response-ops-cases (Feature:Cases)

@jonathan-buttner
Copy link
Contributor Author

@elasticmachine merge upstream

const [loading, setLoading] = useState(false);
const [alerts, setAlerts] = useState<Record<string, unknown> | undefined>(undefined);

const fetch = useCallback(
Copy link
Contributor

@academo academo Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

alternatively you can write this fetch function out of the hook, accept parameters and returns a promise, then where you use it you await the promise and call setAlerts there.

@@ -52,7 +53,7 @@ export interface UserActionBuilderArgs {
selectedOutlineCommentId: string;
loadingCommentIds: string[];
loadingAlertData: boolean;
alertData: Record<string, Ecs>;
alertData: Record<string, unknown>;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is unknown really the best type here? is there a closer real type we can use for this? like a Record or a string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm open to other ideas, but I'm not quite sure what to do since security solution's implementation of this hook used to return an Ecs object with the fields broken done into nested objects like:

{
  kibana: {
    alert: "some value",
  }
}

Where as this function will return it as:

{
  "kibana.alert": "some value"
}

So the values could be object | string | string[] | number | number[] and potentially nested

By putting unknown I think we force the recipient to figure out what type the data is before they use it which might be safe.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's roll with this one and create an issue to work on a proper data type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will do, I'll create an issue

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Issue: #124048

import { BASE_RAC_ALERTS_API_PATH } from '../../../../rule_registry/common/constants';

export const useFetchAlertData = (alertIds: string[]): [boolean, Record<string, unknown>] => {
const { http } = useKibana().services;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tip: you can also use useHttp() it returns the http object directly.

Copy link
Contributor Author

@jonathan-buttner jonathan-buttner Jan 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you referring to this one? https://github.com/elastic/kibana/blob/main/x-pack/plugins/cases/public/common/lib/kibana/hooks.ts#L32

Doesn't look like I can access that while inside of observability, should I move the useHttp hook into cases/common?

image

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do not think you should move it to cases/common so other plugins can use it. useHttp is a cases helper for internal use and useKibana is more appropriate in other plugins (unless they have their own helpers).

@jonathan-buttner
Copy link
Contributor Author

@elasticmachine merge upstream

@kibanamachine kibanamachine requested a review from a team as a code owner January 30, 2022 16:35
@jonathan-buttner
Copy link
Contributor Author

@elasticmachine merge upstream

});

useEffect(() => {
fetch();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a way to do it but it adds extra complications that are not necessary.

You can start the fetch immediately inside useDataFetcher and invoke it here, have it return a promise and await for that promise here.

@jonathan-buttner
Copy link
Contributor Author

@elasticmachine merge upstream

@cnasikas
Copy link
Member

cnasikas commented Feb 7, 2022

@elasticmachine merge upstream

@cnasikas cnasikas added Feature:Grok Debugger Dev Tools Grok Debugger feature bug Fixes for quality problems that affect the customer experience and removed Feature:Grok Debugger Dev Tools Grok Debugger feature labels Feb 7, 2022
@academo
Copy link
Contributor

academo commented Feb 7, 2022

🐑🐑🐑

Copy link
Contributor

@angorayc angorayc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tested locally and LGTM

@jonathan-buttner
Copy link
Contributor Author

@elasticmachine merge upstream

@jonathan-buttner
Copy link
Contributor Author

@elasticmachine merge upstream

@kibana-ci
Copy link
Collaborator

💚 Build Succeeded

Metrics [docs]

Module Count

Fewer modules leads to a faster build time

id before after diff
observability 349 352 +3

Async chunks

Total size of all lazy-loaded chunks that will be downloaded as the user navigates the app

id before after diff
cases 294.8KB 294.8KB +42.0B
observability 392.6KB 393.6KB +1.0KB
total +1.1KB

History

To update your PR or re-run it, just comment with:
@elasticmachine merge upstream

@cnasikas cnasikas merged commit 30ed7bb into elastic:main Feb 11, 2022
@cnasikas cnasikas deleted the cases-obs-rule-link branch February 11, 2022 09:50
@cnasikas cnasikas added the auto-backport Deprecated - use backport:version if exact versions are needed label Feb 11, 2022
kibanamachine pushed a commit to kibanamachine/kibana that referenced this pull request Feb 11, 2022
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit 30ed7bb)
@kibanamachine
Copy link
Contributor

💔 Some backports could not be created

Status Branch Result
8.1
8.0 Backport failed because of merge conflicts

How to fix

Re-run the backport manually:

node scripts/backport --pr 123883

Note: Successful backport PRs will be merged automatically after passing CI.

Questions ?

Please refer to the Backport tool documentation

kibanamachine added a commit that referenced this pull request Feb 11, 2022
…25347)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit 30ed7bb)

Co-authored-by: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com>
cnasikas pushed a commit to cnasikas/kibana that referenced this pull request Feb 11, 2022
Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
(cherry picked from commit 30ed7bb)

# Conflicts:
#	x-pack/plugins/cases/README.md
#	x-pack/plugins/cases/public/components/app/types.ts
#	x-pack/plugins/cases/public/components/case_view/types.ts
#	x-pack/plugins/cases/public/components/user_actions/comment/alert.tsx
#	x-pack/plugins/cases/public/components/user_actions/index.test.tsx
#	x-pack/plugins/cases/public/components/user_actions/index.tsx
#	x-pack/plugins/cases/public/components/user_actions/types.ts
#	x-pack/plugins/observability/public/pages/cases/cases.tsx
#	x-pack/plugins/security_solution/public/cases/pages/use_fetch_alert_data.ts
cnasikas added a commit that referenced this pull request Feb 11, 2022
… (#125370)

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
Co-authored-by: Jonathan Buttner <56361221+jonathan-buttner@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
auto-backport Deprecated - use backport:version if exact versions are needed bug Fixes for quality problems that affect the customer experience Feature:Cases Cases feature release_note:fix Team:ResponseOps Label for the ResponseOps team (formerly the Cases and Alerting teams) v8.0.1 v8.1.0 v8.2.0
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Response Ops][Cases] Observability rules show Unknown after upgrading to 8.0
9 participants