diff --git a/x-pack/plugins/apm/common/utils/formatters/duration.ts b/x-pack/plugins/apm/common/utils/formatters/duration.ts index a068e6ca7f38a..b060f1aa6e005 100644 --- a/x-pack/plugins/apm/common/utils/formatters/duration.ts +++ b/x-pack/plugins/apm/common/utils/formatters/duration.ts @@ -13,6 +13,8 @@ import { asDecimalOrInteger, asInteger, asDecimal } from './formatters'; import { TimeUnit } from './datetime'; import { Maybe } from '../../../typings/common'; import { isFiniteNumber } from '../is_finite_number'; +// eslint-disable-next-line @kbn/eslint/no-restricted-paths +import type { ThroughputUnit } from '../../../server/lib/helpers/calculate_throughput'; interface FormatterOptions { defaultValue?: string; @@ -161,10 +163,15 @@ export function asTransactionRate(value: Maybe) { } return i18n.translate('xpack.apm.transactionRateLabel', { - defaultMessage: `{value} tpm`, - values: { - value: displayedValue, - }, + defaultMessage: `{displayedValue} tpm`, + values: { displayedValue }, + }); +} + +export function asExactTransactionRate(value: number, unit: ThroughputUnit) { + return i18n.translate('xpack.apm.exactTransactionRateLabel', { + defaultMessage: `{value} { unit, select, minute {tpm} other {tps} }`, + values: { value: asDecimalOrInteger(value), unit }, }); } diff --git a/x-pack/plugins/apm/common/utils/offset_previous_period_coordinate.ts b/x-pack/plugins/apm/common/utils/offset_previous_period_coordinate.ts index 4d095a79394a1..9300ec61fe42d 100644 --- a/x-pack/plugins/apm/common/utils/offset_previous_period_coordinate.ts +++ b/x-pack/plugins/apm/common/utils/offset_previous_period_coordinate.ts @@ -18,10 +18,7 @@ export function offsetPreviousPeriodCoordinates({ if (!previousPeriodTimeseries?.length) { return []; } - const currentPeriodStart = currentPeriodTimeseries?.length - ? currentPeriodTimeseries[0].x - : 0; - + const currentPeriodStart = currentPeriodTimeseries?.[0].x ?? 0; const dateDiff = currentPeriodStart - previousPeriodTimeseries[0].x; return previousPeriodTimeseries.map(({ x, y }) => { diff --git a/x-pack/plugins/apm/e2e/cypress/integration/csm_dashboard.feature b/x-pack/plugins/apm/e2e/cypress/integration/csm_dashboard.feature index 4ea7c72fbc9ad..4d68089417138 100644 --- a/x-pack/plugins/apm/e2e/cypress/integration/csm_dashboard.feature +++ b/x-pack/plugins/apm/e2e/cypress/integration/csm_dashboard.feature @@ -30,11 +30,6 @@ Feature: CSM Dashboard Then should display percentile for page load chart And should display tooltip on hover - Scenario: Breakdown filter - Given a user clicks the page load breakdown filter - When the user selected the breakdown - Then breakdown series should appear in chart - Scenario: Search by url filter focus When a user clicks inside url search field Then it displays top pages in the suggestion popover diff --git a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx index 1d6c538570f8f..5eb130140ec90 100644 --- a/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx +++ b/x-pack/plugins/apm/public/components/app/service_overview/service_overview_throughput_chart.tsx @@ -5,10 +5,16 @@ * 2.0. */ -import { EuiPanel, EuiTitle } from '@elastic/eui'; +import { + EuiPanel, + EuiTitle, + EuiIconTip, + EuiFlexItem, + EuiFlexGroup, +} from '@elastic/eui'; import { i18n } from '@kbn/i18n'; import React from 'react'; -import { asTransactionRate } from '../../../../common/utils/formatters'; +import { asExactTransactionRate } from '../../../../common/utils/formatters'; import { useApmServiceContext } from '../../../context/apm_service/use_apm_service_context'; import { useUrlParams } from '../../../context/url_params_context/use_url_params'; import { useFetcher } from '../../../hooks/use_fetcher'; @@ -22,6 +28,7 @@ import { const INITIAL_STATE = { currentPeriod: [], previousPeriod: [], + throughputUnit: 'minute' as const, }; export function ServiceOverviewThroughputChart({ @@ -111,20 +118,49 @@ export function ServiceOverviewThroughputChart({ return ( - -

