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
Changes from 7 commits
63a10b8
0633e88
43d7a85
1ce425c
cb61232
1ca029d
56e21dd
b25e6b6
b52b3e0
5e9d247
e70878c
1554436
19b430f
5ceed16
c6940c1
f4ecc66
b780c79
014b5cd
6bbb68c
ad490d2
bcec466
fb6bb05
caf5c29
1af8288
d709dc1
557a520
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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]; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 }; | ||
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); | ||
|
@@ -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> | ||
/ | ||
<EuiLink | ||
href={createHref(history, { | ||
query: { | ||
kuery: `not ${term.fieldName}:"${encodeURIComponent( | ||
term.fieldValue | ||
)}"`, | ||
}, | ||
})} | ||
> | ||
<EuiIcon type="magnifyWithMinus" /> | ||
</EuiLink> | ||
</> | ||
); | ||
}, | ||
}, | ||
]; | ||
const tableColumns: Array<EuiBasicTableColumn<T>> = columns ?? []; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Updated here bcec466 |
||
|
||
return ( | ||
<EuiBasicTable | ||
|
@@ -238,7 +88,7 @@ export function CorrelationsTable<T extends SignificantTerm>({ | |
return { | ||
onMouseEnter: () => { | ||
setSelectedSignificantTerm(term); | ||
trackSelectSignificantTerm(); | ||
trackSelectSignificantCorrelationTerm(); | ||
}, | ||
onMouseLeave: () => setSelectedSignificantTerm(null), | ||
style: | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we can remove this file as part of this PR already? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Deleted here e70878c |
||
significantTerms={ | ||
hasFieldNames && correlationsData?.significantTerms | ||
? correlationsData.significantTerms | ||
|
There was a problem hiding this comment.
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
?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fixed here f4ecc66