Skip to content

Commit

Permalink
[ML] AIOps: UI action for Change Point Detection embeddable to open i…
Browse files Browse the repository at this point in the history
…n the ML app (elastic#176694)

## Summary

Closes elastic#161248 

Added a UI action to open change point detection in the AIOps labs.

<img width="1137" alt="image"
src="https://github.com/elastic/kibana/assets/5236598/077c0e34-0ac0-4790-8cbe-c6048ee90d22">

### 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)
- [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)
  • Loading branch information
darnautov authored and fkanout committed Mar 4, 2024
1 parent beaa289 commit 064a8b8
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 3 deletions.
3 changes: 2 additions & 1 deletion x-pack/plugins/aiops/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
"presentationUtil",
"dashboard",
"fieldFormats",
"unifiedSearch"
"unifiedSearch",
"share"
],
"optionalPlugins": [
"cases",
Expand Down
5 changes: 5 additions & 0 deletions x-pack/plugins/aiops/public/ui_actions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
} from '@kbn/ml-ui-actions/src/aiops/ui_actions';

import type { CoreStart } from '@kbn/core/public';
import { createOpenChangePointInMlAppAction } from './open_change_point_ml';
import type { AiopsPluginStartDeps } from '../types';
import { createEditChangePointChartsPanelAction } from './edit_change_point_charts_panel';
import { createCategorizeFieldAction } from '../components/log_categorization';
Expand All @@ -27,6 +28,8 @@ export function registerAiopsUiActions(
coreStart,
pluginStart
);
const openChangePointInMlAppAction = createOpenChangePointInMlAppAction(coreStart, pluginStart);

// // Register actions and triggers
uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, editChangePointChartPanelAction);

Expand All @@ -36,4 +39,6 @@ export function registerAiopsUiActions(
CATEGORIZE_FIELD_TRIGGER,
createCategorizeFieldAction(coreStart, pluginStart)
);

uiActions.addTriggerAction(CONTEXT_MENU_TRIGGER, openChangePointInMlAppAction);
}
58 changes: 58 additions & 0 deletions x-pack/plugins/aiops/public/ui_actions/open_change_point_ml.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/*
* 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 type { UiActionsActionDefinition } from '@kbn/ui-actions-plugin/public';
import { i18n } from '@kbn/i18n';
import type { CoreStart } from '@kbn/core/public';
import type { AiopsPluginStartDeps } from '../types';
import type { EditChangePointChartsPanelContext } from '../embeddable/types';
import { EMBEDDABLE_CHANGE_POINT_CHART_TYPE } from '../../common/constants';

export const OPEN_CHANGE_POINT_IN_ML_APP_ACTION = 'openChangePointInMlAppAction';

export function createOpenChangePointInMlAppAction(
coreStart: CoreStart,
pluginStart: AiopsPluginStartDeps
): UiActionsActionDefinition<EditChangePointChartsPanelContext> {
return {
id: 'open-change-point-in-ml-app',
type: OPEN_CHANGE_POINT_IN_ML_APP_ACTION,
getIconType(context): string {
return 'link';
},
getDisplayName: () =>
i18n.translate('xpack.aiops.actions.openChangePointInMlAppName', {
defaultMessage: 'Open in AIOps Labs',
}),
async getHref(context): Promise<string | undefined> {
const locator = pluginStart.share.url.locators.get('ML_APP_LOCATOR')!;

const { timeRange, metricField, fn, splitField, dataViewId } = context.embeddable.getInput();

return locator.getUrl({
page: 'aiops/change_point_detection',
pageState: {
index: dataViewId,
timeRange,
fieldConfigs: [{ fn, metricField, ...(splitField ? { splitField } : {}) }],
},
});
},
async execute(context) {
if (!context.embeddable) {
throw new Error('Not possible to execute an action without the embeddable context');
}
const aiopsChangePointUrl = await this.getHref!(context);
if (aiopsChangePointUrl) {
await coreStart.application.navigateToUrl(aiopsChangePointUrl!);
}
},
async isCompatible({ embeddable }) {
return embeddable.type === EMBEDDABLE_CHANGE_POINT_CHART_TYPE;
},
};
}
19 changes: 18 additions & 1 deletion x-pack/plugins/ml/common/types/locator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export interface ExplorerAppState {
query?: any;
mlShowCharts?: boolean;
}

export interface ExplorerGlobalState {
ml: { jobIds: JobId[] };
time?: TimeRange;
Expand Down Expand Up @@ -279,7 +280,8 @@ export type MlLocatorState =
| MlGenericUrlState
| NotificationsUrlState
| TrainedModelsUrlState
| MemoryUsageUrlState;
| MemoryUsageUrlState
| ChangePointDetectionUrlState;

export type MlLocatorParams = MlLocatorState & SerializableRecord;

Expand All @@ -303,3 +305,18 @@ export type NotificationsUrlState = MLPageState<
typeof ML_PAGES.NOTIFICATIONS,
NotificationsQueryState | undefined
>;

export interface ChangePointDetectionQueryState {
index: string;
timeRange?: TimeRange;
fieldConfigs: Array<{
fn: string;
splitField?: string;
metricField: string;
}>;
}

export type ChangePointDetectionUrlState = MLPageState<
typeof ML_PAGES.AIOPS_CHANGE_POINT_DETECTION,
ChangePointDetectionQueryState
>;
49 changes: 49 additions & 0 deletions x-pack/plugins/ml/public/locator/formatters/aiops.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* 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 { setStateToKbnUrl } from '@kbn/kibana-utils-plugin/public';
import { ML_PAGES } from '../../../common/constants/locator';
import type { ChangePointDetectionUrlState } from '../../../common/types/locator';

/**
* Creates URL to the Change Point Detection page
*/
export function formatChangePointDetectionUrl(
appBasePath: string,
params: ChangePointDetectionUrlState['pageState']
): string {
let url = `${appBasePath}/${ML_PAGES.AIOPS_CHANGE_POINT_DETECTION}`;

if (!params?.fieldConfigs) {
throw new Error('Field configs are required to create a change point detection URL');
}

if (!params.index) {
throw new Error('Data view is required to create a change point detection URL');
}

url = `${url}?index=${params.index}`;

const { timeRange, fieldConfigs } = params;

const appState = {
fieldConfigs,
};
const queryState = {
time: timeRange,
};

url = setStateToKbnUrl('_g', queryState, { useHash: false, storeInHashQuery: false }, url);
url = setStateToKbnUrl(
'_a',
{ changePoint: appState },
{ useHash: false, storeInHashQuery: false },
url
);

return url;
}
51 changes: 51 additions & 0 deletions x-pack/plugins/ml/public/locator/ml_locator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -340,5 +340,56 @@ describe('ML locator', () => {
});
});
});

describe('AIOps labs', () => {
it('should throw an error for invalid Change point detection page state', async () => {
await expect(
definition.getLocation({
page: ML_PAGES.AIOPS_CHANGE_POINT_DETECTION,
pageState: {
index: '123123',
},
})
).rejects.toThrow('Field configs are required to create a change point detection URL');

await expect(
definition.getLocation({
page: ML_PAGES.AIOPS_CHANGE_POINT_DETECTION,
pageState: {
fieldConfigs: [
{
fn: 'max',
metricField: 'CPUUtilization',
splitField: 'instance',
},
],
},
})
).rejects.toThrow('Data view is required to create a change point detection URL');
});

it('should generate valid URL for the Change point detection page', async () => {
const location = await definition.getLocation({
page: ML_PAGES.AIOPS_CHANGE_POINT_DETECTION,
pageState: {
index: 'test-index',
timeRange: { from: '2019-10-28T00:00:00.000Z', to: '2019-11-11T13:31:00.000Z' },
fieldConfigs: [
{
fn: 'max',
metricField: 'CPUUtilization',
splitField: 'instance',
},
],
},
});

expect(location).toMatchObject({
app: 'ml',
path: "/aiops/change_point_detection?index=test-index&_g=(time:(from:'2019-10-28T00:00:00.000Z',to:'2019-11-11T13:31:00.000Z'))&_a=(changePoint:(fieldConfigs:!((fn:max,metricField:CPUUtilization,splitField:instance))))",
state: {},
});
});
});
});
});
9 changes: 8 additions & 1 deletion x-pack/plugins/ml/public/locator/ml_locator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,13 @@
*/

import type { LocatorDefinition, KibanaLocation } from '@kbn/share-plugin/public';
import { formatChangePointDetectionUrl } from './formatters/aiops';
import { formatNotificationsUrl } from './formatters/notifications';
import {
DataFrameAnalyticsExplorationUrlState,
MlLocatorParams,
MlLocator,
ChangePointDetectionQueryState,
} from '../../common/types/locator';
import { ML_APP_LOCATOR, ML_PAGES } from '../../common/constants/locator';
import {
Expand Down Expand Up @@ -77,6 +79,12 @@ export class MlLocatorDefinition implements LocatorDefinition<MlLocatorParams> {
case ML_PAGES.MEMORY_USAGE:
path = formatMemoryUsageUrl('', params.pageState);
break;
case ML_PAGES.AIOPS_CHANGE_POINT_DETECTION:
path = formatChangePointDetectionUrl(
'',
params.pageState as ChangePointDetectionQueryState
);
break;
case ML_PAGES.DATA_DRIFT_INDEX_SELECT:
case ML_PAGES.DATA_DRIFT_CUSTOM:
case ML_PAGES.DATA_DRIFT:
Expand All @@ -96,7 +104,6 @@ export class MlLocatorDefinition implements LocatorDefinition<MlLocatorParams> {
case ML_PAGES.AIOPS_LOG_RATE_ANALYSIS_INDEX_SELECT:
case ML_PAGES.AIOPS_LOG_CATEGORIZATION:
case ML_PAGES.AIOPS_LOG_CATEGORIZATION_INDEX_SELECT:
case ML_PAGES.AIOPS_CHANGE_POINT_DETECTION:
case ML_PAGES.AIOPS_CHANGE_POINT_DETECTION_INDEX_SELECT:
case ML_PAGES.OVERVIEW:
case ML_PAGES.SETTINGS:
Expand Down

0 comments on commit 064a8b8

Please sign in to comment.