Skip to content

Commit

Permalink
add O11y AI Assistant contextual insight to AIOps Log Rate Analysis p…
Browse files Browse the repository at this point in the history
…age.
  • Loading branch information
walterra committed Jun 20, 2024
1 parent d9fc2ca commit a897ede
Show file tree
Hide file tree
Showing 10 changed files with 140 additions and 8 deletions.
1 change: 1 addition & 0 deletions x-pack/plugins/aiops/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
],
"optionalPlugins": [
"cases",
"observabilityAIAssistant",
"usageCollection"
],
"requiredBundles": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@
*/

import type { FC } from 'react';
import React, { useCallback, useEffect, useState } from 'react';
import { isEqual } from 'lodash';
import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { isEqual, orderBy } from 'lodash';

import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { EuiFlexGroup, EuiFlexItem, EuiPageBody, EuiPageSection, EuiSpacer } from '@elastic/eui';

import { i18n } from '@kbn/i18n';
import type { Message } from '@kbn/observability-ai-assistant-plugin/public';
import type { Filter, Query } from '@kbn/es-query';
import { FilterStateStore } from '@kbn/es-query';
import { useUrlState, usePageUrlState } from '@kbn/ml-url-state';
Expand All @@ -25,6 +27,10 @@ import {
setInitialAnalysisStart,
setDocumentCountChartData,
} from '@kbn/aiops-log-rate-analysis/state';
import {
LOG_RATE_ANALYSIS_TYPE,
type LogRateAnalysisType,
} from '@kbn/aiops-log-rate-analysis/log_rate_analysis_type';

