From eea60c8abbab699dcb71f18b45a6a309af500957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cau=C3=AA=20Marcondes?= <55978943+cauemarcondes@users.noreply.github.com> Date: Thu, 14 Oct 2021 14:48:15 -0400 Subject: [PATCH] [APM] Remove rate aggregations (#114187) * fixing throughput chart api * change backends * adding intervalString to the observability callback functions * fixing transaction group detailed stats * fixing tests * fixing test * fixing obs tests * fixing tests * adding tests * fixing ci * using data generator * changing name * fixing i18n * updating opbs test to use data generator * fixing api tests * fixing tests * using data generator to run the tests * fixing tests * fixing test --- .../apm/common/utils/formatters/duration.ts | 9 +- .../service_overview_throughput_chart.tsx | 23 +- ...pm_observability_overview_fetchers.test.ts | 3 +- .../apm_observability_overview_fetchers.ts | 2 + x-pack/plugins/apm/server/index.ts | 2 +- .../get_throughput_charts_for_backend.ts | 30 +- .../lib/helpers/calculate_throughput.ts | 27 + .../get_transactions_per_minute.ts | 21 +- ...e_transaction_group_detailed_statistics.ts | 7 +- .../apm/server/lib/services/get_throughput.ts | 17 +- .../server/routes/observability_overview.ts | 9 +- x-pack/plugins/apm/server/routes/services.ts | 6 +- x-pack/plugins/apm/typings/common.d.ts | 8 + .../public/metrics_overview_fetchers.test.ts | 6 +- .../infra/public/metrics_overview_fetchers.ts | 4 +- .../public/utils/logs_overview_fetchers.ts | 2 +- .../utils/logs_overview_fetches.test.ts | 3 +- .../components/app/section/apm/index.test.tsx | 12 +- .../components/app/section/apm/index.tsx | 5 +- .../components/app/section/logs/index.tsx | 5 +- .../components/app/section/metrics/index.tsx | 5 +- .../components/app/section/uptime/index.tsx | 5 +- .../components/app/section/ux/index.test.tsx | 12 +- .../components/app/section/ux/index.tsx | 5 +- .../observability/public/data_handler.test.ts | 3 +- .../public/pages/overview/data_sections.tsx | 3 +- .../public/pages/overview/index.tsx | 4 +- .../typings/fetch_overview_data/index.ts | 5 +- .../translations/translations/ja-JP.json | 3 - .../translations/translations/zh-CN.json | 3 - .../public/apps/uptime_overview_fetcher.ts | 8 +- .../fixtures/es_archiver/archives_metadata.ts | 3 +- .../test/apm_api_integration/tests/index.ts | 8 + .../tests/inspect/inspect.ts | 2 +- .../observability_overview.ts | 193 ++-- .../tests/service_maps/service_maps.ts | 4 +- .../__snapshots__/instance_details.snap | 2 +- .../instances_detailed_statistics.snap | 324 +++--- .../instances_main_statistics.ts | 18 +- .../services/__snapshots__/throughput.snap | 139 --- .../tests/services/throughput.ts | 403 +++----- .../tests/services/top_services.ts | 32 +- .../tests/throughput/dependencies_apis.ts | 236 +++++ .../tests/throughput/service_apis.ts | 163 +++ .../traces/__snapshots__/top_traces.snap | 610 ++++++------ .../tests/traces/top_traces.ts | 6 +- .../__snapshots__/error_rate.snap | 836 ++++++++++++++-- .../transactions/__snapshots__/latency.snap | 356 ++++++- ...ansactions_groups_detailed_statistics.snap | 931 ------------------ .../tests/transactions/error_rate.ts | 20 +- .../tests/transactions/latency.ts | 8 +- ...transactions_groups_detailed_statistics.ts | 434 ++++---- .../transactions_groups_main_statistics.ts | 32 +- 53 files changed, 2675 insertions(+), 2342 deletions(-) delete mode 100644 x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap create mode 100644 x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts create mode 100644 x-pack/test/apm_api_integration/tests/throughput/service_apis.ts delete mode 100644 x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_groups_detailed_statistics.snap diff --git a/x-pack/plugins/apm/common/utils/formatters/duration.ts b/x-pack/plugins/apm/common/utils/formatters/duration.ts index bc4d58831ff35..5b20b2e1827a1 100644 --- a/x-pack/plugins/apm/common/utils/formatters/duration.ts +++ b/x-pack/plugins/apm/common/utils/formatters/duration.ts @@ -13,8 +13,6 @@ 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; @@ -182,13 +180,12 @@ export function asTransactionRate(value: Maybe) { }); } -export function asExactTransactionRate(value: number, unit: ThroughputUnit) { +export function asExactTransactionRate(value: number) { return i18n.translate('xpack.apm.exactTransactionRateLabel', { - defaultMessage: `{value} { unit, select, minute {tpm} other {tps} }`, - values: { value: asDecimalOrInteger(value), unit }, + defaultMessage: `{value} tpm`, + values: { value: asDecimalOrInteger(value) }, }); } - /** * Converts value and returns it formatted - 00 unit */ 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 0780c2d272715..6648eaec80fa6 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 @@ -135,29 +135,16 @@ export function ServiceOverviewThroughputChart({ 'xpack.apm.serviceOverview.throughtputChartTitle', { defaultMessage: 'Throughput' } )} - {data.throughputUnit === 'second' - ? i18n.translate( - 'xpack.apm.serviceOverview.throughtputPerSecondChartTitle', - { defaultMessage: ' (per second)' } - ) - : ''} @@ -169,7 +156,7 @@ export function ServiceOverviewThroughputChart({ showAnnotations={false} fetchStatus={status} timeseries={timeseries} - yLabelFormat={(y) => asExactTransactionRate(y, data.throughputUnit)} + yLabelFormat={asExactTransactionRate} customTheme={comparisonChartTheme} /> diff --git a/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts b/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts index 00447607cf787..c6513aa24df6b 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.test.ts @@ -23,7 +23,8 @@ describe('Observability dashboard data', () => { start: 'now-15m', end: 'now', }, - bucketSize: '600s', + intervalString: '600s', + bucketSize: 600, }; afterEach(() => { callApmApiMock.mockClear(); diff --git a/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.ts b/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.ts index f26fd85bde968..4e7114ebb9e35 100644 --- a/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.ts +++ b/x-pack/plugins/apm/public/services/rest/apm_observability_overview_fetchers.ts @@ -15,6 +15,7 @@ export const fetchObservabilityOverviewPageData = async ({ absoluteTime, relativeTime, bucketSize, + intervalString, }: FetchDataParams): Promise => { const data = await callApmApi({ endpoint: 'GET /internal/apm/observability_overview', @@ -24,6 +25,7 @@ export const fetchObservabilityOverviewPageData = async ({ start: new Date(absoluteTime.start).toISOString(), end: new Date(absoluteTime.end).toISOString(), bucketSize, + intervalString, }, }, }); diff --git a/x-pack/plugins/apm/server/index.ts b/x-pack/plugins/apm/server/index.ts index c0dffc50e4e4f..abf9b3f5fb774 100644 --- a/x-pack/plugins/apm/server/index.ts +++ b/x-pack/plugins/apm/server/index.ts @@ -38,7 +38,7 @@ const configSchema = schema.object({ schema.literal(SearchAggregatedTransactionSetting.always), schema.literal(SearchAggregatedTransactionSetting.never), ], - { defaultValue: SearchAggregatedTransactionSetting.auto } + { defaultValue: SearchAggregatedTransactionSetting.never } ), telemetryCollectionEnabled: schema.boolean({ defaultValue: true }), metricsInterval: schema.number({ defaultValue: 30 }), diff --git a/x-pack/plugins/apm/server/lib/backends/get_throughput_charts_for_backend.ts b/x-pack/plugins/apm/server/lib/backends/get_throughput_charts_for_backend.ts index 19a26c3fcf035..1fbdd1c680c58 100644 --- a/x-pack/plugins/apm/server/lib/backends/get_throughput_charts_for_backend.ts +++ b/x-pack/plugins/apm/server/lib/backends/get_throughput_charts_for_backend.ts @@ -13,8 +13,9 @@ import { environmentQuery } from '../../../common/utils/environment_query'; import { kqlQuery, rangeQuery } from '../../../../observability/server'; import { ProcessorEvent } from '../../../common/processor_event'; import { Setup } from '../helpers/setup_request'; -import { getMetricsDateHistogramParams } from '../helpers/metrics'; import { getOffsetInMs } from '../../../common/utils/get_offset_in_ms'; +import { getBucketSize } from '../helpers/get_bucket_size'; +import { calculateThroughputWithInterval } from '../helpers/calculate_throughput'; export async function getThroughputChartsForBackend({ backendName, @@ -41,6 +42,12 @@ export async function getThroughputChartsForBackend({ offset, }); + const { intervalString, bucketSize } = getBucketSize({ + start: startWithOffset, + end: endWithOffset, + minBucketSize: 60, + }); + const response = await apmEventClient.search('get_throughput_for_backend', { apm: { events: [ProcessorEvent.metric], @@ -59,16 +66,16 @@ export async function getThroughputChartsForBackend({ }, aggs: { timeseries: { - date_histogram: getMetricsDateHistogramParams({ - start: startWithOffset, - end: endWithOffset, - metricsInterval: 60, - }), + date_histogram: { + field: '@timestamp', + fixed_interval: intervalString, + min_doc_count: 0, + extended_bounds: { min: startWithOffset, max: endWithOffset }, + }, aggs: { - throughput: { - rate: { + spanDestinationLatencySum: { + sum: { field: SPAN_DESTINATION_SERVICE_RESPONSE_TIME_COUNT, - unit: 'minute', }, }, }, @@ -81,7 +88,10 @@ export async function getThroughputChartsForBackend({ response.aggregations?.timeseries.buckets.map((bucket) => { return { x: bucket.key + offsetInMs, - y: bucket.throughput.value, + y: calculateThroughputWithInterval({ + bucketSize, + value: bucket.spanDestinationLatencySum.value || 0, + }), }; }) ?? [] ); 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 6508329a494ff..9c99f94f82861 100644 --- a/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts +++ b/x-pack/plugins/apm/server/lib/helpers/calculate_throughput.ts @@ -5,6 +5,9 @@ * 2.0. */ +/** + * @deprecated use calculateThroughputWithRange instead + */ export function calculateThroughput({ start, end, @@ -18,6 +21,30 @@ export function calculateThroughput({ return value / durationAsMinutes; } +export function calculateThroughputWithRange({ + start, + end, + value, +}: { + start: number; + end: number; + value: number; +}) { + const durationAsMinutes = (end - start) / 1000 / 60; + return value / durationAsMinutes; +} + +export function calculateThroughputWithInterval({ + bucketSize, + value, +}: { + bucketSize: number; + value: number; +}) { + const durationAsMinutes = bucketSize / 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/observability_overview/get_transactions_per_minute.ts b/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts index bfa8d53d2a9fb..8c64670f5d2e9 100644 --- a/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts +++ b/x-pack/plugins/apm/server/lib/observability_overview/get_transactions_per_minute.ts @@ -16,7 +16,10 @@ import { getDocumentTypeFilterForAggregatedTransactions, getProcessorEventForAggregatedTransactions, } from '../helpers/aggregated_transactions'; -import { calculateThroughput } from '../helpers/calculate_throughput'; +import { + calculateThroughputWithInterval, + calculateThroughputWithRange, +} from '../helpers/calculate_throughput'; export async function getTransactionsPerMinute({ setup, @@ -24,9 +27,11 @@ export async function getTransactionsPerMinute({ searchAggregatedTransactions, start, end, + intervalString, }: { setup: Setup; - bucketSize: string; + bucketSize: number; + intervalString: string; searchAggregatedTransactions: boolean; start: number; end: number; @@ -64,12 +69,9 @@ export async function getTransactionsPerMinute({ timeseries: { date_histogram: { field: '@timestamp', - fixed_interval: bucketSize, + fixed_interval: intervalString, min_doc_count: 0, }, - aggs: { - throughput: { rate: { unit: 'minute' as const } }, - }, }, }, }, @@ -90,7 +92,7 @@ export async function getTransactionsPerMinute({ ) || aggregations.transactionType.buckets[0]; return { - value: calculateThroughput({ + value: calculateThroughputWithRange({ start, end, value: topTransactionTypeBucket?.doc_count || 0, @@ -98,7 +100,10 @@ export async function getTransactionsPerMinute({ timeseries: topTransactionTypeBucket?.timeseries.buckets.map((bucket) => ({ x: bucket.key, - y: bucket.throughput.value, + y: calculateThroughputWithInterval({ + bucketSize, + value: bucket.doc_count, + }), })) || [], }; } 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 adf0317ccf174..feab6d78f02c8 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 @@ -125,11 +125,6 @@ export async function getServiceTransactionGroupDetailedStatistics({ }, }, aggs: { - throughput_rate: { - rate: { - unit: 'minute', - }, - }, ...getLatencyAggregation(latencyAggregationType, field), [EVENT_OUTCOME]: { terms: { @@ -160,7 +155,7 @@ export async function getServiceTransactionGroupDetailedStatistics({ })); const throughput = bucket.timeseries.buckets.map((timeseriesBucket) => ({ x: timeseriesBucket.key, - y: timeseriesBucket.throughput_rate.value, + y: timeseriesBucket.doc_count, // sparklines only shows trend (no axis) })); const errorRate = bucket.timeseries.buckets.map((timeseriesBucket) => ({ x: timeseriesBucket.key, 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 76d6000a161e6..669203ad198b9 100644 --- a/x-pack/plugins/apm/server/lib/services/get_throughput.ts +++ b/x-pack/plugins/apm/server/lib/services/get_throughput.ts @@ -18,6 +18,7 @@ import { getProcessorEventForAggregatedTransactions, } from '../helpers/aggregated_transactions'; import { Setup } from '../helpers/setup_request'; +import { calculateThroughputWithInterval } from '../helpers/calculate_throughput'; interface Options { environment: string; @@ -30,7 +31,7 @@ interface Options { start: number; end: number; intervalString: string; - throughputUnit: 'minute' | 'second'; + bucketSize: number; } export async function getThroughput({ @@ -44,7 +45,7 @@ export async function getThroughput({ start, end, intervalString, - throughputUnit, + bucketSize, }: Options) { const { apmEventClient } = setup; @@ -86,13 +87,6 @@ export async function getThroughput({ min_doc_count: 0, extended_bounds: { min: start, max: end }, }, - aggs: { - throughput: { - rate: { - unit: throughputUnit, - }, - }, - }, }, }, }, @@ -107,7 +101,10 @@ export async function getThroughput({ response.aggregations?.timeseries.buckets.map((bucket) => { return { x: bucket.key, - y: bucket.throughput.value, + y: calculateThroughputWithInterval({ + bucketSize, + value: bucket.doc_count, + }), }; }) ?? [] ); diff --git a/x-pack/plugins/apm/server/routes/observability_overview.ts b/x-pack/plugins/apm/server/routes/observability_overview.ts index a99291ff32bb6..0dbebd061e8be 100644 --- a/x-pack/plugins/apm/server/routes/observability_overview.ts +++ b/x-pack/plugins/apm/server/routes/observability_overview.ts @@ -6,6 +6,7 @@ */ import * as t from 'io-ts'; +import { toNumberRt } from '@kbn/io-ts-utils'; import { setupRequest } from '../lib/helpers/setup_request'; import { getServiceCount } from '../lib/observability_overview/get_service_count'; import { getTransactionsPerMinute } from '../lib/observability_overview/get_transactions_per_minute'; @@ -28,12 +29,15 @@ const observabilityOverviewHasDataRoute = createApmServerRoute({ const observabilityOverviewRoute = createApmServerRoute({ endpoint: 'GET /internal/apm/observability_overview', params: t.type({ - query: t.intersection([rangeRt, t.type({ bucketSize: t.string })]), + query: t.intersection([ + rangeRt, + t.type({ bucketSize: toNumberRt, intervalString: t.string }), + ]), }), options: { tags: ['access:apm'] }, handler: async (resources) => { const setup = await setupRequest(resources); - const { bucketSize, start, end } = resources.params.query; + const { bucketSize, intervalString, start, end } = resources.params.query; const searchAggregatedTransactions = await getSearchAggregatedTransactions({ apmEventClient: setup.apmEventClient, @@ -57,6 +61,7 @@ const observabilityOverviewRoute = createApmServerRoute({ searchAggregatedTransactions, start, end, + intervalString, }), ]); return { serviceCount, transactionPerMinute }; diff --git a/x-pack/plugins/apm/server/routes/services.ts b/x-pack/plugins/apm/server/routes/services.ts index d4af7315b9c23..f1f29dc2f036c 100644 --- a/x-pack/plugins/apm/server/routes/services.ts +++ b/x-pack/plugins/apm/server/routes/services.ts @@ -12,7 +12,6 @@ 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'; @@ -515,8 +514,6 @@ const serviceThroughputRoute = createApmServerRoute({ searchAggregatedTransactions, }); - const throughputUnit = getThroughputUnit(bucketSize); - const commonProps = { environment, kuery, @@ -525,8 +522,8 @@ const serviceThroughputRoute = createApmServerRoute({ setup, transactionType, transactionName, - throughputUnit, intervalString, + bucketSize, }; const [currentPeriod, previousPeriod] = await Promise.all([ @@ -550,7 +547,6 @@ const serviceThroughputRoute = createApmServerRoute({ currentPeriodTimeseries: currentPeriod, previousPeriodTimeseries: previousPeriod, }), - throughputUnit, }; }, }); diff --git a/x-pack/plugins/apm/typings/common.d.ts b/x-pack/plugins/apm/typings/common.d.ts index b94eb6cd97b06..a3af717b5949b 100644 --- a/x-pack/plugins/apm/typings/common.d.ts +++ b/x-pack/plugins/apm/typings/common.d.ts @@ -27,3 +27,11 @@ type AllowUnknownObjectProperties = T extends object export type PromiseValueType> = UnwrapPromise; export type Maybe = T | null | undefined; + +export type RecursivePartial = { + [P in keyof T]?: T[P] extends Array + ? Array> + : T[P] extends object + ? RecursivePartial + : T[P]; +}; diff --git a/x-pack/plugins/infra/public/metrics_overview_fetchers.test.ts b/x-pack/plugins/infra/public/metrics_overview_fetchers.test.ts index e6ffbc30fe24d..c2e60090d81f3 100644 --- a/x-pack/plugins/infra/public/metrics_overview_fetchers.test.ts +++ b/x-pack/plugins/infra/public/metrics_overview_fetchers.test.ts @@ -56,7 +56,8 @@ describe('Metrics UI Observability Homepage Functions', () => { const fetchData = createMetricsFetchData(mockedGetStartServices); const endTime = moment('2020-07-02T13:25:11.629Z'); const startTime = endTime.clone().subtract(1, 'h'); - const bucketSize = '300s'; + const bucketSize = 300; + const intervalString = '300s'; const response = await fetchData({ absoluteTime: { start: startTime.valueOf(), @@ -67,12 +68,13 @@ describe('Metrics UI Observability Homepage Functions', () => { end: 'now', }, bucketSize, + intervalString, }); expect(core.http.post).toHaveBeenCalledTimes(1); expect(core.http.post).toHaveBeenCalledWith('/api/metrics/overview/top', { body: JSON.stringify({ sourceId: 'default', - bucketSize, + bucketSize: intervalString, size: 5, timerange: { from: startTime.valueOf(), diff --git a/x-pack/plugins/infra/public/metrics_overview_fetchers.ts b/x-pack/plugins/infra/public/metrics_overview_fetchers.ts index 57017d25ecc64..c69ed451ea6d6 100644 --- a/x-pack/plugins/infra/public/metrics_overview_fetchers.ts +++ b/x-pack/plugins/infra/public/metrics_overview_fetchers.ts @@ -27,7 +27,7 @@ export const createMetricsHasData = export const createMetricsFetchData = (getStartServices: InfraClientCoreSetup['getStartServices']) => - async ({ absoluteTime, bucketSize }: FetchDataParams): Promise => { + async ({ absoluteTime, intervalString }: FetchDataParams): Promise => { const [coreServices] = await getStartServices(); const { http } = coreServices; @@ -36,7 +36,7 @@ export const createMetricsFetchData = const overviewRequest: TopNodesRequest = { sourceId: 'default', - bucketSize, + bucketSize: intervalString, size: 5, timerange: { from: start, diff --git a/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts b/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts index 67db6a4721941..c813bd3dae781 100644 --- a/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts +++ b/x-pack/plugins/infra/public/utils/logs_overview_fetchers.ts @@ -138,7 +138,7 @@ function buildLogOverviewAggregations(logParams: LogParams, params: FetchDataPar series: { date_histogram: { field: logParams.timestampField, - fixed_interval: params.bucketSize, + fixed_interval: params.intervalString, }, }, }, diff --git a/x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts b/x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts index 4fcb83fd02754..d0349ab20710f 100644 --- a/x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts +++ b/x-pack/plugins/infra/public/utils/logs_overview_fetches.test.ts @@ -29,7 +29,8 @@ const mockedCallFetchLogSourceConfigurationAPI = const DEFAULT_PARAMS = { absoluteTime: { start: 1593430680000, end: 1593430800000 }, relativeTime: { start: 'now-2m', end: 'now' }, // Doesn't matter for the test - bucketSize: '30s', // Doesn't matter for the test + intervalString: '30s', // Doesn't matter for the test + bucketSize: 30, // Doesn't matter for the test }; function setup() { diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx index 8b1480246210a..c9c2ed549a1c3 100644 --- a/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx +++ b/x-pack/plugins/observability/public/components/app/section/apm/index.test.tsx @@ -78,7 +78,9 @@ describe('APMSection', () => { status: fetcherHook.FETCH_STATUS.SUCCESS, refetch: jest.fn(), }); - const { getByText, queryAllByTestId } = render(); + const { getByText, queryAllByTestId } = render( + + ); expect(getByText('APM')).toBeInTheDocument(); expect(getByText('View in app')).toBeInTheDocument(); @@ -93,7 +95,9 @@ describe('APMSection', () => { status: fetcherHook.FETCH_STATUS.SUCCESS, refetch: jest.fn(), }); - const { getByText, queryAllByTestId } = render(); + const { getByText, queryAllByTestId } = render( + + ); expect(getByText('APM')).toBeInTheDocument(); expect(getByText('View in app')).toBeInTheDocument(); @@ -107,7 +111,9 @@ describe('APMSection', () => { status: fetcherHook.FETCH_STATUS.LOADING, refetch: jest.fn(), }); - const { getByText, queryAllByText, getByTestId } = render(); + const { getByText, queryAllByText, getByTestId } = render( + + ); expect(getByText('APM')).toBeInTheDocument(); expect(getByTestId('loading')).toBeInTheDocument(); diff --git a/x-pack/plugins/observability/public/components/app/section/apm/index.tsx b/x-pack/plugins/observability/public/components/app/section/apm/index.tsx index 8df14129623f6..11565cfb972e7 100644 --- a/x-pack/plugins/observability/public/components/app/section/apm/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/apm/index.tsx @@ -30,9 +30,10 @@ import { useHasData } from '../../../../hooks/use_has_data'; import { ChartContainer } from '../../chart_container'; import { StyledStat } from '../../styled_stat'; import { onBrushEnd } from '../helper'; +import { BucketSize } from '../../../../pages/overview'; interface Props { - bucketSize?: string; + bucketSize: BucketSize; } function formatTpm(value?: number) { @@ -65,7 +66,7 @@ export function APMSection({ bucketSize }: Props) { return getDataHandler('apm')?.fetchData({ absoluteTime: { start: absoluteStart, end: absoluteEnd }, relativeTime: { start: relativeStart, end: relativeEnd }, - bucketSize, + ...bucketSize, }); } }, diff --git a/x-pack/plugins/observability/public/components/app/section/logs/index.tsx b/x-pack/plugins/observability/public/components/app/section/logs/index.tsx index dcd51a531a73d..0ff2c203c7707 100644 --- a/x-pack/plugins/observability/public/components/app/section/logs/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/logs/index.tsx @@ -32,9 +32,10 @@ import { formatStatValue } from '../../../../utils/format_stat_value'; import { ChartContainer } from '../../chart_container'; import { StyledStat } from '../../styled_stat'; import { onBrushEnd } from '../helper'; +import { BucketSize } from '../../../../pages/overview'; interface Props { - bucketSize?: string; + bucketSize: BucketSize; } function getColorPerItem(series?: LogsFetchDataResponse['series']) { @@ -64,7 +65,7 @@ export function LogsSection({ bucketSize }: Props) { return getDataHandler('infra_logs')?.fetchData({ absoluteTime: { start: absoluteStart, end: absoluteEnd }, relativeTime: { start: relativeStart, end: relativeEnd }, - bucketSize, + ...bucketSize, }); } }, diff --git a/x-pack/plugins/observability/public/components/app/section/metrics/index.tsx b/x-pack/plugins/observability/public/components/app/section/metrics/index.tsx index fd1e356f849a2..8cd49efe4787a 100644 --- a/x-pack/plugins/observability/public/components/app/section/metrics/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/metrics/index.tsx @@ -29,6 +29,7 @@ import { useTimeRange } from '../../../../hooks/use_time_range'; import { HostLink } from './host_link'; import { formatDuration } from './lib/format_duration'; import { MetricWithSparkline } from './metric_with_sparkline'; +import { BucketSize } from '../../../../pages/overview'; const COLOR_ORANGE = 7; const COLOR_BLUE = 1; @@ -36,7 +37,7 @@ const COLOR_GREEN = 0; const COLOR_PURPLE = 3; interface Props { - bucketSize?: string; + bucketSize: BucketSize; } const percentFormatter = (value: NumberOrNull) => @@ -61,7 +62,7 @@ export function MetricsSection({ bucketSize }: Props) { return getDataHandler('infra_metrics')?.fetchData({ absoluteTime: { start: absoluteStart, end: absoluteEnd }, relativeTime: { start: relativeStart, end: relativeEnd }, - bucketSize, + ...bucketSize, }); } }, diff --git a/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx b/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx index 8c0f1f8db7c1a..4c9e7b42f40c6 100644 --- a/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/uptime/index.tsx @@ -32,9 +32,10 @@ import { Series } from '../../../../typings'; import { ChartContainer } from '../../chart_container'; import { StyledStat } from '../../styled_stat'; import { onBrushEnd } from '../helper'; +import { BucketSize } from '../../../../pages/overview'; interface Props { - bucketSize?: string; + bucketSize: BucketSize; } export function UptimeSection({ bucketSize }: Props) { @@ -50,7 +51,7 @@ export function UptimeSection({ bucketSize }: Props) { return getDataHandler('synthetics')?.fetchData({ absoluteTime: { start: absoluteStart, end: absoluteEnd }, relativeTime: { start: relativeStart, end: relativeEnd }, - bucketSize, + ...bucketSize, }); } }, diff --git a/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx b/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx index 19bc20f5da605..8a99b6a53cf06 100644 --- a/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx +++ b/x-pack/plugins/observability/public/components/app/section/ux/index.test.tsx @@ -67,7 +67,9 @@ describe('UXSection', () => { status: fetcherHook.FETCH_STATUS.SUCCESS, refetch: jest.fn(), }); - const { getByText, getAllByText } = render(); + const { getByText, getAllByText } = render( + + ); expect(getByText('User Experience')).toBeInTheDocument(); expect(getByText('View in app')).toBeInTheDocument(); @@ -99,7 +101,9 @@ describe('UXSection', () => { status: fetcherHook.FETCH_STATUS.LOADING, refetch: jest.fn(), }); - const { getByText, queryAllByText, getAllByText } = render(); + const { getByText, queryAllByText, getAllByText } = render( + + ); expect(getByText('User Experience')).toBeInTheDocument(); expect(getAllByText('--')).toHaveLength(3); @@ -112,7 +116,9 @@ describe('UXSection', () => { status: fetcherHook.FETCH_STATUS.SUCCESS, refetch: jest.fn(), }); - const { getByText, queryAllByText, getAllByText } = render(); + const { getByText, queryAllByText, getAllByText } = render( + + ); expect(getByText('User Experience')).toBeInTheDocument(); expect(getAllByText('No data is available.')).toHaveLength(3); diff --git a/x-pack/plugins/observability/public/components/app/section/ux/index.tsx b/x-pack/plugins/observability/public/components/app/section/ux/index.tsx index 5aa89eb2d3074..3092c7bf77f7a 100644 --- a/x-pack/plugins/observability/public/components/app/section/ux/index.tsx +++ b/x-pack/plugins/observability/public/components/app/section/ux/index.tsx @@ -13,9 +13,10 @@ import { FETCH_STATUS, useFetcher } from '../../../../hooks/use_fetcher'; import { useHasData } from '../../../../hooks/use_has_data'; import { useTimeRange } from '../../../../hooks/use_time_range'; import CoreVitals from '../../../shared/core_web_vitals'; +import { BucketSize } from '../../../../pages/overview'; interface Props { - bucketSize: string; + bucketSize: BucketSize; } export function UXSection({ bucketSize }: Props) { @@ -31,7 +32,7 @@ export function UXSection({ bucketSize }: Props) { absoluteTime: { start: absoluteStart, end: absoluteEnd }, relativeTime: { start: relativeStart, end: relativeEnd }, serviceName, - bucketSize, + ...bucketSize, }); } }, diff --git a/x-pack/plugins/observability/public/data_handler.test.ts b/x-pack/plugins/observability/public/data_handler.test.ts index 2beae5d111f7d..8325997e75ec9 100644 --- a/x-pack/plugins/observability/public/data_handler.test.ts +++ b/x-pack/plugins/observability/public/data_handler.test.ts @@ -20,7 +20,8 @@ const params = { start: 'now-15m', end: 'now', }, - bucketSize: '10s', + intervalString: '10s', + bucketSize: 10, }; describe('registerDataHandler', () => { diff --git a/x-pack/plugins/observability/public/pages/overview/data_sections.tsx b/x-pack/plugins/observability/public/pages/overview/data_sections.tsx index 82231304e65b2..335f527560c7a 100644 --- a/x-pack/plugins/observability/public/pages/overview/data_sections.tsx +++ b/x-pack/plugins/observability/public/pages/overview/data_sections.tsx @@ -13,9 +13,10 @@ import { MetricsSection } from '../../components/app/section/metrics'; import { UptimeSection } from '../../components/app/section/uptime'; import { UXSection } from '../../components/app/section/ux'; import { HasDataMap } from '../../context/has_data_context'; +import { BucketSize } from '.'; interface Props { - bucketSize: string; + bucketSize: BucketSize; hasData?: Partial; } diff --git a/x-pack/plugins/observability/public/pages/overview/index.tsx b/x-pack/plugins/observability/public/pages/overview/index.tsx index 26dbf5ece400c..b817a83d59e0d 100644 --- a/x-pack/plugins/observability/public/pages/overview/index.tsx +++ b/x-pack/plugins/observability/public/pages/overview/index.tsx @@ -31,7 +31,7 @@ import { LoadingObservability } from './loading_observability'; interface Props { routeParams: RouteParams<'/overview'>; } - +export type BucketSize = ReturnType; function calculateBucketSize({ start, end }: { start?: number; end?: number }) { if (start && end) { return getBucketSize({ start, end, minInterval: '60s' }); @@ -106,7 +106,7 @@ export function OverviewPage({ routeParams }: Props) { {/* Data sections */} - {hasAnyData && } + {hasAnyData && } diff --git a/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts b/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts index 197a8c1060cdb..50ce0e392de0e 100644 --- a/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts +++ b/x-pack/plugins/observability/public/typings/fetch_overview_data/index.ts @@ -26,8 +26,11 @@ export interface Series { export interface FetchDataParams { absoluteTime: { start: number; end: number }; relativeTime: { start: string; end: string }; - bucketSize: string; serviceName?: string; + // Bucket size in seconds (number) + bucketSize: number; + // Bucket size in seconds (string) + intervalString: string; } export interface HasDataParams { diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 28687dcb4ee5d..2f8125f99d8d8 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -6446,7 +6446,6 @@ "xpack.apm.errorsTable.occurrencesColumnLabel": "オカレンス", "xpack.apm.errorsTable.typeColumnLabel": "型", "xpack.apm.errorsTable.unhandledLabel": "未対応", - "xpack.apm.exactTransactionRateLabel": "{value} { unit, select, minute {tpm} other {tps} }", "xpack.apm.failedTransactionsCorrelations.licenseCheckText": "失敗したトランザクションの相関関係機能を使用するには、Elastic Platinumライセンスのサブスクリプションが必要です。", "xpack.apm.featureRegistry.apmFeatureName": "APMおよびユーザーエクスペリエンス", "xpack.apm.feedbackMenu.appName": "APM", @@ -6756,9 +6755,7 @@ "xpack.apm.serviceOverview.mlNudgeMessage.learnMoreButton": "使ってみる", "xpack.apm.serviceOverview.throughtputChart.previousPeriodLabel": "前の期間", "xpack.apm.serviceOverview.throughtputChartTitle": "スループット", - "xpack.apm.serviceOverview.throughtputPerSecondChartTitle": " (秒単位)", "xpack.apm.serviceOverview.tpmHelp": "スループットは1分あたりのトランザクション数(tpm)で測定されます", - "xpack.apm.serviceOverview.tpsHelp": "スループットは1秒あたりのトランザクション数(tps)で測定されます", "xpack.apm.serviceOverview.transactionsTableColumnErrorRate": "失敗したトランザクション率", "xpack.apm.serviceOverview.transactionsTableColumnImpact": "インパクト", "xpack.apm.serviceOverview.transactionsTableColumnName": "名前", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index d0d01049df177..876e6bffe974e 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -6498,7 +6498,6 @@ "xpack.apm.errorsTable.occurrencesColumnLabel": "发生次数", "xpack.apm.errorsTable.typeColumnLabel": "类型", "xpack.apm.errorsTable.unhandledLabel": "未处理", - "xpack.apm.exactTransactionRateLabel": "{value} { unit, select, minute {tpm} other {tps} }", "xpack.apm.failedTransactionsCorrelations.licenseCheckText": "要使用失败事务相关性功能,必须订阅 Elastic 白金级许可证。", "xpack.apm.featureRegistry.apmFeatureName": "APM 和用户体验", "xpack.apm.feedbackMenu.appName": "APM", @@ -6811,9 +6810,7 @@ "xpack.apm.serviceOverview.mlNudgeMessage.learnMoreButton": "开始使用", "xpack.apm.serviceOverview.throughtputChart.previousPeriodLabel": "上一时段", "xpack.apm.serviceOverview.throughtputChartTitle": "吞吐量", - "xpack.apm.serviceOverview.throughtputPerSecondChartTitle": " (每秒)", "xpack.apm.serviceOverview.tpmHelp": "吞吐量按每分钟事务数 (tpm) 来度量", - "xpack.apm.serviceOverview.tpsHelp": "吞吐量按每秒事务数 (tps) 来度量", "xpack.apm.serviceOverview.transactionsTableColumnErrorRate": "失败事务率", "xpack.apm.serviceOverview.transactionsTableColumnImpact": "影响", "xpack.apm.serviceOverview.transactionsTableColumnName": "名称", diff --git a/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts b/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts index e1cab29abec4b..8f8cf16d1e383 100644 --- a/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts +++ b/x-pack/plugins/uptime/public/apps/uptime_overview_fetcher.ts @@ -13,7 +13,7 @@ import { kibanaService } from '../state/kibana_service'; async function fetchUptimeOverviewData({ absoluteTime, relativeTime, - bucketSize, + intervalString, }: FetchDataParams) { const start = new Date(absoluteTime.start).toISOString(); const end = new Date(absoluteTime.end).toISOString(); @@ -22,7 +22,11 @@ async function fetchUptimeOverviewData({ dateRangeEnd: end, }); - const pings = await fetchPingHistogram({ dateStart: start, dateEnd: end, bucketSize }); + const pings = await fetchPingHistogram({ + dateStart: start, + dateEnd: end, + bucketSize: intervalString, + }); const response: UptimeFetchDataResponse = { appLink: `/app/uptime?dateRangeStart=${relativeTime.start}&dateRangeEnd=${relativeTime.end}`, diff --git a/x-pack/test/apm_api_integration/common/fixtures/es_archiver/archives_metadata.ts b/x-pack/test/apm_api_integration/common/fixtures/es_archiver/archives_metadata.ts index 3382f0f8ee460..bea2b54d05eeb 100644 --- a/x-pack/test/apm_api_integration/common/fixtures/es_archiver/archives_metadata.ts +++ b/x-pack/test/apm_api_integration/common/fixtures/es_archiver/archives_metadata.ts @@ -5,8 +5,7 @@ * 2.0. */ -/* eslint-disable-next-line*/ - export default { +export default { 'apm_8.0.0': { start: '2021-08-03T06:50:15.910Z', end: '2021-08-03T07:20:15.910Z', diff --git a/x-pack/test/apm_api_integration/tests/index.ts b/x-pack/test/apm_api_integration/tests/index.ts index 49f1ae91c6282..8caae0afe746e 100644 --- a/x-pack/test/apm_api_integration/tests/index.ts +++ b/x-pack/test/apm_api_integration/tests/index.ts @@ -96,6 +96,14 @@ export default function apmApiIntegrationTests(providerContext: FtrProviderConte loadTestFile(require.resolve('./services/throughput')); }); + describe('service apis throughput', function () { + loadTestFile(require.resolve('./throughput/service_apis')); + }); + + describe('dependencies throughput', function () { + loadTestFile(require.resolve('./throughput/dependencies_apis')); + }); + describe('services/top_services', function () { loadTestFile(require.resolve('./services/top_services')); }); diff --git a/x-pack/test/apm_api_integration/tests/inspect/inspect.ts b/x-pack/test/apm_api_integration/tests/inspect/inspect.ts index 75b5a02fff800..a010c150124f0 100644 --- a/x-pack/test/apm_api_integration/tests/inspect/inspect.ts +++ b/x-pack/test/apm_api_integration/tests/inspect/inspect.ts @@ -49,7 +49,7 @@ export default function customLinksTests({ getService }: FtrProviderContext) { }, }); expect(status).to.be(200); - expect(body._inspect?.length).to.be(2); + expect(body._inspect?.length).to.be(1); // @ts-expect-error expect(Object.keys(body._inspect[0])).to.eql([ diff --git a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts index b463db81e6c99..458372196452a 100644 --- a/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts +++ b/x-pack/test/apm_api_integration/tests/observability_overview/observability_overview.ts @@ -4,22 +4,58 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { service, timerange } from '@elastic/apm-generator'; import expect from '@kbn/expect'; -import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { meanBy, sumBy } from 'lodash'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { registry } from '../../common/registry'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { roundNumber } from '../../utils'; export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('legacySupertestAsApmReadUser'); + const apmApiClient = getService('apmApiClient'); + + const traceData = getService('traceData'); - const archiveName = 'apm_8.0.0'; - const metadata = archives_metadata[archiveName]; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + const intervalString = '60s'; + const bucketSize = 60; - // url parameters - const start = encodeURIComponent(metadata.start); - const end = encodeURIComponent(metadata.end); - const bucketSize = '60s'; + async function getThroughputValues() { + const commonQuery = { start: new Date(start).toISOString(), end: new Date(end).toISOString() }; + const [serviceInventoryAPIResponse, observabilityOverviewAPIResponse] = await Promise.all([ + apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services', + params: { + query: { + ...commonQuery, + environment: 'ENVIRONMENT_ALL', + kuery: '', + }, + }, + }), + apmApiClient.readUser({ + endpoint: `GET /internal/apm/observability_overview`, + params: { + query: { + ...commonQuery, + bucketSize, + intervalString, + }, + }, + }), + ]); + const serviceInventoryThroughputSum = roundNumber( + sumBy(serviceInventoryAPIResponse.body.items, 'throughput') + ); + + return { + serviceInventoryCount: serviceInventoryAPIResponse.body.items.length, + serviceInventoryThroughputSum, + observabilityOverview: observabilityOverviewAPIResponse.body, + }; + } registry.when( 'Observability overview when data is not loaded', @@ -27,9 +63,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { () => { describe('when data is not loaded', () => { it('handles the empty state', async () => { - const response = await supertest.get( - `/internal/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` - ); + const response = await apmApiClient.readUser({ + endpoint: `GET /internal/apm/observability_overview`, + params: { + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + bucketSize, + intervalString, + }, + }, + }); expect(response.status).to.be(200); expect(response.body.serviceCount).to.be(0); @@ -39,56 +83,89 @@ export default function ApiTest({ getService }: FtrProviderContext) { } ); - registry.when( - 'Observability overview when data is loaded', - { config: 'basic', archives: [archiveName] }, - () => { - it('returns the service count and transaction coordinates', async () => { - const response = await supertest.get( - `/internal/apm/observability_overview?start=${start}&end=${end}&bucketSize=${bucketSize}` + registry.when('data is loaded', { config: 'basic', archives: ['apm_8.0.0_empty'] }, () => { + describe('Observability overview api ', () => { + const GO_PROD_RATE = 50; + const GO_DEV_RATE = 5; + const JAVA_PROD_RATE = 45; + before(async () => { + const serviceGoProdInstance = service('synth-go', 'production', 'go').instance( + 'instance-a' + ); + const serviceGoDevInstance = service('synth-go', 'development', 'go').instance( + 'instance-b' + ); + const serviceJavaInstance = service('synth-java', 'production', 'java').instance( + 'instance-c' ); - expect(response.status).to.be(200); - expect(response.body.serviceCount).to.be.greaterThan(0); - expect(response.body.transactionPerMinute.timeseries.length).to.be.greaterThan(0); + await traceData.index([ + ...timerange(start, end) + .interval('1m') + .rate(GO_PROD_RATE) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction('GET /api/product/list') + .duration(1000) + .timestamp(timestamp) + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(GO_DEV_RATE) + .flatMap((timestamp) => + serviceGoDevInstance + .transaction('GET /api/product/:id') + .duration(1000) + .timestamp(timestamp) + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(JAVA_PROD_RATE) + .flatMap((timestamp) => + serviceJavaInstance + .transaction('POST /api/product/buy') + .duration(1000) + .timestamp(timestamp) + .serialize() + ), + ]); + }); - expectSnapshot(response.body.serviceCount).toMatchInline(`8`); + after(() => traceData.clean()); - expectSnapshot(response.body.transactionPerMinute.value).toMatchInline(`58.9`); - expectSnapshot(response.body.transactionPerMinute.timeseries.length).toMatchInline(`30`); + describe('compare throughput values', () => { + let throughputValues: PromiseReturnType; + before(async () => { + throughputValues = await getThroughputValues(); + }); - expectSnapshot( - response.body.transactionPerMinute.timeseries - .slice(0, 5) - .map(({ x, y }: { x: number; y: number }) => ({ - x: new Date(x).toISOString(), - y, - })) - ).toMatchInline(` - Array [ - Object { - "x": "2021-08-03T06:50:00.000Z", - "y": 36, - }, - Object { - "x": "2021-08-03T06:51:00.000Z", - "y": 55, - }, - Object { - "x": "2021-08-03T06:52:00.000Z", - "y": 40, - }, - Object { - "x": "2021-08-03T06:53:00.000Z", - "y": 53, - }, - Object { - "x": "2021-08-03T06:54:00.000Z", - "y": 39, - }, - ] - `); + it('returns same number of service as shown on service inventory API', () => { + const { serviceInventoryCount, observabilityOverview } = throughputValues; + [serviceInventoryCount, observabilityOverview.serviceCount].forEach((value) => + expect(value).to.be.equal(2) + ); + }); + + it('returns same throughput value on service inventory and obs throughput count', () => { + const { serviceInventoryThroughputSum, observabilityOverview } = throughputValues; + const obsThroughputCount = roundNumber(observabilityOverview.transactionPerMinute.value); + [serviceInventoryThroughputSum, obsThroughputCount].forEach((value) => + expect(value).to.be.equal(roundNumber(GO_PROD_RATE + GO_DEV_RATE + JAVA_PROD_RATE)) + ); + }); + + it('returns same throughput value on service inventory and obs mean throughput timeseries', () => { + const { serviceInventoryThroughputSum, observabilityOverview } = throughputValues; + const obsThroughputMean = roundNumber( + meanBy(observabilityOverview.transactionPerMinute.timeseries, 'y') + ); + [serviceInventoryThroughputSum, obsThroughputMean].forEach((value) => + expect(value).to.be.equal(roundNumber(GO_PROD_RATE + GO_DEV_RATE + JAVA_PROD_RATE)) + ); + }); }); - } - ); + }); + }); } diff --git a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts index 37fe340d75194..ab1be97e0fd8a 100644 --- a/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts +++ b/x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts @@ -301,8 +301,8 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext) "avgErrorRate": 0, "avgMemoryUsage": 0.202572668763642, "transactionStats": Object { - "avgRequestsPerMinute": 5.2, - "avgTransactionDuration": 53906.6603773585, + "avgRequestsPerMinute": 7.13333333333333, + "avgTransactionDuration": 53147.5747663551, }, } `); diff --git a/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instance_details.snap b/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instance_details.snap index 5daadd8079baa..91b0b7f2da6e4 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instance_details.snap +++ b/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instance_details.snap @@ -2,7 +2,7 @@ exports[`APM API tests basic apm_8.0.0 Instance details when data is loaded fetch instance details return the correct data 1`] = ` Object { - "@timestamp": "2021-08-03T06:50:50.204Z", + "@timestamp": "2021-08-03T06:50:20.205Z", "agent": Object { "ephemeral_id": "2745d454-f57f-4473-a09b-fe6bef295860", "name": "java", diff --git a/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.snap b/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.snap index 7ae3fa1da3380..971c14262f0b0 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.snap +++ b/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.snap @@ -73,11 +73,11 @@ Object { "errorRate": Array [ Object { "x": 1627974300000, - "y": 0, + "y": null, }, Object { "x": 1627974360000, - "y": null, + "y": 0, }, Object { "x": 1627974420000, @@ -93,15 +93,15 @@ Object { }, Object { "x": 1627974600000, - "y": 0.0526315789473684, + "y": 0.5, }, Object { "x": 1627974660000, - "y": 0.142857142857143, + "y": 0.4, }, Object { "x": 1627974720000, - "y": 0.0416666666666667, + "y": 0, }, Object { "x": 1627974780000, @@ -109,11 +109,11 @@ Object { }, Object { "x": 1627974840000, - "y": 0, + "y": 0.166666666666667, }, Object { "x": 1627974900000, - "y": 0.024390243902439, + "y": 0, }, Object { "x": 1627974960000, @@ -125,11 +125,11 @@ Object { }, Object { "x": 1627975080000, - "y": 0, + "y": 0.142857142857143, }, Object { "x": 1627975140000, - "y": 0.0555555555555556, + "y": 0.2, }, Object { "x": 1627975200000, @@ -139,63 +139,63 @@ Object { "latency": Array [ Object { "x": 1627974300000, - "y": 34887.8888888889, + "y": null, }, Object { "x": 1627974360000, - "y": null, + "y": 5578, }, Object { "x": 1627974420000, - "y": 4983, + "y": 34851.1666666667, }, Object { "x": 1627974480000, - "y": 41285.4, + "y": 15896.4, }, Object { "x": 1627974540000, - "y": 13820.3333333333, + "y": 15174.1666666667, }, Object { "x": 1627974600000, - "y": 13782, + "y": 9185.16666666667, }, Object { "x": 1627974660000, - "y": 13392.6, + "y": 12363.2, }, Object { "x": 1627974720000, - "y": 6991, + "y": 6206.44444444444, }, Object { "x": 1627974780000, - "y": 6885.85714285714, + "y": 6707, }, Object { "x": 1627974840000, - "y": 7935, + "y": 12409.1666666667, }, Object { "x": 1627974900000, - "y": 10828.3333333333, + "y": 9188.36363636364, }, Object { "x": 1627974960000, - "y": 6079, + "y": 4279.6, }, Object { "x": 1627975020000, - "y": 5217, + "y": 6827.3, }, Object { "x": 1627975080000, - "y": 8477.76923076923, + "y": 7445.78571428571, }, Object { "x": 1627975140000, - "y": 5937.18181818182, + "y": 563288.6, }, Object { "x": 1627975200000, @@ -272,63 +272,63 @@ Object { "throughput": Array [ Object { "x": 1627974300000, - "y": 21, + "y": 0, }, Object { "x": 1627974360000, - "y": 0, + "y": 2, }, Object { "x": 1627974420000, - "y": 24, + "y": 6, }, Object { "x": 1627974480000, - "y": 17, + "y": 5, }, Object { "x": 1627974540000, - "y": 17, + "y": 6, }, Object { "x": 1627974600000, - "y": 19, + "y": 6, }, Object { "x": 1627974660000, - "y": 21, + "y": 5, }, Object { "x": 1627974720000, - "y": 24, + "y": 9, }, Object { "x": 1627974780000, - "y": 22, + "y": 3, }, Object { "x": 1627974840000, - "y": 19, + "y": 6, }, Object { "x": 1627974900000, - "y": 41, + "y": 11, }, Object { "x": 1627974960000, - "y": 11, + "y": 5, }, Object { "x": 1627975020000, - "y": 23, + "y": 10, }, Object { "x": 1627975080000, - "y": 47, + "y": 14, }, Object { "x": 1627975140000, - "y": 36, + "y": 10, }, Object { "x": 1627975200000, @@ -412,15 +412,15 @@ Object { }, Object { "x": 1627974360000, - "y": 0, + "y": 0.25, }, Object { "x": 1627974420000, - "y": 0.0434782608695652, + "y": 0.111111111111111, }, Object { "x": 1627974480000, - "y": 0.0833333333333333, + "y": 0.2, }, Object { "x": 1627974540000, @@ -428,15 +428,15 @@ Object { }, Object { "x": 1627974600000, - "y": 0, + "y": 0.142857142857143, }, Object { "x": 1627974660000, - "y": 0.03125, + "y": 0.1, }, Object { "x": 1627974720000, - "y": 0.0555555555555556, + "y": 0.125, }, Object { "x": 1627974780000, @@ -444,15 +444,15 @@ Object { }, Object { "x": 1627974840000, - "y": 0, + "y": 0.111111111111111, }, Object { "x": 1627974900000, - "y": 0.0232558139534884, + "y": 0, }, Object { "x": 1627974960000, - "y": 0.032258064516129, + "y": 0.333333333333333, }, Object { "x": 1627975020000, @@ -460,81 +460,81 @@ Object { }, Object { "x": 1627975080000, - "y": 0.027027027027027, + "y": 0.0833333333333333, }, Object { "x": 1627975140000, - "y": 0.0571428571428571, + "y": 0.1, }, Object { "x": 1627975200000, - "y": null, + "y": 0, }, ], "latency": Array [ Object { "x": 1627974300000, - "y": 11839, + "y": 5372.5, }, Object { "x": 1627974360000, - "y": 7407, + "y": 1441598.25, }, Object { "x": 1627974420000, - "y": 1925569.66666667, + "y": 9380.22222222222, }, Object { "x": 1627974480000, - "y": 9017.18181818182, + "y": 10949.4, }, Object { "x": 1627974540000, - "y": 63575, + "y": 77148.6666666667, }, Object { "x": 1627974600000, - "y": 7577.66666666667, + "y": 6461, }, Object { "x": 1627974660000, - "y": 6844.33333333333, + "y": 549308.4, }, Object { "x": 1627974720000, - "y": 503471, + "y": 10797.75, }, Object { "x": 1627974780000, - "y": 6247.8, + "y": 9758.53846153846, }, Object { "x": 1627974840000, - "y": 1137247, + "y": 1281052.66666667, }, Object { "x": 1627974900000, - "y": 27951.6666666667, + "y": 9511.0625, }, Object { "x": 1627974960000, - "y": 10248.8461538462, + "y": 11151203.3333333, }, Object { "x": 1627975020000, - "y": 13529, + "y": 8647.2, }, Object { "x": 1627975080000, - "y": 6691247.8, + "y": 9048.33333333333, }, Object { "x": 1627975140000, - "y": 12098.6923076923, + "y": 12671.6, }, Object { "x": 1627975200000, - "y": null, + "y": 57275.4, }, ], "memoryUsage": Array [ @@ -607,67 +607,67 @@ Object { "throughput": Array [ Object { "x": 1627974300000, - "y": 15, + "y": 2, }, Object { "x": 1627974360000, - "y": 13, + "y": 4, }, Object { "x": 1627974420000, - "y": 23, + "y": 9, }, Object { "x": 1627974480000, - "y": 24, + "y": 5, }, Object { "x": 1627974540000, - "y": 10, + "y": 3, }, Object { "x": 1627974600000, - "y": 18, + "y": 7, }, Object { "x": 1627974660000, - "y": 32, + "y": 10, }, Object { "x": 1627974720000, - "y": 36, + "y": 8, }, Object { "x": 1627974780000, - "y": 36, + "y": 13, }, Object { "x": 1627974840000, - "y": 22, + "y": 9, }, Object { "x": 1627974900000, - "y": 43, + "y": 16, }, Object { "x": 1627974960000, - "y": 31, + "y": 6, }, Object { "x": 1627975020000, - "y": 35, + "y": 10, }, Object { "x": 1627975080000, - "y": 37, + "y": 12, }, Object { "x": 1627975140000, - "y": 35, + "y": 10, }, Object { "x": 1627975200000, - "y": 0, + "y": 5, }, ], }, @@ -812,15 +812,15 @@ Object { }, Object { "x": 1627973460000, - "y": 0, + "y": 0.25, }, Object { "x": 1627973520000, - "y": 0.0434782608695652, + "y": 0.111111111111111, }, Object { "x": 1627973580000, - "y": 0.0833333333333333, + "y": 0.2, }, Object { "x": 1627973640000, @@ -828,15 +828,15 @@ Object { }, Object { "x": 1627973700000, - "y": 0, + "y": 0.142857142857143, }, Object { "x": 1627973760000, - "y": 0.03125, + "y": 0.1, }, Object { "x": 1627973820000, - "y": 0.0555555555555556, + "y": 0.125, }, Object { "x": 1627973880000, @@ -844,15 +844,15 @@ Object { }, Object { "x": 1627973940000, - "y": 0, + "y": 0.111111111111111, }, Object { "x": 1627974000000, - "y": 0.0232558139534884, + "y": 0, }, Object { "x": 1627974060000, - "y": 0.032258064516129, + "y": 0.333333333333333, }, Object { "x": 1627974120000, @@ -860,11 +860,11 @@ Object { }, Object { "x": 1627974180000, - "y": 0.027027027027027, + "y": 0.0833333333333333, }, Object { "x": 1627974240000, - "y": 0.0571428571428571, + "y": 0.1, }, Object { "x": 1627974300000, @@ -872,7 +872,7 @@ Object { }, Object { "x": 1627974360000, - "y": null, + "y": 0, }, Object { "x": 1627974420000, @@ -888,15 +888,15 @@ Object { }, Object { "x": 1627974600000, - "y": 0.0526315789473684, + "y": 0.5, }, Object { "x": 1627974660000, - "y": 0.142857142857143, + "y": 0.4, }, Object { "x": 1627974720000, - "y": 0.0416666666666667, + "y": 0, }, Object { "x": 1627974780000, @@ -904,11 +904,11 @@ Object { }, Object { "x": 1627974840000, - "y": 0, + "y": 0.166666666666667, }, Object { "x": 1627974900000, - "y": 0.024390243902439, + "y": 0, }, Object { "x": 1627974960000, @@ -920,11 +920,11 @@ Object { }, Object { "x": 1627975080000, - "y": 0, + "y": 0.142857142857143, }, Object { "x": 1627975140000, - "y": 0.0555555555555556, + "y": 0.2, }, Object { "x": 1627975200000, @@ -934,123 +934,123 @@ Object { "latency": Array [ Object { "x": 1627973400000, - "y": 11839, + "y": 5372.5, }, Object { "x": 1627973460000, - "y": 7407, + "y": 1441598.25, }, Object { "x": 1627973520000, - "y": 1925569.66666667, + "y": 9380.22222222222, }, Object { "x": 1627973580000, - "y": 9017.18181818182, + "y": 10949.4, }, Object { "x": 1627973640000, - "y": 63575, + "y": 77148.6666666667, }, Object { "x": 1627973700000, - "y": 7577.66666666667, + "y": 6461, }, Object { "x": 1627973760000, - "y": 6844.33333333333, + "y": 549308.4, }, Object { "x": 1627973820000, - "y": 503471, + "y": 10797.75, }, Object { "x": 1627973880000, - "y": 6247.8, + "y": 9758.53846153846, }, Object { "x": 1627973940000, - "y": 1137247, + "y": 1281052.66666667, }, Object { "x": 1627974000000, - "y": 27951.6666666667, + "y": 9511.0625, }, Object { "x": 1627974060000, - "y": 10248.8461538462, + "y": 11151203.3333333, }, Object { "x": 1627974120000, - "y": 13529, + "y": 8647.2, }, Object { "x": 1627974180000, - "y": 6691247.8, + "y": 9048.33333333333, }, Object { "x": 1627974240000, - "y": 12098.6923076923, + "y": 12671.6, }, Object { "x": 1627974300000, - "y": 34887.8888888889, + "y": 57275.4, }, Object { "x": 1627974360000, - "y": null, + "y": 5578, }, Object { "x": 1627974420000, - "y": 4983, + "y": 34851.1666666667, }, Object { "x": 1627974480000, - "y": 41285.4, + "y": 15896.4, }, Object { "x": 1627974540000, - "y": 13820.3333333333, + "y": 15174.1666666667, }, Object { "x": 1627974600000, - "y": 13782, + "y": 9185.16666666667, }, Object { "x": 1627974660000, - "y": 13392.6, + "y": 12363.2, }, Object { "x": 1627974720000, - "y": 6991, + "y": 6206.44444444444, }, Object { "x": 1627974780000, - "y": 6885.85714285714, + "y": 6707, }, Object { "x": 1627974840000, - "y": 7935, + "y": 12409.1666666667, }, Object { "x": 1627974900000, - "y": 10828.3333333333, + "y": 9188.36363636364, }, Object { "x": 1627974960000, - "y": 6079, + "y": 4279.6, }, Object { "x": 1627975020000, - "y": 5217, + "y": 6827.3, }, Object { "x": 1627975080000, - "y": 8477.76923076923, + "y": 7445.78571428571, }, Object { "x": 1627975140000, - "y": 5937.18181818182, + "y": 563288.6, }, Object { "x": 1627975200000, @@ -1187,123 +1187,123 @@ Object { "throughput": Array [ Object { "x": 1627973400000, - "y": 15, + "y": 2, }, Object { "x": 1627973460000, - "y": 13, + "y": 4, }, Object { "x": 1627973520000, - "y": 23, + "y": 9, }, Object { "x": 1627973580000, - "y": 24, + "y": 5, }, Object { "x": 1627973640000, - "y": 10, + "y": 3, }, Object { "x": 1627973700000, - "y": 18, + "y": 7, }, Object { "x": 1627973760000, - "y": 32, + "y": 10, }, Object { "x": 1627973820000, - "y": 36, + "y": 8, }, Object { "x": 1627973880000, - "y": 36, + "y": 13, }, Object { "x": 1627973940000, - "y": 22, + "y": 9, }, Object { "x": 1627974000000, - "y": 43, + "y": 16, }, Object { "x": 1627974060000, - "y": 31, + "y": 6, }, Object { "x": 1627974120000, - "y": 35, + "y": 10, }, Object { "x": 1627974180000, - "y": 37, + "y": 12, }, Object { "x": 1627974240000, - "y": 35, + "y": 10, }, Object { "x": 1627974300000, - "y": 21, + "y": 5, }, Object { "x": 1627974360000, - "y": 0, + "y": 2, }, Object { "x": 1627974420000, - "y": 24, + "y": 6, }, Object { "x": 1627974480000, - "y": 17, + "y": 5, }, Object { "x": 1627974540000, - "y": 17, + "y": 6, }, Object { "x": 1627974600000, - "y": 19, + "y": 6, }, Object { "x": 1627974660000, - "y": 21, + "y": 5, }, Object { "x": 1627974720000, - "y": 24, + "y": 9, }, Object { "x": 1627974780000, - "y": 22, + "y": 3, }, Object { "x": 1627974840000, - "y": 19, + "y": 6, }, Object { "x": 1627974900000, - "y": 41, + "y": 11, }, Object { "x": 1627974960000, - "y": 11, + "y": 5, }, Object { "x": 1627975020000, - "y": 23, + "y": 10, }, Object { "x": 1627975080000, - "y": 47, + "y": 14, }, Object { "x": 1627975140000, - "y": 36, + "y": 10, }, Object { "x": 1627975200000, diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts index cdf62053a821b..5585a292d317e 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/service_overview/instances_main_statistics.ts @@ -122,10 +122,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(values).toMatchInline(` Object { "cpuUsage": 0.002, - "errorRate": 0.0252659574468085, - "latency": 411589.785714286, + "errorRate": 0.092511013215859, + "latency": 430318.696035242, "memoryUsage": 0.786029688517253, - "throughput": 25.0666666666667, + "throughput": 7.56666666666667, } `); }); @@ -183,9 +183,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(values).toMatchInline(` Object { "cpuUsage": 0.001, - "errorRate": 0.000907441016333938, - "latency": 40989.5802047782, - "throughput": 36.7333333333333, + "errorRate": 0.00343642611683849, + "latency": 21520.4776632302, + "throughput": 9.7, } `); @@ -272,10 +272,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(values).toMatchInline(` Object { "cpuUsage": 0.00223333333333333, - "errorRate": 0.0268292682926829, - "latency": 739013.634146341, + "errorRate": 0.0852713178294574, + "latency": 706173.046511628, "memoryUsage": 0.783296203613281, - "throughput": 27.3333333333333, + "throughput": 8.6, } `); }); 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 deleted file mode 100644 index a27f7047bb9b3..0000000000000 --- a/x-pack/test/apm_api_integration/tests/services/__snapshots__/throughput.snap +++ /dev/null @@ -1,139 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -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 { - "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, - }, - ], - "previousPeriod": Array [ - Object { - "x": 1627974300000, - "y": 4, - }, - Object { - "x": 1627974360000, - "y": 2, - }, - Object { - "x": 1627974420000, - "y": 3, - }, - Object { - "x": 1627974480000, - "y": 8, - }, - Object { - "x": 1627974540000, - "y": 4, - }, - Object { - "x": 1627974600000, - "y": 4, - }, - Object { - "x": 1627974660000, - "y": 6, - }, - Object { - "x": 1627974720000, - "y": 10, - }, - Object { - "x": 1627974780000, - "y": 8, - }, - Object { - "x": 1627974840000, - "y": 9, - }, - Object { - "x": 1627974900000, - "y": 10, - }, - Object { - "x": 1627974960000, - "y": 11, - }, - Object { - "x": 1627975020000, - "y": 7, - }, - Object { - "x": 1627975080000, - "y": 10, - }, - Object { - "x": 1627975140000, - "y": 12, - }, - Object { - "x": 1627975200000, - "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 d960cccc2877e..561680e2725cf 100644 --- a/x-pack/test/apm_api_integration/tests/services/throughput.ts +++ b/x-pack/test/apm_api_integration/tests/services/throughput.ts @@ -7,15 +7,17 @@ import { service, timerange } from '@elastic/apm-generator'; import expect from '@kbn/expect'; -import { first, last, mean, uniq } from 'lodash'; +import { first, last, meanBy } from 'lodash'; import moment from 'moment'; -import { ENVIRONMENT_ALL } from '../../../../plugins/apm/common/environment_filter_values'; import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number'; -import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; -import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; -import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata'; +import { + APIClientRequestParamsOf, + APIReturnType, +} from '../../../../plugins/apm/public/services/rest/createCallApmApi'; +import { RecursivePartial } from '../../../../plugins/apm/typings/common'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { registry } from '../../common/registry'; +import { roundNumber } from '../../utils'; type ThroughputReturn = APIReturnType<'GET /internal/apm/services/{serviceName}/throughput'>; @@ -23,34 +25,65 @@ export default function ApiTest({ getService }: FtrProviderContext) { const apmApiClient = getService('apmApiClient'); const traceData = getService('traceData'); - const archiveName = 'apm_8.0.0'; - const metadata = archives_metadata[archiveName]; + const serviceName = 'synth-go'; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + + async function callApi( + overrides?: RecursivePartial< + APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/throughput'>['params'] + > + ) { + const response = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/throughput', + params: { + path: { + serviceName: 'synth-go', + ...overrides?.path, + }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + transactionType: 'request', + environment: 'ENVIRONMENT_ALL', + kuery: '', + ...overrides?.query, + }, + }, + }); + return response; + } - registry.when( - 'Throughput with statically generated data', - { config: 'basic', archives: ['apm_8.0.0_empty'] }, - () => { - const start = new Date('2021-01-01T00:00:00.000Z').getTime(); - const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + registry.when('Throughput when data is not loaded', { config: 'basic', archives: [] }, () => { + it('handles the empty state', async () => { + const response = await callApi(); + expect(response.status).to.be(200); + expect(response.body.currentPeriod.length).to.be(0); + expect(response.body.previousPeriod.length).to.be(0); + }); + }); - const GO_PROD_RATE = 10; + registry.when('data is loaded', { config: 'basic', archives: ['apm_8.0.0_empty'] }, () => { + describe('Throughput chart api', () => { + const GO_PROD_RATE = 50; const GO_DEV_RATE = 5; - const JAVA_PROD_RATE = 20; + const JAVA_PROD_RATE = 45; before(async () => { - const serviceGoProdInstance = service('synth-go', 'production', 'go').instance( + const serviceGoProdInstance = service(serviceName, 'production', 'go').instance( 'instance-a' ); - const serviceGoDevInstance = service('synth-go', 'development', 'go').instance( + const serviceGoDevInstance = service(serviceName, 'development', 'go').instance( 'instance-b' ); - const serviceJavaInstance = service('synth-java', 'production', 'java').instance( + + const serviceJavaInstance = service('synth-java', 'development', 'java').instance( 'instance-c' ); await traceData.index([ ...timerange(start, end) - .interval('1s') + .interval('1m') .rate(GO_PROD_RATE) .flatMap((timestamp) => serviceGoProdInstance @@ -60,7 +93,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .serialize() ), ...timerange(start, end) - .interval('1s') + .interval('1m') .rate(GO_DEV_RATE) .flatMap((timestamp) => serviceGoDevInstance @@ -70,7 +103,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { .serialize() ), ...timerange(start, end) - .interval('1s') + .interval('1m') .rate(JAVA_PROD_RATE) .flatMap((timestamp) => serviceJavaInstance @@ -84,129 +117,104 @@ export default function ApiTest({ getService }: FtrProviderContext) { after(() => traceData.clean()); - async function callApi(overrides?: { - start?: string; - end?: string; - transactionType?: string; - environment?: string; - kuery?: string; - }) { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/throughput', - params: { - path: { - serviceName: 'synth-go', - }, - query: { - start: new Date(start).toISOString(), - end: new Date(end).toISOString(), - transactionType: 'request', - environment: 'production', - kuery: 'processor.event:transaction', - ...overrides, - }, - }, + describe('compare transactions and metrics based throughput', () => { + let throughputMetrics: ThroughputReturn; + let throughputTransactions: ThroughputReturn; + + before(async () => { + const [throughputMetricsResponse, throughputTransactionsResponse] = await Promise.all([ + callApi({ query: { kuery: 'processor.event : "metric"' } }), + callApi({ query: { kuery: 'processor.event : "transaction"' } }), + ]); + throughputMetrics = throughputMetricsResponse.body; + throughputTransactions = throughputTransactionsResponse.body; }); - return response.body; - } + it('returns some transactions data', () => { + expect(throughputTransactions.currentPeriod.length).to.be.greaterThan(0); + const hasData = throughputTransactions.currentPeriod.some(({ y }) => isFiniteNumber(y)); + expect(hasData).to.equal(true); + }); - describe('when calling it with the default parameters', () => { - let body: PromiseReturnType; + it('returns some metrics data', () => { + expect(throughputMetrics.currentPeriod.length).to.be.greaterThan(0); + const hasData = throughputMetrics.currentPeriod.some(({ y }) => isFiniteNumber(y)); + expect(hasData).to.equal(true); + }); - before(async () => { - body = await callApi(); + it('has same mean value for metrics and transactions data', () => { + const transactionsMean = meanBy(throughputTransactions.currentPeriod, 'y'); + const metricsMean = meanBy(throughputMetrics.currentPeriod, 'y'); + [transactionsMean, metricsMean].forEach((value) => + expect(roundNumber(value)).to.be.equal(roundNumber(GO_PROD_RATE + GO_DEV_RATE)) + ); }); - it('returns the throughput in seconds', () => { - expect(body.throughputUnit).to.eql('second'); + it('has a bucket size of 10 seconds for transactions data', () => { + const firstTimerange = throughputTransactions.currentPeriod[0].x; + const secondTimerange = throughputTransactions.currentPeriod[1].x; + const timeIntervalAsSeconds = (secondTimerange - firstTimerange) / 1000; + expect(timeIntervalAsSeconds).to.equal(10); }); - it('returns the expected throughput', () => { - const throughputValues = uniq(body.currentPeriod.map((coord) => coord.y)); - expect(throughputValues).to.eql([GO_PROD_RATE]); + it('has a bucket size of 1 minute for metrics data', () => { + const firstTimerange = throughputMetrics.currentPeriod[0].x; + const secondTimerange = throughputMetrics.currentPeriod[1].x; + const timeIntervalAsMinutes = (secondTimerange - firstTimerange) / 1000 / 60; + expect(timeIntervalAsMinutes).to.equal(1); }); }); - describe('when setting environment to all', () => { - let body: PromiseReturnType; + describe('production environment', () => { + let throughput: ThroughputReturn; before(async () => { - body = await callApi({ - environment: ENVIRONMENT_ALL.value, - }); + const throughputResponse = await callApi({ query: { environment: 'production' } }); + throughput = throughputResponse.body; + }); + + it('returns some data', () => { + expect(throughput.currentPeriod.length).to.be.greaterThan(0); + const hasData = throughput.currentPeriod.some(({ y }) => isFiniteNumber(y)); + expect(hasData).to.equal(true); }); - it('returns data for all environments', () => { - const throughputValues = body.currentPeriod.map(({ y }) => y); - expect(uniq(throughputValues)).to.eql([GO_PROD_RATE + GO_DEV_RATE]); - expect(body.throughputUnit).to.eql('second'); + it('returns correct average throughput', () => { + const throughputMean = meanBy(throughput.currentPeriod, 'y'); + expect(roundNumber(throughputMean)).to.be.equal(roundNumber(GO_PROD_RATE)); }); }); - describe('when defining a kuery', () => { - let body: PromiseReturnType; + describe('when synth-java is selected', () => { + let throughput: ThroughputReturn; before(async () => { - body = await callApi({ - kuery: `processor.event:transaction and transaction.name:"GET /api/product/:id"`, - environment: ENVIRONMENT_ALL.value, - }); + const throughputResponse = await callApi({ path: { serviceName: 'synth-java' } }); + throughput = throughputResponse.body; }); - it('returns data that matches the kuery', () => { - const throughputValues = body.currentPeriod.map(({ y }) => y); - expect(uniq(throughputValues)).to.eql([GO_DEV_RATE]); - expect(body.throughputUnit).to.eql('second'); + it('returns some data', () => { + expect(throughput.currentPeriod.length).to.be.greaterThan(0); + const hasData = throughput.currentPeriod.some(({ y }) => isFiniteNumber(y)); + expect(hasData).to.equal(true); }); - }); - } - ); - registry.when('Throughput when data is not loaded', { config: 'basic', archives: [] }, () => { - it('handles the empty state', async () => { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/throughput', - params: { - path: { - serviceName: 'opbeans-java', - }, - query: { - start: metadata.start, - end: metadata.end, - transactionType: 'request', - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }, + it('returns throughput related to java agent', () => { + const throughputMean = meanBy(throughput.currentPeriod, 'y'); + expect(roundNumber(throughputMean)).to.be.equal(roundNumber(JAVA_PROD_RATE)); + }); }); - expect(response.status).to.be(200); - expect(response.body.currentPeriod.length).to.be(0); - expect(response.body.previousPeriod.length).to.be(0); - }); - }); + describe('time comparisons', () => { + let throughputResponse: ThroughputReturn; - let throughputResponse: ThroughputReturn; - registry.when( - 'Throughput when data is loaded', - { config: 'basic', archives: [archiveName] }, - () => { - describe('when querying without kql filter', () => { before(async () => { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/throughput', - params: { - path: { - serviceName: 'opbeans-java', - }, - query: { - start: metadata.start, - end: metadata.end, - transactionType: 'request', - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, + const response = await callApi({ + query: { + start: moment(end).subtract(7, 'minutes').toISOString(), + end: new Date(end).toISOString(), + comparisonStart: new Date(start).toISOString(), + comparisonEnd: moment(start).add(7, 'minutes').toISOString(), }, }); throughputResponse = response.body; @@ -214,141 +222,58 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('returns some data', () => { expect(throughputResponse.currentPeriod.length).to.be.greaterThan(0); - expect(throughputResponse.previousPeriod.length).not.to.be.greaterThan(0); + expect(throughputResponse.previousPeriod.length).to.be.greaterThan(0); - const nonNullDataPoints = throughputResponse.currentPeriod.filter(({ y }) => + const hasCurrentPeriodData = throughputResponse.currentPeriod.some(({ y }) => + isFiniteNumber(y) + ); + const hasPreviousPeriodData = throughputResponse.previousPeriod.some(({ 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"`); + expect(hasCurrentPeriodData).to.equal(true); + expect(hasPreviousPeriodData).to.equal(true); }); - it('has the correct number of buckets', () => { - expectSnapshot(throughputResponse.currentPeriod.length).toMatchInline(`31`); + it('has same start time for both periods', () => { + expect(first(throughputResponse.currentPeriod)?.x).to.equal( + first(throughputResponse.previousPeriod)?.x + ); }); - 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"`); - }); - }); - - describe('with kql filter to force transaction-based UI', () => { - before(async () => { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/throughput', - params: { - path: { - serviceName: 'opbeans-java', - }, - query: { - kuery: 'processor.event : "transaction"', - start: metadata.start, - end: metadata.end, - transactionType: 'request', - environment: 'ENVIRONMENT_ALL', - }, - }, - }); - throughputResponse = response.body; + it('has same end time for both periods', () => { + expect(last(throughputResponse.currentPeriod)?.x).to.equal( + last(throughputResponse.previousPeriod)?.x + ); }); - 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`); + it('returns same number of buckets for both periods', () => { + expect(throughputResponse.currentPeriod.length).to.be( + throughputResponse.previousPeriod.length + ); }); - }); - } - ); - registry.when( - 'Throughput when data is loaded with time comparison', - { config: 'basic', archives: [archiveName] }, - () => { - before(async () => { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/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(), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }, + it('has same mean value for both periods', () => { + const currentPeriodMean = meanBy( + throughputResponse.currentPeriod.filter((item) => isFiniteNumber(item.y) && item.y > 0), + 'y' + ); + const previousPeriodMean = meanBy( + throughputResponse.previousPeriod.filter( + (item) => isFiniteNumber(item.y) && item.y > 0 + ), + 'y' + ); + const currentPeriod = throughputResponse.currentPeriod; + const bucketSize = currentPeriod[1].x - currentPeriod[0].x; + const durationAsMinutes = bucketSize / 1000 / 60; + [currentPeriodMean, previousPeriodMean].every((value) => + expect(roundNumber(value)).to.be.equal( + roundNumber((GO_PROD_RATE + GO_DEV_RATE) / durationAsMinutes) + ) + ); }); - - throughputResponse = response.body; }); - - it('returns some data', () => { - expect(throughputResponse.currentPeriod.length).to.be.greaterThan(0); - expect(throughputResponse.previousPeriod.length).to.be.greaterThan(0); - - const currentPeriodNonNullDataPoints = throughputResponse.currentPeriod.filter(({ y }) => - isFiniteNumber(y) - ); - const previousPeriodNonNullDataPoints = throughputResponse.previousPeriod.filter(({ y }) => - isFiniteNumber(y) - ); - - expect(currentPeriodNonNullDataPoints.length).to.be.greaterThan(0); - expect(previousPeriodNonNullDataPoints.length).to.be.greaterThan(0); - }); - - it('has the correct start date', () => { - expectSnapshot( - new Date(first(throughputResponse.currentPeriod)?.x ?? NaN).toISOString() - ).toMatchInline(`"2021-08-03T07:05:00.000Z"`); - - expectSnapshot( - new Date(first(throughputResponse.previousPeriod)?.x ?? NaN).toISOString() - ).toMatchInline(`"2021-08-03T07:05:00.000Z"`); - }); - - it('has the correct end date', () => { - expectSnapshot( - new Date(last(throughputResponse.currentPeriod)?.x ?? NaN).toISOString() - ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); - - expectSnapshot( - new Date(last(throughputResponse.previousPeriod)?.x ?? NaN).toISOString() - ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); - }); - - it('has the correct number of buckets', () => { - expectSnapshot(throughputResponse.currentPeriod.length).toMatchInline(`16`); - expectSnapshot(throughputResponse.previousPeriod.length).toMatchInline(`16`); - }); - - it('has the correct throughput in tpm', () => { - expectSnapshot(throughputResponse).toMatch(); - expectSnapshot(throughputResponse.throughputUnit).toMatchInline(`"minute"`); - }); - } - ); + }); + }); } diff --git a/x-pack/test/apm_api_integration/tests/services/top_services.ts b/x-pack/test/apm_api_integration/tests/services/top_services.ts index 18700fb041252..d85331b8be45d 100644 --- a/x-pack/test/apm_api_integration/tests/services/top_services.ts +++ b/x-pack/test/apm_api_integration/tests/services/top_services.ts @@ -91,37 +91,37 @@ export default function ApiTest({ getService }: FtrProviderContext) { Array [ Object {}, Object { - "latency": 520294.126436782, - "throughput": 11.6, - "transactionErrorRate": 0.0316091954022989, + "latency": 496794.054441261, + "throughput": 11.6333333333333, + "transactionErrorRate": 0.0315186246418338, }, Object { - "latency": 74805.1452830189, - "throughput": 17.6666666666667, - "transactionErrorRate": 0.00566037735849057, + "latency": 83395.638576779, + "throughput": 17.8, + "transactionErrorRate": 0.00936329588014981, }, Object { - "latency": 411589.785714286, - "throughput": 7.46666666666667, - "transactionErrorRate": 0.0848214285714286, + "latency": 430318.696035242, + "throughput": 7.56666666666667, + "transactionErrorRate": 0.092511013215859, }, Object { - "latency": 53906.6603773585, - "throughput": 7.06666666666667, + "latency": 53147.5747663551, + "throughput": 7.13333333333333, "transactionErrorRate": 0, }, Object { - "latency": 420634.9, + "latency": 419826.24375, "throughput": 5.33333333333333, "transactionErrorRate": 0.025, }, Object { - "latency": 40989.5802047782, - "throughput": 9.76666666666667, - "transactionErrorRate": 0.00341296928327645, + "latency": 21520.4776632302, + "throughput": 9.7, + "transactionErrorRate": 0.00343642611683849, }, Object { - "latency": 1040880.77777778, + "latency": 1040388.88888889, "throughput": 2.4, "transactionErrorRate": null, }, diff --git a/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts new file mode 100644 index 0000000000000..4b3820ee7f033 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/throughput/dependencies_apis.ts @@ -0,0 +1,236 @@ +/* + * 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 { service, timerange } from '@elastic/apm-generator'; +import expect from '@kbn/expect'; +import { meanBy, sumBy } from 'lodash'; +import { BackendNode, ServiceNode } from '../../../../plugins/apm/common/connections'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; +import { roundNumber } from '../../utils'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const apmApiClient = getService('apmApiClient'); + const traceData = getService('traceData'); + + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + + async function getThroughputValues(overrides?: { serviceName?: string; backendName?: string }) { + const commonQuery = { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + environment: 'ENVIRONMENT_ALL', + }; + const [topBackendsAPIResponse, backendThroughputChartAPIResponse, upstreamServicesApiResponse] = + await Promise.all([ + apmApiClient.readUser({ + endpoint: `GET /internal/apm/backends/top_backends`, + params: { + query: { + ...commonQuery, + numBuckets: 20, + kuery: '', + }, + }, + }), + apmApiClient.readUser({ + endpoint: `GET /internal/apm/backends/{backendName}/charts/throughput`, + params: { + path: { backendName: overrides?.backendName || 'elasticsearch' }, + query: { + ...commonQuery, + kuery: '', + }, + }, + }), + apmApiClient.readUser({ + endpoint: `GET /internal/apm/backends/{backendName}/upstream_services`, + params: { + path: { backendName: overrides?.backendName || 'elasticsearch' }, + query: { + ...commonQuery, + numBuckets: 20, + offset: '1d', + kuery: '', + }, + }, + }), + ]); + const backendThroughputChartMean = roundNumber( + meanBy(backendThroughputChartAPIResponse.body.currentTimeseries, 'y') + ); + + const upstreamServicesThroughput = upstreamServicesApiResponse.body.services.map( + (upstreamService) => { + return { + serviceName: (upstreamService.location as ServiceNode).serviceName, + throughput: upstreamService.currentStats.throughput.value, + }; + } + ); + + return { + topBackends: topBackendsAPIResponse.body.backends.map((item) => [ + (item.location as BackendNode).backendName, + roundNumber(item.currentStats.throughput.value), + ]), + backendThroughputChartMean, + upstreamServicesThroughput, + }; + } + + let throughputValues: PromiseReturnType; + + registry.when( + 'Dependencies throughput value', + { config: 'basic', archives: ['apm_8.0.0_empty'] }, + () => { + describe('when data is loaded', () => { + const GO_PROD_RATE = 75; + const JAVA_PROD_RATE = 25; + before(async () => { + const serviceGoProdInstance = service('synth-go', 'production', 'go').instance( + 'instance-a' + ); + const serviceJavaInstance = service('synth-java', 'development', 'java').instance( + 'instance-c' + ); + + await traceData.index([ + ...timerange(start, end) + .interval('1m') + .rate(GO_PROD_RATE) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction('GET /api/product/list') + .duration(1000) + .timestamp(timestamp) + .children( + serviceGoProdInstance + .span('GET apm-*/_search', 'db', 'elasticsearch') + .duration(1000) + .success() + .destination('elasticsearch') + .timestamp(timestamp), + serviceGoProdInstance + .span('custom_operation', 'app') + .duration(550) + .children( + serviceGoProdInstance + .span('SELECT FROM products', 'db', 'postgresql') + .duration(500) + .success() + .destination('postgresql') + .timestamp(timestamp) + ) + .success() + .timestamp(timestamp) + ) + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(JAVA_PROD_RATE) + .flatMap((timestamp) => + serviceJavaInstance + .transaction('POST /api/product/buy') + .duration(1000) + .timestamp(timestamp) + .children( + serviceJavaInstance + .span('GET apm-*/_search', 'db', 'elasticsearch') + .duration(1000) + .success() + .destination('elasticsearch') + .timestamp(timestamp), + serviceJavaInstance + .span('custom_operation', 'app') + .duration(50) + .success() + .timestamp(timestamp) + ) + .serialize() + ), + ]); + }); + + after(() => traceData.clean()); + + describe('verify top dependencies', () => { + before(async () => { + throughputValues = await getThroughputValues(); + }); + + it('returns elasticsearch and postgresql as dependencies', () => { + const { topBackends } = throughputValues; + const topBackendsAsObj = Object.fromEntries(topBackends); + expect(topBackendsAsObj.elasticsearch).to.equal( + roundNumber(JAVA_PROD_RATE + GO_PROD_RATE) + ); + expect(topBackendsAsObj.postgresql).to.equal(roundNumber(GO_PROD_RATE)); + }); + }); + + describe('compare throughput value between top backends, backend throughput chart and upstream services apis', () => { + describe('elasticsearch dependency', () => { + before(async () => { + throughputValues = await getThroughputValues({ backendName: 'elasticsearch' }); + }); + + it('matches throughput values between throughput chart and top dependency', () => { + const { topBackends, backendThroughputChartMean } = throughputValues; + const topBackendsAsObj = Object.fromEntries(topBackends); + const elasticsearchDependency = topBackendsAsObj.elasticsearch; + [elasticsearchDependency, backendThroughputChartMean].forEach((value) => + expect(value).to.be.equal(roundNumber(JAVA_PROD_RATE + GO_PROD_RATE)) + ); + }); + + it('matches throughput values between upstream services and top dependency', () => { + const { topBackends, upstreamServicesThroughput } = throughputValues; + const topBackendsAsObj = Object.fromEntries(topBackends); + const elasticsearchDependency = topBackendsAsObj.elasticsearch; + const upstreamServiceThroughputSum = roundNumber( + sumBy(upstreamServicesThroughput, 'throughput') + ); + [elasticsearchDependency, upstreamServiceThroughputSum].forEach((value) => + expect(value).to.be.equal(roundNumber(JAVA_PROD_RATE + GO_PROD_RATE)) + ); + }); + }); + describe('postgresql dependency', () => { + before(async () => { + throughputValues = await getThroughputValues({ backendName: 'postgresql' }); + }); + + it('matches throughput values between throughput chart and top dependency', () => { + const { topBackends, backendThroughputChartMean } = throughputValues; + const topBackendsAsObj = Object.fromEntries(topBackends); + const postgresqlDependency = topBackendsAsObj.postgresql; + [postgresqlDependency, backendThroughputChartMean].forEach((value) => + expect(value).to.be.equal(roundNumber(GO_PROD_RATE)) + ); + }); + + it('matches throughput values between upstream services and top dependency', () => { + const { topBackends, upstreamServicesThroughput } = throughputValues; + const topBackendsAsObj = Object.fromEntries(topBackends); + const postgresqlDependency = topBackendsAsObj.postgresql; + const upstreamServiceThroughputSum = roundNumber( + sumBy(upstreamServicesThroughput, 'throughput') + ); + [postgresqlDependency, upstreamServiceThroughputSum].forEach((value) => + expect(value).to.be.equal(roundNumber(GO_PROD_RATE)) + ); + }); + }); + }); + }); + } + ); +} diff --git a/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts b/x-pack/test/apm_api_integration/tests/throughput/service_apis.ts new file mode 100644 index 0000000000000..6bf0e8c14fb23 --- /dev/null +++ b/x-pack/test/apm_api_integration/tests/throughput/service_apis.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 + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { service, timerange } from '@elastic/apm-generator'; +import expect from '@kbn/expect'; +import { meanBy, sumBy } from 'lodash'; +import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types'; +import { PromiseReturnType } from '../../../../plugins/observability/typings/common'; +import { FtrProviderContext } from '../../common/ftr_provider_context'; +import { registry } from '../../common/registry'; +import { roundNumber } from '../../utils'; + +export default function ApiTest({ getService }: FtrProviderContext) { + const apmApiClient = getService('apmApiClient'); + const traceData = getService('traceData'); + + const serviceName = 'synth-go'; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + + async function getThroughputValues(processorEvent: 'transaction' | 'metric') { + const commonQuery = { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + environment: 'ENVIRONMENT_ALL', + }; + const [ + serviceInventoryAPIResponse, + serviceThroughputAPIResponse, + transactionsGroupDetailsAPIResponse, + serviceInstancesAPIResponse, + ] = await Promise.all([ + apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services', + params: { + query: { + ...commonQuery, + kuery: `service.name : "${serviceName}" and processor.event : "${processorEvent}"`, + }, + }, + }), + apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/throughput', + params: { + path: { serviceName }, + query: { + ...commonQuery, + kuery: `processor.event : "${processorEvent}"`, + transactionType: 'request', + }, + }, + }), + apmApiClient.readUser({ + endpoint: `GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics`, + params: { + path: { serviceName }, + query: { + ...commonQuery, + kuery: `processor.event : "${processorEvent}"`, + transactionType: 'request', + latencyAggregationType: 'avg' as LatencyAggregationType, + }, + }, + }), + apmApiClient.readUser({ + endpoint: `GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics`, + params: { + path: { serviceName }, + query: { + ...commonQuery, + kuery: `processor.event : "${processorEvent}"`, + transactionType: 'request', + latencyAggregationType: 'avg' as LatencyAggregationType, + }, + }, + }), + ]); + + const serviceInventoryThroughput = serviceInventoryAPIResponse.body.items[0].throughput; + + const throughputChartApiMean = meanBy(serviceThroughputAPIResponse.body.currentPeriod, 'y'); + + const transactionsGroupThroughputSum = sumBy( + transactionsGroupDetailsAPIResponse.body.transactionGroups, + 'throughput' + ); + + const serviceInstancesThroughputSum = sumBy( + serviceInstancesAPIResponse.body.currentPeriod, + 'throughput' + ); + + return { + serviceInventoryThroughput, + throughputChartApiMean, + transactionsGroupThroughputSum, + serviceInstancesThroughputSum, + }; + } + + let throughputMetricValues: PromiseReturnType; + let throughputTransactionValues: PromiseReturnType; + + registry.when('Services APIs', { config: 'basic', archives: ['apm_8.0.0_empty'] }, () => { + describe('when data is loaded ', () => { + const GO_PROD_RATE = 80; + const GO_DEV_RATE = 20; + before(async () => { + const serviceGoProdInstance = service(serviceName, 'production', 'go').instance( + 'instance-a' + ); + const serviceGoDevInstance = service(serviceName, 'development', 'go').instance( + 'instance-b' + ); + await traceData.index([ + ...timerange(start, end) + .interval('1m') + .rate(GO_PROD_RATE) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction('GET /api/product/list') + .duration(1000) + .timestamp(timestamp) + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(GO_DEV_RATE) + .flatMap((timestamp) => + serviceGoDevInstance + .transaction('GET /api/product/:id') + .duration(1000) + .timestamp(timestamp) + .serialize() + ), + ]); + }); + + after(() => traceData.clean()); + + describe('compare throughput value between service inventory, throughput chart, service inventory and transactions apis', () => { + before(async () => { + [throughputTransactionValues, throughputMetricValues] = await Promise.all([ + getThroughputValues('transaction'), + getThroughputValues('metric'), + ]); + }); + + it('returns same throughput value for Transaction-based and Metric-based data', () => { + [ + ...Object.values(throughputTransactionValues), + ...Object.values(throughputMetricValues), + ].forEach((value) => + expect(roundNumber(value)).to.be.equal(roundNumber(GO_PROD_RATE + GO_DEV_RATE)) + ); + }); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap b/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap index 604348355f38c..64e1754c9570f 100644 --- a/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap +++ b/x-pack/test/apm_api_integration/tests/traces/__snapshots__/top_traces.snap @@ -3,7 +3,7 @@ exports[`APM API tests basic apm_8.0.0 Top traces when data is loaded returns the correct buckets 1`] = ` Array [ Object { - "averageResponseTime": 1639, + "averageResponseTime": 1638, "impact": 0, "key": Object { "service.name": "opbeans-java", @@ -15,8 +15,8 @@ Array [ "transactionsPerMinute": 0.0333333333333333, }, Object { - "averageResponseTime": 3279, - "impact": 0.00144735571024101, + "averageResponseTime": 3278, + "impact": 0.00153950779720334, "key": Object { "service.name": "opbeans-node", "transaction.name": "POST /api/orders", @@ -27,8 +27,8 @@ Array [ "transactionsPerMinute": 0.0333333333333333, }, Object { - "averageResponseTime": 6175, - "impact": 0.00400317408637392, + "averageResponseTime": 6169, + "impact": 0.00425335965190752, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/products/:id", @@ -39,8 +39,8 @@ Array [ "transactionsPerMinute": 0.0333333333333333, }, Object { - "averageResponseTime": 3495, - "impact": 0.00472243927164613, + "averageResponseTime": 3486, + "impact": 0.00500715523797721, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "POST Orders/Post", @@ -51,8 +51,8 @@ Array [ "transactionsPerMinute": 0.0666666666666667, }, Object { - "averageResponseTime": 7039, - "impact": 0.00476568343615943, + "averageResponseTime": 7022, + "impact": 0.00505409145130658, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.product", @@ -63,8 +63,8 @@ Array [ "transactionsPerMinute": 0.0333333333333333, }, Object { - "averageResponseTime": 6303, - "impact": 0.00967875004525193, + "averageResponseTime": 6279, + "impact": 0.0102508689911344, "key": Object { "service.name": "opbeans-ruby", "transaction.name": "Api::OrdersController#create", @@ -75,8 +75,8 @@ Array [ "transactionsPerMinute": 0.0666666666666667, }, Object { - "averageResponseTime": 7209.66666666667, - "impact": 0.0176418540534865, + "averageResponseTime": 7959, + "impact": 0.0134049825268681, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#products", @@ -84,35 +84,47 @@ Array [ "serviceName": "opbeans-java", "transactionName": "APIRestController#products", "transactionType": "request", + "transactionsPerMinute": 0.0666666666666667, + }, + Object { + "averageResponseTime": 7411.33333333333, + "impact": 0.0193339649946342, + "key": Object { + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.order", + }, + "serviceName": "opbeans-python", + "transactionName": "GET opbeans.views.order", + "transactionType": "request", "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 4511, - "impact": 0.0224401912465233, + "averageResponseTime": 11729, + "impact": 0.0204829634969371, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#orders", + "service.name": "opbeans-ruby", + "transaction.name": "Api::OrdersController#show", }, - "serviceName": "opbeans-java", - "transactionName": "APIRestController#orders", + "serviceName": "opbeans-ruby", + "transactionName": "Api::OrdersController#show", "transactionType": "request", - "transactionsPerMinute": 0.2, + "transactionsPerMinute": 0.0666666666666667, }, Object { - "averageResponseTime": 7607, - "impact": 0.0254072704525173, + "averageResponseTime": 4499.16666666667, + "impact": 0.0238032312278568, "key": Object { - "service.name": "opbeans-python", - "transaction.name": "GET opbeans.views.order", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#orders", }, - "serviceName": "opbeans-python", - "transactionName": "GET opbeans.views.order", + "serviceName": "opbeans-java", + "transactionName": "APIRestController#orders", "transactionType": "request", - "transactionsPerMinute": 0.133333333333333, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 10143, - "impact": 0.025408152986487, + "averageResponseTime": 10126.3333333333, + "impact": 0.0269798741459886, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/types", @@ -123,32 +135,32 @@ Array [ "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 6105.66666666667, - "impact": 0.0308842762682221, + "averageResponseTime": 6089.83333333333, + "impact": 0.032762415628167, "key": Object { - "service.name": "opbeans-ruby", - "transaction.name": "Api::TypesController#index", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#customerWhoBought", }, - "serviceName": "opbeans-ruby", - "transactionName": "Api::TypesController#index", + "serviceName": "opbeans-java", + "transactionName": "APIRestController#customerWhoBought", "transactionType": "request", "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 6116.33333333333, - "impact": 0.0309407584422802, + "averageResponseTime": 6094.83333333333, + "impact": 0.0327905773561646, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#customerWhoBought", + "service.name": "opbeans-ruby", + "transaction.name": "Api::TypesController#index", }, - "serviceName": "opbeans-java", - "transactionName": "APIRestController#customerWhoBought", + "serviceName": "opbeans-ruby", + "transactionName": "Api::TypesController#index", "transactionType": "request", "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 12543, - "impact": 0.0317623975680329, + "averageResponseTime": 12527.3333333333, + "impact": 0.0337415050382176, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#customers", @@ -159,8 +171,8 @@ Array [ "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 5551, - "impact": 0.0328461492827744, + "averageResponseTime": 5534.85714285714, + "impact": 0.0348323026359922, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/orders/:id", @@ -171,8 +183,8 @@ Array [ "transactionsPerMinute": 0.233333333333333, }, Object { - "averageResponseTime": 13183, - "impact": 0.0334568627897785, + "averageResponseTime": 13149.3333333333, + "impact": 0.0354931645196697, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#stats", @@ -183,8 +195,8 @@ Array [ "transactionsPerMinute": 0.1, }, Object { - "averageResponseTime": 8050.2, - "impact": 0.0340764016364792, + "averageResponseTime": 8025.8, + "impact": 0.0361324357452157, "key": Object { "service.name": "opbeans-go", "transaction.name": "POST /api/orders", @@ -195,20 +207,8 @@ Array [ "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 10079, - "impact": 0.0341337663445071, - "key": Object { - "service.name": "opbeans-ruby", - "transaction.name": "Api::OrdersController#show", - }, - "serviceName": "opbeans-ruby", - "transactionName": "Api::OrdersController#show", - "transactionType": "request", - "transactionsPerMinute": 0.133333333333333, - }, - Object { - "averageResponseTime": 8463, - "impact": 0.0358979517498557, + "averageResponseTime": 8432.8, + "impact": 0.0380427396277211, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/products/:id/customers", @@ -219,32 +219,32 @@ Array [ "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 10799, - "impact": 0.0366754641771254, + "averageResponseTime": 7408, + "impact": 0.0401867858526067, "key": Object { "service.name": "opbeans-ruby", - "transaction.name": "Api::ProductsController#show", + "transaction.name": "Api::TypesController#show", }, "serviceName": "opbeans-ruby", - "transactionName": "Api::ProductsController#show", + "transactionName": "Api::TypesController#show", "transactionType": "request", - "transactionsPerMinute": 0.133333333333333, + "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 7428.33333333333, - "impact": 0.0378880658514371, + "averageResponseTime": 6869.42857142857, + "impact": 0.0436018647344517, "key": Object { - "service.name": "opbeans-ruby", - "transaction.name": "Api::TypesController#show", + "service.name": "opbeans-java", + "transaction.name": "APIRestController#order", }, - "serviceName": "opbeans-ruby", - "transactionName": "Api::TypesController#show", + "serviceName": "opbeans-java", + "transactionName": "APIRestController#order", "transactionType": "request", - "transactionsPerMinute": 0.2, + "transactionsPerMinute": 0.233333333333333, }, Object { - "averageResponseTime": 3105.13333333333, - "impact": 0.039659311528543, + "averageResponseTime": 3050, + "impact": 0.0442721138607951, "key": Object { "service.name": "opbeans-java", "transaction.name": "ResourceHttpRequestHandler", @@ -252,23 +252,23 @@ Array [ "serviceName": "opbeans-java", "transactionName": "ResourceHttpRequestHandler", "transactionType": "request", - "transactionsPerMinute": 0.5, + "transactionsPerMinute": 0.533333333333333, }, Object { - "averageResponseTime": 6883.57142857143, - "impact": 0.0410784261517549, + "averageResponseTime": 10786.2, + "impact": 0.0490887080726551, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "APIRestController#order", + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#show", }, - "serviceName": "opbeans-java", - "transactionName": "APIRestController#order", + "serviceName": "opbeans-ruby", + "transactionName": "Api::ProductsController#show", "transactionType": "request", - "transactionsPerMinute": 0.233333333333333, + "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 3505, - "impact": 0.0480460318422139, + "averageResponseTime": 3497.6875, + "impact": 0.0509961957823607, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Products/Get", @@ -279,8 +279,8 @@ Array [ "transactionsPerMinute": 0.533333333333333, }, Object { - "averageResponseTime": 5621.4, - "impact": 0.0481642913941483, + "averageResponseTime": 5604.9, + "impact": 0.0510769260692872, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#topProducts", @@ -291,44 +291,44 @@ Array [ "transactionsPerMinute": 0.333333333333333, }, Object { - "averageResponseTime": 8428.71428571429, - "impact": 0.0506239135675883, + "averageResponseTime": 8500.57142857143, + "impact": 0.0543202184103467, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/orders", + "transaction.name": "GET /api/customers/:id", }, "serviceName": "opbeans-node", - "transactionName": "GET /api/orders", + "transactionName": "GET /api/customers/:id", "transactionType": "request", "transactionsPerMinute": 0.233333333333333, }, Object { - "averageResponseTime": 8520.14285714286, - "impact": 0.0511887353081702, + "averageResponseTime": 6658.88888888889, + "impact": 0.0547201149479129, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/customers/:id", + "transaction.name": "GET /api/products/top", }, "serviceName": "opbeans-node", - "transactionName": "GET /api/customers/:id", + "transactionName": "GET /api/products/top", "transactionType": "request", - "transactionsPerMinute": 0.233333333333333, + "transactionsPerMinute": 0.3, }, Object { - "averageResponseTime": 6683.44444444444, - "impact": 0.0516388276326964, + "averageResponseTime": 8141.125, + "impact": 0.0596005424099008, "key": Object { "service.name": "opbeans-node", - "transaction.name": "GET /api/products/top", + "transaction.name": "GET /api/orders", }, "serviceName": "opbeans-node", - "transactionName": "GET /api/products/top", + "transactionName": "GET /api/orders", "transactionType": "request", - "transactionsPerMinute": 0.3, + "transactionsPerMinute": 0.266666666666667, }, Object { - "averageResponseTime": 3482.78947368421, - "impact": 0.0569534471979838, + "averageResponseTime": 3473.52631578947, + "impact": 0.0604153550732987, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Types/Get", @@ -339,20 +339,20 @@ Array [ "transactionsPerMinute": 0.633333333333333, }, Object { - "averageResponseTime": 16703, - "impact": 0.057517386404596, + "averageResponseTime": 7875, + "impact": 0.064994452045712, "key": Object { - "service.name": "opbeans-python", - "transaction.name": "GET opbeans.views.product_type", + "service.name": "opbeans-node", + "transaction.name": "GET /api/types/:id", }, - "serviceName": "opbeans-python", - "transactionName": "GET opbeans.views.product_type", + "serviceName": "opbeans-node", + "transactionName": "GET /api/types/:id", "transactionType": "request", - "transactionsPerMinute": 0.133333333333333, + "transactionsPerMinute": 0.3, }, Object { - "averageResponseTime": 4943, - "impact": 0.0596266425920813, + "averageResponseTime": 4889, + "impact": 0.0673037137415171, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Products/Get {id}", @@ -360,23 +360,23 @@ Array [ "serviceName": "opbeans-dotnet", "transactionName": "GET Products/Get {id}", "transactionType": "request", - "transactionsPerMinute": 0.466666666666667, + "transactionsPerMinute": 0.5, }, Object { - "averageResponseTime": 7892.33333333333, - "impact": 0.0612407972225879, + "averageResponseTime": 14902.4, + "impact": 0.0684085922032904, "key": Object { - "service.name": "opbeans-node", - "transaction.name": "GET /api/types/:id", + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.product_type", }, - "serviceName": "opbeans-node", - "transactionName": "GET /api/types/:id", + "serviceName": "opbeans-python", + "transactionName": "GET opbeans.views.product_type", "transactionType": "request", - "transactionsPerMinute": 0.3, + "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 6346.42857142857, - "impact": 0.0769666700279444, + "averageResponseTime": 6329.35714285714, + "impact": 0.0816436656379062, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Orders/Get {id}", @@ -387,8 +387,8 @@ Array [ "transactionsPerMinute": 0.466666666666667, }, Object { - "averageResponseTime": 7052.84615384615, - "impact": 0.0794704188998674, + "averageResponseTime": 6627.42857142857, + "impact": 0.0855609620023755, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/products", @@ -396,11 +396,11 @@ Array [ "serviceName": "opbeans-go", "transactionName": "GET /api/products", "transactionType": "request", - "transactionsPerMinute": 0.433333333333333, + "transactionsPerMinute": 0.466666666666667, }, Object { - "averageResponseTime": 10484.3333333333, - "impact": 0.0818285496667966, + "averageResponseTime": 10459, + "impact": 0.0868254235894687, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#product", @@ -411,8 +411,8 @@ Array [ "transactionsPerMinute": 0.3, }, Object { - "averageResponseTime": 23711, - "impact": 0.0822565786420813, + "averageResponseTime": 23652.5, + "impact": 0.087275072513164, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/stats", @@ -423,8 +423,8 @@ Array [ "transactionsPerMinute": 0.133333333333333, }, Object { - "averageResponseTime": 4491.36363636364, - "impact": 0.0857567083657495, + "averageResponseTime": 4480.95454545455, + "impact": 0.0910027465757826, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Types/Get {id}", @@ -435,8 +435,8 @@ Array [ "transactionsPerMinute": 0.733333333333333, }, Object { - "averageResponseTime": 20715.8, - "impact": 0.089965512867054, + "averageResponseTime": 20677.4, + "impact": 0.0955142554010017, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.stats", @@ -447,8 +447,8 @@ Array [ "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 9036.33333333333, - "impact": 0.0942519803576885, + "averageResponseTime": 9015.33333333333, + "impact": 0.100017315707821, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/products", @@ -459,8 +459,20 @@ Array [ "transactionsPerMinute": 0.4, }, Object { - "averageResponseTime": 7504.06666666667, - "impact": 0.0978924329825326, + "averageResponseTime": 12096.8888888889, + "impact": 0.100663158003234, + "key": Object { + "service.name": "opbeans-go", + "transaction.name": "GET /api/customers", + }, + "serviceName": "opbeans-go", + "transactionName": "GET /api/customers", + "transactionType": "request", + "transactionsPerMinute": 0.3, + }, + Object { + "averageResponseTime": 7361.46666666667, + "impact": 0.102118180616444, "key": Object { "service.name": "opbeans-java", "transaction.name": "APIRestController#customer", @@ -471,8 +483,8 @@ Array [ "transactionsPerMinute": 0.5, }, Object { - "averageResponseTime": 4250.55555555556, - "impact": 0.0998375378516613, + "averageResponseTime": 4141.07142857143, + "impact": 0.107307448362139, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/types/:id", @@ -480,11 +492,11 @@ Array [ "serviceName": "opbeans-go", "transactionName": "GET /api/types/:id", "transactionType": "request", - "transactionsPerMinute": 0.9, + "transactionsPerMinute": 0.933333333333333, }, Object { - "averageResponseTime": 21343, - "impact": 0.11156906191034, + "averageResponseTime": 21277, + "impact": 0.118301786972411, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api/customers", @@ -495,8 +507,8 @@ Array [ "transactionsPerMinute": 0.2, }, Object { - "averageResponseTime": 16655, - "impact": 0.116142352941114, + "averageResponseTime": 16602.25, + "impact": 0.123141849290936, "key": Object { "service.name": "opbeans-ruby", "transaction.name": "Api::ProductsController#top", @@ -507,20 +519,8 @@ Array [ "transactionsPerMinute": 0.266666666666667, }, Object { - "averageResponseTime": 5749, - "impact": 0.12032203382142, - "key": Object { - "service.name": "opbeans-go", - "transaction.name": "GET /api/types", - }, - "serviceName": "opbeans-go", - "transactionName": "GET /api/types", - "transactionType": "request", - "transactionsPerMinute": 0.8, - }, - Object { - "averageResponseTime": 9951, - "impact": 0.121502864272824, + "averageResponseTime": 9924.07142857143, + "impact": 0.128885903078184, "key": Object { "service.name": "opbeans-ruby", "transaction.name": "Api::StatsController#index", @@ -531,20 +531,20 @@ Array [ "transactionsPerMinute": 0.466666666666667, }, Object { - "averageResponseTime": 14040.6, - "impact": 0.122466591367692, + "averageResponseTime": 5444.5, + "impact": 0.131345360656643, "key": Object { "service.name": "opbeans-go", - "transaction.name": "GET /api/customers", + "transaction.name": "GET /api/types", }, "serviceName": "opbeans-go", - "transactionName": "GET /api/customers", + "transactionName": "GET /api/types", "transactionType": "request", - "transactionsPerMinute": 0.333333333333333, + "transactionsPerMinute": 0.866666666666667, }, Object { - "averageResponseTime": 20963.5714285714, - "impact": 0.128060974201361, + "averageResponseTime": 20932.4285714286, + "impact": 0.136010820261582, "key": Object { "service.name": "opbeans-ruby", "transaction.name": "Api::OrdersController#index", @@ -555,8 +555,20 @@ Array [ "transactionsPerMinute": 0.233333333333333, }, Object { - "averageResponseTime": 22874.4285714286, - "impact": 0.139865748579522, + "averageResponseTime": 12301.3333333333, + "impact": 0.137033090987896, + "key": Object { + "service.name": "opbeans-ruby", + "transaction.name": "Api::ProductsController#index", + }, + "serviceName": "opbeans-ruby", + "transactionName": "Api::ProductsController#index", + "transactionType": "request", + "transactionsPerMinute": 0.4, + }, + Object { + "averageResponseTime": 22818.7142857143, + "impact": 0.148405735477602, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.customer", @@ -567,8 +579,8 @@ Array [ "transactionsPerMinute": 0.233333333333333, }, Object { - "averageResponseTime": 32203.8, - "impact": 0.140658264084276, + "averageResponseTime": 32098.4, + "impact": 0.149120104644475, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.customers", @@ -579,8 +591,8 @@ Array [ "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 4482.11111111111, - "impact": 0.140955678032051, + "averageResponseTime": 4585.91428571429, + "impact": 0.149134185508474, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/customers/:id", @@ -588,23 +600,23 @@ Array [ "serviceName": "opbeans-go", "transactionName": "GET /api/customers/:id", "transactionType": "request", - "transactionsPerMinute": 1.2, + "transactionsPerMinute": 1.16666666666667, }, Object { - "averageResponseTime": 12582.3846153846, - "impact": 0.142910490774846, + "averageResponseTime": 20449.3333333333, + "impact": 0.171228938571142, "key": Object { - "service.name": "opbeans-ruby", - "transaction.name": "Api::ProductsController#index", + "service.name": "opbeans-python", + "transaction.name": "GET opbeans.views.orders", }, - "serviceName": "opbeans-ruby", - "transactionName": "Api::ProductsController#index", + "serviceName": "opbeans-python", + "transactionName": "GET opbeans.views.orders", "transactionType": "request", - "transactionsPerMinute": 0.433333333333333, + "transactionsPerMinute": 0.3, }, Object { - "averageResponseTime": 10009.9473684211, - "impact": 0.166401779979233, + "averageResponseTime": 9981.1052631579, + "impact": 0.176482978291232, "key": Object { "service.name": "opbeans-ruby", "transaction.name": "Api::CustomersController#show", @@ -615,8 +627,8 @@ Array [ "transactionsPerMinute": 0.633333333333333, }, Object { - "averageResponseTime": 27825.2857142857, - "impact": 0.170450845832029, + "averageResponseTime": 27758.7142857143, + "impact": 0.180866820616195, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.product_types", @@ -627,20 +639,20 @@ Array [ "transactionsPerMinute": 0.233333333333333, }, Object { - "averageResponseTime": 20562.2, - "impact": 0.180021926732983, + "averageResponseTime": 8332.06896551724, + "impact": 0.225286314186844, "key": Object { - "service.name": "opbeans-python", - "transaction.name": "GET opbeans.views.orders", + "service.name": "opbeans-go", + "transaction.name": "GET /api/orders/:id", }, - "serviceName": "opbeans-python", - "transactionName": "GET opbeans.views.orders", + "serviceName": "opbeans-go", + "transactionName": "GET /api/orders/:id", "transactionType": "request", - "transactionsPerMinute": 0.333333333333333, + "transactionsPerMinute": 0.966666666666667, }, Object { - "averageResponseTime": 7106.76470588235, - "impact": 0.21180020991247, + "averageResponseTime": 6976.62857142857, + "impact": 0.227681938515175, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Customers/Get {id}", @@ -648,23 +660,11 @@ Array [ "serviceName": "opbeans-dotnet", "transactionName": "GET Customers/Get {id}", "transactionType": "request", - "transactionsPerMinute": 1.13333333333333, - }, - Object { - "averageResponseTime": 8612.51724137931, - "impact": 0.218977858687708, - "key": Object { - "service.name": "opbeans-go", - "transaction.name": "GET /api/orders/:id", - }, - "serviceName": "opbeans-go", - "transactionName": "GET /api/orders/:id", - "transactionType": "request", - "transactionsPerMinute": 0.966666666666667, + "transactionsPerMinute": 1.16666666666667, }, Object { - "averageResponseTime": 11295, - "impact": 0.277663720068132, + "averageResponseTime": 11321.7777777778, + "impact": 0.2854191132559, "key": Object { "service.name": "opbeans-ruby", "transaction.name": "Api::CustomersController#index", @@ -672,11 +672,11 @@ Array [ "serviceName": "opbeans-ruby", "transactionName": "Api::CustomersController#index", "transactionType": "request", - "transactionsPerMinute": 0.933333333333333, + "transactionsPerMinute": 0.9, }, Object { - "averageResponseTime": 65035.8, - "impact": 0.285535040543522, + "averageResponseTime": 64824.2, + "impact": 0.302722617661906, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.product_customers", @@ -687,8 +687,8 @@ Array [ "transactionsPerMinute": 0.166666666666667, }, Object { - "averageResponseTime": 30999.4705882353, - "impact": 0.463640986028375, + "averageResponseTime": 32155.5625, + "impact": 0.481425678843616, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/stats", @@ -696,11 +696,23 @@ Array [ "serviceName": "opbeans-go", "transactionName": "GET /api/stats", "transactionType": "request", - "transactionsPerMinute": 0.566666666666667, + "transactionsPerMinute": 0.533333333333333, }, Object { - "averageResponseTime": 20197.4, - "impact": 0.622424732781511, + "averageResponseTime": 32890.5714285714, + "impact": 0.646841098031782, + "key": Object { + "service.name": "opbeans-dotnet", + "transaction.name": "GET Customers/Get", + }, + "serviceName": "opbeans-dotnet", + "transactionName": "GET Customers/Get", + "transactionType": "request", + "transactionsPerMinute": 0.7, + }, + Object { + "averageResponseTime": 20133.0571428571, + "impact": 0.65994099517201, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/products/:id/customers", @@ -711,8 +723,8 @@ Array [ "transactionsPerMinute": 1.16666666666667, }, Object { - "averageResponseTime": 64681.6666666667, - "impact": 0.68355874339377, + "averageResponseTime": 64534, + "impact": 0.725417951490748, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.top_products", @@ -723,20 +735,8 @@ Array [ "transactionsPerMinute": 0.4, }, Object { - "averageResponseTime": 41416.1428571429, - "impact": 0.766127739061111, - "key": Object { - "service.name": "opbeans-dotnet", - "transaction.name": "GET Customers/Get", - }, - "serviceName": "opbeans-dotnet", - "transactionName": "GET Customers/Get", - "transactionType": "request", - "transactionsPerMinute": 0.7, - }, - Object { - "averageResponseTime": 19429, - "impact": 0.821597646656097, + "averageResponseTime": 19259.8775510204, + "impact": 0.884368376654926, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/products/:id", @@ -744,11 +744,11 @@ Array [ "serviceName": "opbeans-go", "transactionName": "GET /api/products/:id", "transactionType": "request", - "transactionsPerMinute": 1.6, + "transactionsPerMinute": 1.63333333333333, }, Object { - "averageResponseTime": 62390.652173913, - "impact": 1.26497653527507, + "averageResponseTime": 62237.5652173913, + "impact": 1.3422123631976, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Products/Customerwhobought {id}", @@ -759,8 +759,8 @@ Array [ "transactionsPerMinute": 0.766666666666667, }, Object { - "averageResponseTime": 33266.2, - "impact": 1.76006661931225, + "averageResponseTime": 33203.5666666667, + "impact": 1.86860199568649, "key": Object { "service.name": "opbeans-python", "transaction.name": "opbeans.tasks.sync_orders", @@ -771,8 +771,8 @@ Array [ "transactionsPerMinute": 2, }, Object { - "averageResponseTime": 38491.4444444444, - "impact": 1.83293391905112, + "averageResponseTime": 37042.1607142857, + "impact": 1.94571537801384, "key": Object { "service.name": "opbeans-node", "transaction.name": "GET /api", @@ -780,11 +780,11 @@ Array [ "serviceName": "opbeans-node", "transactionName": "GET /api", "transactionType": "request", - "transactionsPerMinute": 1.8, + "transactionsPerMinute": 1.86666666666667, }, Object { - "averageResponseTime": 118488.6, - "impact": 2.08995781717084, + "averageResponseTime": 116654.571428571, + "impact": 2.29809838682675, "key": Object { "service.name": "opbeans-dotnet", "transaction.name": "GET Stats/Get", @@ -792,47 +792,35 @@ Array [ "serviceName": "opbeans-dotnet", "transactionName": "GET Stats/Get", "transactionType": "request", - "transactionsPerMinute": 0.666666666666667, - }, - Object { - "averageResponseTime": 250440.142857143, - "impact": 4.64001412901584, - "key": Object { - "service.name": "opbeans-dotnet", - "transaction.name": "GET Products/Top", - }, - "serviceName": "opbeans-dotnet", - "transactionName": "GET Products/Top", - "transactionType": "request", "transactionsPerMinute": 0.7, }, Object { - "averageResponseTime": 312096.523809524, - "impact": 5.782704992387, + "averageResponseTime": 28741.0333333333, + "impact": 2.4266538589631, "key": Object { - "service.name": "opbeans-java", - "transaction.name": "DispatcherServlet#doGet", + "service.name": "opbeans-ruby", + "transaction.name": "Rack", }, - "serviceName": "opbeans-java", - "transactionName": "DispatcherServlet#doGet", + "serviceName": "opbeans-ruby", + "transactionName": "Rack", "transactionType": "request", - "transactionsPerMinute": 0.7, + "transactionsPerMinute": 3, }, Object { - "averageResponseTime": 91519.7032967033, - "impact": 7.34855500859826, + "averageResponseTime": 249714.952380952, + "impact": 4.9211455657754, "key": Object { - "service.name": "opbeans-ruby", - "transaction.name": "Rack", + "service.name": "opbeans-dotnet", + "transaction.name": "GET Products/Top", }, - "serviceName": "opbeans-ruby", - "transactionName": "Rack", + "serviceName": "opbeans-dotnet", + "transactionName": "GET Products/Top", "transactionType": "request", - "transactionsPerMinute": 3.03333333333333, + "transactionsPerMinute": 0.7, }, Object { - "averageResponseTime": 648269.769230769, - "impact": 7.43611473386403, + "averageResponseTime": 653461.538461538, + "impact": 7.97292501431132, "key": Object { "service.name": "opbeans-rum", "transaction.name": "/customers", @@ -843,8 +831,20 @@ Array [ "transactionsPerMinute": 0.433333333333333, }, Object { - "averageResponseTime": 1398919.72727273, - "impact": 13.5790895084132, + "averageResponseTime": 575328.095238095, + "impact": 11.340025698891, + "key": Object { + "service.name": "opbeans-java", + "transaction.name": "DispatcherServlet#doGet", + }, + "serviceName": "opbeans-java", + "transactionName": "DispatcherServlet#doGet", + "transactionType": "request", + "transactionsPerMinute": 0.7, + }, + Object { + "averageResponseTime": 1534606.6, + "impact": 14.4041869205032, "key": Object { "service.name": "opbeans-python", "transaction.name": "GET opbeans.views.products", @@ -852,11 +852,11 @@ Array [ "serviceName": "opbeans-python", "transactionName": "GET opbeans.views.products", "transactionType": "request", - "transactionsPerMinute": 0.366666666666667, + "transactionsPerMinute": 0.333333333333333, }, Object { - "averageResponseTime": 1199907.57142857, - "impact": 14.8239822181408, + "averageResponseTime": 1197500, + "impact": 15.7361746989891, "key": Object { "service.name": "opbeans-rum", "transaction.name": "/orders", @@ -867,8 +867,8 @@ Array [ "transactionsPerMinute": 0.466666666666667, }, Object { - "averageResponseTime": 955876.052631579, - "impact": 16.026822184214, + "averageResponseTime": 953684.210526316, + "impact": 17.0081460802151, "key": Object { "service.name": "opbeans-rum", "transaction.name": "/products", @@ -879,8 +879,8 @@ Array [ "transactionsPerMinute": 0.633333333333333, }, Object { - "averageResponseTime": 965009.526315789, - "impact": 16.1799735991728, + "averageResponseTime": 962252.473684211, + "impact": 17.1609675746427, "key": Object { "service.name": "opbeans-go", "transaction.name": "GET /api/orders", @@ -891,8 +891,8 @@ Array [ "transactionsPerMinute": 0.633333333333333, }, Object { - "averageResponseTime": 1213675.30769231, - "impact": 27.8474053933734, + "averageResponseTime": 1212615.38461538, + "impact": 29.594561046619, "key": Object { "service.name": "opbeans-rum", "transaction.name": "/dashboard", @@ -903,8 +903,8 @@ Array [ "transactionsPerMinute": 0.866666666666667, }, Object { - "averageResponseTime": 924019.363636364, - "impact": 35.8796065162284, + "averageResponseTime": 896783.309523809, + "impact": 35.3554170595149, "key": Object { "service.name": "opbeans-node", "transaction.name": "Update shipping status", @@ -912,23 +912,11 @@ Array [ "serviceName": "opbeans-node", "transactionName": "Update shipping status", "transactionType": "Worker", - "transactionsPerMinute": 1.46666666666667, - }, - Object { - "averageResponseTime": 1060469.15384615, - "impact": 36.498655556576, - "key": Object { - "service.name": "opbeans-node", - "transaction.name": "Process payment", - }, - "serviceName": "opbeans-node", - "transactionName": "Process payment", - "transactionType": "Worker", - "transactionsPerMinute": 1.3, + "transactionsPerMinute": 1.4, }, Object { - "averageResponseTime": 118686.822222222, - "impact": 37.7068083771466, + "averageResponseTime": 119062.672222222, + "impact": 40.2345894471584, "key": Object { "service.name": "opbeans-python", "transaction.name": "opbeans.tasks.update_stats", @@ -939,8 +927,20 @@ Array [ "transactionsPerMinute": 12, }, Object { - "averageResponseTime": 1039228.27659574, - "impact": 43.1048035741496, + "averageResponseTime": 1078328.675, + "impact": 40.488594152833, + "key": Object { + "service.name": "opbeans-node", + "transaction.name": "Process payment", + }, + "serviceName": "opbeans-node", + "transactionName": "Process payment", + "transactionType": "Worker", + "transactionsPerMinute": 1.33333333333333, + }, + Object { + "averageResponseTime": 1057995.65957447, + "impact": 46.6772737502262, "key": Object { "service.name": "opbeans-node", "transaction.name": "Process completed order", @@ -951,8 +951,8 @@ Array [ "transactionsPerMinute": 1.56666666666667, }, Object { - "averageResponseTime": 1949922.55555556, - "impact": 61.9499776921889, + "averageResponseTime": 1947354.08333333, + "impact": 65.8074895815218, "key": Object { "service.name": "opbeans-python", "transaction.name": "opbeans.tasks.sync_customers", @@ -963,7 +963,7 @@ Array [ "transactionsPerMinute": 1.2, }, Object { - "averageResponseTime": 5963775, + "averageResponseTime": 5918288.44444444, "impact": 100, "key": Object { "service.name": "opbeans-dotnet", @@ -972,7 +972,7 @@ Array [ "serviceName": "opbeans-dotnet", "transactionName": "GET Orders/Get", "transactionType": "request", - "transactionsPerMinute": 0.633333333333333, + "transactionsPerMinute": 0.6, }, ] `; diff --git a/x-pack/test/apm_api_integration/tests/traces/top_traces.ts b/x-pack/test/apm_api_integration/tests/traces/top_traces.ts index 4968732f82203..e67c2cb66df69 100644 --- a/x-pack/test/apm_api_integration/tests/traces/top_traces.ts +++ b/x-pack/test/apm_api_integration/tests/traces/top_traces.ts @@ -63,7 +63,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(firstItem).toMatchInline(` Object { - "averageResponseTime": 1639, + "averageResponseTime": 1638, "impact": 0, "key": Object { "service.name": "opbeans-java", @@ -78,7 +78,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(lastItem).toMatchInline(` Object { - "averageResponseTime": 5963775, + "averageResponseTime": 5918288.44444444, "impact": 100, "key": Object { "service.name": "opbeans-dotnet", @@ -87,7 +87,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { "serviceName": "opbeans-dotnet", "transactionName": "GET Orders/Get", "transactionType": "request", - "transactionsPerMinute": 0.633333333333333, + "transactionsPerMinute": 0.6, } `); diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap index c4dfaf346d015..878e5775c4ef5 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/error_rate.snap @@ -6,121 +6,241 @@ Array [ "x": 1627973400000, "y": 0, }, + Object { + "x": 1627973430000, + "y": 0, + }, Object { "x": 1627973460000, "y": 0, }, Object { - "x": 1627973520000, + "x": 1627973490000, "y": 0.333333333333333, }, + Object { + "x": 1627973520000, + "y": 0, + }, + Object { + "x": 1627973550000, + "y": 0.125, + }, Object { "x": 1627973580000, - "y": 0.181818181818182, + "y": 0.25, + }, + Object { + "x": 1627973610000, + "y": 0, }, Object { "x": 1627973640000, "y": 0, }, + Object { + "x": 1627973670000, + "y": 0, + }, Object { "x": 1627973700000, "y": 0, }, + Object { + "x": 1627973730000, + "y": 0.333333333333333, + }, Object { "x": 1627973760000, "y": 0.166666666666667, }, + Object { + "x": 1627973790000, + "y": 0, + }, Object { "x": 1627973820000, - "y": 0.181818181818182, + "y": 0.2, + }, + Object { + "x": 1627973850000, + "y": 0, }, Object { "x": 1627973880000, "y": 0, }, + Object { + "x": 1627973910000, + "y": 0, + }, Object { "x": 1627973940000, "y": 0, }, + Object { + "x": 1627973970000, + "y": 0.166666666666667, + }, Object { "x": 1627974000000, - "y": 0.0833333333333333, + "y": 0, + }, + Object { + "x": 1627974030000, + "y": 0, }, Object { "x": 1627974060000, - "y": 0.0769230769230769, + "y": 0.25, + }, + Object { + "x": 1627974090000, + "y": 0.5, }, Object { "x": 1627974120000, "y": 0, }, + Object { + "x": 1627974150000, + "y": 0, + }, Object { "x": 1627974180000, - "y": 0.1, + "y": 0, + }, + Object { + "x": 1627974210000, + "y": 0.2, }, Object { "x": 1627974240000, - "y": 0.153846153846154, + "y": 0.142857142857143, + }, + Object { + "x": 1627974270000, + "y": 0, }, Object { "x": 1627974300000, "y": 0, }, + Object { + "x": 1627974330000, + "y": null, + }, Object { "x": 1627974360000, "y": null, }, + Object { + "x": 1627974390000, + "y": 0, + }, Object { "x": 1627974420000, "y": 0, }, + Object { + "x": 1627974450000, + "y": 0, + }, Object { "x": 1627974480000, "y": 0, }, + Object { + "x": 1627974510000, + "y": 0, + }, Object { "x": 1627974540000, "y": 0, }, + Object { + "x": 1627974570000, + "y": 0, + }, Object { "x": 1627974600000, - "y": 0.125, + "y": 0.4, + }, + Object { + "x": 1627974630000, + "y": 1, }, Object { "x": 1627974660000, - "y": 0.6, + "y": 0.333333333333333, + }, + Object { + "x": 1627974690000, + "y": 0.5, }, Object { "x": 1627974720000, - "y": 0.2, + "y": 0, + }, + Object { + "x": 1627974750000, + "y": 0, }, Object { "x": 1627974780000, "y": 0, }, + Object { + "x": 1627974810000, + "y": 0, + }, Object { "x": 1627974840000, + "y": 0.333333333333333, + }, + Object { + "x": 1627974870000, "y": 0, }, Object { "x": 1627974900000, - "y": 0.0666666666666667, + "y": 0, + }, + Object { + "x": 1627974930000, + "y": 0, }, Object { "x": 1627974960000, "y": 0, }, + Object { + "x": 1627974990000, + "y": 0, + }, Object { "x": 1627975020000, "y": 0, }, + Object { + "x": 1627975050000, + "y": 0, + }, Object { "x": 1627975080000, "y": 0, }, + Object { + "x": 1627975110000, + "y": 0.4, + }, Object { "x": 1627975140000, - "y": 0.181818181818182, + "y": 0, + }, + Object { + "x": 1627975170000, + "y": 0.333333333333333, }, Object { "x": 1627975200000, @@ -132,136 +252,736 @@ Array [ exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate with comparison data has the correct error rate 1`] = ` Array [ Object { - "x": 1627974300000, - "y": 0, + "x": 1627974310000, + "y": null, + }, + Object { + "x": 1627974320000, + "y": null, + }, + Object { + "x": 1627974330000, + "y": null, + }, + Object { + "x": 1627974340000, + "y": null, + }, + Object { + "x": 1627974350000, + "y": null, }, Object { "x": 1627974360000, "y": null, }, + Object { + "x": 1627974370000, + "y": null, + }, + Object { + "x": 1627974380000, + "y": null, + }, + Object { + "x": 1627974390000, + "y": null, + }, + Object { + "x": 1627974400000, + "y": null, + }, + Object { + "x": 1627974410000, + "y": 0, + }, Object { "x": 1627974420000, "y": 0, }, Object { - "x": 1627974480000, + "x": 1627974430000, + "y": null, + }, + Object { + "x": 1627974440000, "y": 0, }, Object { - "x": 1627974540000, + "x": 1627974450000, "y": 0, }, Object { - "x": 1627974600000, - "y": 0.125, + "x": 1627974460000, + "y": 0, }, Object { - "x": 1627974660000, - "y": 0.6, + "x": 1627974470000, + "y": null, }, Object { - "x": 1627974720000, - "y": 0.2, + "x": 1627974480000, + "y": 0, }, Object { - "x": 1627974780000, + "x": 1627974490000, + "y": null, + }, + Object { + "x": 1627974500000, "y": 0, }, Object { - "x": 1627974840000, + "x": 1627974510000, + "y": null, + }, + Object { + "x": 1627974520000, "y": 0, }, Object { - "x": 1627974900000, - "y": 0.0666666666666667, + "x": 1627974530000, + "y": null, }, Object { - "x": 1627974960000, + "x": 1627974540000, "y": 0, }, Object { - "x": 1627975020000, + "x": 1627974550000, "y": 0, }, Object { - "x": 1627975080000, + "x": 1627974560000, + "y": null, + }, + Object { + "x": 1627974570000, "y": 0, }, Object { - "x": 1627975140000, - "y": 0.181818181818182, + "x": 1627974580000, + "y": null, }, Object { - "x": 1627975200000, + "x": 1627974590000, "y": null, }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate with comparison data has the correct error rate 2`] = ` -Array [ Object { - "x": 1627974300000, + "x": 1627974600000, + "y": null, + }, + Object { + "x": 1627974610000, "y": 0, }, Object { - "x": 1627974360000, + "x": 1627974620000, + "y": 1, + }, + Object { + "x": 1627974630000, + "y": null, + }, + Object { + "x": 1627974640000, + "y": null, + }, + Object { + "x": 1627974650000, + "y": 1, + }, + Object { + "x": 1627974660000, "y": 0, }, Object { - "x": 1627974420000, - "y": 0.333333333333333, + "x": 1627974670000, + "y": 0.5, }, Object { - "x": 1627974480000, - "y": 0.181818181818182, + "x": 1627974680000, + "y": null, }, Object { - "x": 1627974540000, + "x": 1627974690000, + "y": 1, + }, + Object { + "x": 1627974700000, + "y": null, + }, + Object { + "x": 1627974710000, "y": 0, }, Object { - "x": 1627974600000, + "x": 1627974720000, + "y": null, + }, + Object { + "x": 1627974730000, "y": 0, }, Object { - "x": 1627974660000, - "y": 0.166666666666667, + "x": 1627974740000, + "y": 0, }, Object { - "x": 1627974720000, - "y": 0.181818181818182, + "x": 1627974750000, + "y": 0, + }, + Object { + "x": 1627974760000, + "y": null, + }, + Object { + "x": 1627974770000, + "y": 0, }, Object { "x": 1627974780000, "y": 0, }, + Object { + "x": 1627974790000, + "y": 0, + }, + Object { + "x": 1627974800000, + "y": null, + }, + Object { + "x": 1627974810000, + "y": 0, + }, + Object { + "x": 1627974820000, + "y": null, + }, + Object { + "x": 1627974830000, + "y": null, + }, Object { "x": 1627974840000, + "y": null, + }, + Object { + "x": 1627974850000, + "y": 0.5, + }, + Object { + "x": 1627974860000, + "y": 0, + }, + Object { + "x": 1627974870000, + "y": 0, + }, + Object { + "x": 1627974880000, + "y": null, + }, + Object { + "x": 1627974890000, "y": 0, }, Object { "x": 1627974900000, - "y": 0.0833333333333333, + "y": 0, }, Object { - "x": 1627974960000, - "y": 0.0769230769230769, + "x": 1627974910000, + "y": 0, }, Object { - "x": 1627975020000, + "x": 1627974920000, + "y": null, + }, + Object { + "x": 1627974930000, "y": 0, }, Object { - "x": 1627975080000, - "y": 0.1, + "x": 1627974940000, + "y": null, }, Object { - "x": 1627975140000, - "y": 0.153846153846154, + "x": 1627974950000, + "y": null, }, Object { - "x": 1627975200000, + "x": 1627974960000, + "y": null, + }, + Object { + "x": 1627974970000, + "y": 0, + }, + Object { + "x": 1627974980000, + "y": null, + }, + Object { + "x": 1627974990000, + "y": 0, + }, + Object { + "x": 1627975000000, + "y": null, + }, + Object { + "x": 1627975010000, + "y": 0, + }, + Object { + "x": 1627975020000, + "y": 0, + }, + Object { + "x": 1627975030000, + "y": 0, + }, + Object { + "x": 1627975040000, + "y": null, + }, + Object { + "x": 1627975050000, + "y": 0, + }, + Object { + "x": 1627975060000, + "y": 0, + }, + Object { + "x": 1627975070000, + "y": 0, + }, + Object { + "x": 1627975080000, + "y": 0, + }, + Object { + "x": 1627975090000, + "y": 0, + }, + Object { + "x": 1627975100000, + "y": 0, + }, + Object { + "x": 1627975110000, + "y": 0.333333333333333, + }, + Object { + "x": 1627975120000, + "y": 0, + }, + Object { + "x": 1627975130000, + "y": 1, + }, + Object { + "x": 1627975140000, + "y": 0, + }, + Object { + "x": 1627975150000, + "y": 0, + }, + Object { + "x": 1627975160000, + "y": null, + }, + Object { + "x": 1627975170000, + "y": 0, + }, + Object { + "x": 1627975180000, + "y": 0.25, + }, + Object { + "x": 1627975190000, + "y": 1, + }, + Object { + "x": 1627975200000, + "y": null, + }, + Object { + "x": 1627975210000, + "y": null, + }, +] +`; + +exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate with comparison data has the correct error rate 2`] = ` +Array [ + Object { + "x": 1627974310000, + "y": null, + }, + Object { + "x": 1627974320000, + "y": 0, + }, + Object { + "x": 1627974330000, + "y": null, + }, + Object { + "x": 1627974340000, + "y": null, + }, + Object { + "x": 1627974350000, + "y": 0, + }, + Object { + "x": 1627974360000, + "y": 0, + }, + Object { + "x": 1627974370000, + "y": null, + }, + Object { + "x": 1627974380000, + "y": null, + }, + Object { + "x": 1627974390000, + "y": 0.5, + }, + Object { + "x": 1627974400000, + "y": null, + }, + Object { + "x": 1627974410000, + "y": 0, + }, + Object { + "x": 1627974420000, + "y": null, + }, + Object { + "x": 1627974430000, + "y": 0, + }, + Object { + "x": 1627974440000, + "y": null, + }, + Object { + "x": 1627974450000, + "y": 0.142857142857143, + }, + Object { + "x": 1627974460000, + "y": 0, + }, + Object { + "x": 1627974470000, + "y": null, + }, + Object { + "x": 1627974480000, + "y": 0.5, + }, + Object { + "x": 1627974490000, + "y": 0, + }, + Object { + "x": 1627974500000, + "y": null, + }, + Object { + "x": 1627974510000, + "y": null, + }, + Object { + "x": 1627974520000, + "y": null, + }, + Object { + "x": 1627974530000, + "y": 0, + }, + Object { + "x": 1627974540000, + "y": null, + }, + Object { + "x": 1627974550000, + "y": 0, + }, + Object { + "x": 1627974560000, + "y": null, + }, + Object { + "x": 1627974570000, + "y": 0, + }, + Object { + "x": 1627974580000, + "y": null, + }, + Object { + "x": 1627974590000, + "y": 0, + }, + Object { + "x": 1627974600000, + "y": 0, + }, + Object { + "x": 1627974610000, + "y": 0, + }, + Object { + "x": 1627974620000, + "y": null, + }, + Object { + "x": 1627974630000, + "y": null, + }, + Object { + "x": 1627974640000, + "y": 0, + }, + Object { + "x": 1627974650000, + "y": 0.5, + }, + Object { + "x": 1627974660000, + "y": 0, + }, + Object { + "x": 1627974670000, + "y": 0.5, + }, + Object { + "x": 1627974680000, + "y": 0, + }, + Object { + "x": 1627974690000, + "y": 0, + }, + Object { + "x": 1627974700000, + "y": 0, + }, + Object { + "x": 1627974710000, + "y": 0, + }, + Object { + "x": 1627974720000, + "y": 0.25, + }, + Object { + "x": 1627974730000, + "y": null, + }, + Object { + "x": 1627974740000, + "y": 0, + }, + Object { + "x": 1627974750000, + "y": 0, + }, + Object { + "x": 1627974760000, + "y": 0, + }, + Object { + "x": 1627974770000, + "y": 0, + }, + Object { + "x": 1627974780000, + "y": 0, + }, + Object { + "x": 1627974790000, + "y": 0, + }, + Object { + "x": 1627974800000, + "y": 0, + }, + Object { + "x": 1627974810000, + "y": 0, + }, + Object { + "x": 1627974820000, + "y": 0, + }, + Object { + "x": 1627974830000, + "y": null, + }, + Object { + "x": 1627974840000, + "y": 0, + }, + Object { + "x": 1627974850000, + "y": 0, + }, + Object { + "x": 1627974860000, + "y": null, + }, + Object { + "x": 1627974870000, + "y": 0.5, + }, + Object { + "x": 1627974880000, + "y": null, + }, + Object { + "x": 1627974890000, + "y": 0, + }, + Object { + "x": 1627974900000, + "y": 0, + }, + Object { + "x": 1627974910000, + "y": 0, + }, + Object { + "x": 1627974920000, + "y": 0, + }, + Object { + "x": 1627974930000, + "y": 0, + }, + Object { + "x": 1627974940000, + "y": 0, + }, + Object { + "x": 1627974950000, + "y": 0, + }, + Object { + "x": 1627974960000, + "y": 0.333333333333333, + }, + Object { + "x": 1627974970000, + "y": 0, + }, + Object { + "x": 1627974980000, + "y": null, + }, + Object { + "x": 1627974990000, + "y": 0, + }, + Object { + "x": 1627975000000, + "y": 1, + }, + Object { + "x": 1627975010000, + "y": null, + }, + Object { + "x": 1627975020000, + "y": 0, + }, + Object { + "x": 1627975030000, + "y": 0, + }, + Object { + "x": 1627975040000, + "y": 0, + }, + Object { + "x": 1627975050000, + "y": 0, + }, + Object { + "x": 1627975060000, + "y": 0, + }, + Object { + "x": 1627975070000, + "y": null, + }, + Object { + "x": 1627975080000, + "y": 0, + }, + Object { + "x": 1627975090000, + "y": 0, + }, + Object { + "x": 1627975100000, + "y": 0, + }, + Object { + "x": 1627975110000, + "y": 0, + }, + Object { + "x": 1627975120000, + "y": 0, + }, + Object { + "x": 1627975130000, + "y": 0.333333333333333, + }, + Object { + "x": 1627975140000, + "y": 0.333333333333333, + }, + Object { + "x": 1627975150000, + "y": 0, + }, + Object { + "x": 1627975160000, + "y": null, + }, + Object { + "x": 1627975170000, + "y": null, + }, + Object { + "x": 1627975180000, + "y": 0, + }, + Object { + "x": 1627975190000, + "y": 0, + }, + Object { + "x": 1627975200000, + "y": 0, + }, + Object { + "x": 1627975210000, "y": null, }, ] diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap index ff9e52b57aeaa..25b995acb87f1 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap +++ b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/latency.snap @@ -3,64 +3,196 @@ exports[`APM API tests basic apm_8.0.0 Latency with a basic license when data is loaded time comparison returns some data 1`] = ` Array [ Object { - "x": 1627974300000, - "y": 22799, + "x": 1627974350000, + "y": 32153, }, Object { - "x": 1627974360000, - "y": 3227391, + "x": 1627974390000, + "y": 15341.3333333333, + }, + Object { + "x": 1627974410000, + "y": 15170.5, }, Object { "x": 1627974420000, - "y": 15565.2222222222, + "y": 17329, + }, + Object { + "x": 1627974460000, + "y": 50039, }, Object { "x": 1627974480000, - "y": 54307.5714285714, + "y": 55816.6, + }, + Object { + "x": 1627974490000, + "y": 17533, + }, + Object { + "x": 1627974510000, + "y": 14888, }, Object { "x": 1627974540000, - "y": 16655, + "y": 12191.5, + }, + Object { + "x": 1627974550000, + "y": 20445.5, + }, + Object { + "x": 1627974590000, + "y": 9859, }, Object { "x": 1627974600000, - "y": 9453, + "y": 11796, + }, + Object { + "x": 1627974610000, + "y": 8774.4, + }, + Object { + "x": 1627974620000, + "y": 42225.6666666667, + }, + Object { + "x": 1627974630000, + "y": 16168, + }, + Object { + "x": 1627974640000, + "y": 7851.33333333333, }, Object { "x": 1627974660000, - "y": 31119, + "y": 45852, }, Object { - "x": 1627974720000, - "y": 15282.2, + "x": 1627974700000, + "y": 21823, + }, + Object { + "x": 1627974710000, + "y": 4156, + }, + Object { + "x": 1627974730000, + "y": 14191.5, + }, + Object { + "x": 1627974740000, + "y": 3997, + }, + Object { + "x": 1627974750000, + "y": 21823.75, + }, + Object { + "x": 1627974760000, + "y": 58178.5, + }, + Object { + "x": 1627974770000, + "y": 24291.5, }, Object { "x": 1627974780000, - "y": 18709, + "y": 7527.75, }, Object { "x": 1627974840000, - "y": 12095, + "y": 12028, }, Object { - "x": 1627974900000, - "y": 16291, + "x": 1627974860000, + "y": 6773.8, }, Object { - "x": 1627974960000, - "y": 13444.3333333333, + "x": 1627974870000, + "y": 37030, }, Object { - "x": 1627975020000, - "y": 13241.6666666667, + "x": 1627974890000, + "y": 29564, + }, + Object { + "x": 1627974910000, + "y": 15606, + }, + Object { + "x": 1627974930000, + "y": 11747, + }, + Object { + "x": 1627974940000, + "y": 9425, + }, + Object { + "x": 1627974950000, + "y": 20220, + }, + Object { + "x": 1627975000000, + "y": 12995.5, + }, + Object { + "x": 1627975030000, + "y": 13606, + }, + Object { + "x": 1627975050000, + "y": 22030, + }, + Object { + "x": 1627975060000, + "y": 10819, + }, + Object { + "x": 1627975070000, + "y": 26343, }, Object { "x": 1627975080000, - "y": 25535, + "y": 33080.5, }, Object { - "x": 1627975140000, - "y": 11024.6, + "x": 1627975090000, + "y": 11899, + }, + Object { + "x": 1627975100000, + "y": 5253, + }, + Object { + "x": 1627975110000, + "y": 16502, + }, + Object { + "x": 1627975120000, + "y": 6945.5, + }, + Object { + "x": 1627975130000, + "y": 7244, + }, + Object { + "x": 1627975150000, + "y": 22631.5, + }, + Object { + "x": 1627975180000, + "y": 23489, + }, + Object { + "x": 1627975190000, + "y": 10133.3333333333, + }, + Object { + "x": 1627975210000, + "y": 52108, }, ] `; @@ -68,64 +200,200 @@ Array [ exports[`APM API tests basic apm_8.0.0 Latency with a basic license when data is loaded time comparison returns some data 2`] = ` Array [ Object { - "x": 1627974300000, - "y": 34866.2, + "x": 1627974310000, + "y": 107053.5, }, Object { - "x": 1627974360000, - "y": 104799, + "x": 1627974370000, + "y": 9857, }, Object { - "x": 1627974420000, - "y": 36247, + "x": 1627974380000, + "y": 266341, + }, + Object { + "x": 1627974390000, + "y": 11715.75, + }, + Object { + "x": 1627974410000, + "y": 7805.25, + }, + Object { + "x": 1627974430000, + "y": 15880, + }, + Object { + "x": 1627974460000, + "y": 21836, + }, + Object { + "x": 1627974470000, + "y": 23962, }, Object { "x": 1627974480000, - "y": 22207, + "y": 21352.5, }, Object { - "x": 1627974540000, - "y": 80191, + "x": 1627974490000, + "y": 21639, }, Object { - "x": 1627974600000, - "y": 11520.4545454545, + "x": 1627974530000, + "y": 13970, + }, + Object { + "x": 1627974550000, + "y": 58140, + }, + Object { + "x": 1627974570000, + "y": 9853.75, + }, + Object { + "x": 1627974580000, + "y": 6490, + }, + Object { + "x": 1627974590000, + "y": 18894, + }, + Object { + "x": 1627974610000, + "y": 14125, + }, + Object { + "x": 1627974640000, + "y": 86268.25, }, Object { "x": 1627974660000, - "y": 47031.8888888889, + "y": 14218, + }, + Object { + "x": 1627974670000, + "y": 19127, + }, + Object { + "x": 1627974680000, + "y": 31538, }, Object { "x": 1627974720000, - "y": 30249.6666666667, + "y": 29535, }, Object { - "x": 1627974780000, - "y": 14868.3333333333, + "x": 1627974740000, + "y": 11229, + }, + Object { + "x": 1627974750000, + "y": 23940, + }, + Object { + "x": 1627974760000, + "y": 9262, + }, + Object { + "x": 1627974790000, + "y": 15650, }, Object { "x": 1627974840000, - "y": 17199, + "y": 17656.3333333333, + }, + Object { + "x": 1627974880000, + "y": 8371.5, + }, + Object { + "x": 1627974890000, + "y": 11386.5, }, Object { "x": 1627974900000, - "y": 19837.2222222222, + "y": 28923.75, + }, + Object { + "x": 1627974910000, + "y": 22670, + }, + Object { + "x": 1627974920000, + "y": 13607.6666666667, + }, + Object { + "x": 1627974930000, + "y": 19640, + }, + Object { + "x": 1627974940000, + "y": 20511, }, Object { "x": 1627974960000, - "y": 19397.6666666667, + "y": 34862, + }, + Object { + "x": 1627974990000, + "y": 27929.2, }, Object { "x": 1627975020000, - "y": 22473.6666666667, + "y": 25569, + }, + Object { + "x": 1627975030000, + "y": 6817.33333333333, + }, + Object { + "x": 1627975040000, + "y": 10467.6666666667, + }, + Object { + "x": 1627975060000, + "y": 6754.33333333333, + }, + Object { + "x": 1627975070000, + "y": 22049, }, Object { "x": 1627975080000, - "y": 11362.2, + "y": 15029, + }, + Object { + "x": 1627975090000, + "y": 14744, + }, + Object { + "x": 1627975110000, + "y": 32192.3333333333, + }, + Object { + "x": 1627975130000, + "y": 8321, + }, + Object { + "x": 1627975160000, + "y": 11648, + }, + Object { + "x": 1627975170000, + "y": 13157, + }, + Object { + "x": 1627975190000, + "y": 12855, + }, + Object { + "x": 1627975200000, + "y": 1322026.8, }, Object { - "x": 1627975140000, - "y": 26319, + "x": 1627975210000, + "y": 4650.33333333333, }, ] `; diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_groups_detailed_statistics.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_groups_detailed_statistics.snap deleted file mode 100644 index 0c9bbb378f74c..0000000000000 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_groups_detailed_statistics.snap +++ /dev/null @@ -1,931 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns data with previous period returns correct error rate data 1`] = ` -Array [ - Object { - "x": 1627974300000, - "y": 0, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": null, - }, - Object { - "x": 1627974480000, - "y": 0, - }, - Object { - "x": 1627974540000, - "y": 0, - }, - Object { - "x": 1627974600000, - "y": 0, - }, - Object { - "x": 1627974660000, - "y": 0, - }, - Object { - "x": 1627974720000, - "y": null, - }, - Object { - "x": 1627974780000, - "y": 0, - }, - Object { - "x": 1627974840000, - "y": null, - }, - Object { - "x": 1627974900000, - "y": 0, - }, - Object { - "x": 1627974960000, - "y": null, - }, - Object { - "x": 1627975020000, - "y": null, - }, - Object { - "x": 1627975080000, - "y": 0, - }, - Object { - "x": 1627975140000, - "y": null, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns data with previous period returns correct error rate data 2`] = ` -Array [ - Object { - "x": 1627974300000, - "y": 0, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": 1, - }, - Object { - "x": 1627974480000, - "y": 0, - }, - Object { - "x": 1627974540000, - "y": 0, - }, - Object { - "x": 1627974600000, - "y": null, - }, - Object { - "x": 1627974660000, - "y": null, - }, - Object { - "x": 1627974720000, - "y": 0.25, - }, - Object { - "x": 1627974780000, - "y": null, - }, - Object { - "x": 1627974840000, - "y": 0, - }, - Object { - "x": 1627974900000, - "y": 0, - }, - Object { - "x": 1627974960000, - "y": 0, - }, - Object { - "x": 1627975020000, - "y": 0, - }, - Object { - "x": 1627975080000, - "y": 0.5, - }, - Object { - "x": 1627975140000, - "y": 0.25, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns data with previous period returns correct latency data 1`] = ` -Array [ - Object { - "x": 1627974300000, - "y": 72303, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": null, - }, - Object { - "x": 1627974480000, - "y": 173055, - }, - Object { - "x": 1627974540000, - "y": 26687, - }, - Object { - "x": 1627974600000, - "y": 17867.8, - }, - Object { - "x": 1627974660000, - "y": 24319, - }, - Object { - "x": 1627974720000, - "y": null, - }, - Object { - "x": 1627974780000, - "y": 15743, - }, - Object { - "x": 1627974840000, - "y": null, - }, - Object { - "x": 1627974900000, - "y": 31679, - }, - Object { - "x": 1627974960000, - "y": null, - }, - Object { - "x": 1627975020000, - "y": null, - }, - Object { - "x": 1627975080000, - "y": 14391, - }, - Object { - "x": 1627975140000, - "y": null, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns data with previous period returns correct latency data 2`] = ` -Array [ - Object { - "x": 1627974300000, - "y": 34047, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": 5767167, - }, - Object { - "x": 1627974480000, - "y": 10335, - }, - Object { - "x": 1627974540000, - "y": 118015, - }, - Object { - "x": 1627974600000, - "y": null, - }, - Object { - "x": 1627974660000, - "y": null, - }, - Object { - "x": 1627974720000, - "y": 1371695, - }, - Object { - "x": 1627974780000, - "y": null, - }, - Object { - "x": 1627974840000, - "y": 3769087, - }, - Object { - "x": 1627974900000, - "y": 19015, - }, - Object { - "x": 1627974960000, - "y": 22356.3333333333, - }, - Object { - "x": 1627975020000, - "y": 28447, - }, - Object { - "x": 1627975080000, - "y": 33434367, - }, - Object { - "x": 1627975140000, - "y": 23407, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns data with previous period returns correct throughput data 1`] = ` -Array [ - Object { - "x": 1627974300000, - "y": 2, - }, - Object { - "x": 1627974360000, - "y": 0, - }, - Object { - "x": 1627974420000, - "y": 0, - }, - Object { - "x": 1627974480000, - "y": 1, - }, - Object { - "x": 1627974540000, - "y": 1, - }, - Object { - "x": 1627974600000, - "y": 2, - }, - Object { - "x": 1627974660000, - "y": 1, - }, - Object { - "x": 1627974720000, - "y": 0, - }, - Object { - "x": 1627974780000, - "y": 1, - }, - Object { - "x": 1627974840000, - "y": 0, - }, - Object { - "x": 1627974900000, - "y": 2, - }, - Object { - "x": 1627974960000, - "y": 0, - }, - Object { - "x": 1627975020000, - "y": 0, - }, - Object { - "x": 1627975080000, - "y": 4, - }, - Object { - "x": 1627975140000, - "y": 0, - }, - Object { - "x": 1627975200000, - "y": 0, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns data with previous period returns correct throughput data 2`] = ` -Array [ - Object { - "x": 1627974300000, - "y": 1, - }, - Object { - "x": 1627974360000, - "y": 0, - }, - Object { - "x": 1627974420000, - "y": 1, - }, - Object { - "x": 1627974480000, - "y": 2, - }, - Object { - "x": 1627974540000, - "y": 2, - }, - Object { - "x": 1627974600000, - "y": 0, - }, - Object { - "x": 1627974660000, - "y": 0, - }, - Object { - "x": 1627974720000, - "y": 3, - }, - Object { - "x": 1627974780000, - "y": 0, - }, - Object { - "x": 1627974840000, - "y": 2, - }, - Object { - "x": 1627974900000, - "y": 3, - }, - Object { - "x": 1627974960000, - "y": 2, - }, - Object { - "x": 1627975020000, - "y": 1, - }, - Object { - "x": 1627975080000, - "y": 2, - }, - Object { - "x": 1627975140000, - "y": 3, - }, - Object { - "x": 1627975200000, - "y": 0, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns the correct data 1`] = ` -Array [ - Object { - "x": 1627973400000, - "y": 34047, - }, - Object { - "x": 1627973460000, - "y": null, - }, - Object { - "x": 1627973520000, - "y": 5767167, - }, - Object { - "x": 1627973580000, - "y": 10335, - }, - Object { - "x": 1627973640000, - "y": 118015, - }, - Object { - "x": 1627973700000, - "y": null, - }, - Object { - "x": 1627973760000, - "y": null, - }, - Object { - "x": 1627973820000, - "y": 1371695, - }, - Object { - "x": 1627973880000, - "y": null, - }, - Object { - "x": 1627973940000, - "y": 3769087, - }, - Object { - "x": 1627974000000, - "y": 19015, - }, - Object { - "x": 1627974060000, - "y": 22356.3333333333, - }, - Object { - "x": 1627974120000, - "y": 28447, - }, - Object { - "x": 1627974180000, - "y": 33434367, - }, - Object { - "x": 1627974240000, - "y": 23407, - }, - Object { - "x": 1627974300000, - "y": 72303, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": null, - }, - Object { - "x": 1627974480000, - "y": 173055, - }, - Object { - "x": 1627974540000, - "y": 26687, - }, - Object { - "x": 1627974600000, - "y": 17867.8, - }, - Object { - "x": 1627974660000, - "y": 24319, - }, - Object { - "x": 1627974720000, - "y": null, - }, - Object { - "x": 1627974780000, - "y": 15743, - }, - Object { - "x": 1627974840000, - "y": null, - }, - Object { - "x": 1627974900000, - "y": 31679, - }, - Object { - "x": 1627974960000, - "y": null, - }, - Object { - "x": 1627975020000, - "y": null, - }, - Object { - "x": 1627975080000, - "y": 14391, - }, - Object { - "x": 1627975140000, - "y": null, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns the correct data 2`] = ` -Array [ - Object { - "x": 1627973400000, - "y": 1, - }, - Object { - "x": 1627973460000, - "y": 0, - }, - Object { - "x": 1627973520000, - "y": 1, - }, - Object { - "x": 1627973580000, - "y": 2, - }, - Object { - "x": 1627973640000, - "y": 2, - }, - Object { - "x": 1627973700000, - "y": 0, - }, - Object { - "x": 1627973760000, - "y": 0, - }, - Object { - "x": 1627973820000, - "y": 3, - }, - Object { - "x": 1627973880000, - "y": 0, - }, - Object { - "x": 1627973940000, - "y": 2, - }, - Object { - "x": 1627974000000, - "y": 3, - }, - Object { - "x": 1627974060000, - "y": 2, - }, - Object { - "x": 1627974120000, - "y": 1, - }, - Object { - "x": 1627974180000, - "y": 2, - }, - Object { - "x": 1627974240000, - "y": 3, - }, - Object { - "x": 1627974300000, - "y": 2, - }, - Object { - "x": 1627974360000, - "y": 0, - }, - Object { - "x": 1627974420000, - "y": 0, - }, - Object { - "x": 1627974480000, - "y": 1, - }, - Object { - "x": 1627974540000, - "y": 1, - }, - Object { - "x": 1627974600000, - "y": 2, - }, - Object { - "x": 1627974660000, - "y": 1, - }, - Object { - "x": 1627974720000, - "y": 0, - }, - Object { - "x": 1627974780000, - "y": 1, - }, - Object { - "x": 1627974840000, - "y": 0, - }, - Object { - "x": 1627974900000, - "y": 2, - }, - Object { - "x": 1627974960000, - "y": 0, - }, - Object { - "x": 1627975020000, - "y": 0, - }, - Object { - "x": 1627975080000, - "y": 4, - }, - Object { - "x": 1627975140000, - "y": 0, - }, - Object { - "x": 1627975200000, - "y": 0, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns the correct data 3`] = ` -Array [ - Object { - "x": 1627973400000, - "y": 0, - }, - Object { - "x": 1627973460000, - "y": null, - }, - Object { - "x": 1627973520000, - "y": 1, - }, - Object { - "x": 1627973580000, - "y": 0, - }, - Object { - "x": 1627973640000, - "y": 0, - }, - Object { - "x": 1627973700000, - "y": null, - }, - Object { - "x": 1627973760000, - "y": null, - }, - Object { - "x": 1627973820000, - "y": 0.25, - }, - Object { - "x": 1627973880000, - "y": null, - }, - Object { - "x": 1627973940000, - "y": 0, - }, - Object { - "x": 1627974000000, - "y": 0, - }, - Object { - "x": 1627974060000, - "y": 0, - }, - Object { - "x": 1627974120000, - "y": 0, - }, - Object { - "x": 1627974180000, - "y": 0.5, - }, - Object { - "x": 1627974240000, - "y": 0.25, - }, - Object { - "x": 1627974300000, - "y": 0, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": null, - }, - Object { - "x": 1627974480000, - "y": 0, - }, - Object { - "x": 1627974540000, - "y": 0, - }, - Object { - "x": 1627974600000, - "y": 0, - }, - Object { - "x": 1627974660000, - "y": 0, - }, - Object { - "x": 1627974720000, - "y": null, - }, - Object { - "x": 1627974780000, - "y": 0, - }, - Object { - "x": 1627974840000, - "y": null, - }, - Object { - "x": 1627974900000, - "y": 0, - }, - Object { - "x": 1627974960000, - "y": null, - }, - Object { - "x": 1627975020000, - "y": null, - }, - Object { - "x": 1627975080000, - "y": 0, - }, - Object { - "x": 1627975140000, - "y": null, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; - -exports[`APM API tests basic apm_8.0.0 Transaction groups detailed statistics when data is loaded returns the correct data for latency aggregation 99th percentile 1`] = ` -Array [ - Object { - "x": 1627973400000, - "y": 34047, - }, - Object { - "x": 1627973460000, - "y": null, - }, - Object { - "x": 1627973520000, - "y": 5767167, - }, - Object { - "x": 1627973580000, - "y": 16127, - }, - Object { - "x": 1627973640000, - "y": 214015, - }, - Object { - "x": 1627973700000, - "y": null, - }, - Object { - "x": 1627973760000, - "y": null, - }, - Object { - "x": 1627973820000, - "y": 5439487, - }, - Object { - "x": 1627973880000, - "y": null, - }, - Object { - "x": 1627973940000, - "y": 5668863, - }, - Object { - "x": 1627974000000, - "y": 32255, - }, - Object { - "x": 1627974060000, - "y": 28159, - }, - Object { - "x": 1627974120000, - "y": 44287, - }, - Object { - "x": 1627974180000, - "y": 66846719, - }, - Object { - "x": 1627974240000, - "y": 42751, - }, - Object { - "x": 1627974300000, - "y": 140287, - }, - Object { - "x": 1627974360000, - "y": null, - }, - Object { - "x": 1627974420000, - "y": null, - }, - Object { - "x": 1627974480000, - "y": 173055, - }, - Object { - "x": 1627974540000, - "y": 28927, - }, - Object { - "x": 1627974600000, - "y": 39679, - }, - Object { - "x": 1627974660000, - "y": 24319, - }, - Object { - "x": 1627974720000, - "y": null, - }, - Object { - "x": 1627974780000, - "y": 15743, - }, - Object { - "x": 1627974840000, - "y": null, - }, - Object { - "x": 1627974900000, - "y": 33791, - }, - Object { - "x": 1627974960000, - "y": null, - }, - Object { - "x": 1627975020000, - "y": null, - }, - Object { - "x": 1627975080000, - "y": 23167, - }, - Object { - "x": 1627975140000, - "y": null, - }, - Object { - "x": 1627975200000, - "y": null, - }, -] -`; diff --git a/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts b/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts index 2ddaa4677394c..89f818f58e875 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/error_rate.ts @@ -117,13 +117,13 @@ export default function ApiTest({ getService }: FtrProviderContext) { it('has the correct number of buckets', () => { expectSnapshot(errorRateResponse.currentPeriod.transactionErrorRate.length).toMatchInline( - `31` + `61` ); }); it('has the correct calculation for average', () => { expectSnapshot(errorRateResponse.currentPeriod.average).toMatchInline( - `0.0848214285714286` + `0.092511013215859` ); }); @@ -175,12 +175,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { new Date( first(errorRateResponse.currentPeriod.transactionErrorRate)?.x ?? NaN ).toISOString() - ).toMatchInline(`"2021-08-03T07:05:00.000Z"`); + ).toMatchInline(`"2021-08-03T07:05:10.000Z"`); expectSnapshot( new Date( first(errorRateResponse.previousPeriod.transactionErrorRate)?.x ?? NaN ).toISOString() - ).toMatchInline(`"2021-08-03T07:05:00.000Z"`); + ).toMatchInline(`"2021-08-03T07:05:10.000Z"`); }); it('has the correct end date', () => { @@ -188,29 +188,29 @@ export default function ApiTest({ getService }: FtrProviderContext) { new Date( last(errorRateResponse.currentPeriod.transactionErrorRate)?.x ?? NaN ).toISOString() - ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); + ).toMatchInline(`"2021-08-03T07:20:10.000Z"`); expectSnapshot( new Date( last(errorRateResponse.previousPeriod.transactionErrorRate)?.x ?? NaN ).toISOString() - ).toMatchInline(`"2021-08-03T07:20:00.000Z"`); + ).toMatchInline(`"2021-08-03T07:20:10.000Z"`); }); it('has the correct number of buckets', () => { expectSnapshot(errorRateResponse.currentPeriod.transactionErrorRate.length).toMatchInline( - `16` + `91` ); expectSnapshot( errorRateResponse.previousPeriod.transactionErrorRate.length - ).toMatchInline(`16`); + ).toMatchInline(`91`); }); it('has the correct calculation for average', () => { expectSnapshot(errorRateResponse.currentPeriod.average).toMatchInline( - `0.0792079207920792` + `0.102040816326531` ); expectSnapshot(errorRateResponse.previousPeriod.average).toMatchInline( - `0.0894308943089431` + `0.0852713178294574` ); }); diff --git a/x-pack/test/apm_api_integration/tests/transactions/latency.ts b/x-pack/test/apm_api_integration/tests/transactions/latency.ts index beaff7647868a..d021e59ecff6c 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/latency.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/latency.ts @@ -113,7 +113,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); const latencyChartReturn = response.body as LatencyChartReturnType; expect(latencyChartReturn.currentPeriod.overallAvgDuration).not.to.be(null); - expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(31); + expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(61); }); }); @@ -138,7 +138,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.status).to.be(200); const latencyChartReturn = response.body as LatencyChartReturnType; expect(latencyChartReturn.currentPeriod.overallAvgDuration).not.to.be(null); - expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(31); + expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(61); }); }); @@ -165,10 +165,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(latencyChartReturn.currentPeriod.overallAvgDuration).not.to.be(null); expectSnapshot(latencyChartReturn.currentPeriod.overallAvgDuration).toMatchInline( - `53906.6603773585` + `53147.5747663551` ); - expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(31); + expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(61); }); }); diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts index add954f490db1..100d3c306b7de 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.ts @@ -4,293 +4,247 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - +import { service, timerange } from '@elastic/apm-generator'; import expect from '@kbn/expect'; -import url from 'url'; +import { first, isEmpty, last, meanBy } from 'lodash'; import moment from 'moment'; -import { pick } from 'lodash'; +import { LatencyAggregationType } from '../../../../plugins/apm/common/latency_aggregation_types'; +import { asPercent } from '../../../../plugins/apm/common/utils/formatters'; import { APIReturnType } from '../../../../plugins/apm/public/services/rest/createCallApmApi'; -import archives from '../../common/fixtures/es_archiver/archives_metadata'; import { FtrProviderContext } from '../../common/ftr_provider_context'; import { registry } from '../../common/registry'; -import { removeEmptyCoordinates, roundNumber } from '../../utils'; +import { roundNumber } from '../../utils'; type TransactionsGroupsDetailedStatistics = APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics'>; export default function ApiTest({ getService }: FtrProviderContext) { - const supertest = getService('legacySupertestAsApmReadUser'); - - const archiveName = 'apm_8.0.0'; - const { start, end } = archives[archiveName]; - const transactionNames = ['DispatcherServlet#doGet', 'APIRestController#customers']; + const apmApiClient = getService('apmApiClient'); + const traceData = getService('traceData'); + + const serviceName = 'synth-go'; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:59.999Z').getTime(); + const transactionNames = ['GET /api/product/list']; + + async function callApi(overrides?: { + path?: { + serviceName?: string; + }; + query?: { + start?: string; + end?: string; + transactionType?: string; + environment?: string; + kuery?: string; + comparisonStart?: string; + comparisonEnd?: string; + transactionNames?: string; + latencyAggregationType?: LatencyAggregationType; + numBuckets?: number; + }; + }) { + const response = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics', + params: { + path: { serviceName, ...overrides?.path }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + numBuckets: 20, + transactionType: 'request', + latencyAggregationType: 'avg' as LatencyAggregationType, + transactionNames: JSON.stringify(transactionNames), + environment: 'ENVIRONMENT_ALL', + kuery: '', + ...overrides?.query, + }, + }, + }); + expect(response.status).to.be(200); + return response.body; + } registry.when( 'Transaction groups detailed statistics when data is not loaded', { config: 'basic', archives: [] }, () => { it('handles the empty state', async () => { - const response = await supertest.get( - url.format({ - pathname: `/internal/apm/services/opbeans-java/transactions/groups/detailed_statistics`, - query: { - start, - end, - numBuckets: 20, - latencyAggregationType: 'avg', - transactionType: 'request', - transactionNames: JSON.stringify(transactionNames), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }) - ); - - expect(response.status).to.be(200); - expect(response.body).to.be.eql({ currentPeriod: {}, previousPeriod: {} }); + const response = await callApi(); + expect(response).to.be.eql({ currentPeriod: {}, previousPeriod: {} }); }); } ); - registry.when( - 'Transaction groups detailed statistics when data is loaded', - { config: 'basic', archives: [archiveName] }, - () => { - it('returns the correct data', async () => { - const response = await supertest.get( - url.format({ - pathname: `/internal/apm/services/opbeans-java/transactions/groups/detailed_statistics`, - query: { - start, - end, - numBuckets: 20, - transactionType: 'request', - latencyAggregationType: 'avg', - transactionNames: JSON.stringify(transactionNames), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }) + registry.when('data is loaded', { config: 'basic', archives: ['apm_8.0.0_empty'] }, () => { + describe('transactions groups detailed stats', () => { + const GO_PROD_RATE = 75; + const GO_PROD_ERROR_RATE = 25; + before(async () => { + const serviceGoProdInstance = service(serviceName, 'production', 'go').instance( + 'instance-a' ); - expect(response.status).to.be(200); - - const { currentPeriod, previousPeriod } = - response.body as TransactionsGroupsDetailedStatistics; - - expect(Object.keys(currentPeriod).sort()).to.be.eql(transactionNames.sort()); - - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); - - expect(previousPeriodItems.length).to.be.eql(0); - - transactionNames.forEach((transactionName) => { - expect(currentPeriod[transactionName]).not.to.be.empty(); - }); - - const firstItem = currentPeriodItems[0]; - const { latency, throughput, errorRate, impact } = pick( - firstItem, - 'latency', - 'throughput', - 'errorRate', - 'impact' - ); - - expect(removeEmptyCoordinates(latency).length).to.be.greaterThan(0); - expectSnapshot(latency).toMatch(); - - expect(removeEmptyCoordinates(throughput).length).to.be.greaterThan(0); - expectSnapshot(throughput).toMatch(); - - expect(removeEmptyCoordinates(errorRate).length).to.be.greaterThan(0); - expectSnapshot(errorRate).toMatch(); - - expectSnapshot(roundNumber(impact)).toMatchInline(`"98.49"`); + const transactionName = 'GET /api/product/list'; + + await traceData.index([ + ...timerange(start, end) + .interval('1m') + .rate(GO_PROD_RATE) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction(transactionName) + .timestamp(timestamp) + .duration(1000) + .success() + .serialize() + ), + ...timerange(start, end) + .interval('1m') + .rate(GO_PROD_ERROR_RATE) + .flatMap((timestamp) => + serviceGoProdInstance + .transaction(transactionName) + .duration(1000) + .timestamp(timestamp) + .failure() + .serialize() + ), + ]); }); - it('returns the correct data for latency aggregation 99th percentile', async () => { - const response = await supertest.get( - url.format({ - pathname: `/internal/apm/services/opbeans-java/transactions/groups/detailed_statistics`, - query: { - start, - end, - numBuckets: 20, - transactionType: 'request', - latencyAggregationType: 'p99', - transactionNames: JSON.stringify(transactionNames), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }) - ); - - expect(response.status).to.be(200); - - const { currentPeriod, previousPeriod } = - response.body as TransactionsGroupsDetailedStatistics; + after(() => traceData.clean()); - expect(Object.keys(currentPeriod).sort()).to.be.eql(transactionNames.sort()); - - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); - - expect(previousPeriodItems).to.be.empty(); - - transactionNames.forEach((transactionName) => { - expect(currentPeriod[transactionName]).not.to.be.empty(); + describe('without comparisons', () => { + let transactionsStatistics: TransactionsGroupsDetailedStatistics; + let metricsStatistics: TransactionsGroupsDetailedStatistics; + before(async () => { + [metricsStatistics, transactionsStatistics] = await Promise.all([ + callApi({ query: { kuery: 'processor.event : "metric"' } }), + callApi({ query: { kuery: 'processor.event : "transaction"' } }), + ]); }); - const firstItem = currentPeriodItems[0]; - const { latency, throughput, errorRate } = pick( - firstItem, - 'latency', - 'throughput', - 'errorRate' - ); - - expect(removeEmptyCoordinates(latency).length).to.be.greaterThan(0); - expectSnapshot(latency).toMatch(); - - expect(removeEmptyCoordinates(throughput).length).to.be.greaterThan(0); - expect(removeEmptyCoordinates(errorRate).length).to.be.greaterThan(0); - }); - - it('returns empty when transaction name is not found', async () => { - const response = await supertest.get( - url.format({ - pathname: `/internal/apm/services/opbeans-java/transactions/groups/detailed_statistics`, - query: { - start, - end, - numBuckets: 20, - transactionType: 'request', - latencyAggregationType: 'avg', - transactionNames: JSON.stringify(['foo']), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }) - ); + it('returns some transactions data', () => { + expect(isEmpty(transactionsStatistics.currentPeriod)).to.be.equal(false); + }); - expect(response.status).to.be(200); - expect(response.body).to.be.eql({ currentPeriod: {}, previousPeriod: {} }); - }); + it('returns some metrics data', () => { + expect(isEmpty(metricsStatistics.currentPeriod)).to.be.equal(false); + }); - describe('returns data with previous period', async () => { - let currentPeriod: TransactionsGroupsDetailedStatistics['currentPeriod']; - let previousPeriod: TransactionsGroupsDetailedStatistics['previousPeriod']; - before(async () => { - const response = await supertest.get( - url.format({ - pathname: `/internal/apm/services/opbeans-java/transactions/groups/detailed_statistics`, - query: { - numBuckets: 20, - transactionType: 'request', - latencyAggregationType: 'avg', - transactionNames: JSON.stringify(transactionNames), - start: moment(end).subtract(15, 'minutes').toISOString(), - end, - comparisonStart: start, - comparisonEnd: moment(start).add(15, 'minutes').toISOString(), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }) + it('has same latency mean value for metrics and transactions data', () => { + const transactionsCurrentPeriod = + transactionsStatistics.currentPeriod[transactionNames[0]]; + const metricsCurrentPeriod = metricsStatistics.currentPeriod[transactionNames[0]]; + const transactionsLatencyMean = meanBy(transactionsCurrentPeriod.latency, 'y'); + const metricsLatencyMean = meanBy(metricsCurrentPeriod.latency, 'y'); + [transactionsLatencyMean, metricsLatencyMean].forEach((value) => + expect(value).to.be.equal(1000000) ); - - expect(response.status).to.be(200); - currentPeriod = response.body.currentPeriod; - previousPeriod = response.body.previousPeriod; }); - it('returns correct number of items', () => { - expect(Object.keys(currentPeriod).sort()).to.be.eql(transactionNames.sort()); - expect(Object.keys(previousPeriod).sort()).to.be.eql(transactionNames.sort()); + it('has same error rate mean value for metrics and transactions data', () => { + const transactionsCurrentPeriod = + transactionsStatistics.currentPeriod[transactionNames[0]]; + const metricsCurrentPeriod = metricsStatistics.currentPeriod[transactionNames[0]]; - transactionNames.forEach((transactionName) => { - expect(currentPeriod[transactionName]).not.to.be.empty(); - expect(previousPeriod[transactionName]).not.to.be.empty(); - }); + const transactionsErrorRateMean = meanBy(transactionsCurrentPeriod.errorRate, 'y'); + const metricsErrorRateMean = meanBy(metricsCurrentPeriod.errorRate, 'y'); + [transactionsErrorRateMean, metricsErrorRateMean].forEach((value) => + expect(asPercent(value, 1)).to.be.equal(`${GO_PROD_ERROR_RATE}%`) + ); }); - it('returns correct latency data', () => { - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); - - const currentPeriodFirstItem = currentPeriodItems[0]; - const previousPeriodFirstItem = previousPeriodItems[0]; - - expect(removeEmptyCoordinates(currentPeriodFirstItem.latency).length).to.be.greaterThan( - 0 + it('has same throughput mean value for metrics and transactions data', () => { + const transactionsCurrentPeriod = + transactionsStatistics.currentPeriod[transactionNames[0]]; + const metricsCurrentPeriod = metricsStatistics.currentPeriod[transactionNames[0]]; + const transactionsThroughputMean = roundNumber( + meanBy(transactionsCurrentPeriod.throughput, 'y') ); - expect(removeEmptyCoordinates(previousPeriodFirstItem.latency).length).to.be.greaterThan( - 0 + const metricsThroughputMean = roundNumber(meanBy(metricsCurrentPeriod.throughput, 'y')); + [transactionsThroughputMean, metricsThroughputMean].forEach((value) => + expect(value).to.be.equal(roundNumber(GO_PROD_RATE + GO_PROD_ERROR_RATE)) ); - expectSnapshot(currentPeriodFirstItem.latency).toMatch(); - expectSnapshot(previousPeriodFirstItem.latency).toMatch(); }); - it('returns correct throughput data', () => { - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); + it('has same impact value for metrics and transactions data', () => { + const transactionsCurrentPeriod = + transactionsStatistics.currentPeriod[transactionNames[0]]; + const metricsCurrentPeriod = metricsStatistics.currentPeriod[transactionNames[0]]; - const currentPeriodFirstItem = currentPeriodItems[0]; - const previousPeriodFirstItem = previousPeriodItems[0]; - - expect( - removeEmptyCoordinates(currentPeriodFirstItem.throughput).length - ).to.be.greaterThan(0); - expect( - removeEmptyCoordinates(previousPeriodFirstItem.throughput).length - ).to.be.greaterThan(0); - expectSnapshot(currentPeriodFirstItem.throughput).toMatch(); - expectSnapshot(previousPeriodFirstItem.throughput).toMatch(); + const transactionsImpact = transactionsCurrentPeriod.impact; + const metricsImpact = metricsCurrentPeriod.impact; + [transactionsImpact, metricsImpact].forEach((value) => expect(value).to.be.equal(100)); }); + }); - it('returns correct error rate data', () => { - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); - - const currentPeriodFirstItem = currentPeriodItems[0]; - const previousPeriodFirstItem = previousPeriodItems[0]; - - expect(removeEmptyCoordinates(currentPeriodFirstItem.errorRate).length).to.be.greaterThan( - 0 - ); - expect( - removeEmptyCoordinates(previousPeriodFirstItem.errorRate).length - ).to.be.greaterThan(0); - - expectSnapshot(currentPeriodFirstItem.errorRate).toMatch(); - expectSnapshot(previousPeriodFirstItem.errorRate).toMatch(); + describe('with comparisons', () => { + let transactionsStatistics: TransactionsGroupsDetailedStatistics; + before(async () => { + transactionsStatistics = await callApi({ + query: { + start: moment(end).subtract(7, 'minutes').toISOString(), + end: new Date(end).toISOString(), + comparisonStart: new Date(start).toISOString(), + comparisonEnd: moment(start).add(7, 'minutes').toISOString(), + }, + }); }); - it('matches x-axis on current period and previous period', () => { - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); - - const currentPeriodFirstItem = currentPeriodItems[0]; - const previousPeriodFirstItem = previousPeriodItems[0]; - - expect(currentPeriodFirstItem.errorRate.map(({ x }) => x)).to.be.eql( - previousPeriodFirstItem.errorRate.map(({ x }) => x) - ); + it('returns some data for both periods', () => { + expect(isEmpty(transactionsStatistics.currentPeriod)).to.be.equal(false); + expect(isEmpty(transactionsStatistics.previousPeriod)).to.be.equal(false); }); - it('returns correct impact data', () => { - const currentPeriodItems = Object.values(currentPeriod); - const previousPeriodItems = Object.values(previousPeriod); - - const currentPeriodFirstItem = currentPeriodItems[0]; - const previousPeriodFirstItem = previousPeriodItems[0]; + it('has same start time for both periods', () => { + const currentPeriod = transactionsStatistics.currentPeriod[transactionNames[0]]; + const previousPeriod = transactionsStatistics.previousPeriod[transactionNames[0]]; + [ + [currentPeriod.latency, previousPeriod.latency], + [currentPeriod.errorRate, previousPeriod.errorRate], + [currentPeriod.throughput, previousPeriod.throughput], + ].forEach(([currentTimeseries, previousTimeseries]) => { + const firstCurrentPeriodDate = new Date( + first(currentTimeseries)?.x ?? NaN + ).toISOString(); + const firstPreviousPeriodDate = new Date( + first(previousPeriod.latency)?.x ?? NaN + ).toISOString(); + + expect(firstCurrentPeriodDate).to.equal(firstPreviousPeriodDate); + }); + }); + it('has same end time for both periods', () => { + const currentPeriod = transactionsStatistics.currentPeriod[transactionNames[0]]; + const previousPeriod = transactionsStatistics.previousPeriod[transactionNames[0]]; + [ + [currentPeriod.latency, previousPeriod.latency], + [currentPeriod.errorRate, previousPeriod.errorRate], + [currentPeriod.throughput, previousPeriod.throughput], + ].forEach(([currentTimeseries, previousTimeseries]) => { + const lastCurrentPeriodDate = new Date(last(currentTimeseries)?.x ?? NaN).toISOString(); + const lastPreviousPeriodDate = new Date( + last(previousPeriod.latency)?.x ?? NaN + ).toISOString(); + + expect(lastCurrentPeriodDate).to.equal(lastPreviousPeriodDate); + }); + }); - expectSnapshot(roundNumber(currentPeriodFirstItem.impact)).toMatchInline(`"59.04"`); - expectSnapshot(roundNumber(previousPeriodFirstItem.impact)).toMatchInline(`"99.05"`); + it('returns same number of buckets for both periods', () => { + const currentPeriod = transactionsStatistics.currentPeriod[transactionNames[0]]; + const previousPeriod = transactionsStatistics.previousPeriod[transactionNames[0]]; + [ + [currentPeriod.latency, previousPeriod.latency], + [currentPeriod.errorRate, previousPeriod.errorRate], + [currentPeriod.throughput, previousPeriod.throughput], + ].forEach(([currentTimeseries, previousTimeseries]) => { + expect(currentTimeseries.length).to.equal(previousTimeseries.length); + }); }); }); - } - ); + }); + }); } diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.ts b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.ts index 7664d28271e14..f95d153b1c96e 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.ts @@ -98,18 +98,18 @@ export default function ApiTest({ getService }: FtrProviderContext) { ); expectSnapshot(impacts).toMatchInline(` Array [ - 98.4867713293593, - 0.0910992862692518, - 0.217172932411727, - 0.197499651612207, - 0.117088451625813, - 0.203168003440319, - 0.0956764857936742, - 0.353287132108131, - 0.043688393280619, - 0.0754467823979389, - 0.115710953190738, - 0.00339059851027124, + 98.5616469236242, + 0.088146942911198, + 0.208815627929649, + 0.189536811278812, + 0.110293217369968, + 0.191163512620049, + 0.0899742946381385, + 0.341831477754056, + 0.0411384477014597, + 0.0652338973356331, + 0.109023796562458, + 0.00319505027438735, ] `); @@ -120,9 +120,9 @@ export default function ApiTest({ getService }: FtrProviderContext) { expectSnapshot(pick(firstItem, 'name', 'latency', 'throughput', 'errorRate', 'impact')) .toMatchInline(` Object { - "errorRate": 0.08, - "impact": 98.4867713293593, - "latency": 1816019.48, + "errorRate": 0.1, + "impact": 98.5616469236242, + "latency": 1925546.54, "name": "DispatcherServlet#doGet", "throughput": 1.66666666666667, } @@ -150,7 +150,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { response.body as TransactionsGroupsPrimaryStatistics; const firstItem = transctionsGroupsPrimaryStatistics.transactionGroups[0]; - expectSnapshot(firstItem.latency).toMatchInline(`66846719`); + expectSnapshot(firstItem.latency).toMatchInline(`66836803`); }); } );