diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts index 5c183fd9150dd0..7c2137ce65d839 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_service_node_info.ts @@ -96,10 +96,12 @@ async function getErrorStats({ setup, serviceName, environment, + searchAggregatedTransactions, }: { setup: Options['setup']; serviceName: string; environment?: string; + searchAggregatedTransactions: boolean; }) { const setupWithBlankUiFilters = { ...setup, @@ -108,6 +110,7 @@ async function getErrorStats({ const { noHits, average } = await getErrorRate({ setup: setupWithBlankUiFilters, serviceName, + searchAggregatedTransactions, }); return { avgErrorRate: noHits ? null : average }; } diff --git a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap index a65536df37bc85..431f11066aaff0 100644 --- a/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap +++ b/x-pack/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap @@ -277,6 +277,13 @@ Array [ "services": Object { "aggs": Object { "outcomes": Object { + "aggs": Object { + "count": Object { + "value_count": Object { + "field": "transaction.duration.us", + }, + }, + }, "terms": Object { "field": "event.outcome", }, @@ -284,6 +291,13 @@ Array [ "timeseries": Object { "aggs": Object { "outcomes": Object { + "aggs": Object { + "count": Object { + "value_count": Object { + "field": "transaction.duration.us", + }, + }, + }, "terms": Object { "field": "event.outcome", }, diff --git a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items_stats.ts b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items_stats.ts index 17799203fe73b9..65bc3f7e47171e 100644 --- a/x-pack/plugins/apm/server/lib/services/get_services/get_services_items_stats.ts +++ b/x-pack/plugins/apm/server/lib/services/get_services/get_services_items_stats.ts @@ -14,7 +14,6 @@ import { EVENT_OUTCOME, } from '../../../../common/elasticsearch_fieldnames'; import { mergeProjection } from '../../../projections/util/merge_projection'; -import { ProcessorEvent } from '../../../../common/processor_event'; import { ServicesItemsSetup, ServicesItemsProjection, @@ -258,6 +257,7 @@ export const getTransactionRates = async ({ export const getTransactionErrorRates = async ({ setup, projection, + searchAggregatedTransactions, }: AggregationParams) => { const { apmEventClient, start, end } = setup; @@ -265,12 +265,25 @@ export const getTransactionErrorRates = async ({ terms: { field: EVENT_OUTCOME, }, + aggs: { + count: { + value_count: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + }, }; const response = await apmEventClient.search( mergeProjection(projection, { apm: { - events: [ProcessorEvent.transaction], + events: [ + getProcessorEventForAggregatedTransactions( + searchAggregatedTransactions + ), + ], }, body: { size: 0, @@ -319,11 +332,11 @@ export const getTransactionErrorRates = async ({ const successfulTransactions = outcomeResponse.buckets.find( (bucket) => bucket.key === EventOutcome.success - )?.doc_count ?? 0; + )?.count.value ?? 0; const failedTransactions = outcomeResponse.buckets.find( (bucket) => bucket.key === EventOutcome.failure - )?.doc_count ?? 0; + )?.count.value ?? 0; return failedTransactions / (successfulTransactions + failedTransactions); } diff --git a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts index 82595317342f15..3dc126c45d328a 100644 --- a/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts +++ b/x-pack/plugins/apm/server/lib/transaction_groups/get_error_rate.ts @@ -11,7 +11,6 @@ import { SERVICE_NAME, EVENT_OUTCOME, } from '../../../common/elasticsearch_fieldnames'; -import { ProcessorEvent } from '../../../common/processor_event'; import { rangeFilter } from '../../../common/utils/range_filter'; import { Setup, @@ -19,17 +18,23 @@ import { SetupUIFilters, } from '../helpers/setup_request'; import { getBucketSize } from '../helpers/get_bucket_size'; +import { + getProcessorEventForAggregatedTransactions, + getTransactionDurationFieldForAggregatedTransactions, +} from '../helpers/aggregated_transactions'; export async function getErrorRate({ serviceName, transactionType, transactionName, setup, + searchAggregatedTransactions, }: { serviceName: string; transactionType?: string; transactionName?: string; setup: Setup & SetupTimeRange & SetupUIFilters; + searchAggregatedTransactions: boolean; }) { const { start, end, uiFiltersES, apmEventClient } = setup; @@ -53,7 +58,11 @@ export async function getErrorRate({ const params = { apm: { - events: [ProcessorEvent.transaction], + events: [ + getProcessorEventForAggregatedTransactions( + searchAggregatedTransactions + ), + ], }, body: { size: 0, @@ -67,8 +76,19 @@ export async function getErrorRate({ extended_bounds: { min: start, max: end }, }, aggs: { - erroneous_transactions: { - filter: { term: { [EVENT_OUTCOME]: EventOutcome.failure } }, + [EVENT_OUTCOME]: { + terms: { + field: EVENT_OUTCOME, + }, + aggs: { + count: { + value_count: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + }, }, }, }, @@ -81,18 +101,24 @@ export async function getErrorRate({ const noHits = resp.hits.total.value === 0; const erroneousTransactionsRate = - resp.aggregations?.total_transactions.buckets.map( - ({ - key, - doc_count: totalTransactions, - erroneous_transactions: erroneousTransactions, - }) => { - return { - x: key, - y: erroneousTransactions.doc_count / totalTransactions, - }; - } - ) || []; + resp.aggregations?.total_transactions.buckets.map((bucket) => { + const successful = + bucket[EVENT_OUTCOME].buckets.find( + (eventOutcomeBucket) => + eventOutcomeBucket.key === EventOutcome.success + )?.count.value ?? 0; + + const failed = + bucket[EVENT_OUTCOME].buckets.find( + (eventOutcomeBucket) => + eventOutcomeBucket.key === EventOutcome.failure + )?.count.value ?? 0; + + return { + x: bucket.key, + y: failed / (successful + failed), + }; + }) || []; const average = mean( erroneousTransactionsRate diff --git a/x-pack/plugins/apm/server/routes/transaction_groups.ts b/x-pack/plugins/apm/server/routes/transaction_groups.ts index 888c4363f77b97..10e917f385e719 100644 --- a/x-pack/plugins/apm/server/routes/transaction_groups.ts +++ b/x-pack/plugins/apm/server/routes/transaction_groups.ts @@ -210,11 +210,17 @@ export const transactionGroupsErrorRateRoute = createRoute(() => ({ const { params } = context; const { serviceName } = params.path; const { transactionType, transactionName } = params.query; + + const searchAggregatedTransactions = await getSearchAggregatedTransactions( + setup + ); + return getErrorRate({ serviceName, transactionType, transactionName, setup, + searchAggregatedTransactions, }); }, }));