import { useDataSource } from '../../hooks/use_data_source';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
Expand All @@ -40,10 +46,20 @@ import {
import { SearchPanel } from '../search_panel';
import { PageHeader } from '../page_header';

import type { LogRateAnalysisResultsData } from './log_rate_analysis_results';

import { LogRateAnalysisContent } from './log_rate_analysis_content/log_rate_analysis_content';

interface SignificantFieldValue {
field: string;
value: string | number;
docCount: number;
pValue: number | null;
}

export const LogRateAnalysisPage: FC = () => {
const { data: dataService } = useAiopsAppContext();
const aiopsAppContext = useAiopsAppContext();
const { data: dataService, observabilityAIAssistant } = aiopsAppContext;
const { dataView, savedSearch } = useDataSource();

const currentSelectedGroup = useCurrentSelectedGroup();
Expand All @@ -58,6 +74,15 @@ export const LogRateAnalysisPage: FC = () => {

const [selectedSavedSearch, setSelectedSavedSearch] = useState(savedSearch);

// Used to store analysis results to be passed on to the AI Assistant.
const [logRateAnalysisParams, setLogRateAnalysisParams] = useState<
| {
logRateAnalysisType: LogRateAnalysisType;
significantFieldValues: SignificantFieldValue[];
}
| undefined
>();

useEffect(() => {
if (savedSearch) {
setSelectedSavedSearch(savedSearch);
Expand Down Expand Up @@ -182,6 +207,88 @@ export const LogRateAnalysisPage: FC = () => {
}
};

const onAnalysisCompleted = (analysisResults: LogRateAnalysisResultsData | undefined) => {
const significantFieldValues = orderBy(
analysisResults?.significantItems?.map((item) => ({
field: item.fieldName,
value: item.fieldValue,
docCount: item.doc_count,
pValue: item.pValue,
})),
['pValue', 'docCount'],
['asc', 'asc']
).slice(0, 50);

const logRateAnalysisType = analysisResults?.analysisType;
setLogRateAnalysisParams(
significantFieldValues && logRateAnalysisType
? { logRateAnalysisType, significantFieldValues }
: undefined
);
};

const messages = useMemo<Message[] | undefined>(() => {
const hasLogRateAnalysisParams =
logRateAnalysisParams && logRateAnalysisParams.significantFieldValues?.length > 0;

if (!hasLogRateAnalysisParams || !observabilityAIAssistant) {
return undefined;
}

const { logRateAnalysisType } = logRateAnalysisParams;

const header = 'Field name,Field value,Doc count,p-value';
const rows = logRateAnalysisParams.significantFieldValues
.map((item) => Object.values(item).join(','))
.join('\n');

return observabilityAIAssistant.getContextualInsightMessages({
message:
'Can you identify possible causes and remediations for these log rate analysis results',
instructions: `You are an AIOps expert using Elastic's Kibana on call being consulted about a log rate change that got triggered by a ${logRateAnalysisType} in log messages. Your job is to take immediate action and proceed with both urgency and precision.
"Log Rate Analysis" is an AIOps feature that uses advanced statistical methods to identify reasons for increases and decreases in log rates. It makes it easy to find and investigate causes of unusual spikes or dips by using the analysis workflow view.
You are using "Log Rate Analysis" and ran the statistical analysis on the log messages which occured during the alert.
You received the following analysis results from "Log Rate Analysis" which list statistically significant co-occuring field/value combinations sorted from most significant (lower p-values) to least significant (higher p-values) that ${
logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE
? 'contribute to the log rate spike'
: 'are less or not present in the log rate dip'
}:
${
logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE
? 'The median log rate in the selected deviation time range is higher than the baseline. Therefore, the results shows statistically significant items within the deviation time range that are contributors to the spike. The "doc count" column refers to the amount of documents in the deviation time range.'
: 'The median log rate in the selected deviation time range is lower than the baseline. Therefore, the analysis results table shows statistically significant items within the baseline time range that are less in number or missing within the deviation time range. The "doc count" column refers to the amount of documents in the baseline time range.'
}
${header}
${rows}
Based on the above analysis results and your observability expert knowledge, output the following:
Analyse the type of these logs and explain their usual purpose (1 paragraph).
${
logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE
? 'Based on the type of these logs do a root cause analysis on why the field and value combinations from the analysis results are causing this log rate spike (2 parapraphs)'
: 'Based on the type of these logs explain why the statistically significant field and value combinations are less in number or missing from the log rate dip with concrete examples based on the analysis results data which contains items that are present in the baseline time range and are missing or less in number in the deviation time range (2 paragraphs)'
}.
${
logRateAnalysisType === LOG_RATE_ANALYSIS_TYPE.SPIKE
? 'Recommend concrete remediations to resolve the root cause (3 bullet points).'
: ''
}
Do not mention individual p-values from the analysis results.
Do not repeat the full list of field names and field values back to the user.
Do not repeat the given instructions in your output.`,
});
}, [logRateAnalysisParams, observabilityAIAssistant]);

const logRateAnalysisTitle = i18n.translate(
'xpack.infra.logs.alertDetails.logRateAnalysisTitle',
{
defaultMessage: 'Possible causes and remediations',
}
);

return (
<EuiPageBody data-test-subj="aiopsLogRateAnalysisPage" paddingSize="none" panelled={false}>
<PageHeader />
Expand All @@ -196,11 +303,22 @@ export const LogRateAnalysisPage: FC = () => {
setSearchParams={setSearchParams}
/>
</EuiFlexItem>
<LogRateAnalysisContent
embeddingOrigin={AIOPS_TELEMETRY_ID.AIOPS_DEFAULT_SOURCE}
esSearchQuery={searchQuery}
onWindowParametersChange={onWindowParametersHandler}
/>
<EuiFlexItem>
<LogRateAnalysisContent
embeddingOrigin={AIOPS_TELEMETRY_ID.AIOPS_DEFAULT_SOURCE}
esSearchQuery={searchQuery}
onWindowParametersChange={onWindowParametersHandler}
onAnalysisCompleted={onAnalysisCompleted}
/>
</EuiFlexItem>
{observabilityAIAssistant?.ObservabilityAIAssistantContextualInsight && messages ? (
<EuiFlexItem grow={false}>
<observabilityAIAssistant.ObservabilityAIAssistantContextualInsight
title={logRateAnalysisTitle}
messages={messages}
/>
</EuiFlexItem>
) : null}
</EuiFlexGroup>
</EuiPageSection>
</EuiPageBody>
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/aiops/public/hooks/use_aiops_app_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import { createContext, type FC, type PropsWithChildren, useContext } from 'react';

import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public';
import type { IStorageWrapper } from '@kbn/kibana-utils-plugin/public';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
Expand Down Expand Up @@ -134,6 +135,8 @@ export interface AiopsAppDependencies {
isServerless?: boolean;
/** Identifier to indicate the plugin utilizing the component */
embeddingOrigin?: string;
/** Observability AI Assistant */
observabilityAIAssistant?: ObservabilityAIAssistantPublicStart;
}

/**
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/aiops/public/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public';
import type { ChartsPluginStart } from '@kbn/charts-plugin/public';
import type { ExecutionContextStart } from '@kbn/core-execution-context-browser';
import type { DataPublicPluginStart } from '@kbn/data-plugin/public';
Expand Down Expand Up @@ -43,6 +44,7 @@ export interface AiopsPluginStartDeps {
licensing: LicensingPluginStart;
executionContext: ExecutionContextStart;
embeddable: EmbeddableStart;
observabilityAIAssistant?: ObservabilityAIAssistantPublicStart;
usageCollection: UsageCollectionSetup;
}

Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/aiops/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@
"@kbn/unified-search-plugin",
"@kbn/usage-collection-plugin",
"@kbn/utility-types",
"@kbn/observability-ai-assistant-plugin",
],
"exclude": [
"target/**/*",
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ml/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
"maps",
"security",
"spaces",
"observabilityAIAssistant",
"usageCollection",
"cases"
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export const LogRateAnalysisPage: FC = () => {
'uiActions',
'uiSettings',
'unifiedSearch',
'observabilityAIAssistant',
])}
/>
)}
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ml/public/application/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ const App: FC<AppProps> = ({
lens: deps.lens,
licenseManagement: deps.licenseManagement,
maps: deps.maps,
observabilityAIAssistant: deps.observabilityAIAssistant,
presentationUtil: deps.presentationUtil,
savedObjectsManagement: deps.savedObjectsManagement,
savedSearch: deps.savedSearch,
Expand Down
3 changes: 3 additions & 0 deletions x-pack/plugins/ml/public/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import type {
import { BehaviorSubject, mergeMap } from 'rxjs';
import { take } from 'rxjs';

import type { ObservabilityAIAssistantPublicStart } from '@kbn/observability-ai-assistant-plugin/public';
import type { UnifiedSearchPublicPluginStart } from '@kbn/unified-search-plugin/public';
import type { ManagementSetup } from '@kbn/management-plugin/public';
import type { LocatorPublic, SharePluginSetup, SharePluginStart } from '@kbn/share-plugin/public';
Expand Down Expand Up @@ -88,6 +89,7 @@ export interface MlStartDependencies {
lens: LensPublicStart;
licensing: LicensingPluginStart;
maps?: MapsStartApi;
observabilityAIAssistant?: ObservabilityAIAssistantPublicStart;
presentationUtil: PresentationUtilPluginStart;
savedObjectsManagement: SavedObjectsManagementPluginStart;
savedSearch: SavedSearchPublicPluginStart;
Expand Down Expand Up @@ -180,6 +182,7 @@ export class MlPlugin implements Plugin<MlPluginSetup, MlPluginStart> {
licensing: pluginsStart.licensing,
management: pluginsSetup.management,
maps: pluginsStart.maps,
observabilityAIAssistant: pluginsStart.observabilityAIAssistant,
presentationUtil: pluginsStart.presentationUtil,
savedObjectsManagement: pluginsStart.savedObjectsManagement,
savedSearch: pluginsStart.savedSearch,
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/ml/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -127,5 +127,6 @@
"@kbn/react-kibana-context-render",
"@kbn/esql-utils",
"@kbn/core-lifecycle-browser",
"@kbn/observability-ai-assistant-plugin",
],
}

0 comments on commit a897ede

Please sign in to comment.