mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[ML] AIOps Fixing field aliases in pattern analysis (#176586)
This commit is contained in:
parent
2d36a14de9
commit
d809be71f0
6 changed files with 60 additions and 20 deletions
|
@ -50,7 +50,12 @@ export function processCategoryResults(
|
|||
regex: b.regex,
|
||||
};
|
||||
});
|
||||
|
||||
// check the first category for examples to determine if examples are available
|
||||
const hasExamples = categories[0]?.examples.some((e) => e !== undefined);
|
||||
|
||||
return {
|
||||
categories,
|
||||
hasExamples,
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,6 +15,8 @@ import {
|
|||
EuiHorizontalRule,
|
||||
EuiSpacer,
|
||||
EuiButtonIcon,
|
||||
EuiToolTip,
|
||||
EuiIcon,
|
||||
} from '@elastic/eui';
|
||||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
|
@ -42,7 +44,7 @@ import type { EventRate } from '../use_categorize_request';
|
|||
import { getLabels } from './labels';
|
||||
import { TableHeader } from './table_header';
|
||||
import { ExpandedRow } from './expanded_row';
|
||||
import { FormattedPatternExamples } from '../format_category';
|
||||
import { FormattedPatternExamples, FormattedTokens } from '../format_category';
|
||||
|
||||
interface Props {
|
||||
categories: Category[];
|
||||
|
@ -60,6 +62,7 @@ interface Props {
|
|||
enableRowActions?: boolean;
|
||||
additionalFilter?: CategorizationAdditionalFilter;
|
||||
navigateToDiscover?: boolean;
|
||||
displayExamples?: boolean;
|
||||
}
|
||||
|
||||
export const CategoryTable: FC<Props> = ({
|
||||
|
@ -78,6 +81,7 @@ export const CategoryTable: FC<Props> = ({
|
|||
enableRowActions = true,
|
||||
additionalFilter,
|
||||
navigateToDiscover = true,
|
||||
displayExamples = true,
|
||||
}) => {
|
||||
const euiTheme = useEuiTheme();
|
||||
const primaryBackgroundColor = useEuiBackgroundColor('primary');
|
||||
|
@ -142,11 +146,13 @@ export const CategoryTable: FC<Props> = ({
|
|||
if (itemIdToExpandedRowMapValues[category.key]) {
|
||||
delete itemIdToExpandedRowMapValues[category.key];
|
||||
} else {
|
||||
itemIdToExpandedRowMapValues[category.key] = <ExpandedRow category={category} />;
|
||||
itemIdToExpandedRowMapValues[category.key] = (
|
||||
<ExpandedRow category={category} displayExamples={displayExamples} />
|
||||
);
|
||||
}
|
||||
setItemIdToExpandedRowMap(itemIdToExpandedRowMapValues);
|
||||
},
|
||||
[itemIdToExpandedRowMap]
|
||||
[displayExamples, itemIdToExpandedRowMap]
|
||||
);
|
||||
|
||||
const columns: Array<EuiBasicTableColumn<Category>> = [
|
||||
|
@ -185,11 +191,7 @@ export const CategoryTable: FC<Props> = ({
|
|||
defaultMessage: 'Examples',
|
||||
}),
|
||||
sortable: true,
|
||||
render: (item: Category) => (
|
||||
<>
|
||||
<FormattedPatternExamples category={item} count={1} />
|
||||
</>
|
||||
),
|
||||
render: (item: Category) => <FormattedPatternExamples category={item} count={1} />,
|
||||
},
|
||||
{
|
||||
name: i18n.translate('xpack.aiops.logCategorization.column.actions', {
|
||||
|
@ -218,6 +220,29 @@ export const CategoryTable: FC<Props> = ({
|
|||
},
|
||||
] as Array<EuiBasicTableColumn<Category>>;
|
||||
|
||||
if (displayExamples === false) {
|
||||
// on the rare occasion that examples are not available, replace the examples column with tokens
|
||||
columns.splice(2, 1, {
|
||||
name: (
|
||||
<EuiToolTip
|
||||
position="top"
|
||||
content={i18n.translate('xpack.aiops.logCategorization.column.tokens.tooltip', {
|
||||
defaultMessage:
|
||||
'If the selected field is an alias, example documents cannot be displayed. Showing pattern tokens instead.',
|
||||
})}
|
||||
>
|
||||
<>
|
||||
{i18n.translate('xpack.aiops.logCategorization.column.tokens', {
|
||||
defaultMessage: 'Tokens',
|
||||
})}
|
||||
<EuiIcon size="s" color="subdued" type="questionInCircle" className="eui-alignTop" />
|
||||
</>
|
||||
</EuiToolTip>
|
||||
),
|
||||
render: (item: Category) => <FormattedTokens category={item} count={1} />,
|
||||
});
|
||||
}
|
||||
|
||||
if (showSparkline === true) {
|
||||
columns.splice(2, 0, {
|
||||
field: 'sparkline',
|
||||
|
|
|
@ -15,9 +15,10 @@ import { FormattedPatternExamples, FormattedRegex, FormattedTokens } from '../fo
|
|||
|
||||
interface ExpandedRowProps {
|
||||
category: Category;
|
||||
displayExamples?: boolean;
|
||||
}
|
||||
|
||||
export const ExpandedRow: FC<ExpandedRowProps> = ({ category }) => {
|
||||
export const ExpandedRow: FC<ExpandedRowProps> = ({ category, displayExamples = true }) => {
|
||||
const { euiTheme } = useEuiTheme();
|
||||
const cssExpandedRow = css({
|
||||
marginRight: euiTheme.size.xxl,
|
||||
|
@ -44,13 +45,15 @@ export const ExpandedRow: FC<ExpandedRowProps> = ({ category }) => {
|
|||
<FormattedRegex category={category} />
|
||||
</Section>
|
||||
|
||||
<Section
|
||||
title={i18n.translate('xpack.aiops.logCategorization.expandedRow.title.examples', {
|
||||
defaultMessage: 'Examples',
|
||||
})}
|
||||
>
|
||||
<FormattedPatternExamples category={category} />
|
||||
</Section>
|
||||
{displayExamples ? (
|
||||
<Section
|
||||
title={i18n.translate('xpack.aiops.logCategorization.expandedRow.title.examples', {
|
||||
defaultMessage: 'Examples',
|
||||
})}
|
||||
>
|
||||
<FormattedPatternExamples category={category} />
|
||||
</Section>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -110,6 +110,7 @@ export const LogCategorizationFlyout: FC<LogCategorizationPageProps> = ({
|
|||
const [data, setData] = useState<{
|
||||
categories: Category[];
|
||||
categoriesInBucket: Category[] | null;
|
||||
displayExamples: boolean;
|
||||
} | null>(null);
|
||||
const [fieldValidationResult, setFieldValidationResult] = useState<FieldValidationResults | null>(
|
||||
null
|
||||
|
@ -191,7 +192,7 @@ export const LogCategorizationFlyout: FC<LogCategorizationPageProps> = ({
|
|||
|
||||
if (mounted.current === true) {
|
||||
setFieldValidationResult(validationResult);
|
||||
const { categories } = categorizationResult;
|
||||
const { categories, hasExamples } = categorizationResult;
|
||||
|
||||
const hasBucketCategories = categories.some((c) => c.subTimeRangeCount !== undefined);
|
||||
let categoriesInBucket: any | null = null;
|
||||
|
@ -210,6 +211,7 @@ export const LogCategorizationFlyout: FC<LogCategorizationPageProps> = ({
|
|||
setData({
|
||||
categories,
|
||||
categoriesInBucket,
|
||||
displayExamples: hasExamples,
|
||||
});
|
||||
|
||||
setShowTabs(hasBucketCategories);
|
||||
|
@ -388,6 +390,7 @@ export const LogCategorizationFlyout: FC<LogCategorizationPageProps> = ({
|
|||
<EuiSpacer size="s" />
|
||||
</>
|
||||
) : null}
|
||||
|
||||
<CategoryTable
|
||||
categories={
|
||||
selectedTab === SELECTED_TAB.BUCKET && data.categoriesInBucket !== null
|
||||
|
@ -412,6 +415,7 @@ export const LogCategorizationFlyout: FC<LogCategorizationPageProps> = ({
|
|||
: undefined
|
||||
}
|
||||
navigateToDiscover={additionalFilter !== undefined}
|
||||
displayExamples={data.displayExamples}
|
||||
/>
|
||||
</>
|
||||
) : null}
|
||||
|
|
|
@ -89,6 +89,7 @@ export const LogCategorizationPage: FC<LogCategorizationPageProps> = ({ embeddin
|
|||
const [pinnedCategory, setPinnedCategory] = useState<Category | null>(null);
|
||||
const [data, setData] = useState<{
|
||||
categories: Category[];
|
||||
displayExamples: boolean;
|
||||
} | null>(null);
|
||||
const [fieldValidationResult, setFieldValidationResult] = useState<FieldValidationResults | null>(
|
||||
null
|
||||
|
@ -212,6 +213,7 @@ export const LogCategorizationPage: FC<LogCategorizationPageProps> = ({ embeddin
|
|||
setFieldValidationResult(validationResult);
|
||||
setData({
|
||||
categories: categorizationResult.categories,
|
||||
displayExamples: categorizationResult.hasExamples,
|
||||
});
|
||||
} catch (error) {
|
||||
toasts.addError(error, {
|
||||
|
@ -401,6 +403,7 @@ export const LogCategorizationPage: FC<LogCategorizationPageProps> = ({ embeddin
|
|||
selectedCategory={selectedCategory}
|
||||
setSelectedCategory={setSelectedCategory}
|
||||
timefilter={timefilter}
|
||||
displayExamples={data.displayExamples}
|
||||
/>
|
||||
) : null}
|
||||
</EuiPageBody>
|
||||
|
|
|
@ -17,7 +17,7 @@ import {
|
|||
createCategoryRequest,
|
||||
} from '../../../common/api/log_categorization/create_category_request';
|
||||
import { processCategoryResults } from '../../../common/api/log_categorization/process_category_results';
|
||||
import type { Category, CatResponse } from '../../../common/api/log_categorization/types';
|
||||
import type { CatResponse } from '../../../common/api/log_categorization/types';
|
||||
|
||||
import { useAiopsAppContext } from '../../hooks/use_aiops_app_context';
|
||||
import {
|
||||
|
@ -71,7 +71,7 @@ export function useCategorizeRequest() {
|
|||
query: QueryDslQueryContainer,
|
||||
intervalMs?: number,
|
||||
additionalFilter?: CategorizationAdditionalFilter
|
||||
): Promise<{ categories: Category[] }> => {
|
||||
): Promise<ReturnType<typeof processCategoryResults>> => {
|
||||
const { wrap, unwrap } = randomSampler.createRandomSamplerWrapper();
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
|
@ -101,7 +101,7 @@ export function useCategorizeRequest() {
|
|||
},
|
||||
error: (error) => {
|
||||
if (error.name === 'AbortError') {
|
||||
return resolve({ categories: [] });
|
||||
return resolve({ categories: [], hasExamples: false });
|
||||
}
|
||||
reject(error);
|
||||
},
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue