From 7d0587513ea9cc6fc9cf33da2689dbdb26e65f2d Mon Sep 17 00:00:00 2001 From: Dario Gieselaar Date: Thu, 19 Nov 2020 12:18:30 +0100 Subject: [PATCH] Reorganize getServiceTransactionGroups --- .../index.tsx | 12 +- ..._timeseries_data_for_transaction_groups.ts | 134 +++++++ .../get_transaction_groups_for_page.ts | 163 +++++++++ .../get_service_transaction_groups/index.ts | 326 +++--------------- .../merge_transaction_group_data.ts | 98 ++++++ x-pack/plugins/apm/server/routes/services.ts | 2 +- .../service_overview/transaction_groups.ts | 31 +- 7 files changed, 462 insertions(+), 304 deletions(-) create mode 100644 x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_timeseries_data_for_transaction_groups.ts create mode 100644 x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts create mode 100644 x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx index 6a95ce2fe36f9..42e0449475f53 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_transactions_table/index.tsx @@ -38,14 +38,14 @@ import { ServiceOverviewTable } from '../service_overview_table'; type ServiceTransactionGroupItem = ValuesType< APIReturnType< 'GET /api/apm/services/{serviceName}/overview_transaction_groups' - >['transaction_groups'] + >['transactionGroups'] >; interface Props { serviceName: string; } -type SortField = 'latency' | 'traffic' | 'error_rate' | 'impact'; +type SortField = 'latency' | 'traffic' | 'errorRate' | 'impact'; type SortDirection = 'asc' | 'desc'; const PAGE_SIZE = 5; @@ -118,8 +118,8 @@ export function ServiceOverviewTransactionsTable(props: Props) { }, }).then((response) => { return { - items: response.transaction_groups, - totalItemCount: response.total_transaction_groups, + items: response.transactionGroups, + totalItemCount: response.totalTransactionGroups, tableOptions: { pageIndex: tableOptions.pageIndex, sort: { @@ -154,7 +154,7 @@ export function ServiceOverviewTransactionsTable(props: Props) { defaultMessage: 'Name', } ), - render: (_, { name, transaction_type: transactionType }) => { + render: (_, { name, transactionType }) => { return ( @@ -223,7 +223,7 @@ export function ServiceOverviewTransactionsTable(props: Props) { } ), width: px(unit * 8), - render: (_, { error_rate: errorRate }) => { + render: (_, { errorRate }) => { return ( ; + +export async function getTimeseriesDataForTransactionGroups({ + apmEventClient, + start, + end, + serviceName, + transactionNames, + esFilter, + searchAggregatedTransactions, + size, + numBuckets, +}: { + apmEventClient: APMEventClient; + start: number; + end: number; + serviceName: string; + transactionNames: string[]; + esFilter: ESFilter[]; + searchAggregatedTransactions: boolean; + size: number; + numBuckets: number; +}) { + const { intervalString } = getBucketSize(start, end, numBuckets); + + const timeseriesResponse = await apmEventClient.search({ + apm: { + events: [ + getProcessorEventForAggregatedTransactions( + searchAggregatedTransactions + ), + ], + }, + body: { + size: 0, + query: { + bool: { + filter: [ + { terms: { [TRANSACTION_NAME]: transactionNames } }, + { term: { [SERVICE_NAME]: serviceName } }, + { range: rangeFilter(start, end) }, + ...esFilter, + ], + }, + }, + aggs: { + transaction_groups: { + terms: { + field: TRANSACTION_NAME, + size, + }, + aggs: { + transaction_types: { + terms: { + field: TRANSACTION_TYPE, + }, + }, + timeseries: { + date_histogram: { + field: '@timestamp', + fixed_interval: intervalString, + min_doc_count: 0, + extended_bounds: { + min: start, + max: end, + }, + }, + aggs: { + avg_latency: { + avg: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + transaction_count: { + value_count: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + [EVENT_OUTCOME]: { + filter: { + term: { + [EVENT_OUTCOME]: EventOutcome.failure, + }, + }, + aggs: { + transaction_count: { + value_count: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, + }); + + return timeseriesResponse.aggregations?.transaction_groups.buckets ?? []; +} diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts new file mode 100644 index 0000000000000..c8ec6dc326585 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/get_transaction_groups_for_page.ts @@ -0,0 +1,163 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ +import { orderBy } from 'lodash'; +import { ValuesType } from 'utility-types'; +import { PromiseReturnType } from '../../../../../observability/typings/common'; +import { EventOutcome } from '../../../../common/event_outcome'; +import { ESFilter } from '../../../../../../typings/elasticsearch'; +import { rangeFilter } from '../../../../common/utils/range_filter'; +import { + EVENT_OUTCOME, + SERVICE_NAME, + TRANSACTION_NAME, +} from '../../../../common/elasticsearch_fieldnames'; +import { + getProcessorEventForAggregatedTransactions, + getTransactionDurationFieldForAggregatedTransactions, +} from '../../helpers/aggregated_transactions'; +import { APMEventClient } from '../../helpers/create_es_client/create_apm_event_client'; +import { ServiceOverviewTransactionGroupSortField } from '.'; + +export type TransactionGroupWithoutTimeseriesData = ValuesType< + PromiseReturnType['transactionGroups'] +>; + +export async function getTransactionGroupsForPage({ + apmEventClient, + searchAggregatedTransactions, + serviceName, + start, + end, + esFilter, + sortField, + sortDirection, + pageIndex, + size, +}: { + apmEventClient: APMEventClient; + searchAggregatedTransactions: boolean; + serviceName: string; + start: number; + end: number; + esFilter: ESFilter[]; + sortField: ServiceOverviewTransactionGroupSortField; + sortDirection: 'asc' | 'desc'; + pageIndex: number; + size: number; +}) { + const response = await apmEventClient.search({ + apm: { + events: [ + getProcessorEventForAggregatedTransactions( + searchAggregatedTransactions + ), + ], + }, + body: { + size: 0, + query: { + bool: { + filter: [ + { term: { [SERVICE_NAME]: serviceName } }, + { range: rangeFilter(start, end) }, + ...esFilter, + ], + }, + }, + aggs: { + transaction_groups: { + terms: { + field: TRANSACTION_NAME, + size: 500, + order: { + _count: 'desc', + }, + }, + aggs: { + avg_latency: { + avg: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + transaction_count: { + value_count: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + [EVENT_OUTCOME]: { + filter: { + term: { + [EVENT_OUTCOME]: EventOutcome.failure, + }, + }, + aggs: { + transaction_count: { + value_count: { + field: getTransactionDurationFieldForAggregatedTransactions( + searchAggregatedTransactions + ), + }, + }, + }, + }, + }, + }, + }, + }, + }); + + const transactionGroups = + response.aggregations?.transaction_groups.buckets.map((bucket) => { + const errorRate = + bucket.transaction_count.value > 0 + ? (bucket[EVENT_OUTCOME].transaction_count.value ?? 0) / + bucket.transaction_count.value + : null; + + return { + name: bucket.key as string, + latency: bucket.avg_latency.value, + traffic: bucket.transaction_count.value, + errorRate, + }; + }) ?? []; + + const totalDurationValues = transactionGroups.map( + (group) => (group.latency ?? 0) * group.traffic + ); + + const minTotalDuration = Math.min(...totalDurationValues); + const maxTotalDuration = Math.max(...totalDurationValues); + + const transactionGroupsWithImpact = transactionGroups.map((group) => ({ + ...group, + impact: + (((group.latency ?? 0) * group.traffic - minTotalDuration) / + (maxTotalDuration - minTotalDuration)) * + 100, + })); + + // Sort transaction groups first, and only get timeseries for data in view. + // This is to limit the possibility of creating too many buckets. + + const sortedAndSlicedTransactionGroups = orderBy( + transactionGroupsWithImpact, + sortField, + [sortDirection] + ).slice(pageIndex * size, pageIndex * size + size); + + return { + transactionGroups: sortedAndSlicedTransactionGroups, + totalTransactionGroups: transactionGroups.length, + isAggregationAccurate: + (response.aggregations?.transaction_groups.sum_other_doc_count ?? 0) === + 0, + }; +} diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts index 2699ffa63c96d..e9dad22519b3c 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/index.ts @@ -4,25 +4,16 @@ * you may not use this file except in compliance with the Elastic License. */ -import { orderBy } from 'lodash'; -import { - TRANSACTION_PAGE_LOAD, - TRANSACTION_REQUEST, -} from '../../../../common/transaction_types'; -import { EventOutcome } from '../../../../common/event_outcome'; -import { rangeFilter } from '../../../../common/utils/range_filter'; -import { - EVENT_OUTCOME, - SERVICE_NAME, - TRANSACTION_NAME, - TRANSACTION_TYPE, -} from '../../../../common/elasticsearch_fieldnames'; import { Setup, SetupTimeRange } from '../../helpers/setup_request'; -import { getBucketSize } from '../../helpers/get_bucket_size'; -import { - getProcessorEventForAggregatedTransactions, - getTransactionDurationFieldForAggregatedTransactions, -} from '../../helpers/aggregated_transactions'; +import { getTimeseriesDataForTransactionGroups } from './get_timeseries_data_for_transaction_groups'; +import { getTransactionGroupsForPage } from './get_transaction_groups_for_page'; +import { mergeTransactionGroupData } from './merge_transaction_group_data'; + +export type ServiceOverviewTransactionGroupSortField = + | 'latency' + | 'traffic' + | 'errorRate' + | 'impact'; export async function getServiceTransactionGroups({ serviceName, @@ -40,277 +31,50 @@ export async function getServiceTransactionGroups({ pageIndex: number; numBuckets: number; sortDirection: 'asc' | 'desc'; - sortField: 'latency' | 'traffic' | 'error_rate' | 'impact'; + sortField: ServiceOverviewTransactionGroupSortField; searchAggregatedTransactions: boolean; }) { const { apmEventClient, start, end, esFilter } = setup; - const { intervalString } = getBucketSize(start, end, numBuckets); - - const response = await apmEventClient.search({ - apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], - }, - body: { - size: 0, - query: { - bool: { - filter: [ - { term: { [SERVICE_NAME]: serviceName } }, - { range: rangeFilter(start, end) }, - ...esFilter, - ], - }, - }, - aggs: { - transaction_groups: { - terms: { - field: TRANSACTION_NAME, - size: 500, - order: { - _count: 'desc', - }, - }, - aggs: { - avg_latency: { - avg: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - transaction_count: { - value_count: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - [EVENT_OUTCOME]: { - terms: { - field: EVENT_OUTCOME, - }, - aggs: { - transaction_count: { - value_count: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - }, - }, - }, - }, - }, - }, - }); - - const transactionGroups = - response.aggregations?.transaction_groups.buckets.map((bucket) => ({ - name: bucket.key as string, - latency: bucket.avg_latency.value, - traffic: bucket.transaction_count.value, - error_rate: - bucket.transaction_count.value > 0 - ? (bucket[EVENT_OUTCOME].buckets.find( - (outcomeBucket) => outcomeBucket.key === EventOutcome.failure - )?.transaction_count.value ?? 0) / bucket.transaction_count.value - : null, - })) ?? []; - - const totalDurationValues = transactionGroups.map( - (group) => (group.latency ?? 0) * group.traffic - ); - - const minTotalDuration = Math.min(...totalDurationValues); - const maxTotalDuration = Math.max(...totalDurationValues); - - const transactionGroupsWithImpact = transactionGroups.map((group) => ({ - ...group, - impact: - (((group.latency ?? 0) * group.traffic - minTotalDuration) / - (maxTotalDuration - minTotalDuration)) * - 100, - })); - - // Sort transaction groups first, and only get timeseries for data in view. - // This is to limit the possibility of creating too many buckets. - - const sortedAndSlicedTransactionGroups = orderBy( - transactionGroupsWithImpact, + const { + transactionGroups, + totalTransactionGroups, + isAggregationAccurate, + } = await getTransactionGroupsForPage({ + apmEventClient, + start, + end, + serviceName, + esFilter, + pageIndex, sortField, - [sortDirection] - ).slice(pageIndex * size, pageIndex * size + size); - - const sortedTransactionGroupNames = sortedAndSlicedTransactionGroups.map( - (group) => group.name - ); - - const timeseriesResponse = await apmEventClient.search({ - apm: { - events: [ - getProcessorEventForAggregatedTransactions( - searchAggregatedTransactions - ), - ], - }, - body: { - size: 0, - query: { - bool: { - filter: [ - { terms: { [TRANSACTION_NAME]: sortedTransactionGroupNames } }, - { term: { [SERVICE_NAME]: serviceName } }, - { range: rangeFilter(start, end) }, - ...esFilter, - ], - }, - }, - aggs: { - transaction_groups: { - terms: { - field: TRANSACTION_NAME, - size, - }, - aggs: { - transaction_types: { - terms: { - field: TRANSACTION_TYPE, - }, - }, - timeseries: { - date_histogram: { - field: '@timestamp', - fixed_interval: intervalString, - min_doc_count: 0, - extended_bounds: { - min: start, - max: end, - }, - }, - aggs: { - avg_latency: { - avg: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - transaction_count: { - value_count: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - [EVENT_OUTCOME]: { - terms: { - field: EVENT_OUTCOME, - }, - aggs: { - transaction_count: { - value_count: { - field: getTransactionDurationFieldForAggregatedTransactions( - searchAggregatedTransactions - ), - }, - }, - }, - }, - }, - }, - }, - }, - }, - }, + sortDirection, + size, + searchAggregatedTransactions, }); - const deltaAsMinutes = (end - start) / 1000 / 60; - - const transactionGroupsWithAllData = sortedAndSlicedTransactionGroups.map( - (transactionGroup) => { - const groupBucket = timeseriesResponse.aggregations?.transaction_groups.buckets.find( - ({ key }) => key === transactionGroup.name - ); - - const transactionTypes = - groupBucket?.transaction_types.buckets.map( - (bucket) => bucket.key as string - ) ?? []; - - const transactionType = - transactionTypes.find( - (type) => - type === TRANSACTION_PAGE_LOAD || type === TRANSACTION_REQUEST - ) ?? transactionTypes[0]; - - const timeseriesBuckets = groupBucket?.timeseries.buckets ?? []; - - return timeseriesBuckets.reduce( - (prev, point) => { - return { - ...prev, - latency: { - ...prev.latency, - timeseries: prev.latency.timeseries.concat({ - x: point.key, - y: point.avg_latency.value, - }), - }, - traffic: { - ...prev.traffic, - timeseries: prev.traffic.timeseries.concat({ - x: point.key, - y: point.transaction_count.value / deltaAsMinutes, - }), - }, - error_rate: { - ...prev.error_rate, - timeseries: prev.error_rate.timeseries.concat({ - x: point.key, - y: - point.transaction_count.value > 0 - ? (point[EVENT_OUTCOME].buckets.find( - (outcomeBucket) => - outcomeBucket.key === EventOutcome.failure - )?.transaction_count.value ?? 0) / - point.transaction_count.value - : null, - }), - }, - }; - }, - { - name: transactionGroup.name, - transaction_type: transactionType, - latency: { - value: transactionGroup.latency, - timeseries: [] as Array<{ x: number; y: number | null }>, - }, - traffic: { - value: transactionGroup.traffic, - timeseries: [] as Array<{ x: number; y: number }>, - }, - error_rate: { - value: transactionGroup.error_rate, - timeseries: [] as Array<{ x: number; y: number | null }>, - }, - impact: transactionGroup.impact, - } - ); - } - ); + const transactionNames = transactionGroups.map((group) => group.name); + + const timeseriesData = await getTimeseriesDataForTransactionGroups({ + apmEventClient, + start, + end, + esFilter, + numBuckets, + searchAggregatedTransactions, + serviceName, + size, + transactionNames, + }); return { - total_transaction_groups: transactionGroups.length, - is_aggregation_accurate: - (response.aggregations?.transaction_groups.sum_other_doc_count ?? 0) === - 0, - transaction_groups: transactionGroupsWithAllData, + transactionGroups: mergeTransactionGroupData({ + transactionGroups, + timeseriesData, + start, + end, + }), + totalTransactionGroups, + isAggregationAccurate, }; } diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts new file mode 100644 index 0000000000000..6ceb52b93d212 --- /dev/null +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_groups/merge_transaction_group_data.ts @@ -0,0 +1,98 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License; + * you may not use this file except in compliance with the Elastic License. + */ + +import { EVENT_OUTCOME } from '../../../../common/elasticsearch_fieldnames'; + +import { + TRANSACTION_PAGE_LOAD, + TRANSACTION_REQUEST, +} from '../../../../common/transaction_types'; + +import { TransactionGroupTimeseriesData } from './get_timeseries_data_for_transaction_groups'; + +import { TransactionGroupWithoutTimeseriesData } from './get_transaction_groups_for_page'; + +export function mergeTransactionGroupData({ + start, + end, + transactionGroups, + timeseriesData, +}: { + start: number; + end: number; + transactionGroups: TransactionGroupWithoutTimeseriesData[]; + timeseriesData: TransactionGroupTimeseriesData; +}) { + const deltaAsMinutes = (end - start) / 1000 / 60; + + return transactionGroups.map((transactionGroup) => { + const groupBucket = timeseriesData.find( + ({ key }) => key === transactionGroup.name + ); + + const transactionTypes = + groupBucket?.transaction_types.buckets.map( + (bucket) => bucket.key as string + ) ?? []; + + const transactionType = + transactionTypes.find( + (type) => type === TRANSACTION_PAGE_LOAD || type === TRANSACTION_REQUEST + ) ?? transactionTypes[0]; + + const timeseriesBuckets = groupBucket?.timeseries.buckets ?? []; + + return timeseriesBuckets.reduce( + (prev, point) => { + return { + ...prev, + latency: { + ...prev.latency, + timeseries: prev.latency.timeseries.concat({ + x: point.key, + y: point.avg_latency.value, + }), + }, + traffic: { + ...prev.traffic, + timeseries: prev.traffic.timeseries.concat({ + x: point.key, + y: point.transaction_count.value / deltaAsMinutes, + }), + }, + errorRate: { + ...prev.errorRate, + timeseries: prev.errorRate.timeseries.concat({ + x: point.key, + y: + point.transaction_count.value > 0 + ? (point[EVENT_OUTCOME].transaction_count.value ?? 0) / + point.transaction_count.value + : null, + }), + }, + }; + }, + { + name: transactionGroup.name, + transactionType, + latency: { + value: transactionGroup.latency, + timeseries: [] as Array<{ x: number; y: number | null }>, + }, + traffic: { + value: transactionGroup.traffic, + timeseries: [] as Array<{ x: number; y: number }>, + }, + errorRate: { + value: transactionGroup.errorRate, + timeseries: [] as Array<{ x: number; y: number | null }>, + }, + impact: transactionGroup.impact, + } + ); + }); +} diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index 764dfecbe5118..b8d474d6cca18 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -255,7 +255,7 @@ export const serviceTransactionGroupsRoute = createRoute({ sortField: t.union([ t.literal('latency'), t.literal('traffic'), - t.literal('error_rate'), + t.literal('errorRate'), t.literal('impact'), ]), }), diff --git a/x-pack/test/apm_api_integration/basic/tests/service_overview/transaction_groups.ts b/x-pack/test/apm_api_integration/basic/tests/service_overview/transaction_groups.ts index 1b011eb25ef69..a80bdd7502ef6 100644 --- a/x-pack/test/apm_api_integration/basic/tests/service_overview/transaction_groups.ts +++ b/x-pack/test/apm_api_integration/basic/tests/service_overview/transaction_groups.ts @@ -7,7 +7,6 @@ import expect from '@kbn/expect'; import { pick, uniqBy } from 'lodash'; import url from 'url'; -import { expectSnapshot } from '../../../common/match_snapshot'; import { FtrProviderContext } from '../../../../common/ftr_provider_context'; import archives from '../../../common/archives_metadata'; @@ -39,9 +38,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); expect(response.body).to.eql({ - total_transaction_groups: 0, - transaction_groups: [], - is_aggregation_accurate: true, + totalTransactionGroups: 0, + transactionGroups: [], + isAggregationAccurate: true, }); }); }); @@ -69,9 +68,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); - expectSnapshot(response.body.total_transaction_groups).toMatchInline(`12`); + expectSnapshot(response.body.totalTransactionGroups).toMatchInline(`12`); - expectSnapshot(response.body.transaction_groups.map((group: any) => group.name)) + expectSnapshot(response.body.transactionGroups.map((group: any) => group.name)) .toMatchInline(` Array [ "DispatcherServlet#doGet", @@ -82,7 +81,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ] `); - expectSnapshot(response.body.transaction_groups.map((group: any) => group.impact)) + expectSnapshot(response.body.transactionGroups.map((group: any) => group.impact)) .toMatchInline(` Array [ 100, @@ -93,13 +92,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { ] `); - const firstItem = response.body.transaction_groups[0]; + const firstItem = response.body.transactionGroups[0]; expectSnapshot( - pick(firstItem, 'name', 'latency.value', 'traffic.value', 'error_rate.value', 'impact') + pick(firstItem, 'name', 'latency.value', 'traffic.value', 'errorRate.value', 'impact') ).toMatchInline(` Object { - "error_rate": Object { + "errorRate": Object { "value": 0.107142857142857, }, "impact": 100, @@ -122,7 +121,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { ).toMatchInline(`15`); expectSnapshot( - firstItem.error_rate.timeseries.filter(({ y }: any) => y > 0).length + firstItem.errorRate.timeseries.filter(({ y }: any) => y > 0).length ).toMatchInline(`3`); }); @@ -145,7 +144,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(descendingResponse.status).to.be(200); - const descendingOccurrences = descendingResponse.body.transaction_groups.map( + const descendingOccurrences = descendingResponse.body.transactionGroups.map( (item: any) => item.impact ); @@ -167,7 +166,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }) ); - const ascendingOccurrences = ascendingResponse.body.transaction_groups.map( + const ascendingOccurrences = ascendingResponse.body.transactionGroups.map( (item: any) => item.impact ); @@ -193,7 +192,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); - const latencies = response.body.transaction_groups.map((group: any) => group.latency.value); + const latencies = response.body.transactionGroups.map((group: any) => group.latency.value); expect(latencies).to.eql(latencies.concat().sort().reverse()); }); @@ -219,7 +218,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(firstPage.status).to.eql(200); - const totalItems = firstPage.body.total_transaction_groups; + const totalItems = firstPage.body.totalTransactionGroups; const pages = Math.floor(totalItems / size); @@ -244,7 +243,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }) ); - return prevItems.concat(thisPage.body.transaction_groups); + return prevItems.concat(thisPage.body.transactionGroups); }, Promise.resolve([])); expect(items.length).to.eql(totalItems);