[ML] Explain Log Rate Spikes: Add link to Discover to grouped results table. (#141071)

Adds link to Discover to grouped results table.
This commit is contained in:
Walter Rafelsberger 2022-09-20 22:46:38 +02:00 committed by GitHub
parent 348b7158f9
commit 841b9300a7
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 157 additions and 11 deletions

View file

@ -134,6 +134,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
defaultMessage: 'Field name',
}),
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisTableColumnFieldValue',
@ -143,6 +144,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
}),
render: (_, { fieldValue }) => String(fieldValue).slice(0, 50),
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisTableColumnLogRate',
@ -176,6 +178,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
/>
),
sortable: false,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisTableColumnDocCount',
@ -185,6 +188,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
defaultMessage: 'Doc count',
}),
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisTableColumnPValue',
@ -212,6 +216,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
),
render: (pValue: number | null) => pValue?.toPrecision(3) ?? NOT_AVAILABLE,
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisTableColumnImpact',
@ -242,6 +247,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
return label ? <EuiBadge color={label.color}>{label.impact}</EuiBadge> : null;
},
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiOpsSpikeAnalysisTableColumnAction',
@ -267,6 +273,7 @@ export const SpikeAnalysisTable: FC<SpikeAnalysisTableProps> = ({
},
],
width: ACTIONS_COLUMN_WIDTH,
valign: 'top',
},
];

View file

@ -22,29 +22,40 @@ import {
} from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { escapeKuery } from '@kbn/es-query';
import { FormattedMessage } from '@kbn/i18n-react';
import type { ChangePoint } from '@kbn/ml-agg-utils';
import { SEARCH_QUERY_LANGUAGE } from '../../application/utils/search_utils';
import { useEuiTheme } from '../../hooks/use_eui_theme';
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
import { MiniHistogram } from '../mini_histogram';
import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transactions_correlation_impact_label';
import { SpikeAnalysisTable } from './spike_analysis_table';
const NARROW_COLUMN_WIDTH = '120px';
const EXPAND_COLUMN_WIDTH = '40px';
const ACTIONS_COLUMN_WIDTH = '60px';
const NOT_AVAILABLE = '--';
const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50];
const DEFAULT_SORT_FIELD = 'pValue';
const DEFAULT_SORT_DIRECTION = 'asc';
const viewInDiscoverMessage = i18n.translate(
'xpack.aiops.spikeAnalysisTable.linksMenu.viewInDiscover',
{
defaultMessage: 'View in Discover',
}
);
interface GroupTableItem {
id: string;
docCount: number;
pValue: number | null;
group: Record<string, any>;
repeatedValues: Record<string, any>;
group: Record<string, string | number>;
repeatedValues: Record<string, string | number>;
histogram: ChangePoint['histogram'];
}
@ -118,6 +129,71 @@ export const SpikeAnalysisGroupsTable: FC<SpikeAnalysisTableProps> = ({
setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues);
};
const { application, share, data } = useAiopsAppContext();
const discoverLocator = useMemo(
() => share.url.locators.get('DISCOVER_APP_LOCATOR'),
[share.url.locators]
);
const discoverUrlError = useMemo(() => {
if (!application.capabilities.discover?.show) {
const discoverNotEnabled = i18n.translate(
'xpack.aiops.spikeAnalysisTable.discoverNotEnabledErrorMessage',
{
defaultMessage: 'Discover is not enabled',
}
);
return discoverNotEnabled;
}
if (!discoverLocator) {
const discoverLocatorMissing = i18n.translate(
'xpack.aiops.spikeAnalysisTable.discoverLocatorMissingErrorMessage',
{
defaultMessage: 'No locator for Discover detected',
}
);
return discoverLocatorMissing;
}
if (!dataViewId) {
const autoGeneratedDiscoverLinkError = i18n.translate(
'xpack.aiops.spikeAnalysisTable.autoGeneratedDiscoverLinkErrorMessage',
{
defaultMessage: 'Unable to link to Discover; no data view exists for this index',
}
);
return autoGeneratedDiscoverLinkError;
}
}, [application.capabilities.discover?.show, dataViewId, discoverLocator]);
const generateDiscoverUrl = async (groupTableItem: GroupTableItem) => {
if (discoverLocator !== undefined) {
const url = await discoverLocator.getRedirectUrl({
indexPatternId: dataViewId,
timeRange: data.query.timefilter.timefilter.getTime(),
filters: data.query.filterManager.getFilters(),
query: {
language: SEARCH_QUERY_LANGUAGE.KUERY,
query: [
...Object.entries(groupTableItem.group).map(
([fieldName, fieldValue]) =>
`${escapeKuery(fieldName)}:${escapeKuery(String(fieldValue))}`
),
...Object.entries(groupTableItem.repeatedValues).map(
([fieldName, fieldValue]) =>
`${escapeKuery(fieldName)}:${escapeKuery(String(fieldValue))}`
),
].join(' AND '),
},
});
return url;
}
};
const columns: Array<EuiBasicTableColumn<GroupTableItem>> = [
{
align: RIGHT_ALIGNMENT,
@ -150,6 +226,7 @@ export const SpikeAnalysisGroupsTable: FC<SpikeAnalysisTableProps> = ({
iconType={itemIdToExpandedRowMap[item.id] ? 'arrowUp' : 'arrowDown'}
/>
),
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnGroup',
@ -200,6 +277,7 @@ export const SpikeAnalysisGroupsTable: FC<SpikeAnalysisTableProps> = ({
},
sortable: false,
textOnly: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnLogRate',
@ -229,11 +307,26 @@ export const SpikeAnalysisGroupsTable: FC<SpikeAnalysisTableProps> = ({
<MiniHistogram
chartData={histogram}
isLoading={loading && histogram === undefined}
label="Group x"
label={i18n.translate(
'xpack.aiops.explainLogRateSpikes.spikeAnalysisTableGroups.groupLabel',
{
defaultMessage: 'Group',
}
)}
/>
),
sortable: false,
},
{
'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnDocCount',
width: NARROW_COLUMN_WIDTH,
field: 'docCount',
name: i18n.translate('xpack.aiops.correlations.spikeAnalysisTableGroups.docCountLabel', {
defaultMessage: 'Doc count',
}),
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnPValue',
width: NARROW_COLUMN_WIDTH,
@ -260,18 +353,64 @@ export const SpikeAnalysisGroupsTable: FC<SpikeAnalysisTableProps> = ({
),
render: (pValue: number | null) => pValue?.toPrecision(3) ?? NOT_AVAILABLE,
sortable: true,
valign: 'top',
},
{
'data-test-subj': 'aiopsSpikeAnalysisGroupsTableColumnDocCount',
field: 'docCount',
name: i18n.translate(
'xpack.aiops.explainLogRateSpikes.spikeAnalysisTableGroups.docCountLabel',
{
defaultMessage: 'Doc count',
}
'data-test-subj': 'aiopsSpikeAnalysisTableColumnImpact',
width: NARROW_COLUMN_WIDTH,
field: 'pValue',
name: (
<EuiToolTip
position="top"
content={i18n.translate(
'xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.impactLabelColumnTooltip',
{
defaultMessage: 'The level of impact of the field on the message rate difference',
}
)}
>
<>
<FormattedMessage
id="xpack.aiops.explainLogRateSpikes.spikeAnalysisTable.impactLabel"
defaultMessage="Impact"
/>
<EuiIcon size="s" color="subdued" type="questionInCircle" className="eui-alignTop" />
</>
</EuiToolTip>
),
render: (_, { pValue }) => {
if (!pValue) return NOT_AVAILABLE;
const label = getFailedTransactionsCorrelationImpactLabel(pValue);
return label ? <EuiBadge color={label.color}>{label.impact}</EuiBadge> : null;
},
sortable: true,
width: '20%',
valign: 'top',
},
{
'data-test-subj': 'aiOpsSpikeAnalysisTableColumnAction',
name: i18n.translate('xpack.aiops.spikeAnalysisTable.actionsColumnName', {
defaultMessage: 'Actions',
}),
actions: [
{
name: () => (
<EuiToolTip content={discoverUrlError ? discoverUrlError : viewInDiscoverMessage}>
<EuiIcon type="discoverApp" />
</EuiToolTip>
),
description: viewInDiscoverMessage,
type: 'button',
onClick: async (tableItem) => {
const openInDiscoverUrl = await generateDiscoverUrl(tableItem);
if (typeof openInDiscoverUrl === 'string') {
await application.navigateToUrl(openInDiscoverUrl);
}
},
enabled: () => discoverUrlError === undefined,
},
],
width: ACTIONS_COLUMN_WIDTH,
valign: 'top',
},
];