mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[Infra] Add 'Show in Hosts list' button in for host anomaly drop-down (#191168)
Closes #174856 ## Summary This PR adds new 'Show affected Hosts' button in host anomaly drop-down in ML anomaly detection fly out. It applies `host.name` filer in hosts list and the same date range that user selected in ML fly out. ## Testing 1. Go to Inventory or Hosts page 2. Click ML anomaly detection button at the top 3. Select Anomaly tab from the fly out 4. Change date range to make sure it applies to Hosts page 5. Click three dots button (more actions) and click 'Show affected Hosts' 6. User is taken to Hosts page, `host.name` filters are applied to display relevant hosts and the same date range as in ML fly out is applied 
This commit is contained in:
parent
51a4cf92ea
commit
a48701029c
7 changed files with 103 additions and 17 deletions
|
@ -20,16 +20,14 @@ export const Anomalies = () => {
|
|||
const { isActiveTab } = useTabSwitcherContext();
|
||||
const { request$ } = useRequestObservable();
|
||||
const { getParsedDateRange } = useDatePickerContext();
|
||||
const { asset, overrides } = useAssetDetailsRenderPropsContext();
|
||||
const { asset } = useAssetDetailsRenderPropsContext();
|
||||
const { kibanaVersion, isCloudEnv, isServerlessEnv } = useContext(KibanaEnvironmentContext);
|
||||
const { onClose = () => {} } = overrides?.anomalies ?? {};
|
||||
|
||||
const parsedDateRange = useMemo(() => getParsedDateRange(), [getParsedDateRange]);
|
||||
|
||||
return (
|
||||
<div ref={ref}>
|
||||
<AnomaliesTable
|
||||
closeFlyout={onClose}
|
||||
hostName={asset.name}
|
||||
dateRange={parsedDateRange}
|
||||
hideDatePicker
|
||||
|
|
|
@ -35,9 +35,6 @@ export interface OverridableTabState {
|
|||
metadata?: {
|
||||
showActionsColumn?: boolean;
|
||||
};
|
||||
anomalies?: {
|
||||
onClose?: () => void;
|
||||
};
|
||||
alertRule?: {
|
||||
options?: Partial<Pick<InfraWaffleMapOptions, 'groupBy' | 'metric'>>;
|
||||
};
|
||||
|
|
|
@ -27,9 +27,13 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { FormattedMessage, FormattedDate } from '@kbn/i18n-react';
|
||||
import { useLinkProps, useUiTracker } from '@kbn/observability-shared-plugin/public';
|
||||
import type { TimeRange } from '@kbn/es-query';
|
||||
import type { Filter, TimeRange } from '@kbn/es-query';
|
||||
import { css } from '@emotion/react';
|
||||
import type { SnapshotMetricType } from '@kbn/metrics-data-access-plugin/common';
|
||||
import { type HostsLocatorParams, HOSTS_LOCATOR_ID } from '@kbn/observability-shared-plugin/common';
|
||||
import { HOST_NAME_FIELD } from '../../../../../common/constants';
|
||||
import { buildCombinedAssetFilter } from '../../../../utils/filters/build';
|
||||
import { useKibanaContextForPlugin } from '../../../../hooks/use_kibana';
|
||||
import { FetcherOptions } from '../../../../hooks/use_fetcher';
|
||||
import { datemathToEpochMillis } from '../../../../utils/datemath';
|
||||
import { useSorting } from '../../../../hooks/use_sorting';
|
||||
|
@ -43,7 +47,7 @@ import type {
|
|||
import { PaginationControls } from './pagination';
|
||||
import { AnomalySummary } from './annomaly_summary';
|
||||
import { AnomalySeverityIndicator } from '../../../logging/log_analysis_results/anomaly_severity_indicator';
|
||||
import { useSourceContext } from '../../../../containers/metrics_source';
|
||||
import { useMetricsDataViewContext, useSourceContext } from '../../../../containers/metrics_source';
|
||||
import { createResultsUrl } from '../flyout_home';
|
||||
import {
|
||||
useWaffleViewState,
|
||||
|
@ -66,19 +70,28 @@ const AnomalyActionMenu = ({
|
|||
influencerField,
|
||||
influencers,
|
||||
disableShowInInventory,
|
||||
hostName,
|
||||
timeRange,
|
||||
}: {
|
||||
jobId: string;
|
||||
type: string;
|
||||
startTime: number;
|
||||
closeFlyout: () => void;
|
||||
closeFlyout?: () => void;
|
||||
influencerField: string;
|
||||
influencers: string[];
|
||||
disableShowInInventory?: boolean;
|
||||
hostName?: string;
|
||||
timeRange: { start: string; end: string };
|
||||
}) => {
|
||||
const [isOpen, setIsOpen] = useState(false);
|
||||
const close = useCallback(() => setIsOpen(false), [setIsOpen]);
|
||||
const handleToggleMenu = useCallback(() => setIsOpen(!isOpen), [isOpen]);
|
||||
const { onViewChange } = useWaffleViewState();
|
||||
const { metricsView } = useMetricsDataViewContext();
|
||||
const {
|
||||
services: { share },
|
||||
} = useKibanaContextForPlugin();
|
||||
const hostsLocator = share.url.locators.get<HostsLocatorParams>(HOSTS_LOCATOR_ID);
|
||||
|
||||
const showInInventory = useCallback(() => {
|
||||
const metricTypeMap: { [key in Metric]: SnapshotMetricType } = {
|
||||
|
@ -116,7 +129,7 @@ const AnomalyActionMenu = ({
|
|||
time: startTime,
|
||||
};
|
||||
onViewChange({ attributes: anomalyViewParams });
|
||||
closeFlyout();
|
||||
if (closeFlyout) closeFlyout();
|
||||
}, [jobId, onViewChange, startTime, type, influencers, influencerField, closeFlyout]);
|
||||
|
||||
const anomaliesUrl = useLinkProps({
|
||||
|
@ -125,7 +138,12 @@ const AnomalyActionMenu = ({
|
|||
});
|
||||
|
||||
const items = [
|
||||
<EuiContextMenuItem key="openInAnomalyExplorer" icon="popout" {...anomaliesUrl}>
|
||||
<EuiContextMenuItem
|
||||
key="openInAnomalyExplorer"
|
||||
icon="popout"
|
||||
data-test-subj="infraAnomalyFlyoutOpenInAnomalyExplorer"
|
||||
{...anomaliesUrl}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.infra.ml.anomalyFlyout.actions.openInAnomalyExplorer"
|
||||
defaultMessage="Open in Anomaly Explorer"
|
||||
|
@ -134,13 +152,54 @@ const AnomalyActionMenu = ({
|
|||
];
|
||||
|
||||
if (!disableShowInInventory) {
|
||||
items.push(
|
||||
<EuiContextMenuItem key="showInInventory" icon="search" onClick={showInInventory}>
|
||||
const buildFilter = buildCombinedAssetFilter({
|
||||
field: HOST_NAME_FIELD,
|
||||
values: influencers,
|
||||
dataView: metricsView?.dataViewReference,
|
||||
});
|
||||
|
||||
let newFilter: Filter[] = [];
|
||||
if (!Array.isArray(buildFilter)) {
|
||||
newFilter = [buildFilter];
|
||||
}
|
||||
|
||||
const showInHostsItem = !hostName ? (
|
||||
<EuiContextMenuItem
|
||||
key="showAffectedHosts"
|
||||
icon="search"
|
||||
data-test-subj="infraAnomalyFlyoutShowAffectedHosts"
|
||||
href={hostsLocator?.getRedirectUrl({
|
||||
dateRange: {
|
||||
from: timeRange.start,
|
||||
to: timeRange.end,
|
||||
},
|
||||
filters: newFilter,
|
||||
})}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.infra.ml.anomalyFlyout.actions.showInInventory"
|
||||
defaultMessage="Show in Inventory"
|
||||
id="xpack.infra.ml.anomalyFlyout.actions.showAffectedHosts"
|
||||
defaultMessage="Show affected Hosts"
|
||||
/>
|
||||
</EuiContextMenuItem>
|
||||
) : (
|
||||
<></>
|
||||
);
|
||||
|
||||
items.push(
|
||||
influencerField === HOST_NAME_FIELD ? (
|
||||
showInHostsItem
|
||||
) : (
|
||||
<EuiContextMenuItem
|
||||
icon="search"
|
||||
data-test-subj="infraAnomalyFlyoutShowInInventory"
|
||||
onClick={showInInventory}
|
||||
>
|
||||
<FormattedMessage
|
||||
id="xpack.infra.ml.anomalyFlyout.actions.showInInventory"
|
||||
defaultMessage="Show in Inventory"
|
||||
/>
|
||||
</EuiContextMenuItem>
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -195,7 +254,7 @@ export const NoAnomaliesFound = () => {
|
|||
);
|
||||
};
|
||||
export interface Props {
|
||||
closeFlyout(): void;
|
||||
closeFlyout?(): void;
|
||||
hostName?: string;
|
||||
dateRange?: TimeRange;
|
||||
// In case the date picker is managed outside this component
|
||||
|
@ -440,6 +499,7 @@ export const AnomaliesTable = ({
|
|||
textOnly: true,
|
||||
truncateText: true,
|
||||
render: (influencers: string[]) => influencers.join(','),
|
||||
'data-test-subj': 'nodeNameRow',
|
||||
},
|
||||
{
|
||||
name: i18n.translate('xpack.infra.ml.anomalyFlyout.columnActionsName', {
|
||||
|
@ -460,6 +520,8 @@ export const AnomaliesTable = ({
|
|||
influencers={anomaly.influencers}
|
||||
startTime={anomaly.startTime}
|
||||
closeFlyout={closeFlyout}
|
||||
hostName={hostName}
|
||||
timeRange={timeRange}
|
||||
/>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -182,4 +182,5 @@ export {
|
|||
FlamegraphLocatorDefinition,
|
||||
StacktracesLocatorDefinition,
|
||||
TopNFunctionsLocatorDefinition,
|
||||
HOSTS_LOCATOR_ID,
|
||||
} from './locators';
|
||||
|
|
|
@ -36,7 +36,7 @@ export interface HostsLocatorParams extends SerializableRecord {
|
|||
};
|
||||
}
|
||||
|
||||
const HOSTS_LOCATOR_ID = 'HOSTS_LOCATOR';
|
||||
export const HOSTS_LOCATOR_ID = 'HOSTS_LOCATOR';
|
||||
const DEFAULT_HOST_LIMIT = 100;
|
||||
|
||||
export class HostsLocatorDefinition implements LocatorDefinition<HostsLocatorParams> {
|
||||
|
|
|
@ -15,6 +15,7 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const pageObjects = getPageObjects(['assetDetails', 'common', 'infraHome', 'infraHostsView']);
|
||||
const infraSourceConfigurationForm = getService('infraSourceConfigurationForm');
|
||||
const testSubjects = getService('testSubjects');
|
||||
const browser = getService('browser');
|
||||
|
||||
describe('Metrics UI Anomaly Flyout', function () {
|
||||
before(async () => {
|
||||
|
@ -135,6 +136,19 @@ export default ({ getPageObjects, getService }: FtrProviderContext) => {
|
|||
const k8sAnomalies = await pageObjects.infraHome.findAnomalies();
|
||||
expect(k8sAnomalies.length).to.be(3);
|
||||
});
|
||||
it("should take users to hosts list when 'Show affected Hosts' is clicked", async () => {
|
||||
await pageObjects.infraHome.goToInventory();
|
||||
await pageObjects.infraHome.openAnomalyFlyout();
|
||||
await pageObjects.infraHome.goToAnomaliesTab();
|
||||
await pageObjects.infraHome.clickHostsAnomaliesDropdown();
|
||||
await pageObjects.infraHome.setAnomaliesDate('Apr 21, 2021 @ 00:00:00.000');
|
||||
const hostName = await pageObjects.infraHome.getAnomalyHostName();
|
||||
await pageObjects.infraHome.clickShowAffectedHostsButton();
|
||||
const currentUrl = await browser.getCurrentUrl();
|
||||
expect(currentUrl).to.contain(
|
||||
encodeURIComponent(`query:(terms:(host.name:!(${hostName})))`)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -508,5 +508,19 @@ export function InfraHomePageProvider({ getService, getPageObjects }: FtrProvide
|
|||
const button = await testSubjects.find('infraModeSwitcherAddMetricButton');
|
||||
expect(await button.getAttribute('disabled')).to.be('true');
|
||||
},
|
||||
|
||||
async clickAnomalyActionMenuButton() {
|
||||
await testSubjects.click('infraAnomalyActionMenuButton');
|
||||
},
|
||||
|
||||
async clickShowAffectedHostsButton() {
|
||||
await this.clickAnomalyActionMenuButton();
|
||||
await testSubjects.click('infraAnomalyFlyoutShowAffectedHosts');
|
||||
},
|
||||
|
||||
async getAnomalyHostName() {
|
||||
const element = await testSubjects.find('nodeNameRow');
|
||||
return await element.getVisibleText();
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue