From 16ac8716421321af2f372a1ff67f4903329713bf Mon Sep 17 00:00:00 2001 From: Kevin Delemme Date: Wed, 2 Oct 2024 09:53:21 -0400 Subject: [PATCH] Add screen context to investigation details page --- .../investigation_details.tsx | 2 + .../pages/details/hooks/use_fetch_alert.tsx | 1 + .../details/hooks/use_screen_context.tsx | 91 +++++++++++++++++++ .../details/investigation_details_page.tsx | 2 +- .../investigate_app/public/types.ts | 6 ++ 5 files changed, 101 insertions(+), 1 deletion(-) create mode 100644 x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_screen_context.tsx diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx index c5f30795535b4..5d5c66a4554fb 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/components/investigation_details/investigation_details.tsx @@ -16,6 +16,7 @@ import { useInvestigation } from '../../contexts/investigation_context'; import { InvestigationHeader } from '../investigation_header/investigation_header'; import { InvestigationItems } from '../investigation_items/investigation_items'; import { InvestigationNotes } from '../investigation_notes/investigation_notes'; +import { useScreenContext } from '../../hooks/use_screen_context'; interface Props { user: AuthenticatedUser; @@ -30,6 +31,7 @@ export function InvestigationDetails({ user }: Props) { start: { observabilityShared }, }, } = useKibana(); + useScreenContext(); const ObservabilityPageTemplate = observabilityShared.navigation.PageTemplate; const { investigation } = useInvestigation(); diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_fetch_alert.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_fetch_alert.tsx index 85246b33bf70d..a64d333bcc9fa 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_fetch_alert.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_fetch_alert.tsx @@ -40,6 +40,7 @@ export function useFetchAlert({ id }: AlertParams): UseFetchAlertResponse { signal, }); }, + staleTime: 60 * 1000, refetchOnWindowFocus: false, onError: (error: Error) => { toasts.addError(error, { diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_screen_context.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_screen_context.tsx new file mode 100644 index 0000000000000..114fec3399958 --- /dev/null +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/hooks/use_screen_context.tsx @@ -0,0 +1,91 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { alertOriginSchema } from '@kbn/investigation-shared'; +import { ALERT_REASON, ALERT_START, ALERT_STATUS } from '@kbn/rule-data-utils'; +import type { EcsFieldsResponse } from '@kbn/rule-registry-plugin/common'; +import dedent from 'dedent'; +import { omit } from 'lodash'; +import { useEffect } from 'react'; +import { useKibana } from '../../../hooks/use_kibana'; +import { useInvestigation } from '../contexts/investigation_context'; +import { useFetchAlert } from './use_fetch_alert'; + +export function useScreenContext() { + const { + dependencies: { + start: { observabilityAIAssistant }, + }, + } = useKibana(); + + const { investigation } = useInvestigation(); + const alertOriginInvestigation = alertOriginSchema.safeParse(investigation?.origin); + const alertId = alertOriginInvestigation.success ? alertOriginInvestigation.data.id : undefined; + const { data: alertDetails } = useFetchAlert({ id: alertId }); + + useEffect(() => { + if (!investigation) { + return; + } + + observabilityAIAssistant.service.setScreenContext({ + screenDescription: dedent(` + The user is looking at the details of an investigation in order to understand the root cause of an issue. + The investigation details include the title, status, tags, and its time range. + + ${alertDetails ? getAlertDetailScreenContext(alertDetails) : ''} + + Title: ${investigation.title} + Tags: ${investigation.tags.join(', ')} + Status: ${investigation.status} + Start time: ${new Date(investigation.params.timeRange.from).toISOString()} + End time: ${new Date(investigation.params.timeRange.to).toISOString()} + `), + data: [ + { + name: 'investigation', + description: 'The investigation details, including metadata, notes and items.', + value: investigation, + }, + ], + }); + }, [observabilityAIAssistant, investigation, alertDetails]); +} + +function getAlertDetailScreenContext(alertDetail: EcsFieldsResponse) { + const alertState = alertDetail[ALERT_STATUS]; + const alertStarted = alertDetail[ALERT_START]; + + return dedent(`The investigation originates from an ${alertState} alert which started at ${alertStarted}. + + ${ + alertDetail[ALERT_REASON] + ? `The reason given for the alert is ${alertDetail[ALERT_REASON]}.` + : '' + } + + Use the following alert fields to understand the context of the alert: + ${Object.entries(getRelevantAlertFields(alertDetail)) + .map(([key, value]) => `${key}: ${JSON.stringify(value)}`) + .join('\n')} + `); +} + +function getRelevantAlertFields(alertDetail: EcsFieldsResponse) { + return omit(alertDetail.fields, [ + 'kibana.alert.rule.revision', + 'kibana.alert.rule.execution.uuid', + 'kibana.alert.flapping_history', + 'kibana.alert.uuid', + 'kibana.alert.rule.uuid', + 'event.action', + 'event.kind', + 'kibana.alert.rule.tags', + 'kibana.alert.maintenance_window_ids', + 'kibana.alert.consecutive_matches', + ]); +} diff --git a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx index 8eadd0de879bd..625664ca98183 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx +++ b/x-pack/plugins/observability_solution/investigate_app/public/pages/details/investigation_details_page.tsx @@ -13,8 +13,8 @@ import { InvestigationNotFound } from '../../components/investigation_not_found/ import { useFetchInvestigation } from '../../hooks/use_fetch_investigation'; import { useKibana } from '../../hooks/use_kibana'; import { InvestigationDetails } from './components/investigation_details/investigation_details'; -import { InvestigationDetailsPathParams } from './types'; import { InvestigationProvider } from './contexts/investigation_context'; +import { InvestigationDetailsPathParams } from './types'; export function InvestigationDetailsPage() { const { diff --git a/x-pack/plugins/observability_solution/investigate_app/public/types.ts b/x-pack/plugins/observability_solution/investigate_app/public/types.ts index 660a9ca9c8d1d..f3b81f3db7b25 100644 --- a/x-pack/plugins/observability_solution/investigate_app/public/types.ts +++ b/x-pack/plugins/observability_solution/investigate_app/public/types.ts @@ -27,6 +27,10 @@ import type { import type { SecurityPluginSetup, SecurityPluginStart } from '@kbn/security-plugin/public'; import type { UiActionsSetup, UiActionsStart } from '@kbn/ui-actions-plugin/public'; import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public'; +import type { + ObservabilityAIAssistantPublicSetup, + ObservabilityAIAssistantPublicStart, +} from '@kbn/observability-ai-assistant-plugin/public'; /* eslint-disable @typescript-eslint/no-empty-interface*/ @@ -46,6 +50,7 @@ export interface InvestigateAppSetupDependencies { unifiedSearch: {}; uiActions: UiActionsSetup; security: SecurityPluginSetup; + observabilityAIAssistant: ObservabilityAIAssistantPublicSetup; } export interface InvestigateAppStartDependencies { @@ -60,6 +65,7 @@ export interface InvestigateAppStartDependencies { unifiedSearch: UnifiedSearchPublicPluginStart; uiActions: UiActionsStart; security: SecurityPluginStart; + observabilityAIAssistant: ObservabilityAIAssistantPublicStart; } export interface InvestigateAppPublicSetup {}