Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ML] Replace APM error rate table with failed transactions correlations #108441

Merged
merged 26 commits into from Aug 17, 2021
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
63a10b8
[ML] Refactor with new table
qn895 Aug 12, 2021
0633e88
[ML] Fix types, rename var
qn895 Aug 13, 2021
43d7a85
[ML] Remove duplicate action columns
qn895 Aug 13, 2021
1ce425c
[ML] Finish renaming for consistency
qn895 Aug 13, 2021
cb61232
[ML] Add failure correlations help popover
qn895 Aug 13, 2021
1ca029d
[ML] Add failure correlations help popover
qn895 Aug 13, 2021
56e21dd
Merge upstream/main into branch
qn895 Aug 13, 2021
b25e6b6
[ML] Extend correlation help
lcawl Aug 13, 2021
b52b3e0
Merge branch 'ml-apm-failure-correlation-in-flyout' of https://github…
qn895 Aug 16, 2021
5e9d247
Update message
qn895 Aug 16, 2021
e70878c
[ML] Delete old legacy correlations pages
qn895 Aug 16, 2021
1554436
[ML] Address comments, rename
qn895 Aug 16, 2021
19b430f
Merge remote-tracking branch 'upstream/master' into ml-apm-failure-co…
qn895 Aug 16, 2021
5ceed16
[ML] Revert deletion of latency_correlations.tsx
qn895 Aug 16, 2021
c6940c1
[ML] Add unit test for getFailedTransactionsCorrelationImpactLabel
qn895 Aug 16, 2021
f4ecc66
[ML] Rename & fix types
qn895 Aug 16, 2021
b780c79
[ML] Fix logic to note include 0.02 threshold
qn895 Aug 16, 2021
014b5cd
Merge branch 'master' into ml-apm-failure-correlation-in-flyout
kibanamachine Aug 17, 2021
6bbb68c
[ML] Refactor to use state handler
qn895 Aug 17, 2021
ad490d2
Merge remote-tracking branch 'upstream/master' into ml-apm-failure-co…
qn895 Aug 17, 2021
bcec466
[ML] Fix hardcoded index, columns, popover
qn895 Aug 17, 2021
fb6bb05
Merge upstream/master into branch
qn895 Aug 17, 2021
caf5c29
[ML] Replace failed transaction tab
qn895 Aug 17, 2021
1af8288
[ML] Fix unused translations
qn895 Aug 17, 2021
d709dc1
[ML] Delete empty files
qn895 Aug 17, 2021
557a520
[ML] Move beta badge to be inside tab content
qn895 Aug 17, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -52,3 +52,8 @@ export interface AsyncSearchProviderProgress {
loadedFieldValuePairs: number;
loadedHistograms: number;
}