- {i18n.translate('xpack.apm.serviceOverview.throughtputChartTitle', { - defaultMessage: 'Throughput', - })} -

-
+ + + +

+ {i18n.translate( + 'xpack.apm.serviceOverview.throughtputChartTitle', + { defaultMessage: 'Throughput' } + )} + {data.throughputUnit === 'second' + ? i18n.translate( + 'xpack.apm.serviceOverview.throughtputPerSecondChartTitle', + { defaultMessage: '(per second)' } + ) + : ''} +

+
+
+ + + + +
+ asExactTransactionRate(y, data.throughputUnit)} customTheme={comparisonChartTheme} />
diff --git a/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts index d09f5d9d3f113..1b9e1b56830af 100644 --- a/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts +++ b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts @@ -15,3 +15,8 @@ export function calculateThroughput({ const durationAsMinutes = (end - start) / 1000 / 60; return value / durationAsMinutes; } + +export type ThroughputUnit = 'minute' | 'second'; +export function getThroughputUnit(bucketSize: number): ThroughputUnit { + return bucketSize >= 60 ? 'minute' : 'second'; +} diff --git a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts index 1e0c8e6f60441..d277967dad774 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_error_groups/get_service_error_group_detailed_statistics.ts @@ -159,7 +159,7 @@ export async function getServiceErrorGroupPeriods({ previousPeriodPromise, ]); - const firtCurrentPeriod = currentPeriod.length ? currentPeriod[0] : undefined; + const firstCurrentPeriod = currentPeriod?.[0]; return { currentPeriod: keyBy(currentPeriod, 'groupId'), @@ -167,7 +167,7 @@ export async function getServiceErrorGroupPeriods({ previousPeriod.map((errorRateGroup) => ({ ...errorRateGroup, timeseries: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.timeseries, + currentPeriodTimeseries: firstCurrentPeriod?.timeseries, previousPeriodTimeseries: errorRateGroup.timeseries, }), })), diff --git a/x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts index 804ed91c54a51..fc91efbc7c6e6 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_instances/detailed_statistics.ts @@ -123,9 +123,7 @@ export async function getServiceInstancesDetailedStatisticsPeriods({ previousPeriodPromise, ]); - const firtCurrentPeriod = currentPeriod.length - ? currentPeriod[0] - : undefined; + const firstCurrentPeriod = currentPeriod?.[0]; return { currentPeriod: keyBy(currentPeriod, 'serviceNodeName'), @@ -134,23 +132,23 @@ export async function getServiceInstancesDetailedStatisticsPeriods({ return { ...data, cpuUsage: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.cpuUsage, + currentPeriodTimeseries: firstCurrentPeriod?.cpuUsage, previousPeriodTimeseries: data.cpuUsage, }), errorRate: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.errorRate, + currentPeriodTimeseries: firstCurrentPeriod?.errorRate, previousPeriodTimeseries: data.errorRate, }), latency: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.latency, + currentPeriodTimeseries: firstCurrentPeriod?.latency, previousPeriodTimeseries: data.latency, }), memoryUsage: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.memoryUsage, + currentPeriodTimeseries: firstCurrentPeriod?.memoryUsage, previousPeriodTimeseries: data.memoryUsage, }), throughput: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.throughput, + currentPeriodTimeseries: firstCurrentPeriod?.throughput, previousPeriodTimeseries: data.throughput, }), }; diff --git a/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts b/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts index 6edec60b6f373..d39b521e6ae97 100644 --- a/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts +++ b/x-pack/plugins/apm/server/lib/services/get_service_transaction_group_detailed_statistics.ts @@ -239,7 +239,7 @@ export async function getServiceTransactionGroupDetailedStatisticsPeriods({ previousPeriodPromise, ]); - const firtCurrentPeriod = currentPeriod.length ? currentPeriod[0] : undefined; + const firstCurrentPeriod = currentPeriod?.[0]; return { currentPeriod: keyBy(currentPeriod, 'transactionName'), @@ -248,15 +248,15 @@ export async function getServiceTransactionGroupDetailedStatisticsPeriods({ return { ...data, errorRate: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.errorRate, + currentPeriodTimeseries: firstCurrentPeriod?.errorRate, previousPeriodTimeseries: data.errorRate, }), throughput: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.throughput, + currentPeriodTimeseries: firstCurrentPeriod?.throughput, previousPeriodTimeseries: data.throughput, }), latency: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod?.latency, + currentPeriodTimeseries: firstCurrentPeriod?.latency, previousPeriodTimeseries: data.latency, }), }; diff --git a/x-pack/plugins/apm/server/lib/services/get_throughput.ts b/x-pack/plugins/apm/server/lib/services/get_throughput.ts index 4004d55da79f6..b7f265daeb465 100644 --- a/x-pack/plugins/apm/server/lib/services/get_throughput.ts +++ b/x-pack/plugins/apm/server/lib/services/get_throughput.ts @@ -16,7 +16,6 @@ import { getDocumentTypeFilterForAggregatedTransactions, getProcessorEventForAggregatedTransactions, } from '../helpers/aggregated_transactions'; -import { getBucketSizeForAggregatedTransactions } from '../helpers/get_bucket_size_for_aggregated_transactions'; import { Setup } from '../helpers/setup_request'; interface Options { @@ -28,9 +27,11 @@ interface Options { transactionType: string; start: number; end: number; + intervalString: string; + throughputUnit: 'minute' | 'second'; } -function fetcher({ +export async function getThroughput({ environment, kuery, searchAggregatedTransactions, @@ -39,13 +40,11 @@ function fetcher({ transactionType, start, end, + intervalString, + throughputUnit, }: Options) { const { apmEventClient } = setup; - const { intervalString } = getBucketSizeForAggregatedTransactions({ - start, - end, - searchAggregatedTransactions, - }); + const filter: ESFilter[] = [ { term: { [SERVICE_NAME]: serviceName } }, { term: { [TRANSACTION_TYPE]: transactionType } }, @@ -79,7 +78,7 @@ function fetcher({ aggs: { throughput: { rate: { - unit: 'minute' as const, + unit: throughputUnit, }, }, }, @@ -88,11 +87,10 @@ function fetcher({ }, }; - return apmEventClient.search('get_throughput_for_service', params); -} - -export async function getThroughput(options: Options) { - const response = await fetcher(options); + const response = await apmEventClient.search( + 'get_throughput_for_service', + params + ); return ( response.aggregations?.timeseries.buckets.map((bucket) => { 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 b27a54a983734..3184c58ce983a 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 @@ -183,16 +183,14 @@ export async function getErrorRatePeriods({ previousPeriodPromise, ]); - const firtCurrentPeriod = currentPeriod.transactionErrorRate.length - ? currentPeriod.transactionErrorRate - : undefined; + const firstCurrentPeriod = currentPeriod.transactionErrorRate; return { currentPeriod, previousPeriod: { ...previousPeriod, transactionErrorRate: offsetPreviousPeriodCoordinates({ - currentPeriodTimeseries: firtCurrentPeriod, + currentPeriodTimeseries: firstCurrentPeriod, previousPeriodTimeseries: previousPeriod.transactionErrorRate, }), }, diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index f5156fe85fbf5..6509c5764edb8 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -12,6 +12,7 @@ import { uniq } from 'lodash'; import { latencyAggregationTypeRt } from '../../common/latency_aggregation_types'; import { ProfilingValueType } from '../../common/profiling'; import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions'; +import { getThroughputUnit } from '../lib/helpers/calculate_throughput'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceAnnotations } from '../lib/services/annotations'; import { getServices } from '../lib/services/get_services'; @@ -43,6 +44,7 @@ import { import { offsetPreviousPeriodCoordinates } from '../../common/utils/offset_previous_period_coordinate'; import { getServicesDetailedStatistics } from '../lib/services/get_services_detailed_statistics'; import { getServiceDependenciesBreakdown } from '../lib/services/get_service_dependencies_breakdown'; +import { getBucketSizeForAggregatedTransactions } from '../lib/helpers/get_bucket_size_for_aggregated_transactions'; const servicesRoute = createApmServerRoute({ endpoint: 'GET /api/apm/services', @@ -451,6 +453,16 @@ const serviceThroughputRoute = createApmServerRoute({ }); const { start, end } = setup; + const { + bucketSize, + intervalString, + } = getBucketSizeForAggregatedTransactions({ + start, + end, + searchAggregatedTransactions, + }); + + const throughputUnit = getThroughputUnit(bucketSize); const commonProps = { environment, @@ -459,6 +471,8 @@ const serviceThroughputRoute = createApmServerRoute({ serviceName, setup, transactionType, + throughputUnit, + intervalString, }; const [currentPeriod, previousPeriod] = await Promise.all([ @@ -482,6 +496,7 @@ const serviceThroughputRoute = createApmServerRoute({ currentPeriodTimeseries: currentPeriod, previousPeriodTimeseries: previousPeriod, }), + throughputUnit, }; }, }); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index c8e3526005963..d383455a5f728 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6107,7 +6107,6 @@ "xpack.apm.transactionDurationLabel": "期間", "xpack.apm.transactionErrorRateAlert.name": "トランザクションエラー率しきい値", "xpack.apm.transactionErrorRateAlertTrigger.isAbove": "より大きい", - "xpack.apm.transactionRateLabel": "{value} tpm", "xpack.apm.transactions.latency.chart.95thPercentileLabel": "95 パーセンタイル", "xpack.apm.transactions.latency.chart.99thPercentileLabel": "99 パーセンタイル", "xpack.apm.transactions.latency.chart.averageLabel": "平均", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index cf31ec8d8eceb..6364af4b5b39f 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6141,7 +6141,6 @@ "xpack.apm.transactionDurationLabel": "持续时间", "xpack.apm.transactionErrorRateAlert.name": "事务错误率阈值", "xpack.apm.transactionErrorRateAlertTrigger.isAbove": "高于", - "xpack.apm.transactionRateLabel": "{value} tpm", "xpack.apm.transactions.latency.chart.95thPercentileLabel": "第 95 个百分位", "xpack.apm.transactions.latency.chart.99thPercentileLabel": "第 99 个百分位", "xpack.apm.transactions.latency.chart.averageLabel": "平均值", diff --git a/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap b/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap index a52084ffef43b..a27f7047bb9b3 100644 --- a/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap +++ b/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap @@ -1,135 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM API tests basic apm_8.0.0 Throughput when data is loaded has the correct throughput 1`] = ` -Array [ - Object { - "x": 1627973400000, - "y": 4, - }, - Object { - "x": 1627973460000, - "y": 2, - }, - Object { - "x": 1627973520000, - "y": 3, - }, - Object { - "x": 1627973580000, - "y": 8, - }, - Object { - "x": 1627973640000, - "y": 4, - }, - Object { - "x": 1627973700000, - "y": 4, - }, - Object { - "x": 1627973760000, - "y": 6, - }, - Object { - "x": 1627973820000, - "y": 10, - }, - Object { - "x": 1627973880000, - "y": 8, - }, - Object { - "x": 1627973940000, - "y": 9, - }, - Object { - "x": 1627974000000, - "y": 10, - }, - Object { - "x": 1627974060000, - "y": 11, - }, - Object { - "x": 1627974120000, - "y": 7, - }, - Object { - "x": 1627974180000, - "y": 10, - }, - Object { - "x": 1627974240000, - "y": 12, - }, - Object { - "x": 1627974300000, - "y": 6, - }, - Object { - "x": 1627974360000, - "y": 0, - }, - Object { - "x": 1627974420000, - "y": 4, - }, - Object { - "x": 1627974480000, - "y": 3, - }, - Object { - "x": 1627974540000, - "y": 5, - }, - Object { - "x": 1627974600000, - "y": 5, - }, - Object { - "x": 1627974660000, - "y": 5, - }, - Object { - "x": 1627974720000, - "y": 4, - }, - Object { - "x": 1627974780000, - "y": 7, - }, - Object { - "x": 1627974840000, - "y": 2, - }, - Object { - "x": 1627974900000, - "y": 14, - }, - Object { - "x": 1627974960000, - "y": 3, - }, - Object { - "x": 1627975020000, - "y": 6, - }, - Object { - "x": 1627975080000, - "y": 12, - }, - Object { - "x": 1627975140000, - "y": 8, - }, - Object { - "x": 1627975200000, - "y": 0, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Throughput when data is loaded with time comparison has the correct throughput 1`] = ` +exports[`APM API tests basic apm_8.0.0 Throughput when data is loaded with time comparison has the correct throughput in tpm 1`] = ` Object { "currentPeriod": Array [ Object { @@ -263,5 +134,6 @@ Object { "y": 0, }, ], + "throughputUnit": "minute", } `; diff --git a/x-pack/test/apm_api_integration/tests/services/throughput.ts b/x-pack/test/apm_api_integration/tests/services/throughput.ts index c9c7d43762e7e..2ecb9055baee4 100644 --- a/x-pack/test/apm_api_integration/tests/services/throughput.ts +++ b/x-pack/test/apm_api_integration/tests/services/throughput.ts @@ -6,32 +6,39 @@ */ import expect from '@kbn/expect'; -import qs from 'querystring'; -import { first, last } from 'lodash'; +import { first, last, mean } from 'lodash'; import moment from 'moment'; import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number'; import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { registry } from '../../common/registry'; +import { createApmApiSupertest } from '../../common/apm_api_supertest'; type ThroughputReturn = APIReturnType<'GET /api/apm/services/{serviceName}/throughput'>; export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('supertest'); + const apmApiSupertest = createApmApiSupertest(getService('supertest')); const archiveName = 'apm_8.0.0'; const metadata = archives_metadata[archiveName]; registry.when('Throughput when data is not loaded', { config: 'basic', archives: [] }, () => { it('handles the empty state', async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-java/throughput?${qs.stringify({ - start: metadata.start, - end: metadata.end, - transactionType: 'request', - })}` - ); + const response = await apmApiSupertest({ + endpoint: 'GET /api/apm/services/{serviceName}/throughput', + params: { + path: { + serviceName: 'opbeans-java', + }, + query: { + start: metadata.start, + end: metadata.end, + transactionType: 'request', + }, + }, + }); + expect(response.status).to.be(200); expect(response.body.currentPeriod.length).to.be(0); expect(response.body.previousPeriod.length).to.be(0); @@ -43,46 +50,86 @@ export default function ApiTest({ getService }: FtrProviderContext) { 'Throughput when data is loaded', { config: 'basic', archives: [archiveName] }, () => { - before(async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-java/throughput?${qs.stringify({ - start: metadata.start, - end: metadata.end, - transactionType: 'request', - })}` - ); - throughputResponse = response.body; + describe('when querying without kql filter', () => { + before(async () => { + const response = await apmApiSupertest({ + endpoint: 'GET /api/apm/services/{serviceName}/throughput', + params: { + path: { + serviceName: 'opbeans-java', + }, + query: { + start: metadata.start, + end: metadata.end, + transactionType: 'request', + }, + }, + }); + throughputResponse = response.body; + }); + + it('returns some data', () => { + expect(throughputResponse.currentPeriod.length).to.be.greaterThan(0); + expect(throughputResponse.previousPeriod.length).not.to.be.greaterThan(0); + + const nonNullDataPoints = throughputResponse.currentPeriod.filter(({ y }) => + isFiniteNumber(y) + ); + + expect(nonNullDataPoints.length).to.be.greaterThan(0); + }); + + it('has the correct start date', () => { + expectSnapshot( + new Date(first(throughputResponse.currentPeriod)?.x ?? NaN).toISOString() + ).toMatchInline(`"2021-08-03T06:50:00.000Z"`); + }); + + it('has the correct end date', () => { + expectSnapshot( + new Date(last(throughputResponse.currentPeriod)?.x ?? NaN).toISOString() + ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); + }); + + it('has the correct number of buckets', () => { + expectSnapshot(throughputResponse.currentPeriod.length).toMatchInline(`31`); + }); + + it('has the correct throughput in tpm', () => { + const avg = mean(throughputResponse.currentPeriod.map((d) => d.y)); + expectSnapshot(avg).toMatchInline(`6.19354838709677`); + expectSnapshot(throughputResponse.throughputUnit).toMatchInline(`"minute"`); + }); }); - it('returns some data', () => { - expect(throughputResponse.currentPeriod.length).to.be.greaterThan(0); - expect(throughputResponse.previousPeriod.length).not.to.be.greaterThan(0); - - const nonNullDataPoints = throughputResponse.currentPeriod.filter(({ y }) => - isFiniteNumber(y) - ); - - expect(nonNullDataPoints.length).to.be.greaterThan(0); - }); - - it('has the correct start date', () => { - expectSnapshot( - new Date(first(throughputResponse.currentPeriod)?.x ?? NaN).toISOString() - ).toMatchInline(`"2021-08-03T06:50:00.000Z"`); - }); - - it('has the correct end date', () => { - expectSnapshot( - new Date(last(throughputResponse.currentPeriod)?.x ?? NaN).toISOString() - ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); - }); - - it('has the correct number of buckets', () => { - expectSnapshot(throughputResponse.currentPeriod.length).toMatchInline(`31`); - }); - - it('has the correct throughput', () => { - expectSnapshot(throughputResponse.currentPeriod).toMatch(); + describe('with kql filter to force transaction-based UI', () => { + before(async () => { + const response = await apmApiSupertest({ + endpoint: 'GET /api/apm/services/{serviceName}/throughput', + params: { + path: { + serviceName: 'opbeans-java', + }, + query: { + kuery: 'processor.event : "transaction"', + start: metadata.start, + end: metadata.end, + transactionType: 'request', + }, + }, + }); + throughputResponse = response.body; + }); + + it('has the correct throughput in tps', async () => { + const avgTps = mean(throughputResponse.currentPeriod.map((d) => d.y)); + expectSnapshot(avgTps).toMatchInline(`0.124043715846995`); + expectSnapshot(throughputResponse.throughputUnit).toMatchInline(`"second"`); + + // this tpm value must be similar tp tpm value calculated in the previous spec where metric docs were used + const avgTpm = avgTps * 60; + expectSnapshot(avgTpm).toMatchInline(`7.44262295081967`); + }); }); } ); @@ -92,15 +139,22 @@ export default function ApiTest({ getService }: FtrProviderContext) { { config: 'basic', archives: [archiveName] }, () => { before(async () => { - const response = await supertest.get( - `/api/apm/services/opbeans-java/throughput?${qs.stringify({ - transactionType: 'request', - start: moment(metadata.end).subtract(15, 'minutes').toISOString(), - end: metadata.end, - comparisonStart: metadata.start, - comparisonEnd: moment(metadata.start).add(15, 'minutes').toISOString(), - })}` - ); + const response = await apmApiSupertest({ + endpoint: 'GET /api/apm/services/{serviceName}/throughput', + params: { + path: { + serviceName: 'opbeans-java', + }, + query: { + transactionType: 'request', + start: moment(metadata.end).subtract(15, 'minutes').toISOString(), + end: metadata.end, + comparisonStart: metadata.start, + comparisonEnd: moment(metadata.start).add(15, 'minutes').toISOString(), + }, + }, + }); + throughputResponse = response.body; }); @@ -144,8 +198,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(throughputResponse.previousPeriod.length).toMatchInline(`16`); }); - it('has the correct throughput', () => { + it('has the correct throughput in tpm', () => { expectSnapshot(throughputResponse).toMatch(); + expectSnapshot(throughputResponse.throughputUnit).toMatchInline(`"minute"`); }); } );