[APM] Adds support for metrics for latency distribution histogram (#136594)

* [APM] Adds support for metrics for latency distribution histogram (#132394)

* PR feedback

* Addresses feedback:
- filters by existing duration field for metrics
- get duration field and event type by chart type

* [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix'

* fixed type errors and removed eventType from being passed to to function specifically for latency correlations

* addressed PR feedback:
- renamed enums to match established pattern
- renamed `LatencyDistributionChartType.transactionDetails` to `*.traceSamples` to align with tab label
- added explanatory line comments

* [CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix'

* rename `LatencyDistributionChartType.traceSamples` -> `*.transactionLatency`

* renamed `LatencyDistributionChartType.dependencyLatency` -> `*.dependencyLatency`

* filters the query passed into getOverallLatencyDistribution when using metrics data

* fixes appendFilterQuery param types

* renames searchAggregatedTransactions -> searchMetrics for latency distribution

* removed unnecessary util function `appendFilterQuery`.

* [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix'

* make the searchMetrics param required

* fixes lint issue

* moves the duration field filter to append to the given query at the tail functions for latency distribution

Co-authored-by: kibanamachine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
Oliver Gupte 2022-07-26 18:22:41 -04:00 committed by GitHub
parent 69dc7e2b77
commit f903899ec0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 264 additions and 94 deletions

View file

@ -0,0 +1,21 @@
/*
* 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 * as t from 'io-ts';
export enum LatencyDistributionChartType {
transactionLatency = 'transactionLatency',
latencyCorrelations = 'latencyCorrelations',
failedTransactionsCorrelations = 'failedTransactionsCorrelations',
dependencyLatency = 'dependencyLatency',
}
export const latencyDistributionChartTypeRt = t.union([
t.literal(LatencyDistributionChartType.transactionLatency),
t.literal(LatencyDistributionChartType.latencyCorrelations),
t.literal(LatencyDistributionChartType.failedTransactionsCorrelations),
t.literal(LatencyDistributionChartType.dependencyLatency),
]);

View file

@ -23,6 +23,7 @@ import type {
FailedTransactionsCorrelation,
FailedTransactionsCorrelationsResponse,
} from '../../../../common/correlations/failed_transactions_correlations/types';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { callApmApi } from '../../../services/rest/create_call_apm_api';
@ -95,6 +96,8 @@ export function useFailedTransactionsCorrelations() {
body: {
...fetchParams,
percentileThreshold: DEFAULT_PERCENTILE_THRESHOLD,
chartType:
LatencyDistributionChartType.failedTransactionsCorrelations,
},
},
}
@ -113,6 +116,8 @@ export function useFailedTransactionsCorrelations() {
fieldValue: EventOutcome.failure,
},
],
chartType:
LatencyDistributionChartType.failedTransactionsCorrelations,
},
},
}

View file

@ -23,6 +23,7 @@ import type {
LatencyCorrelation,
LatencyCorrelationsResponse,
} from '../../../../common/correlations/latency_correlations/types';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { callApmApi } from '../../../services/rest/create_call_apm_api';
@ -94,6 +95,7 @@ export function useLatencyCorrelations() {
body: {
...fetchParams,
percentileThreshold: DEFAULT_PERCENTILE_THRESHOLD,
chartType: LatencyDistributionChartType.latencyCorrelations,
},
},
}

View file

@ -10,6 +10,7 @@ import { i18n } from '@kbn/i18n';
import { DEFAULT_PERCENTILE_THRESHOLD } from '../../../../../common/correlations/constants';
import { EVENT_OUTCOME } from '../../../../../common/elasticsearch_fieldnames';
import { EventOutcome } from '../../../../../common/event_outcome';
import { LatencyDistributionChartType } from '../../../../../common/latency_distribution_chart_types';
import { useApmPluginContext } from '../../../../context/apm_plugin/use_apm_plugin_context';
import { useFetcher, FETCH_STATUS } from '../../../../hooks/use_fetcher';
import { isErrorMessage } from '../../correlations/utils/is_error_message';
@ -44,6 +45,7 @@ export const useTransactionDistributionChartData = () => {
body: {
...params,
percentileThreshold: DEFAULT_PERCENTILE_THRESHOLD,
chartType: LatencyDistributionChartType.transactionLatency,
},
},
}
@ -99,6 +101,7 @@ export const useTransactionDistributionChartData = () => {
fieldValue: EventOutcome.failure,
},
],
chartType: LatencyDistributionChartType.transactionLatency,
},
},
}

View file

@ -18,14 +18,15 @@ import {
KS_TEST_THRESHOLD,
} from '../../../../common/correlations/constants';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { Setup } from '../../../lib/helpers/setup_request';
import { fetchDurationCorrelation } from './fetch_duration_correlation';
import { fetchDurationRanges } from './fetch_duration_ranges';
import { getEventType } from '../utils';
export async function fetchDurationCorrelationWithHistogram({
setup,
eventType,
chartType,
start,
end,
environment,
@ -39,7 +40,7 @@ export async function fetchDurationCorrelationWithHistogram({
fieldValuePair,
}: CommonCorrelationsQueryParams & {
setup: Setup;
eventType: ProcessorEvent;
chartType: LatencyDistributionChartType;
expectations: number[];
ranges: estypes.AggregationsAggregationRange[];
fractions: number[];
@ -47,6 +48,8 @@ export async function fetchDurationCorrelationWithHistogram({
totalDocCount: number;
fieldValuePair: FieldValuePair;
}) {
const searchMetrics = false; // latency correlations does not search metrics documents
const eventType = getEventType(chartType, searchMetrics);
const queryWithFieldValuePair = {
bool: {
filter: [
@ -74,13 +77,14 @@ export async function fetchDurationCorrelationWithHistogram({
if (correlation > CORRELATION_THRESHOLD && ksTest < KS_TEST_THRESHOLD) {
const { durationRanges: histogram } = await fetchDurationRanges({
setup,
eventType,
chartType,
start,
end,
environment,
kuery,
query: queryWithFieldValuePair,
rangeSteps: histogramRangeSteps,
searchMetrics,
});
return {
...fieldValuePair,

View file

@ -9,13 +9,10 @@ import { scaleLog } from 'd3-scale';
import { isFiniteNumber } from '@kbn/observability-plugin/common/utils/is_finite_number';
import { CommonCorrelationsQueryParams } from '../../../../common/correlations/types';
import {
SPAN_DURATION,
TRANSACTION_DURATION,
} from '../../../../common/elasticsearch_fieldnames';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { Setup } from '../../../lib/helpers/setup_request';
import { getCommonCorrelationsQuery } from './get_common_correlations_query';
import { getDurationField, getEventType } from '../utils';
const getHistogramRangeSteps = (min: number, max: number, steps: number) => {
// A d3 based scale function as a helper to get equally distributed bins on a log scale.
@ -27,29 +24,34 @@ const getHistogramRangeSteps = (min: number, max: number, steps: number) => {
};
export const fetchDurationHistogramRangeSteps = async ({
eventType,
chartType,
setup,
start,
end,
environment,
kuery,
query,
searchMetrics,
}: CommonCorrelationsQueryParams & {
eventType: ProcessorEvent;
chartType: LatencyDistributionChartType;
setup: Setup;
searchMetrics: boolean;
}): Promise<number[]> => {
const { apmEventClient } = setup;
const steps = 100;
const durationField = getDurationField(chartType, searchMetrics);
const durationField =
eventType === ProcessorEvent.span ? SPAN_DURATION : TRANSACTION_DURATION;
// when using metrics data, ensure we filter by docs with the appropriate duration field
const filteredQuery = searchMetrics
? { bool: { filter: [query, { exists: { field: durationField } }] } }
: query;
const resp = await apmEventClient.search(
'get_duration_histogram_range_steps',
{
apm: {
events: [eventType],
events: [getEventType(chartType, searchMetrics)],
},
body: {
size: 0,
@ -58,7 +60,7 @@ export const fetchDurationHistogramRangeSteps = async ({
end,
environment,
kuery,
query,
query: filteredQuery,
}),
aggs: {
duration_min: { min: { field: durationField } },

View file

@ -5,18 +5,15 @@
* 2.0.
*/
import {
SPAN_DURATION,
TRANSACTION_DURATION,
} from '../../../../common/elasticsearch_fieldnames';
import { SIGNIFICANT_VALUE_DIGITS } from '../../../../common/correlations/constants';
import { Setup } from '../../../lib/helpers/setup_request';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { getCommonCorrelationsQuery } from './get_common_correlations_query';
import { CommonCorrelationsQueryParams } from '../../../../common/correlations/types';
import { getDurationField, getEventType } from '../utils';
export const fetchDurationPercentiles = async ({
eventType,
chartType,
setup,
start,
end,
@ -24,44 +21,51 @@ export const fetchDurationPercentiles = async ({
kuery,
query,
percents,
searchMetrics,
}: CommonCorrelationsQueryParams & {
eventType: ProcessorEvent;
chartType: LatencyDistributionChartType;
setup: Setup;
percents?: number[];
searchMetrics: boolean;
}): Promise<{
totalDocs: number;
percentiles: Record<string, number>;
}> => {
const response = await setup.apmEventClient.search(
'get_duration_percentiles',
{
apm: { events: [eventType] },
body: {
track_total_hits: true,
query: getCommonCorrelationsQuery({
start,
end,
environment,
kuery,
query,
}),
size: 0,
aggs: {
duration_percentiles: {
percentiles: {
hdr: {
number_of_significant_value_digits: SIGNIFICANT_VALUE_DIGITS,
},
field:
eventType === ProcessorEvent.span
? SPAN_DURATION
: TRANSACTION_DURATION,
...(Array.isArray(percents) ? { percents } : {}),
const durationField = getDurationField(chartType, searchMetrics);
// when using metrics data, ensure we filter by docs with the appropriate duration field
const filteredQuery = searchMetrics
? { bool: { filter: [query, { exists: { field: durationField } }] } }
: query;
const params = {
apm: { events: [getEventType(chartType, searchMetrics)] },
body: {
track_total_hits: true,
query: getCommonCorrelationsQuery({
start,
end,
environment,
kuery,
query: filteredQuery,
}),
size: 0,
aggs: {
duration_percentiles: {
percentiles: {
hdr: {
number_of_significant_value_digits: SIGNIFICANT_VALUE_DIGITS,
},
field: getDurationField(chartType, searchMetrics),
...(Array.isArray(percents) ? { percents } : {}),
},
},
},
}
},
};
const response = await setup.apmEventClient.search(
'get_duration_percentiles',
params
);
// return early with no results if the search didn't return any documents

View file

@ -7,14 +7,11 @@
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { sumBy } from 'lodash';
import {
SPAN_DURATION,
TRANSACTION_DURATION,
} from '../../../../common/elasticsearch_fieldnames';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { Setup } from '../../../lib/helpers/setup_request';
import { getCommonCorrelationsQuery } from './get_common_correlations_query';
import { Environment } from '../../../../common/environment_rt';
import { getDurationField, getEventType } from '../utils';
export const fetchDurationRanges = async ({
rangeSteps,
@ -24,7 +21,8 @@ export const fetchDurationRanges = async ({
environment,
kuery,
query,
eventType,
chartType,
searchMetrics,
}: {
rangeSteps: number[];
setup: Setup;
@ -33,12 +31,19 @@ export const fetchDurationRanges = async ({
environment: Environment;
kuery: string;
query: estypes.QueryDslQueryContainer;
eventType: ProcessorEvent;
chartType: LatencyDistributionChartType;
searchMetrics: boolean;
}): Promise<{
totalDocCount: number;
durationRanges: Array<{ key: number; doc_count: number }>;
}> => {
const { apmEventClient } = setup;
const durationField = getDurationField(chartType, searchMetrics);
// when using metrics data, ensure we filter by docs with the appropriate duration field
const filteredQuery = searchMetrics
? { bool: { filter: [query, { exists: { field: durationField } }] } }
: query;
const ranges = rangeSteps.reduce(
(p, to) => {
@ -54,7 +59,7 @@ export const fetchDurationRanges = async ({
const resp = await apmEventClient.search('get_duration_ranges', {
apm: {
events: [eventType],
events: [getEventType(chartType, searchMetrics)],
},
body: {
size: 0,
@ -63,15 +68,12 @@ export const fetchDurationRanges = async ({
end,
environment,
kuery,
query,
query: filteredQuery,
}),
aggs: {
logspace_ranges: {
range: {
field:
eventType === ProcessorEvent.span
? SPAN_DURATION
: TRANSACTION_DURATION,
field: getDurationField(chartType, searchMetrics),
ranges,
},
},

View file

@ -12,14 +12,14 @@ import {
PROCESSOR_EVENT,
} from '../../../../common/elasticsearch_fieldnames';
import { EventOutcome } from '../../../../common/event_outcome';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { Setup } from '../../../lib/helpers/setup_request';
import { getCommonCorrelationsQuery } from './get_common_correlations_query';
import { fetchDurationRanges } from './fetch_duration_ranges';
import { getEventType } from '../utils';
export const fetchFailedEventsCorrelationPValues = async ({
setup,
eventType,
start,
end,
environment,
@ -29,12 +29,15 @@ export const fetchFailedEventsCorrelationPValues = async ({
fieldName,
}: CommonCorrelationsQueryParams & {
setup: Setup;
eventType: ProcessorEvent;
rangeSteps: number[];
fieldName: string;
}) => {
const { apmEventClient } = setup;
const chartType = LatencyDistributionChartType.failedTransactionsCorrelations;
const searchMetrics = false; // failed transactions correlations does not search metrics documents
const eventType = getEventType(chartType, searchMetrics);
const commonQuery = getCommonCorrelationsQuery({
start,
end,
@ -103,7 +106,7 @@ export const fetchFailedEventsCorrelationPValues = async ({
const { durationRanges: histogram } = await fetchDurationRanges({
setup,
eventType,
chartType,
start,
end,
environment,
@ -114,6 +117,7 @@ export const fetchFailedEventsCorrelationPValues = async ({
},
},
rangeSteps,
searchMetrics,
});
result.push({

View file

@ -9,15 +9,14 @@ import { ERROR_CORRELATION_THRESHOLD } from '../../../../common/correlations/con
import type { FailedTransactionsCorrelation } from '../../../../common/correlations/failed_transactions_correlations/types';
import { CommonCorrelationsQueryParams } from '../../../../common/correlations/types';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { Setup } from '../../../lib/helpers/setup_request';
import { splitAllSettledPromises } from '../utils';
import { splitAllSettledPromises, getEventType } from '../utils';
import { fetchDurationHistogramRangeSteps } from './fetch_duration_histogram_range_steps';
import { fetchFailedEventsCorrelationPValues } from './fetch_failed_events_correlation_p_values';
export const fetchPValues = async ({
setup,
eventType,
start,
end,
environment,
@ -26,17 +25,21 @@ export const fetchPValues = async ({
fieldCandidates,
}: CommonCorrelationsQueryParams & {
setup: Setup;
eventType: ProcessorEvent;
fieldCandidates: string[];
}) => {
const chartType = LatencyDistributionChartType.failedTransactionsCorrelations;
const searchMetrics = false; // failed transactions correlations does not search metrics documents
const eventType = getEventType(chartType, searchMetrics);
const rangeSteps = await fetchDurationHistogramRangeSteps({
setup,
eventType,
chartType,
start,
end,
environment,
kuery,
query,
searchMetrics,
});
const { fulfilled, rejected } = splitAllSettledPromises(
@ -44,7 +47,6 @@ export const fetchPValues = async ({
fieldCandidates.map((fieldName) =>
fetchFailedEventsCorrelationPValues({
setup,
eventType,
start,
end,
environment,

View file

@ -14,7 +14,7 @@ import type {
FieldValuePair,
} from '../../../../common/correlations/types';
import { ProcessorEvent } from '../../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { Setup } from '../../../lib/helpers/setup_request';
import {
computeExpectationsAndRanges,
@ -25,10 +25,10 @@ import { fetchDurationCorrelationWithHistogram } from './fetch_duration_correlat
import { fetchDurationFractions } from './fetch_duration_fractions';
import { fetchDurationHistogramRangeSteps } from './fetch_duration_histogram_range_steps';
import { fetchDurationRanges } from './fetch_duration_ranges';
import { getEventType } from '../utils';
export const fetchSignificantCorrelations = async ({
setup,
eventType,
start,
end,
environment,
@ -37,20 +37,24 @@ export const fetchSignificantCorrelations = async ({
fieldValuePairs,
}: CommonCorrelationsQueryParams & {
setup: Setup;
eventType: ProcessorEvent;
fieldValuePairs: FieldValuePair[];
}) => {
// Create an array of ranges [2, 4, 6, ..., 98]
const percentileAggregationPercents = range(2, 100, 2);
const chartType = LatencyDistributionChartType.latencyCorrelations;
const searchMetrics = false; // latency correlations does not search metrics documents
const eventType = getEventType(chartType, searchMetrics);
const { percentiles: percentilesRecords } = await fetchDurationPercentiles({
setup,
eventType,
chartType,
start,
end,
environment,
kuery,
query,
percents: percentileAggregationPercents,
searchMetrics,
});
// We need to round the percentiles values
@ -73,12 +77,13 @@ export const fetchSignificantCorrelations = async ({
const histogramRangeSteps = await fetchDurationHistogramRangeSteps({
setup,
eventType,
chartType,
start,
end,
environment,
kuery,
query,
searchMetrics,
});
const { fulfilled, rejected } = splitAllSettledPromises(
@ -86,7 +91,7 @@ export const fetchSignificantCorrelations = async ({
fieldValuePairs.map((fieldValuePair) =>
fetchDurationCorrelationWithHistogram({
setup,
eventType,
chartType,
start,
end,
environment,
@ -132,7 +137,7 @@ export const fetchSignificantCorrelations = async ({
const { fieldName, fieldValue } = fallbackResult;
const { durationRanges: histogram } = await fetchDurationRanges({
setup,
eventType,
chartType,
start,
end,
environment,
@ -143,6 +148,7 @@ export const fetchSignificantCorrelations = async ({
},
},
rangeSteps: histogramRangeSteps,
searchMetrics,
});
if (fallbackResult) {

View file

@ -349,7 +349,6 @@ const significantCorrelationsTransactionsRoute = createApmServerRoute({
return fetchSignificantCorrelations({
setup,
eventType: ProcessorEvent.transaction,
start,
end,
environment,
@ -412,7 +411,6 @@ const pValuesTransactionsRoute = createApmServerRoute({
return fetchPValues({
setup,
eventType: ProcessorEvent.transaction,
start,
end,
environment,

View file

@ -0,0 +1,41 @@
/*
* 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 {
SPAN_DURATION,
TRANSACTION_DURATION,
TRANSACTION_DURATION_HISTOGRAM,
} from '../../../../common/elasticsearch_fieldnames';
import { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
const {
transactionLatency,
latencyCorrelations,
failedTransactionsCorrelations,
dependencyLatency,
} = LatencyDistributionChartType;
export function getDurationField(
chartType: LatencyDistributionChartType,
searchMetrics: boolean
) {
switch (chartType) {
case transactionLatency:
if (searchMetrics) {
return TRANSACTION_DURATION_HISTOGRAM;
}
return TRANSACTION_DURATION;
case latencyCorrelations:
return TRANSACTION_DURATION;
case failedTransactionsCorrelations:
return TRANSACTION_DURATION;
case dependencyLatency:
return SPAN_DURATION;
default:
return TRANSACTION_DURATION;
}
}

View file

@ -0,0 +1,37 @@
/*
* 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 { LatencyDistributionChartType } from '../../../../common/latency_distribution_chart_types';
import { ProcessorEvent } from '../../../../common/processor_event';
const {
transactionLatency,
latencyCorrelations,
failedTransactionsCorrelations,
dependencyLatency,
} = LatencyDistributionChartType;
export function getEventType(
chartType: LatencyDistributionChartType,
searchMetrics: boolean
): ProcessorEvent {
switch (chartType) {
case transactionLatency:
if (searchMetrics) {
return ProcessorEvent.metric;
}
return ProcessorEvent.transaction;
case latencyCorrelations:
return ProcessorEvent.transaction;
case failedTransactionsCorrelations:
return ProcessorEvent.transaction;
case dependencyLatency:
return ProcessorEvent.span;
default:
return ProcessorEvent.transaction;
}
}

View file

@ -7,3 +7,5 @@
export { computeExpectationsAndRanges } from './compute_expectations_and_ranges';
export { splitAllSettledPromises } from './split_all_settled_promises';
export { getDurationField } from './get_duration_field';
export { getEventType } from './get_event_type';

View file

@ -13,7 +13,7 @@ import {
} from '../../../common/elasticsearch_fieldnames';
import { Environment } from '../../../common/environment_rt';
import { EventOutcome } from '../../../common/event_outcome';
import { ProcessorEvent } from '../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../common/latency_distribution_chart_types';
import { Setup } from '../../lib/helpers/setup_request';
import { getOverallLatencyDistribution } from '../latency_distribution/get_overall_latency_distribution';
import { OverallLatencyDistributionResponse } from '../latency_distribution/types';
@ -41,13 +41,14 @@ export async function getDependencyLatencyDistribution({
failedSpansDistribution: OverallLatencyDistributionResponse;
}> {
const commonProps = {
eventType: ProcessorEvent.span,
chartType: LatencyDistributionChartType.dependencyLatency,
setup,
start,
end,
environment,
kuery,
percentileThreshold,
searchMetrics: false,
};
const commonQuery = {

View file

@ -8,7 +8,6 @@
import type * as estypes from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { Environment } from '../../../common/environment_rt';
import { ProcessorEvent } from '../../../common/processor_event';
import { Setup } from '../../lib/helpers/setup_request';
import { withApmSpan } from '../../utils/with_apm_span';
@ -18,9 +17,10 @@ import { fetchDurationHistogramRangeSteps } from '../correlations/queries/fetch_
import { getPercentileThresholdValue } from './get_percentile_threshold_value';
import type { OverallLatencyDistributionResponse } from './types';
import { LatencyDistributionChartType } from '../../../common/latency_distribution_chart_types';
export async function getOverallLatencyDistribution({
eventType,
chartType,
setup,
start,
end,
@ -28,8 +28,9 @@ export async function getOverallLatencyDistribution({
kuery,
query,
percentileThreshold,
searchMetrics,
}: {
eventType: ProcessorEvent;
chartType: LatencyDistributionChartType;
setup: Setup;
start: number;
end: number;
@ -37,6 +38,7 @@ export async function getOverallLatencyDistribution({
kuery: string;
query: estypes.QueryDslQueryContainer;
percentileThreshold: number;
searchMetrics: boolean;
}) {
return withApmSpan('get_overall_latency_distribution', async () => {
const overallLatencyDistribution: OverallLatencyDistributionResponse = {};
@ -44,7 +46,7 @@ export async function getOverallLatencyDistribution({
// #1: get 95th percentile to be displayed as a marker in the log log chart
overallLatencyDistribution.percentileThresholdValue =
await getPercentileThresholdValue({
eventType,
chartType,
setup,
start,
end,
@ -52,6 +54,7 @@ export async function getOverallLatencyDistribution({
kuery,
query,
percentileThreshold,
searchMetrics,
});
// finish early if we weren't able to identify the percentileThresholdValue.
@ -61,13 +64,14 @@ export async function getOverallLatencyDistribution({
// #2: get histogram range steps
const rangeSteps = await fetchDurationHistogramRangeSteps({
eventType,
chartType,
setup,
start,
end,
environment,
kuery,
query,
searchMetrics,
});
if (!rangeSteps) {
@ -77,7 +81,7 @@ export async function getOverallLatencyDistribution({
// #3: get histogram chart data
const { totalDocCount, durationRanges } = await fetchDurationRanges({
eventType,
chartType,
setup,
start,
end,
@ -85,6 +89,7 @@ export async function getOverallLatencyDistribution({
kuery,
query,
rangeSteps,
searchMetrics,
});
overallLatencyDistribution.totalDocCount = totalDocCount;

View file

@ -6,32 +6,35 @@
*/
import { CommonCorrelationsQueryParams } from '../../../common/correlations/types';
import { ProcessorEvent } from '../../../common/processor_event';
import { LatencyDistributionChartType } from '../../../common/latency_distribution_chart_types';
import { Setup } from '../../lib/helpers/setup_request';
import { fetchDurationPercentiles } from '../correlations/queries/fetch_duration_percentiles';
export async function getPercentileThresholdValue({
setup,
eventType,
chartType,
start,
end,
environment,
kuery,
query,
percentileThreshold,
searchMetrics,
}: CommonCorrelationsQueryParams & {
setup: Setup;
eventType: ProcessorEvent;
chartType: LatencyDistributionChartType;
percentileThreshold: number;
searchMetrics: boolean;
}) {
const durationPercentiles = await fetchDurationPercentiles({
setup,
eventType,
chartType,
start,
end,
environment,
kuery,
query,
searchMetrics,
});
return durationPercentiles.percentiles[`${percentileThreshold}.0`];

View file

@ -11,6 +11,7 @@ import { termQuery } from '@kbn/observability-plugin/server';
import { QueryDslQueryContainer } from '@elastic/elasticsearch/lib/api/typesWithBodyKey';
import { getOverallLatencyDistribution } from './get_overall_latency_distribution';
import { setupRequest } from '../../lib/helpers/setup_request';
import { getSearchAggregatedTransactions } from '../../lib/helpers/transactions';
import { createApmServerRoute } from '../apm_routes/create_apm_server_route';
import { environmentRt, kueryRt, rangeRt } from '../default_api_types';
import {
@ -18,7 +19,10 @@ import {
TRANSACTION_NAME,
TRANSACTION_TYPE,
} from '../../../common/elasticsearch_fieldnames';
import { ProcessorEvent } from '../../../common/processor_event';
import {
latencyDistributionChartTypeRt,
LatencyDistributionChartType,
} from '../../../common/latency_distribution_chart_types';
const latencyOverallTransactionDistributionRoute = createApmServerRoute({
endpoint: 'POST /internal/apm/latency/overall_distribution/transactions',
@ -40,6 +44,7 @@ const latencyOverallTransactionDistributionRoute = createApmServerRoute({
rangeRt,
t.type({
percentileThreshold: toNumberRt,
chartType: latencyDistributionChartTypeRt,
}),
]),
}),
@ -59,11 +64,23 @@ const latencyOverallTransactionDistributionRoute = createApmServerRoute({
end,
percentileThreshold,
termFilters,
chartType,
} = resources.params.body;
// only the transaction latency distribution chart can use metrics data
const searchAggregatedTransactions =
chartType === LatencyDistributionChartType.transactionLatency
? await getSearchAggregatedTransactions({
...setup,
kuery,
start,
end,
})
: false;
return getOverallLatencyDistribution({
setup,
eventType: ProcessorEvent.transaction,
chartType,
environment,
kuery,
start,
@ -82,6 +99,7 @@ const latencyOverallTransactionDistributionRoute = createApmServerRoute({
},
},
percentileThreshold,
searchMetrics: searchAggregatedTransactions,
});
},
});

View file

@ -10,6 +10,7 @@ import expect from '@kbn/expect';
import type { FailedTransactionsCorrelationsResponse } from '@kbn/apm-plugin/common/correlations/failed_transactions_correlations/types';
import { EVENT_OUTCOME } from '@kbn/apm-plugin/common/elasticsearch_fieldnames';
import { EventOutcome } from '@kbn/apm-plugin/common/event_outcome';
import { LatencyDistributionChartType } from '@kbn/apm-plugin/common/latency_distribution_chart_types';
import { FtrProviderContext } from '../../common/ftr_provider_context';
// These tests go through the full sequence of queries required
@ -34,6 +35,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
body: {
...getOptions(),
percentileThreshold: 95,
chartType: LatencyDistributionChartType.failedTransactionsCorrelations,
},
},
});
@ -50,6 +52,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
...getOptions(),
percentileThreshold: 95,
termFilters: [{ fieldName: EVENT_OUTCOME, fieldValue: EventOutcome.failure }],
chartType: LatencyDistributionChartType.failedTransactionsCorrelations,
},
},
});
@ -109,6 +112,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
body: {
...getOptions(),
percentileThreshold: 95,
chartType: LatencyDistributionChartType.failedTransactionsCorrelations,
},
},
});
@ -125,6 +129,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
...getOptions(),
percentileThreshold: 95,
termFilters: [{ fieldName: EVENT_OUTCOME, fieldValue: EventOutcome.failure }],
chartType: LatencyDistributionChartType.failedTransactionsCorrelations,
},
},
});

View file

@ -13,6 +13,7 @@ import type {
LatencyCorrelation,
LatencyCorrelationsResponse,
} from '@kbn/apm-plugin/common/correlations/latency_correlations/types';
import { LatencyDistributionChartType } from '@kbn/apm-plugin/common/latency_distribution_chart_types';
import { FtrProviderContext } from '../../common/ftr_provider_context';
// These tests go through the full sequence of queries required
@ -40,6 +41,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
body: {
...getOptions(),
percentileThreshold: 95,
chartType: LatencyDistributionChartType.latencyCorrelations,
},
},
});
@ -117,6 +119,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
body: {
...getOptions(),
percentileThreshold: 95,
chartType: LatencyDistributionChartType.latencyCorrelations,
},
},
});

View file

@ -6,6 +6,7 @@
*/
import expect from '@kbn/expect';
import { LatencyDistributionChartType } from '@kbn/apm-plugin/common/latency_distribution_chart_types';
import { FtrProviderContext } from '../../common/ftr_provider_context';
export default function ApiTest({ getService }: FtrProviderContext) {
@ -23,6 +24,7 @@ export default function ApiTest({ getService }: FtrProviderContext) {
end: '2021',
kuery: '',
percentileThreshold: 95,
chartType: LatencyDistributionChartType.transactionLatency,
},
},
});