export interface SelectedSignificantTerm {
fieldName: string;
fieldValue: string;
}
@@ -0,0 +1,31 @@
/*
* 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 { i18n } from '@kbn/i18n';

export const FAILURE_CORRELATION_SEARCH_STRATEGY =
'apmFailureCorrelationsSearchStrategy';
export const FAILURE_CORRELATION_IMPACT_THRESHOLD = {
HIGH: i18n.translate(
'xpack.apm.correlations.failedTransactions.highImpactText',
{
defaultMessage: 'High',
}
),
MEDIUM: i18n.translate(
'xpack.apm.correlations.failedTransactions.mediumImpactText',
{
defaultMessage: 'Medium',
}
),
LOW: i18n.translate(
'xpack.apm.correlations.failedTransactions.lowImpactText',
{
defaultMessage: 'Low',
}
),
} as const;
@@ -0,0 +1,33 @@
/*
* 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 { FAILURE_CORRELATION_IMPACT_THRESHOLD } from './constants';

export interface FailureCorrelationValue {
key: string;
doc_count: number;
bg_count: number;
score: number;
pValue: number | null;
fieldName: string;
fieldValue: string;
}

export interface BaseSearchStrategyResponse {
took: number;
log: string[];
ccsWarning: boolean;
error?: Error;
isComplete: boolean;
isRunning: boolean;
progress: number;
timeTook: number;
startFetch: () => void;
cancelFetch: () => void;
}

export type FailureCorrelationImpactThreshold = typeof FAILURE_CORRELATION_IMPACT_THRESHOLD[keyof typeof FAILURE_CORRELATION_IMPACT_THRESHOLD];
Expand Up @@ -7,65 +7,47 @@

import React, { useCallback, useMemo, useState } from 'react';
import { debounce } from 'lodash';
import {
EuiIcon,
EuiLink,
EuiBasicTable,
EuiBasicTableColumn,
EuiToolTip,
} from '@elastic/eui';
import { EuiBasicTable, EuiBasicTableColumn } from '@elastic/eui';
import { i18n } from '@kbn/i18n';
import { useHistory } from 'react-router-dom';
import { asInteger, asPercent } from '../../../../common/utils/formatters';
import { APIReturnType } from '../../../services/rest/createCallApmApi';
import { FETCH_STATUS } from '../../../hooks/use_fetcher';
import { createHref, push } from '../../shared/Links/url_helpers';
import { ImpactBar } from '../../shared/ImpactBar';
import { useUiTracker } from '../../../../../observability/public';
import { useTheme } from '../../../hooks/use_theme';
import type { SelectedSignificantTerm } from '../../../../common/search_strategies/correlations/types';

export type { SelectedSignificantTerm };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this is necessary? Can the other places that use this type also import from common?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed here f4ecc66

const PAGINATION_SIZE_OPTIONS = [5, 10, 20, 50];
type CorrelationsApiResponse =
| APIReturnType<'GET /api/apm/correlations/errors/failed_transactions'>
| APIReturnType<'GET /api/apm/correlations/latency/slow_transactions'>;

export type SignificantTerm = CorrelationsApiResponse['significantTerms'][0];

export type SelectedSignificantTerm = Pick<
SignificantTerm,
'fieldName' | 'fieldValue'
>;
export type SelectedSignificantCorrelationTerm<
T extends SelectedSignificantTerm
> = Pick<T, 'fieldName' | 'fieldValue'>;

interface Props<T> {
significantTerms?: T[];
status: FETCH_STATUS;
percentageColumnName?: string;
setSelectedSignificantTerm: (term: SelectedSignificantTerm | null) => void;
setSelectedSignificantTerm: (term: T | null) => void;
selectedTerm?: { fieldName: string; fieldValue: string };
onFilter: () => void;
columns?: Array<EuiBasicTableColumn<T>>;
onFilter?: () => void;
columns: Array<EuiBasicTableColumn<T>>;
}

export function CorrelationsTable<T extends SignificantTerm>({
export function CorrelationsTable<T extends SelectedSignificantTerm>({
significantTerms,
status,
percentageColumnName,
setSelectedSignificantTerm,
onFilter,
columns,
selectedTerm,
}: Props<T>) {
const euiTheme = useTheme();
const trackApmEvent = useUiTracker({ app: 'apm' });
const trackSelectSignificantTerm = useCallback(
const trackSelectSignificantCorrelationTerm = useCallback(
() =>
debounce(
() => trackApmEvent({ metric: 'select_significant_term' }),
1000
),
[trackApmEvent]
);
const history = useHistory();

const [pageIndex, setPageIndex] = useState(0);
const [pageSize, setPageSize] = useState(10);
Expand All @@ -92,139 +74,7 @@ export function CorrelationsTable<T extends SignificantTerm>({
setPageSize(size);
}, []);

const tableColumns: Array<EuiBasicTableColumn<T>> = columns ?? [
{
width: '116px',
field: 'impact',
name: i18n.translate(
'xpack.apm.correlations.correlationsTable.impactLabel',
{ defaultMessage: 'Impact' }
),
render: (_: any, term: T) => {
return <ImpactBar size="m" value={term.impact * 100} />;
},
},
{
field: 'percentage',
name:
percentageColumnName ??
i18n.translate(
'xpack.apm.correlations.correlationsTable.percentageLabel',
{ defaultMessage: 'Percentage' }
),
render: (_: any, term: T) => {
return (
<EuiToolTip
position="right"
content={`${asInteger(term.valueCount)} / ${asInteger(
term.fieldCount
)}`}
>
<>{asPercent(term.valueCount, term.fieldCount)}</>
</EuiToolTip>
);
},
},
{
field: 'fieldName',
name: i18n.translate(
'xpack.apm.correlations.correlationsTable.fieldNameLabel',
{ defaultMessage: 'Field name' }
),
},
{
field: 'fieldValue',
name: i18n.translate(
'xpack.apm.correlations.correlationsTable.fieldValueLabel',
{ defaultMessage: 'Field value' }
),
render: (_: any, term: T) => String(term.fieldValue).slice(0, 50),
},
{
width: '100px',
actions: [
{
name: i18n.translate(
'xpack.apm.correlations.correlationsTable.filterLabel',
{ defaultMessage: 'Filter' }
),
description: i18n.translate(
'xpack.apm.correlations.correlationsTable.filterDescription',
{ defaultMessage: 'Filter by value' }
),
icon: 'plusInCircle',
type: 'icon',
onClick: (term: T) => {
push(history, {
query: {
kuery: `${term.fieldName}:"${encodeURIComponent(
term.fieldValue
)}"`,
},
});
onFilter();
trackApmEvent({ metric: 'correlations_term_include_filter' });
},
},
{
name: i18n.translate(
'xpack.apm.correlations.correlationsTable.excludeLabel',
{ defaultMessage: 'Exclude' }
),
description: i18n.translate(
'xpack.apm.correlations.correlationsTable.excludeDescription',
{ defaultMessage: 'Filter out value' }
),
icon: 'minusInCircle',
type: 'icon',
onClick: (term: T) => {
push(history, {
query: {
kuery: `not ${term.fieldName}:"${encodeURIComponent(
term.fieldValue
)}"`,
},
});
onFilter();
trackApmEvent({ metric: 'correlations_term_exclude_filter' });
},
},
],
name: i18n.translate(
'xpack.apm.correlations.correlationsTable.actionsLabel',
{ defaultMessage: 'Filter' }
),
render: (_: any, term: T) => {
return (
<>
<EuiLink
href={createHref(history, {
query: {
kuery: `${term.fieldName}:"${encodeURIComponent(
term.fieldValue
)}"`,
},
})}
>
<EuiIcon type="magnifyWithPlus" />
</EuiLink>
&nbsp;/&nbsp;
<EuiLink
href={createHref(history, {
query: {
kuery: `not ${term.fieldName}:"${encodeURIComponent(
term.fieldValue
)}"`,
},
})}
>
<EuiIcon type="magnifyWithMinus" />
</EuiLink>
</>
);
},
},
];
const tableColumns: Array<EuiBasicTableColumn<T>> = columns ?? [];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If columns is already a required prop with this type do we need this assignment or the ?? [] at all?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated here bcec466


return (
<EuiBasicTable
Expand All @@ -238,7 +88,7 @@ export function CorrelationsTable<T extends SignificantTerm>({
return {
onMouseEnter: () => {
setSelectedSignificantTerm(term);
trackSelectSignificantTerm();
trackSelectSignificantCorrelationTerm();
},
onMouseLeave: () => setSelectedSignificantTerm(null),
style:
Expand Down
Expand Up @@ -170,6 +170,7 @@ export function ErrorCorrelations({ onClose }: Props) {
'xpack.apm.correlations.error.percentageColumnName',
{ defaultMessage: '% of failed transactions' }
)}
// @ts-expect-error: this file to be removed
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe we can remove this file as part of this PR already?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Deleted here e70878c

significantTerms={
hasFieldNames && correlationsData?.significantTerms
? correlationsData.significantTerms
Expand Down
17 changes: 10 additions & 7 deletions x-pack/plugins/apm/public/components/app/correlations/index.tsx
Expand Up @@ -25,7 +25,6 @@ import {
import { i18n } from '@kbn/i18n';
import { useHistory } from 'react-router-dom';
import { MlLatencyCorrelations } from './ml_latency_correlations';
import { ErrorCorrelations } from './error_correlations';
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
import { createHref } from '../../shared/Links/url_helpers';
import {
Expand All @@ -50,13 +49,17 @@ import {
TRANSACTION_NAME,
} from '../../../../common/elasticsearch_fieldnames';
import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context';
import { MlFailureCorrelations } from './ml_failure_correlations';

const errorRateTab = {
const failureCorrelationsTab = {
key: 'errorRate',
label: i18n.translate('xpack.apm.correlations.tabs.errorRateLabel', {
defaultMessage: 'Failed transaction rate',
}),
component: ErrorCorrelations,
label: i18n.translate(
'xpack.apm.correlations.tabs.failureCorrelationsLabel',
{
defaultMessage: 'Failure correlations',
}
),
component: MlFailureCorrelations,
};
const latencyCorrelationsTab = {
key: 'latencyCorrelations',
Expand All @@ -65,7 +68,7 @@ const latencyCorrelationsTab = {
}),
component: MlLatencyCorrelations,
};
const tabs = [latencyCorrelationsTab, errorRateTab];
const tabs = [latencyCorrelationsTab, failureCorrelationsTab];

export function Correlations() {
const license = useLicenseContext();
Expand Down
Expand Up @@ -194,6 +194,7 @@ export function LatencyCorrelations({ onClose }: Props) {
'xpack.apm.correlations.latency.percentageColumnName',
{ defaultMessage: '% of slow transactions' }
)}
// @ts-expect-error: this file to be removed
significantTerms={
hasFieldNames && correlationsData
? correlationsData?.significantTerms
Expand Down