diff --git a/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/constants.ts b/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/constants.ts index 09e3e22a1d352..8a838360b3d44 100644 --- a/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/constants.ts +++ b/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/constants.ts @@ -7,23 +7,17 @@ import { i18n } from '@kbn/i18n'; -export const FAILED_TRANSACTIONS_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', - } - ), +export const CORRELATIONS_IMPACT_THRESHOLD = { + HIGH: i18n.translate('xpack.apm.correlations.highImpactText', { + defaultMessage: 'High', + }), + MEDIUM: i18n.translate('xpack.apm.correlations.mediumImpactText', { + defaultMessage: 'Medium', + }), + LOW: i18n.translate('xpack.apm.correlations.lowImpactText', { + defaultMessage: 'Low', + }), + VERY_LOW: i18n.translate('xpack.apm.correlations.veryLowImpactText', { + defaultMessage: 'Very low', + }), } as const; diff --git a/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/types.ts b/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/types.ts index 8b09d45c1e1b6..e63d3d6faa92e 100644 --- a/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/types.ts +++ b/x-pack/plugins/apm/common/correlations/failed_transactions_correlations/types.ts @@ -7,7 +7,7 @@ import { FieldValuePair, HistogramItem } from '../types'; -import { FAILED_TRANSACTIONS_IMPACT_THRESHOLD } from './constants'; +import { CORRELATIONS_IMPACT_THRESHOLD } from './constants'; import { FieldStats } from '../field_stats_types'; export interface FailedTransactionsCorrelation extends FieldValuePair { @@ -22,7 +22,7 @@ export interface FailedTransactionsCorrelation extends FieldValuePair { } export type FailedTransactionsCorrelationsImpactThreshold = - typeof FAILED_TRANSACTIONS_IMPACT_THRESHOLD[keyof typeof FAILED_TRANSACTIONS_IMPACT_THRESHOLD]; + typeof CORRELATIONS_IMPACT_THRESHOLD[keyof typeof CORRELATIONS_IMPACT_THRESHOLD]; export interface FailedTransactionsCorrelationsResponse { ccsWarning: boolean; @@ -31,4 +31,5 @@ export interface FailedTransactionsCorrelationsResponse { overallHistogram?: HistogramItem[]; errorHistogram?: HistogramItem[]; fieldStats?: FieldStats[]; + fallbackResult?: FailedTransactionsCorrelation; } diff --git a/x-pack/plugins/apm/common/correlations/latency_correlations/types.ts b/x-pack/plugins/apm/common/correlations/latency_correlations/types.ts index 23c91554b6547..cf20490774e18 100644 --- a/x-pack/plugins/apm/common/correlations/latency_correlations/types.ts +++ b/x-pack/plugins/apm/common/correlations/latency_correlations/types.ts @@ -10,8 +10,9 @@ import { FieldStats } from '../field_stats_types'; export interface LatencyCorrelation extends FieldValuePair { correlation: number; - histogram: HistogramItem[]; + histogram?: HistogramItem[]; ksTest: number; + isFallbackResult?: boolean; } export interface LatencyCorrelationsResponse { diff --git a/x-pack/plugins/apm/common/correlations/types.ts b/x-pack/plugins/apm/common/correlations/types.ts index 402750b72b2ab..6884d8c627fd0 100644 --- a/x-pack/plugins/apm/common/correlations/types.ts +++ b/x-pack/plugins/apm/common/correlations/types.ts @@ -11,6 +11,7 @@ export interface FieldValuePair { // but for example `http.response.status_code` which is part of // of the list of predefined field candidates is of type long/number. fieldValue: string | number; + isFallbackResult?: boolean; } export interface HistogramItem { diff --git a/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx b/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx index 6d20faae89a10..c970838f8b8c3 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx +++ b/x-pack/plugins/apm/public/components/app/correlations/failed_transactions_correlations.tsx @@ -28,7 +28,10 @@ import { i18n } from '@kbn/i18n'; import { useUiTracker } from '../../../../../observability/public'; -import { asPercent } from '../../../../common/utils/formatters'; +import { + asPercent, + asPreciseDecimal, +} from '../../../../common/utils/formatters'; import { FailedTransactionsCorrelation } from '../../../../common/correlations/failed_transactions_correlations/types'; import { FieldStats } from '../../../../common/correlations/field_stats_types'; @@ -36,8 +39,6 @@ import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_ import { useLocalStorage } from '../../../hooks/use_local_storage'; import { FETCH_STATUS } from '../../../hooks/use_fetcher'; import { useTheme } from '../../../hooks/use_theme'; - -import { ImpactBar } from '../../shared/impact_bar'; import { push } from '../../shared/links/url_helpers'; import { CorrelationsTable } from './correlations_table'; @@ -229,21 +230,33 @@ export function FailedTransactionsCorrelations({ width: '116px', field: 'normalizedScore', name: ( - <> - {i18n.translate( - 'xpack.apm.correlations.failedTransactions.correlationsTable.scoreLabel', + - ), - render: (_, { normalizedScore }) => { - return ( + > <> - + {i18n.translate( + 'xpack.apm.correlations.failedTransactions.correlationsTable.scoreLabel', + { + defaultMessage: 'Score', + } + )} + - ); + + ), + render: (_, { normalizedScore }) => { + return
{asPreciseDecimal(normalizedScore, 2)}
; }, sortable: true, }, @@ -260,8 +273,11 @@ export function FailedTransactionsCorrelations({ )} ), - render: (_, { pValue }) => { - const label = getFailedTransactionsCorrelationImpactLabel(pValue); + render: (_, { pValue, isFallbackResult }) => { + const label = getFailedTransactionsCorrelationImpactLabel( + pValue, + isFallbackResult + ); return label ? ( {label.impact} ) : null; @@ -377,18 +393,30 @@ export function FailedTransactionsCorrelations({ sort: { field: sortField, direction: sortDirection }, }; - const correlationTerms = useMemo( - () => - orderBy( - response.failedTransactionsCorrelations, - // The smaller the p value the higher the impact - // So we want to sort by the normalized score here - // which goes from 0 -> 1 - sortField === 'pValue' ? 'normalizedScore' : sortField, - sortDirection - ), - [response.failedTransactionsCorrelations, sortField, sortDirection] - ); + const correlationTerms = useMemo(() => { + if ( + progress.loaded === 1 && + response?.failedTransactionsCorrelations?.length === 0 && + response.fallbackResult !== undefined + ) { + return [{ ...response.fallbackResult, isFallbackResult: true }]; + } + + return orderBy( + response.failedTransactionsCorrelations, + // The smaller the p value the higher the impact + // So we want to sort by the normalized score here + // which goes from 0 -> 1 + sortField === 'pValue' ? 'normalizedScore' : sortField, + sortDirection + ); + }, [ + response.failedTransactionsCorrelations, + response.fallbackResult, + progress.loaded, + sortField, + sortDirection, + ]); const [pinnedSignificantTerm, setPinnedSignificantTerm] = useState(null); diff --git a/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts b/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts index 49ddd8aec0fe4..12799e5edc726 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts +++ b/x-pack/plugins/apm/public/components/app/correlations/get_transaction_distribution_chart_data.ts @@ -7,11 +7,10 @@ import { i18n } from '@kbn/i18n'; import { EuiTheme } from '../../../../../../../src/plugins/kibana_react/common'; -import type { - FieldValuePair, - HistogramItem, -} from '../../../../common/correlations/types'; +import type { HistogramItem } from '../../../../common/correlations/types'; import { TransactionDistributionChartData } from '../../shared/charts/transaction_distribution_chart'; +import { LatencyCorrelation } from '../../../../common/correlations/latency_correlations/types'; +import { FailedTransactionsCorrelation } from '../../../../common/correlations/failed_transactions_correlations/types'; export function getTransactionDistributionChartData({ euiTheme, @@ -22,7 +21,7 @@ export function getTransactionDistributionChartData({ euiTheme: EuiTheme; allTransactionsHistogram?: HistogramItem[]; failedTransactionsHistogram?: HistogramItem[]; - selectedTerm?: FieldValuePair & { histogram: HistogramItem[] }; + selectedTerm?: LatencyCorrelation | FailedTransactionsCorrelation | undefined; }) { const transactionDistributionChartData: TransactionDistributionChartData[] = []; diff --git a/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx b/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx index 5b37a14b4e4e5..f3734dae5d247 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx +++ b/x-pack/plugins/apm/public/components/app/correlations/latency_correlations.tsx @@ -17,12 +17,14 @@ import { EuiSpacer, EuiTitle, EuiToolTip, + EuiBadge, } from '@elastic/eui'; import { Direction } from '@elastic/eui/src/services/sort/sort_direction'; import { EuiTableSortingType } from '@elastic/eui/src/components/basic_table/table_types'; import { i18n } from '@kbn/i18n'; +import { FormattedMessage } from '@kbn/i18n-react'; import { useUiTracker } from '../../../../../observability/public'; import { asPreciseDecimal } from '../../../../common/utils/formatters'; @@ -48,6 +50,18 @@ import { getTransactionDistributionChartData } from './get_transaction_distribut import { useTheme } from '../../../hooks/use_theme'; import { ChartTitleToolTip } from './chart_title_tool_tip'; import { MIN_TAB_TITLE_HEIGHT } from '../transaction_details/distribution'; +import { getLatencyCorrelationImpactLabel } from './utils/get_failed_transactions_correlation_impact_label'; + +export function FallbackCorrelationBadge() { + return ( + + + + ); +} export function LatencyCorrelations({ onFilter }: { onFilter: () => void }) { const { @@ -151,6 +165,31 @@ export function LatencyCorrelations({ onFilter }: { onFilter: () => void }) { }, sortable: true, }, + { + width: '116px', + field: 'pValue', + name: ( + <> + {i18n.translate( + 'xpack.apm.correlations.failedTransactions.correlationsTable.impactLabel', + { + defaultMessage: 'Impact', + } + )} + + ), + render: (_, { correlation, isFallbackResult }) => { + const label = getLatencyCorrelationImpactLabel( + correlation, + isFallbackResult + ); + return label ? ( + {label.impact} + ) : null; + }, + sortable: true, + }, + { field: 'fieldName', name: i18n.translate( diff --git a/x-pack/plugins/apm/public/components/app/correlations/use_failed_transactions_correlations.ts b/x-pack/plugins/apm/public/components/app/correlations/use_failed_transactions_correlations.ts index 41a2afada6e65..26f63e1ab0c59 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/use_failed_transactions_correlations.ts +++ b/x-pack/plugins/apm/public/components/app/correlations/use_failed_transactions_correlations.ts @@ -77,6 +77,7 @@ export function useFailedTransactionsCorrelations() { // and histogram data for statistically significant results. const responseUpdate: FailedTransactionsCorrelationsResponse = { ccsWarning: false, + fallbackResult: undefined, }; const [overallHistogramResponse, errorHistogramRespone] = @@ -149,6 +150,7 @@ export function useFailedTransactionsCorrelations() { const failedTransactionsCorrelations: FailedTransactionsCorrelation[] = []; + let fallbackResult: FailedTransactionsCorrelation | undefined; const fieldsToSample = new Set(); const chunkSize = 10; let chunkLoadCounter = 0; @@ -177,6 +179,21 @@ export function useFailedTransactionsCorrelations() { getFailedTransactionsCorrelationsSortedByScore([ ...failedTransactionsCorrelations, ]); + } else { + // If there's no significant correlations found and there's a fallback result + // Update the highest ranked/scored fall back result + if (pValues.fallbackResult) { + if (!fallbackResult) { + fallbackResult = pValues.fallbackResult; + } else { + if ( + pValues.fallbackResult.normalizedScore > + fallbackResult.normalizedScore + ) { + fallbackResult = pValues.fallbackResult; + } + } + } } chunkLoadCounter++; @@ -209,7 +226,12 @@ export function useFailedTransactionsCorrelations() { ); responseUpdate.fieldStats = stats; - setResponse({ ...responseUpdate, loaded: LOADED_DONE, isRunning: false }); + setResponse({ + ...responseUpdate, + fallbackResult, + loaded: LOADED_DONE, + isRunning: false, + }); setResponse.flush(); } catch (e) { if (!abortCtrl.current.signal.aborted) { diff --git a/x-pack/plugins/apm/public/components/app/correlations/use_latency_correlations.ts b/x-pack/plugins/apm/public/components/app/correlations/use_latency_correlations.ts index 0e166344d0dec..428fdcda7cfc6 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/use_latency_correlations.ts +++ b/x-pack/plugins/apm/public/components/app/correlations/use_latency_correlations.ts @@ -177,6 +177,7 @@ export function useLatencyCorrelations() { chunkSize ); + const fallbackResults: LatencyCorrelation[] = []; for (const fieldValuePairChunk of fieldValuePairChunks) { const significantCorrelations = await callApmApi( 'POST /internal/apm/correlations/significant_correlations', @@ -197,6 +198,12 @@ export function useLatencyCorrelations() { ); responseUpdate.latencyCorrelations = getLatencyCorrelationsSortedByCorrelation([...latencyCorrelations]); + } else { + // If there's no correlation results that matches the criteria + // Consider the fallback results + if (significantCorrelations.fallbackResult) { + fallbackResults.push(significantCorrelations.fallbackResult); + } } chunkLoadCounter++; @@ -213,6 +220,23 @@ export function useLatencyCorrelations() { } } + if (latencyCorrelations.length === 0 && fallbackResults.length > 0) { + // Rank the fallback results and show at least one value + const sortedFallbackResults = fallbackResults + .filter((r) => r.correlation > 0) + .sort((a, b) => b.correlation - a.correlation); + + responseUpdate.latencyCorrelations = sortedFallbackResults + .slice(0, 1) + .map((r) => ({ ...r, isFallbackResult: true })); + setResponse({ + ...responseUpdate, + loaded: + LOADED_FIELD_VALUE_PAIRS + + (chunkLoadCounter / fieldValuePairChunks.length) * + PROGRESS_STEP_CORRELATIONS, + }); + } setResponse.flush(); const { stats } = await callApmApi( diff --git a/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.test.ts b/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.test.ts index d35833295703f..b85121ea94a9c 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.test.ts +++ b/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.test.ts @@ -6,19 +6,19 @@ */ import { getFailedTransactionsCorrelationImpactLabel } from './get_failed_transactions_correlation_impact_label'; -import { FAILED_TRANSACTIONS_IMPACT_THRESHOLD } from '../../../../../common/correlations/failed_transactions_correlations/constants'; +import { CORRELATIONS_IMPACT_THRESHOLD } from '../../../../../common/correlations/failed_transactions_correlations/constants'; const EXPECTED_RESULT = { HIGH: { - impact: FAILED_TRANSACTIONS_IMPACT_THRESHOLD.HIGH, + impact: CORRELATIONS_IMPACT_THRESHOLD.HIGH, color: 'danger', }, MEDIUM: { - impact: FAILED_TRANSACTIONS_IMPACT_THRESHOLD.MEDIUM, + impact: CORRELATIONS_IMPACT_THRESHOLD.MEDIUM, color: 'warning', }, LOW: { - impact: FAILED_TRANSACTIONS_IMPACT_THRESHOLD.LOW, + impact: CORRELATIONS_IMPACT_THRESHOLD.LOW, color: 'default', }, }; diff --git a/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.ts b/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.ts index d5d0fd4dcae51..556c13d7467bb 100644 --- a/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.ts +++ b/x-pack/plugins/apm/public/components/app/correlations/utils/get_failed_transactions_correlation_impact_label.ts @@ -9,10 +9,11 @@ import { FailedTransactionsCorrelation, FailedTransactionsCorrelationsImpactThreshold, } from '../../../../../common/correlations/failed_transactions_correlations/types'; -import { FAILED_TRANSACTIONS_IMPACT_THRESHOLD } from '../../../../../common/correlations/failed_transactions_correlations/constants'; +import { CORRELATIONS_IMPACT_THRESHOLD } from '../../../../../common/correlations/failed_transactions_correlations/constants'; export function getFailedTransactionsCorrelationImpactLabel( - pValue: FailedTransactionsCorrelation['pValue'] + pValue: FailedTransactionsCorrelation['pValue'], + isFallbackResult?: boolean ): { impact: FailedTransactionsCorrelationsImpactThreshold; color: string; @@ -21,22 +22,64 @@ export function getFailedTransactionsCorrelationImpactLabel( return null; } + if (isFallbackResult) + return { + impact: CORRELATIONS_IMPACT_THRESHOLD.VERY_LOW, + color: 'default', + }; + // The lower the p value, the higher the impact if (pValue >= 0 && pValue < 1e-6) return { - impact: FAILED_TRANSACTIONS_IMPACT_THRESHOLD.HIGH, + impact: CORRELATIONS_IMPACT_THRESHOLD.HIGH, color: 'danger', }; if (pValue >= 1e-6 && pValue < 0.001) return { - impact: FAILED_TRANSACTIONS_IMPACT_THRESHOLD.MEDIUM, + impact: CORRELATIONS_IMPACT_THRESHOLD.MEDIUM, color: 'warning', }; if (pValue >= 0.001 && pValue < 0.02) return { - impact: FAILED_TRANSACTIONS_IMPACT_THRESHOLD.LOW, + impact: CORRELATIONS_IMPACT_THRESHOLD.LOW, + color: 'default', + }; + + return null; +} + +export function getLatencyCorrelationImpactLabel( + correlation: FailedTransactionsCorrelation['pValue'], + isFallbackResult?: boolean +): { + impact: FailedTransactionsCorrelationsImpactThreshold; + color: string; +} | null { + if (correlation === null || correlation < 0) { + return null; + } + + // The lower the p value, the higher the impact + if (isFallbackResult) + return { + impact: CORRELATIONS_IMPACT_THRESHOLD.VERY_LOW, + color: 'default', + }; + if (correlation < 0.4) + return { + impact: CORRELATIONS_IMPACT_THRESHOLD.LOW, color: 'default', }; + if (correlation < 0.6) + return { + impact: CORRELATIONS_IMPACT_THRESHOLD.MEDIUM, + color: 'warning', + }; + if (correlation < 1) + return { + impact: CORRELATIONS_IMPACT_THRESHOLD.HIGH, + color: 'danger', + }; return null; } diff --git a/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.ts index 03b28b28d521a..5c6b8f3594aa0 100644 --- a/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.ts +++ b/x-pack/plugins/apm/server/routes/correlations/queries/query_correlation_with_histogram.ts @@ -32,7 +32,7 @@ export async function fetchTransactionDurationCorrelationWithHistogram( histogramRangeSteps: number[], totalDocCount: number, fieldValuePair: FieldValuePair -): Promise { +) { const { correlation, ksTest } = await fetchTransactionDurationCorrelation( esClient, params, @@ -43,23 +43,28 @@ export async function fetchTransactionDurationCorrelationWithHistogram( [fieldValuePair] ); - if ( - correlation !== null && - correlation > CORRELATION_THRESHOLD && - ksTest !== null && - ksTest < KS_TEST_THRESHOLD - ) { - const logHistogram = await fetchTransactionDurationRanges( - esClient, - params, - histogramRangeSteps, - [fieldValuePair] - ); - return { - ...fieldValuePair, - correlation, - ksTest, - histogram: logHistogram, - }; + if (correlation !== null && ksTest !== null && !isNaN(ksTest)) { + if (correlation > CORRELATION_THRESHOLD && ksTest < KS_TEST_THRESHOLD) { + const logHistogram = await fetchTransactionDurationRanges( + esClient, + params, + histogramRangeSteps, + [fieldValuePair] + ); + return { + ...fieldValuePair, + correlation, + ksTest, + histogram: logHistogram, + } as LatencyCorrelation; + } else { + return { + ...fieldValuePair, + correlation, + ksTest, + } as Omit; + } } + + return undefined; } diff --git a/x-pack/plugins/apm/server/routes/correlations/queries/query_p_values.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_p_values.ts index 7c471aebd0f7a..ee59925c47f27 100644 --- a/x-pack/plugins/apm/server/routes/correlations/queries/query_p_values.ts +++ b/x-pack/plugins/apm/server/routes/correlations/queries/query_p_values.ts @@ -41,18 +41,39 @@ export const fetchPValues = async ( ) ); - const failedTransactionsCorrelations: FailedTransactionsCorrelation[] = - fulfilled - .flat() - .filter( - (record) => - record && - typeof record.pValue === 'number' && - record.pValue < ERROR_CORRELATION_THRESHOLD - ); + const flattenedResults = fulfilled.flat(); + + const failedTransactionsCorrelations: FailedTransactionsCorrelation[] = []; + let fallbackResult: FailedTransactionsCorrelation | undefined; + + flattenedResults.forEach((record) => { + if ( + record && + typeof record.pValue === 'number' && + record.pValue < ERROR_CORRELATION_THRESHOLD + ) { + failedTransactionsCorrelations.push(record); + } else { + // If there's no result matching the criteria + // Find the next highest/closest result to the threshold + // to use as a fallback result + if (!fallbackResult) { + fallbackResult = record; + } else { + if ( + record.pValue !== null && + fallbackResult && + fallbackResult.pValue !== null && + record.pValue < fallbackResult.pValue + ) { + fallbackResult = record; + } + } + } + }); const ccsWarning = rejected.length > 0 && paramsWithIndex?.index.includes(':'); - return { failedTransactionsCorrelations, ccsWarning }; + return { failedTransactionsCorrelations, ccsWarning, fallbackResult }; }; diff --git a/x-pack/plugins/apm/server/routes/correlations/queries/query_significant_correlations.ts b/x-pack/plugins/apm/server/routes/correlations/queries/query_significant_correlations.ts index ed5ad1c278143..2fc1e69eab356 100644 --- a/x-pack/plugins/apm/server/routes/correlations/queries/query_significant_correlations.ts +++ b/x-pack/plugins/apm/server/routes/correlations/queries/query_significant_correlations.ts @@ -13,7 +13,7 @@ import type { FieldValuePair, CorrelationsParams, } from '../../../../common/correlations/types'; -import { LatencyCorrelation } from '../../../../common/correlations/latency_correlations/types'; +import type { LatencyCorrelation } from '../../../../common/correlations/latency_correlations/types'; import { computeExpectationsAndRanges, @@ -25,6 +25,7 @@ import { fetchTransactionDurationFractions, fetchTransactionDurationHistogramRangeSteps, fetchTransactionDurationPercentiles, + fetchTransactionDurationRanges, } from './index'; export const fetchSignificantCorrelations = async ( @@ -76,12 +77,54 @@ export const fetchSignificantCorrelations = async ( ) ); - const latencyCorrelations: LatencyCorrelation[] = fulfilled.filter( - (d): d is LatencyCorrelation => d !== undefined - ); + const latencyCorrelations = fulfilled.filter( + (d) => d && 'histogram' in d + ) as LatencyCorrelation[]; + let fallbackResult: LatencyCorrelation | undefined = + latencyCorrelations.length > 0 + ? undefined + : fulfilled + .filter((d) => !(d as LatencyCorrelation)?.histogram) + .reduce((d, result) => { + if (d?.correlation !== undefined) { + if (!result) { + result = d?.correlation > 0 ? d : undefined; + } else { + if ( + d.correlation > 0 && + d.ksTest > result.ksTest && + d.correlation > result.correlation + ) { + result = d; + } + } + } + return result; + }, undefined); + if (latencyCorrelations.length === 0 && fallbackResult) { + const { fieldName, fieldValue } = fallbackResult; + const logHistogram = await fetchTransactionDurationRanges( + esClient, + paramsWithIndex, + histogramRangeSteps, + [{ fieldName, fieldValue }] + ); + + if (fallbackResult) { + fallbackResult = { + ...fallbackResult, + histogram: logHistogram, + }; + } + } const ccsWarning = rejected.length > 0 && paramsWithIndex?.index.includes(':'); - return { latencyCorrelations, ccsWarning, totalDocCount }; + return { + latencyCorrelations, + ccsWarning, + totalDocCount, + fallbackResult, + }; }; diff --git a/x-pack/plugins/apm/server/routes/correlations/route.ts b/x-pack/plugins/apm/server/routes/correlations/route.ts index fd0bce7a62ff8..b0735c7c57b36 100644 --- a/x-pack/plugins/apm/server/routes/correlations/route.ts +++ b/x-pack/plugins/apm/server/routes/correlations/route.ts @@ -257,6 +257,7 @@ const significantCorrelationsRoute = createApmServerRoute({ >; ccsWarning: boolean; totalDocCount: number; + fallbackResult?: import('./../../../common/correlations/latency_correlations/types').LatencyCorrelation; }> => { const { context } = resources; if (!isActivePlatinumLicense(context.licensing.license)) { @@ -314,6 +315,7 @@ const pValuesRoute = createApmServerRoute({ import('./../../../common/correlations/failed_transactions_correlations/types').FailedTransactionsCorrelation >; ccsWarning: boolean; + fallbackResult?: import('./../../../common/correlations/failed_transactions_correlations/types').FailedTransactionsCorrelation; }> => { const { context } = resources; if (!isActivePlatinumLicense(context.licensing.license)) { diff --git a/x-pack/plugins/translations/translations/fr-FR.json b/x-pack/plugins/translations/translations/fr-FR.json index b7240d8653f90..3aaea1021494d 100644 --- a/x-pack/plugins/translations/translations/fr-FR.json +++ b/x-pack/plugins/translations/translations/fr-FR.json @@ -5920,9 +5920,6 @@ "xpack.apm.correlations.failedTransactions.correlationsTable.impactLabel": "Impact", "xpack.apm.correlations.failedTransactions.correlationsTable.pValueLabel": "Score", "xpack.apm.correlations.failedTransactions.errorTitle": "Une erreur est survenue lors de l'exécution de corrélations sur les transactions ayant échoué", - "xpack.apm.correlations.failedTransactions.highImpactText": "Élevé", - "xpack.apm.correlations.failedTransactions.lowImpactText": "Bas", - "xpack.apm.correlations.failedTransactions.mediumImpactText": "Moyen", "xpack.apm.correlations.failedTransactions.panelTitle": "Transactions ayant échoué", "xpack.apm.correlations.latencyCorrelations.correlationsTable.actionsLabel": "Filtre", "xpack.apm.correlations.latencyCorrelations.correlationsTable.correlationColumnDescription": "Score de corrélation [0-1] d'un attribut ; plus le score est élevé, plus un attribut augmente la latence.", diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 5a710d8f2c0df..22f1777bd67cc 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6912,9 +6912,9 @@ "xpack.apm.correlations.failedTransactions.helpPopover.performanceExplanation": "この分析は多数の属性に対して統計検索を実行します。広い時間範囲やトランザクションスループットが高いサービスでは、時間がかかる場合があります。パフォーマンスを改善するには、時間範囲を絞り込みます。", "xpack.apm.correlations.failedTransactions.helpPopover.tableExplanation": "表はスコア別に並べ替えられます。これは高、中、低影響度にマッピングされます。影響度が高い属性は、失敗したトランザクションの原因である可能性が高くなります。", "xpack.apm.correlations.failedTransactions.helpPopover.title": "失敗したトランザクションの相関関係", - "xpack.apm.correlations.failedTransactions.highImpactText": "高", - "xpack.apm.correlations.failedTransactions.lowImpactText": "低", - "xpack.apm.correlations.failedTransactions.mediumImpactText": "中", + "xpack.apm.correlations.highImpactText": "高", + "xpack.apm.correlations.lowImpactText": "低", + "xpack.apm.correlations.mediumImpactText": "中", "xpack.apm.correlations.failedTransactions.panelTitle": "失敗したトランザクションの遅延分布", "xpack.apm.correlations.failedTransactions.tableTitle": "相関関係", "xpack.apm.correlations.fieldContextPopover.addFilterAriaLabel": "{fieldName}のフィルター:\"{value}\"", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index 15ab16a10fe54..e270a12c50ef3 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6927,9 +6927,9 @@ "xpack.apm.correlations.failedTransactions.helpPopover.performanceExplanation": "此分析会对大量属性执行统计搜索。对于较大时间范围和具有高事务吞吐量的服务,这可能需要些时间。减少时间范围以改善性能。", "xpack.apm.correlations.failedTransactions.helpPopover.tableExplanation": "表按分数排序,分数映射高、中或低影响级别。具有高影响级别的属性更可能造成事务失败。", "xpack.apm.correlations.failedTransactions.helpPopover.title": "失败事务相关性", - "xpack.apm.correlations.failedTransactions.highImpactText": "高", - "xpack.apm.correlations.failedTransactions.lowImpactText": "低", - "xpack.apm.correlations.failedTransactions.mediumImpactText": "中", + "xpack.apm.correlations.highImpactText": "高", + "xpack.apm.correlations.lowImpactText": "低", + "xpack.apm.correlations.mediumImpactText": "中", "xpack.apm.correlations.failedTransactions.panelTitle": "失败事务延迟分布", "xpack.apm.correlations.failedTransactions.tableTitle": "相关性", "xpack.apm.correlations.fieldContextPopover.addFilterAriaLabel": "筛留 {fieldName}:“{value}”", diff --git a/x-pack/test/apm_api_integration/tests/correlations/latency.spec.ts b/x-pack/test/apm_api_integration/tests/correlations/latency.spec.ts index e5062961e2f2c..1cdd59777c1c5 100644 --- a/x-pack/test/apm_api_integration/tests/correlations/latency.spec.ts +++ b/x-pack/test/apm_api_integration/tests/correlations/latency.spec.ts @@ -254,7 +254,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(correlation?.fieldValue).to.be('success'); expect(correlation?.correlation).to.be(0.6275246559191225); expect(correlation?.ksTest).to.be(4.806503252860024e-13); - expect(correlation?.histogram.length).to.be(101); + expect(correlation?.histogram?.length).to.be(101); const fieldStats = finalRawResponse?.fieldStats?.[0]; expect(typeof fieldStats).to.be('object');