From 00ff9d83b1b1b58628f30982279ce1ee2829fb31 Mon Sep 17 00:00:00 2001 From: Sergi Romeu Date: Wed, 20 Nov 2024 16:48:14 +0100 Subject: [PATCH] [APM] Migrate `/transactions` to deployment agnostic test (#200694) ## Summary Closes https://github.com/elastic/kibana/issues/198997 Part of https://github.com/elastic/kibana/issues/193245 This PR contains the changes to migrate `transactions` test folder to Deployment-agnostic testing strategy. ### How to test - Serverless ``` node scripts/functional_tests_server --config x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.apm.serverless.config.ts node scripts/functional_test_runner --config x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.apm.serverless.config.ts ``` It's recommended to be run against [MKI](https://github.com/elastic/kibana/blob/main/x-pack/test_serverless/README.md#run-tests-on-mki) - Stateful ``` node scripts/functional_tests_server --config x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.apm.stateful.config.ts node scripts/functional_test_runner --config x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.apm.stateful.config.ts ``` ## Checks - [x] (OPTIONAL, only if a test has been unskipped) Run flaky test suite - [x] local run for serverless - [x] local run for stateful - [x] MKI run for serverless --- .../apis/observability/apm/index.ts | 1 + .../apm/transactions/breakdown.spec.ts | 41 + .../apm/transactions/error_rate.spec.ts | 436 ++++ .../observability/apm/transactions/index.ts | 21 + .../apm}/transactions/latency.spec.ts | 34 +- .../latency_overall_distribution.spec.ts | 37 +- .../apm/transactions/trace_samples.spec.ts | 42 + .../transactions_groups_alerts.spec.ts | 149 +- ...actions_groups_detailed_statistics.spec.ts | 28 +- ...ransactions_groups_main_statistics.spec.ts | 28 +- .../top_transaction_groups.spec.snap | 146 -- .../transaction_charts.spec.snap | 1751 ----------------- .../transactions_charts.spec.snap | 61 - .../tests/transactions/breakdown.spec.ts | 21 - .../tests/transactions/error_rate.spec.ts | 433 ---- .../tests/transactions/trace_samples.spec.ts | 27 - 16 files changed, 696 insertions(+), 2560 deletions(-) create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/breakdown.spec.ts create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/error_rate.spec.ts create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/index.ts rename x-pack/test/{apm_api_integration/tests => api_integration/deployment_agnostic/apis/observability/apm}/transactions/latency.spec.ts (96%) rename x-pack/test/{apm_api_integration/tests => api_integration/deployment_agnostic/apis/observability/apm}/transactions/latency_overall_distribution.spec.ts (68%) create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/trace_samples.spec.ts rename x-pack/test/{apm_api_integration/tests => api_integration/deployment_agnostic/apis/observability/apm}/transactions/transactions_groups_alerts.spec.ts (73%) rename x-pack/test/{apm_api_integration/tests => api_integration/deployment_agnostic/apis/observability/apm}/transactions/transactions_groups_detailed_statistics.spec.ts (94%) rename x-pack/test/{apm_api_integration/tests => api_integration/deployment_agnostic/apis/observability/apm}/transactions/transactions_groups_main_statistics.spec.ts (88%) delete mode 100644 x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.spec.snap delete mode 100644 x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transaction_charts.spec.snap delete mode 100644 x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_charts.spec.snap delete mode 100644 x-pack/test/apm_api_integration/tests/transactions/error_rate.spec.ts diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts index 8b80eab51157e..a8e360ad5a06f 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/index.ts @@ -38,6 +38,7 @@ export default function apmApiIntegrationTests({ loadTestFile(require.resolve('./span_links')); loadTestFile(require.resolve('./suggestions')); loadTestFile(require.resolve('./throughput')); + loadTestFile(require.resolve('./transactions')); loadTestFile(require.resolve('./service_overview')); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/breakdown.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/breakdown.spec.ts new file mode 100644 index 0000000000000..73437daa08654 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/breakdown.spec.ts @@ -0,0 +1,41 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import expect from '@kbn/expect'; +import archives from '../constants/archives_metadata'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + + const archiveName = 'apm_8.0.0'; + const { start, end } = archives[archiveName]; + const transactionType = 'request'; + + describe('Breakdown', () => { + describe('when data is not loaded', () => { + it('handles the empty state', async () => { + const response = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/transaction/charts/breakdown', + params: { + path: { serviceName: 'opbeans-node' }, + query: { + start, + end, + transactionType, + environment: 'ENVIRONMENT_ALL', + kuery: '', + }, + }, + }); + + expect(response.status).to.be(200); + expect(response.body).to.eql({ timeseries: [] }); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/error_rate.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/error_rate.spec.ts new file mode 100644 index 0000000000000..976f33a59488f --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/error_rate.spec.ts @@ -0,0 +1,436 @@ +/* + * 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 { apm, timerange } from '@kbn/apm-synthtrace-client'; +import expect from '@kbn/expect'; +import { buildQueryFromFilters } from '@kbn/es-query'; +import { first, last } from 'lodash'; +import moment from 'moment'; +import { + APIClientRequestParamsOf, + APIReturnType, +} from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; +import { RecursivePartial } from '@kbn/apm-plugin/typings/common'; +import { ApmDocumentType } from '@kbn/apm-plugin/common/document_type'; +import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +type ErrorRate = + APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate'>; + +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); + + // url parameters + 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 fetchErrorCharts( + overrides?: RecursivePartial< + APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate'>['params'] + > + ) { + return await apmApiClient.readUser({ + endpoint: `GET /internal/apm/services/{serviceName}/transactions/charts/error_rate`, + params: { + path: { serviceName: overrides?.path?.serviceName || 'opbeans-go' }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + transactionType: 'request', + environment: 'ENVIRONMENT_ALL', + kuery: '', + documentType: ApmDocumentType.TransactionMetric, + rollupInterval: RollupInterval.OneMinute, + bucketSizeInSeconds: 60, + ...overrides?.query, + }, + }, + }); + } + + describe('Error rate', () => { + describe('Error rate when data is not loaded', () => { + it('handles the empty state', async () => { + const response = await fetchErrorCharts(); + expect(response.status).to.be(200); + + const body = response.body as ErrorRate; + expect(body).to.be.eql({ + currentPeriod: { timeseries: [], average: null }, + previousPeriod: { timeseries: [], average: null }, + }); + }); + + it('handles the empty state with comparison data', async () => { + const response = await fetchErrorCharts({ + query: { + start: moment(end).subtract(7, 'minutes').toISOString(), + offset: '7m', + }, + }); + expect(response.status).to.be(200); + + const body = response.body as ErrorRate; + expect(body).to.be.eql({ + currentPeriod: { timeseries: [], average: null }, + previousPeriod: { timeseries: [], average: null }, + }); + }); + }); + + describe('Error rate when data is loaded', () => { + const config = { + firstTransaction: { + name: 'GET /apple 🍎 ', + successRate: 50, + failureRate: 50, + }, + secondTransaction: { + name: 'GET /pear 🍎 ', + successRate: 25, + failureRate: 75, + }, + }; + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); + const serviceGoProdInstance = apm + .service({ name: 'opbeans-go', environment: 'production', agentName: 'go' }) + .instance('instance-a'); + + const { firstTransaction, secondTransaction } = config; + + const documents = [ + timerange(start, end) + .ratePerMinute(firstTransaction.successRate) + .generator((timestamp) => + serviceGoProdInstance + .transaction({ transactionName: firstTransaction.name }) + .timestamp(timestamp) + .duration(1000) + .success() + ), + timerange(start, end) + .ratePerMinute(firstTransaction.failureRate) + .generator((timestamp) => + serviceGoProdInstance + .transaction({ transactionName: firstTransaction.name }) + .duration(1000) + .timestamp(timestamp) + .failure() + ), + timerange(start, end) + .ratePerMinute(secondTransaction.successRate) + .generator((timestamp) => + serviceGoProdInstance + .transaction({ transactionName: secondTransaction.name }) + .timestamp(timestamp) + .duration(1000) + .success() + ), + timerange(start, end) + .ratePerMinute(secondTransaction.failureRate) + .generator((timestamp) => + serviceGoProdInstance + .transaction({ transactionName: secondTransaction.name }) + .duration(1000) + .timestamp(timestamp) + .failure() + ), + ]; + await apmSynthtraceEsClient.index(documents); + }); + + after(() => apmSynthtraceEsClient.clean()); + + describe('returns the transaction error rate', () => { + let errorRateResponse: ErrorRate; + + before(async () => { + const response = await fetchErrorCharts({ + query: { transactionName: config.firstTransaction.name }, + }); + errorRateResponse = response.body; + }); + + it('returns some data', () => { + expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0); + expect(errorRateResponse.previousPeriod.average).to.be(null); + + expect(errorRateResponse.currentPeriod.timeseries).not.to.be.empty(); + expect(errorRateResponse.previousPeriod.timeseries).to.empty(); + + const nonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter( + ({ y }) => y !== null + ); + + expect(nonNullDataPoints).not.to.be.empty(); + }); + + it('has the correct start date', () => { + expect( + new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() + ).to.eql('2021-01-01T00:00:00.000Z'); + }); + + it('has the correct end date', () => { + expect( + new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() + ).to.eql('2021-01-01T00:14:00.000Z'); + }); + + it('has the correct number of buckets', () => { + expect(errorRateResponse.currentPeriod.timeseries.length).to.be.eql(15); + }); + + it('has the correct calculation for average', () => { + expect(errorRateResponse.currentPeriod.average).to.eql( + config.firstTransaction.failureRate / 100 + ); + }); + }); + + describe('returns the transaction error rate with comparison data per transaction name', () => { + let errorRateResponse: ErrorRate; + + before(async () => { + const query = { + transactionName: config.firstTransaction.name, + start: moment(end).subtract(7, 'minutes').toISOString(), + offset: '7m', + }; + + const response = await fetchErrorCharts({ query }); + + errorRateResponse = response.body; + }); + + it('returns some data', () => { + expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0); + expect(errorRateResponse.previousPeriod.average).to.be.greaterThan(0); + + expect(errorRateResponse.currentPeriod.timeseries).not.to.be.empty(); + expect(errorRateResponse.previousPeriod.timeseries).not.to.be.empty(); + + const currentPeriodNonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter( + ({ y }) => y !== null + ); + + const previousPeriodNonNullDataPoints = + errorRateResponse.previousPeriod.timeseries.filter(({ y }) => y !== null); + + expect(currentPeriodNonNullDataPoints).not.to.be.empty(); + expect(previousPeriodNonNullDataPoints).not.to.be.empty(); + }); + + it('has the correct start date', () => { + expect( + new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() + ).to.eql('2021-01-01T00:07:00.000Z'); + expect( + new Date(first(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString() + ).to.eql('2021-01-01T00:07:00.000Z'); + }); + + it('has the correct end date', () => { + expect( + new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() + ).to.eql('2021-01-01T00:14:00.000Z'); + expect( + new Date(last(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString() + ).to.eql('2021-01-01T00:14:00.000Z'); + }); + + it('has the correct number of buckets', () => { + expect(errorRateResponse.currentPeriod.timeseries.length).to.eql(8); + expect(errorRateResponse.previousPeriod.timeseries.length).to.eql(8); + }); + + it('has the correct calculation for average', () => { + expect(errorRateResponse.currentPeriod.average).to.eql( + config.firstTransaction.failureRate / 100 + ); + expect(errorRateResponse.previousPeriod.average).to.eql( + config.firstTransaction.failureRate / 100 + ); + }); + + it('matches x-axis on current period and previous period', () => { + expect(errorRateResponse.currentPeriod.timeseries.map(({ x }) => x)).to.be.eql( + errorRateResponse.previousPeriod.timeseries.map(({ x }) => x) + ); + }); + }); + + describe('returns the same error rate for tx metrics and service tx metrics ', () => { + let txMetricsErrorRateResponse: ErrorRate; + let serviceTxMetricsErrorRateResponse: ErrorRate; + + before(async () => { + const [txMetricsResponse, serviceTxMetricsResponse] = await Promise.all([ + fetchErrorCharts(), + fetchErrorCharts({ + query: { documentType: ApmDocumentType.ServiceTransactionMetric }, + }), + ]); + + txMetricsErrorRateResponse = txMetricsResponse.body; + serviceTxMetricsErrorRateResponse = serviceTxMetricsResponse.body; + }); + + describe('has the correct calculation for average', () => { + const expectedFailureRate = + (config.firstTransaction.failureRate + config.secondTransaction.failureRate) / 2 / 100; + + it('for tx metrics', () => { + expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); + }); + + it('for service tx metrics', () => { + expect(serviceTxMetricsErrorRateResponse.currentPeriod.average).to.eql( + expectedFailureRate + ); + }); + }); + }); + + describe('handles kuery', () => { + let txMetricsErrorRateResponse: ErrorRate; + + before(async () => { + const txMetricsResponse = await fetchErrorCharts({ + query: { + kuery: 'transaction.name : "GET /pear 🍎 "', + }, + }); + txMetricsErrorRateResponse = txMetricsResponse.body; + }); + + describe('has the correct calculation for average with kuery', () => { + const expectedFailureRate = config.secondTransaction.failureRate / 100; + + it('for tx metrics', () => { + expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); + }); + }); + }); + + describe('handles filters', () => { + const filters = [ + { + meta: { + disabled: false, + negate: false, + alias: null, + key: 'transaction.name', + params: ['GET /api/product/list'], + type: 'phrases', + }, + query: { + bool: { + minimum_should_match: 1, + should: { + match_phrase: { + 'transaction.name': 'GET /pear 🍎 ', + }, + }, + }, + }, + }, + ]; + const serializedFilters = JSON.stringify(buildQueryFromFilters(filters, undefined)); + let txMetricsErrorRateResponse: ErrorRate; + + before(async () => { + const txMetricsResponse = await fetchErrorCharts({ + query: { + filters: serializedFilters, + }, + }); + txMetricsErrorRateResponse = txMetricsResponse.body; + }); + + describe('has the correct calculation for average with filter', () => { + const expectedFailureRate = config.secondTransaction.failureRate / 100; + + it('for tx metrics', () => { + expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); + }); + }); + + describe('has the correct calculation for average with negate filter', () => { + const expectedFailureRate = config.secondTransaction.failureRate / 100; + + it('for tx metrics', () => { + expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); + }); + }); + }); + + describe('handles negate filters', () => { + const filters = [ + { + meta: { + disabled: false, + negate: true, + alias: null, + key: 'transaction.name', + params: ['GET /api/product/list'], + type: 'phrases', + }, + query: { + bool: { + minimum_should_match: 1, + should: { + match_phrase: { + 'transaction.name': 'GET /pear 🍎 ', + }, + }, + }, + }, + }, + ]; + const serializedFilters = JSON.stringify(buildQueryFromFilters(filters, undefined)); + let txMetricsErrorRateResponse: ErrorRate; + + before(async () => { + const txMetricsResponse = await fetchErrorCharts({ + query: { + filters: serializedFilters, + }, + }); + txMetricsErrorRateResponse = txMetricsResponse.body; + }); + + describe('has the correct calculation for average with filter', () => { + const expectedFailureRate = config.firstTransaction.failureRate / 100; + + it('for tx metrics', () => { + expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); + }); + }); + }); + + describe('handles bad filters request', () => { + it('for tx metrics', async () => { + try { + await fetchErrorCharts({ + query: { + filters: '{}}}', + }, + }); + } catch (e) { + expect(e.res.status).to.eql(400); + } + }); + }); + }); + }); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/index.ts new file mode 100644 index 0000000000000..30715c862c7f5 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/index.ts @@ -0,0 +1,21 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) { + describe('transactions', () => { + loadTestFile(require.resolve('./breakdown.spec.ts')); + loadTestFile(require.resolve('./error_rate.spec.ts')); + loadTestFile(require.resolve('./latency_overall_distribution.spec.ts')); + loadTestFile(require.resolve('./latency.spec.ts')); + loadTestFile(require.resolve('./transactions_groups_alerts.spec.ts')); + loadTestFile(require.resolve('./transactions_groups_detailed_statistics.spec.ts')); + loadTestFile(require.resolve('./transactions_groups_main_statistics.spec.ts')); + loadTestFile(require.resolve('./trace_samples.spec.ts')); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/transactions/latency.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/latency.spec.ts similarity index 96% rename from x-pack/test/apm_api_integration/tests/transactions/latency.spec.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/latency.spec.ts index eefe5cfb0d0fe..f369bc63ca4ef 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/latency.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/latency.spec.ts @@ -17,15 +17,15 @@ import { RecursivePartial } from '@kbn/apm-plugin/typings/common'; import { meanBy } from 'lodash'; import { ApmDocumentType } from '@kbn/apm-plugin/common/document_type'; import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; type LatencyChartReturnType = APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/latency'>; -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - const apmSynthtraceEsClient = getService('apmSynthtraceEsClient'); +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -57,10 +57,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); } - registry.when( - 'Latency with a basic license when data is not loaded ', - { config: 'basic', archives: [] }, - () => { + describe('Latency', () => { + describe('when data is not loaded ', () => { it('handles the empty state', async () => { const response = await fetchLatencyCharts(); expect(response.status).to.be(200); @@ -70,19 +68,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be(0); expect(latencyChartReturn.previousPeriod.latencyTimeseries.length).to.be(0); }); - } - ); - - // FLAKY: https://github.com/elastic/kibana/issues/177596 - registry.when( - 'Latency with a basic license when data is loaded', - { config: 'basic', archives: [] }, - () => { + }); + + describe('when data is loaded', () => { const GO_PROD_RATE = 80; const GO_DEV_RATE = 20; const GO_PROD_DURATION = 1000; const GO_DEV_DURATION = 500; + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); const serviceGoProdInstance = apm .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); @@ -439,6 +435,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { } }); }); - } - ); + }); + }); } diff --git a/x-pack/test/apm_api_integration/tests/transactions/latency_overall_distribution.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/latency_overall_distribution.spec.ts similarity index 68% rename from x-pack/test/apm_api_integration/tests/transactions/latency_overall_distribution.spec.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/latency_overall_distribution.spec.ts index 0f6060517db3b..2b78a7b10088d 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/latency_overall_distribution.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/latency_overall_distribution.spec.ts @@ -7,12 +7,12 @@ import expect from '@kbn/expect'; import { LatencyDistributionChartType } from '@kbn/apm-plugin/common/latency_distribution_chart_types'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; +import { ARCHIVER_ROUTES } from '../constants/archiver'; +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const esArchiver = getService('esArchiver'); const endpoint = 'POST /internal/apm/latency/overall_distribution/transactions'; // This matches the parameters used for the other tab's search strategy approach in `../correlations/*`. @@ -29,10 +29,8 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }); - registry.when.skip( - 'latency overall distribution without data', - { config: 'trial', archives: [] }, - () => { + describe('Latency overall distribution', () => { + describe('without data', () => { it('handles the empty state', async () => { const response = await apmApiClient.readUser({ endpoint, @@ -43,14 +41,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body?.percentileThresholdValue).to.be(undefined); expect(response.body?.overallHistogram?.length).to.be(undefined); }); - } - ); + }); - registry.when.skip( - 'latency overall distribution with data and default args', - // This uses the same archive used for the other tab's search strategy approach in `../correlations/*`. - { config: 'trial', archives: ['8.0.0'] }, - () => { + describe('with data and default args', () => { + before(async () => { + await esArchiver.load(ARCHIVER_ROUTES['8.0.0']); + }); + after(async () => { + await esArchiver.unload(ARCHIVER_ROUTES['8.0.0']); + }); + + // This uses the same archive used for the other tab's search strategy approach in `../correlations/*`. it('returns percentileThresholdValue and overall histogram', async () => { const response = await apmApiClient.readUser({ endpoint, @@ -62,6 +63,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { expect(response.body?.percentileThresholdValue).to.be(1309695.875); expect(response.body?.overallHistogram?.length).to.be(101); }); - } - ); + }); + }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/trace_samples.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/trace_samples.spec.ts new file mode 100644 index 0000000000000..004165905916d --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/trace_samples.spec.ts @@ -0,0 +1,42 @@ +/* + * 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 expect from '@kbn/expect'; +import archives from '../constants/archives_metadata'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; + +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + + const archiveName = 'apm_8.0.0'; + const { start, end } = archives[archiveName]; + + describe('Transaction trace samples', () => { + describe('when data is not loaded', () => { + it('handles empty state', async () => { + const response = await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/transactions/traces/samples', + params: { + path: { serviceName: 'opbeans-java' }, + query: { + start, + end, + transactionType: 'request', + environment: 'ENVIRONMENT_ALL', + transactionName: 'APIRestController#stats', + kuery: '', + }, + }, + }); + + expect(response.status).to.be(200); + + expect(response.body.traceSamples.length).to.be(0); + }); + }); + }); +} diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_alerts.spec.ts similarity index 73% rename from x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_alerts.spec.ts index f6b2c7c3a74a7..6abefb559bc2d 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_alerts.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_alerts.spec.ts @@ -13,26 +13,26 @@ import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; import { AggregationType } from '@kbn/apm-plugin/common/rules/apm_rule_types'; import { ApmRuleType } from '@kbn/rule-data-utils'; -import { waitForAlertsForRule } from '../alerts/helpers/wait_for_alerts_for_rule'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { createApmRule, runRuleSoon, ApmAlertFields } from '../alerts/helpers/alerting_api_helper'; -import { waitForActiveRule } from '../alerts/helpers/wait_for_active_rule'; -import { cleanupRuleAndAlertState } from '../alerts/helpers/cleanup_rule_and_alert_state'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import type { RoleCredentials } from '@kbn/ftr-common-functional-services'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; +import { APM_ACTION_VARIABLE_INDEX, APM_ALERTS_INDEX } from '../alerts/helpers/alerting_helper'; type TransactionsGroupsMainStatistics = APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/groups/main_statistics'>; -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - const apmSynthtraceEsClient = getService('apmSynthtraceEsClient'); - const supertest = getService('supertest'); - const es = getService('es'); +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); + const alertingApi = getService('alertingApi'); + const samlAuth = getService('samlAuth'); + const serviceName = 'synth-go'; const dayInMs = 24 * 60 * 60 * 1000; const start = Date.now() - dayInMs; const end = Date.now() + dayInMs; - const logger = getService('log'); + + type Alerts = Awaited>; async function getTransactionGroups(overrides?: { path?: { @@ -69,12 +69,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { }, }); expect(response.status).to.be(200); + return response.body as TransactionsGroupsMainStatistics; } - // FLAKY: https://github.com/elastic/kibana/issues/177617 - registry.when('when data is loaded', { config: 'basic', archives: [] }, () => { - describe('Alerts', () => { + describe('Transaction groups alerts', () => { + describe('when data is loaded', () => { const transactions = [ { name: 'GET /api/task/avg', @@ -102,7 +102,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { type: 'request', }, ]; + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + let roleAuthc: RoleCredentials; + before(async () => { + roleAuthc = await samlAuth.createM2mApiKeyWithRoleScope('admin'); + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); const serviceGoProdInstance = apm .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); @@ -135,16 +140,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { ]); }); - after(() => apmSynthtraceEsClient.clean()); + after(async () => { + await samlAuth.invalidateM2mApiKeyWithRoleScope(roleAuthc); + await apmSynthtraceEsClient.clean(); + }); - // FLAKY: https://github.com/elastic/kibana/issues/198866 - describe.skip('Transaction groups with avg transaction duration alerts', () => { + describe('with avg transaction duration alerts', () => { let ruleId: string; - let alerts: ApmAlertFields[]; + let alerts: Alerts; before(async () => { - const createdRule = await createApmRule({ - supertest, + const createdRule = await alertingApi.createRule({ name: `Latency threshold | ${serviceName}`, params: { serviceName, @@ -163,30 +169,42 @@ export default function ApiTest({ getService }: FtrProviderContext) { ], }, ruleTypeId: ApmRuleType.TransactionDuration, + consumer: 'apm', + roleAuthc, }); ruleId = createdRule.id; - alerts = await waitForAlertsForRule({ es, ruleId }); + alerts = await alertingApi.waitForAlertInIndex({ + ruleId, + indexName: APM_ALERTS_INDEX, + }); }); after(async () => { - await cleanupRuleAndAlertState({ es, supertest, logger }); + await alertingApi.cleanUpAlerts({ + ruleId, + alertIndexName: APM_ALERTS_INDEX, + connectorIndexName: APM_ACTION_VARIABLE_INDEX, + consumer: 'apm', + roleAuthc, + }); }); it('checks if rule is active', async () => { - const ruleStatus = await waitForActiveRule({ ruleId, supertest }); + const ruleStatus = await alertingApi.waitForRuleStatus({ + ruleId, + expectedStatus: 'active', + roleAuthc, + }); expect(ruleStatus).to.be('active'); }); it('should successfully run the rule', async () => { - const response = await runRuleSoon({ - ruleId, - supertest, - }); + const response = await alertingApi.runRule(roleAuthc, ruleId); expect(response.status).to.be(204); }); it('indexes alert document', async () => { - expect(alerts.length).to.be(1); + expect(alerts.hits.hits.length).to.be(1); }); it('returns the correct number of alert counts', async () => { @@ -210,13 +228,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); - describe('Transaction groups with p99 transaction duration alerts', () => { + describe('with p99 transaction duration alerts', () => { let ruleId: string; - let alerts: ApmAlertFields[]; + let alerts: Alerts; before(async () => { - const createdRule = await createApmRule({ - supertest, + const createdRule = await alertingApi.createRule({ name: `Latency threshold | ${serviceName}`, params: { serviceName, @@ -235,31 +252,43 @@ export default function ApiTest({ getService }: FtrProviderContext) { ], }, ruleTypeId: ApmRuleType.TransactionDuration, + consumer: 'apm', + roleAuthc, }); ruleId = createdRule.id; - alerts = await waitForAlertsForRule({ es, ruleId }); + alerts = await alertingApi.waitForAlertInIndex({ + ruleId, + indexName: APM_ALERTS_INDEX, + }); }); after(async () => { - await cleanupRuleAndAlertState({ es, supertest, logger }); + await alertingApi.cleanUpAlerts({ + ruleId, + alertIndexName: APM_ALERTS_INDEX, + connectorIndexName: APM_ACTION_VARIABLE_INDEX, + consumer: 'apm', + roleAuthc, + }); }); it('checks if rule is active', async () => { - const ruleStatus = await waitForActiveRule({ ruleId, supertest }); + const ruleStatus = await alertingApi.waitForRuleStatus({ + ruleId, + expectedStatus: 'active', + roleAuthc, + }); expect(ruleStatus).to.be('active'); }); it('should successfully run the rule', async () => { - const response = await runRuleSoon({ - ruleId, - supertest, - }); + const response = await alertingApi.runRule(roleAuthc, ruleId); expect(response.status).to.be(204); }); it('indexes alert document', async () => { - expect(alerts.length).to.be(1); + expect(alerts.hits.hits.length).to.be(1); }); it('returns the correct number of alert counts', async () => { @@ -286,13 +315,12 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); - describe('Transaction groups with error rate alerts', () => { + describe('with error rate alerts', () => { let ruleId: string; - let alerts: ApmAlertFields[]; + let alerts: Alerts; before(async () => { - const createdRule = await createApmRule({ - supertest, + const createdRule = await alertingApi.createRule({ name: `Error rate | ${serviceName}`, params: { serviceName, @@ -310,30 +338,43 @@ export default function ApiTest({ getService }: FtrProviderContext) { ], }, ruleTypeId: ApmRuleType.TransactionErrorRate, + consumer: 'apm', + roleAuthc, }); + ruleId = createdRule.id; - alerts = await waitForAlertsForRule({ es, ruleId }); + alerts = await alertingApi.waitForAlertInIndex({ + ruleId, + indexName: APM_ALERTS_INDEX, + }); }); after(async () => { - await cleanupRuleAndAlertState({ es, supertest, logger }); + await alertingApi.cleanUpAlerts({ + ruleId, + alertIndexName: APM_ALERTS_INDEX, + connectorIndexName: APM_ACTION_VARIABLE_INDEX, + consumer: 'apm', + roleAuthc, + }); }); it('checks if rule is active', async () => { - const ruleStatus = await waitForActiveRule({ ruleId, supertest }); + const ruleStatus = await alertingApi.waitForRuleStatus({ + ruleId, + expectedStatus: 'active', + roleAuthc, + }); expect(ruleStatus).to.be('active'); }); it('should successfully run the rule', async () => { - const response = await runRuleSoon({ - ruleId, - supertest, - }); + const response = await alertingApi.runRule(roleAuthc, ruleId); expect(response.status).to.be(204); }); it('indexes alert document', async () => { - expect(alerts.length).to.be(1); + expect(alerts.hits.hits.length).to.be(1); }); it('returns the correct number of alert counts', async () => { @@ -360,7 +401,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { }); }); - describe('Transaction groups without alerts', () => { + describe('without alerts', () => { it('returns the correct number of alert counts', async () => { const txGroupsTypeTask = await getTransactionGroups({ query: { transactionType: 'task' }, diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_detailed_statistics.spec.ts similarity index 94% rename from x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_detailed_statistics.spec.ts index 77a4b67b4bc4e..bc0ea9e1f501d 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_detailed_statistics.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_detailed_statistics.spec.ts @@ -12,16 +12,16 @@ import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregati import { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; import { ApmDocumentType, ApmTransactionDocumentType } from '@kbn/apm-plugin/common/document_type'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; -import { roundNumber } from '../../utils'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import { roundNumber } from '../../../../../../apm_api_integration/utils'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; type TransactionsGroupsDetailedStatistics = APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/groups/detailed_statistics'>; -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - const apmSynthtraceEsClient = getService('apmSynthtraceEsClient'); +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -71,23 +71,21 @@ export default function ApiTest({ getService }: FtrProviderContext) { return response.body; } - registry.when( - 'Transaction groups detailed statistics when data is not loaded', - { config: 'basic', archives: [] }, - () => { + describe('Transactions groups detailed statistics', () => { + describe('when data is not loaded', () => { it('handles the empty state', async () => { const response = await callApi(); expect(response).to.be.eql({ currentPeriod: {}, previousPeriod: {} }); }); - } - ); + }); - // FLAKY: https://github.com/elastic/kibana/issues/177619 - registry.when('data is loaded', { config: 'basic', archives: [] }, () => { - describe('transactions groups detailed stats', () => { + describe('when data is loaded', () => { const GO_PROD_RATE = 75; const GO_PROD_ERROR_RATE = 25; + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); const serviceGoProdInstance = apm .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); diff --git a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_main_statistics.spec.ts similarity index 88% rename from x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.spec.ts rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_main_statistics.spec.ts index d7c5e78fdcd12..df86780629f4d 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/transactions_groups_main_statistics.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/transactions/transactions_groups_main_statistics.spec.ts @@ -11,12 +11,12 @@ import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregati import { ApmDocumentType, ApmTransactionDocumentType } from '@kbn/apm-plugin/common/document_type'; import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; import { apm, timerange } from '@kbn/apm-synthtrace-client'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - const apmSynthtraceEsClient = getService('apmSynthtraceEsClient'); +export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { + const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); const serviceName = 'synth-go'; const start = new Date('2021-01-01T00:00:00.000Z').getTime(); @@ -45,7 +45,7 @@ export default function ApiTest({ getService }: FtrProviderContext) { query: { start: new Date(start).toISOString(), end: new Date(end).toISOString(), - latencyAggregationType: 'avg' as LatencyAggregationType, + latencyAggregationType: LatencyAggregationType.avg, transactionType: 'request', environment: 'ENVIRONMENT_ALL', useDurationSummary: false, @@ -60,22 +60,17 @@ export default function ApiTest({ getService }: FtrProviderContext) { return response.body; } - registry.when( - 'Transaction groups main statistics when data is not loaded', - { config: 'basic', archives: [] }, - () => { + describe('Transaction groups main statistics', () => { + describe('when data is not loaded', () => { it('handles the empty state', async () => { const transactionsGroupsPrimaryStatistics = await callApi(); expect(transactionsGroupsPrimaryStatistics.transactionGroups).to.empty(); expect(transactionsGroupsPrimaryStatistics.maxCountExceeded).to.be(false); }); - } - ); + }); - // FLAKY: https://github.com/elastic/kibana/issues/177620 - registry.when('when data is loaded', { config: 'basic', archives: [] }, () => { - describe('Transaction groups main statistics', () => { + describe('when data is loaded', () => { const GO_PROD_RATE = 75; const GO_PROD_ERROR_RATE = 25; const transactions = [ @@ -92,7 +87,10 @@ export default function ApiTest({ getService }: FtrProviderContext) { duration: 1000, }, ]; + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); const serviceGoProdInstance = apm .service({ name: serviceName, environment: 'production', agentName: 'go' }) .instance('instance-a'); diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.spec.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.spec.snap deleted file mode 100644 index e21c870c7eb52..0000000000000 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/top_transaction_groups.spec.snap +++ /dev/null @@ -1,146 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`APM API tests basic apm_8.0.0 Top transaction groups when data is loaded returns the correct buckets (when ignoring samples) 1`] = ` -Array [ - Object { - "averageResponseTime": 3279, - "impact": 0, - "key": "POST /api/orders", - "p95": 3264, - "serviceName": "opbeans-node", - "transactionName": "POST /api/orders", - "transactionType": "request", - "transactionsPerMinute": 0.0333333333333333, - }, - Object { - "averageResponseTime": 2119, - "impact": 0.030253201010799, - "key": "GET /*", - "p95": 2296, - "serviceName": "opbeans-node", - "transactionName": "GET /*", - "transactionType": "request", - "transactionsPerMinute": 0.1, - }, - Object { - "averageResponseTime": 5167, - "impact": 0.0693425383792029, - "key": "GET /api/products/:id", - "p95": 6144, - "serviceName": "opbeans-node", - "transactionName": "GET /api/products/:id", - "transactionType": "request", - "transactionsPerMinute": 0.0666666666666667, - }, - Object { - "averageResponseTime": 5551, - "impact": 0.349690833515986, - "key": "GET /api/orders/:id", - "p95": 11696, - "serviceName": "opbeans-node", - "transactionName": "GET /api/orders/:id", - "transactionType": "request", - "transactionsPerMinute": 0.233333333333333, - }, - Object { - "averageResponseTime": 9607, - "impact": 0.723177313441051, - "key": "GET /api/types", - "p95": 18672, - "serviceName": "opbeans-node", - "transactionName": "GET /api/types", - "transactionType": "request", - "transactionsPerMinute": 0.266666666666667, - }, - Object { - "averageResponseTime": 8669.22222222222, - "impact": 0.734647581660545, - "key": "GET /api/products/:id/customers", - "p95": 15920, - "serviceName": "opbeans-node", - "transactionName": "GET /api/products/:id/customers", - "transactionType": "request", - "transactionsPerMinute": 0.3, - }, - Object { - "averageResponseTime": 7571, - "impact": 0.860741901273131, - "key": "GET /api/types/:id", - "p95": 13552, - "serviceName": "opbeans-node", - "transactionName": "GET /api/types/:id", - "transactionType": "request", - "transactionsPerMinute": 0.4, - }, - Object { - "averageResponseTime": 8753.90909090909, - "impact": 0.914220675379615, - "key": "GET /api/customers/:id", - "p95": 11248, - "serviceName": "opbeans-node", - "transactionName": "GET /api/customers/:id", - "transactionType": "request", - "transactionsPerMinute": 0.366666666666667, - }, - Object { - "averageResponseTime": 7807, - "impact": 1.04204487263284, - "key": "GET /api/products/top", - "p95": 14000, - "serviceName": "opbeans-node", - "transactionName": "GET /api/products/top", - "transactionType": "request", - "transactionsPerMinute": 0.466666666666667, - }, - Object { - "averageResponseTime": 11913.6666666667, - "impact": 1.37294294450729, - "key": "GET /api/orders", - "p95": 15008, - "serviceName": "opbeans-node", - "transactionName": "GET /api/orders", - "transactionType": "request", - "transactionsPerMinute": 0.4, - }, - Object { - "averageResponseTime": 9062.52941176471, - "impact": 1.48203335322037, - "key": "GET /api/products", - "p95": 15728, - "serviceName": "opbeans-node", - "transactionName": "GET /api/products", - "transactionType": "request", - "transactionsPerMinute": 0.566666666666667, - }, - Object { - "averageResponseTime": 19858.2, - "impact": 1.91960393665109, - "key": "GET /api/stats", - "p95": 33984, - "serviceName": "opbeans-node", - "transactionName": "GET /api/stats", - "transactionType": "request", - "transactionsPerMinute": 0.333333333333333, - }, - Object { - "averageResponseTime": 22276.8181818182, - "impact": 2.37628180493074, - "key": "GET /api/customers", - "p95": 26304, - "serviceName": "opbeans-node", - "transactionName": "GET /api/customers", - "transactionType": "request", - "transactionsPerMinute": 0.366666666666667, - }, - Object { - "averageResponseTime": 107130.621052632, - "impact": 100, - "key": "GET /api", - "p95": 151520, - "serviceName": "opbeans-node", - "transactionName": "GET /api", - "transactionType": "request", - "transactionsPerMinute": 3.16666666666667, - }, -] -`; diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transaction_charts.spec.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transaction_charts.spec.snap deleted file mode 100644 index 4b3f2293498cc..0000000000000 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transaction_charts.spec.snap +++ /dev/null @@ -1,1751 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`Transaction charts when data is loaded returns the correct data 4`] = ` -Object { - "apmTimeseries": Object { - "overallAvgDuration": 563605.417040359, - "responseTimes": Object { - "avg": Array [ - Object { - "x": 1607435850000, - "y": null, - }, - Object { - "x": 1607435880000, - "y": 233725.666666667, - }, - Object { - "x": 1607435910000, - "y": 761099.333333333, - }, - Object { - "x": 1607435940000, - "y": 444231.666666667, - }, - Object { - "x": 1607435970000, - "y": 999194.666666667, - }, - Object { - "x": 1607436000000, - "y": 558128.666666667, - }, - Object { - "x": 1607436030000, - "y": 842340, - }, - Object { - "x": 1607436060000, - "y": 1070088, - }, - Object { - "x": 1607436090000, - "y": 1289537.66666667, - }, - Object { - "x": 1607436120000, - "y": 320373, - }, - Object { - "x": 1607436150000, - "y": 412243.857142857, - }, - Object { - "x": 1607436180000, - "y": 604852, - }, - Object { - "x": 1607436210000, - "y": 1293499, - }, - Object { - "x": 1607436240000, - "y": 272394.571428571, - }, - Object { - "x": 1607436270000, - "y": 930978.4, - }, - Object { - "x": 1607436300000, - "y": 906360, - }, - Object { - "x": 1607436330000, - "y": 232498.25, - }, - Object { - "x": 1607436360000, - "y": 201226.333333333, - }, - Object { - "x": 1607436390000, - "y": 621694.833333333, - }, - Object { - "x": 1607436420000, - "y": 1935481, - }, - Object { - "x": 1607436450000, - "y": 1157048, - }, - Object { - "x": 1607436480000, - "y": 717248.333333333, - }, - Object { - "x": 1607436510000, - "y": 660264.833333333, - }, - Object { - "x": 1607436540000, - "y": 1305048, - }, - Object { - "x": 1607436570000, - "y": 715224, - }, - Object { - "x": 1607436600000, - "y": 144978.5, - }, - Object { - "x": 1607436630000, - "y": 102661, - }, - Object { - "x": 1607436660000, - "y": 810296.5, - }, - Object { - "x": 1607436690000, - "y": 938002.25, - }, - Object { - "x": 1607436720000, - "y": 63220, - }, - Object { - "x": 1607436750000, - "y": 737306.2, - }, - Object { - "x": 1607436780000, - "y": 963865.75, - }, - Object { - "x": 1607436810000, - "y": 38124, - }, - Object { - "x": 1607436840000, - "y": 860345.6, - }, - Object { - "x": 1607436870000, - "y": null, - }, - Object { - "x": 1607436900000, - "y": 742157, - }, - Object { - "x": 1607436930000, - "y": 584849, - }, - Object { - "x": 1607436960000, - "y": 165453.2, - }, - Object { - "x": 1607436990000, - "y": 334794, - }, - Object { - "x": 1607437020000, - "y": 1397727.5, - }, - Object { - "x": 1607437050000, - "y": 1104933, - }, - Object { - "x": 1607437080000, - "y": 755694.571428571, - }, - Object { - "x": 1607437110000, - "y": 252777.25, - }, - Object { - "x": 1607437140000, - "y": 708401.333333333, - }, - Object { - "x": 1607437170000, - "y": 1153244, - }, - Object { - "x": 1607437200000, - "y": 730186.25, - }, - Object { - "x": 1607437230000, - "y": 270504.222222222, - }, - Object { - "x": 1607437260000, - "y": 938813.333333333, - }, - Object { - "x": 1607437290000, - "y": 171339, - }, - Object { - "x": 1607437320000, - "y": 345618.2, - }, - Object { - "x": 1607437350000, - "y": 1100982.25, - }, - Object { - "x": 1607437380000, - "y": 724415, - }, - Object { - "x": 1607437410000, - "y": 1273571.5, - }, - Object { - "x": 1607437440000, - "y": 329748, - }, - Object { - "x": 1607437470000, - "y": 231693.538461538, - }, - Object { - "x": 1607437500000, - "y": 620042, - }, - Object { - "x": 1607437530000, - "y": null, - }, - Object { - "x": 1607437560000, - "y": 640575.666666667, - }, - Object { - "x": 1607437590000, - "y": 177960.714285714, - }, - Object { - "x": 1607437620000, - "y": 1142976, - }, - Object { - "x": 1607437650000, - "y": 530845.5, - }, - ], - "p95": Array [ - Object { - "x": 1607435850000, - "y": null, - }, - Object { - "x": 1607435880000, - "y": 1032160, - }, - Object { - "x": 1607435910000, - "y": 1400704, - }, - Object { - "x": 1607435940000, - "y": 831360, - }, - Object { - "x": 1607435970000, - "y": 1118208, - }, - Object { - "x": 1607436000000, - "y": 921472, - }, - Object { - "x": 1607436030000, - "y": 995328, - }, - Object { - "x": 1607436060000, - "y": 1064960, - }, - Object { - "x": 1607436090000, - "y": 1560576, - }, - Object { - "x": 1607436120000, - "y": 610176, - }, - Object { - "x": 1607436150000, - "y": 1490912, - }, - Object { - "x": 1607436180000, - "y": 614400, - }, - Object { - "x": 1607436210000, - "y": 1286144, - }, - Object { - "x": 1607436240000, - "y": 1114096, - }, - Object { - "x": 1607436270000, - "y": 1843072, - }, - Object { - "x": 1607436300000, - "y": 1118208, - }, - Object { - "x": 1607436330000, - "y": 481152, - }, - Object { - "x": 1607436360000, - "y": 548848, - }, - Object { - "x": 1607436390000, - "y": 1695680, - }, - Object { - "x": 1607436420000, - "y": 1933312, - }, - Object { - "x": 1607436450000, - "y": 1429504, - }, - Object { - "x": 1607436480000, - "y": 1081216, - }, - Object { - "x": 1607436510000, - "y": 1572832, - }, - Object { - "x": 1607436540000, - "y": 1751040, - }, - Object { - "x": 1607436570000, - "y": 1087488, - }, - Object { - "x": 1607436600000, - "y": 1294320, - }, - Object { - "x": 1607436630000, - "y": 198528, - }, - Object { - "x": 1607436660000, - "y": 880640, - }, - Object { - "x": 1607436690000, - "y": 1257472, - }, - Object { - "x": 1607436720000, - "y": 180192, - }, - Object { - "x": 1607436750000, - "y": 1179520, - }, - Object { - "x": 1607436780000, - "y": 1556224, - }, - Object { - "x": 1607436810000, - "y": 37888, - }, - Object { - "x": 1607436840000, - "y": 1261504, - }, - Object { - "x": 1607436870000, - "y": null, - }, - Object { - "x": 1607436900000, - "y": 1087488, - }, - Object { - "x": 1607436930000, - "y": 581632, - }, - Object { - "x": 1607436960000, - "y": 294784, - }, - Object { - "x": 1607436990000, - "y": 1245152, - }, - Object { - "x": 1607437020000, - "y": 1654784, - }, - Object { - "x": 1607437050000, - "y": 1097728, - }, - Object { - "x": 1607437080000, - "y": 1433584, - }, - Object { - "x": 1607437110000, - "y": 925568, - }, - Object { - "x": 1607437140000, - "y": 919552, - }, - Object { - "x": 1607437170000, - "y": 1146880, - }, - Object { - "x": 1607437200000, - "y": 1507072, - }, - Object { - "x": 1607437230000, - "y": 1318880, - }, - Object { - "x": 1607437260000, - "y": 1867712, - }, - Object { - "x": 1607437290000, - "y": 210944, - }, - Object { - "x": 1607437320000, - "y": 1449952, - }, - Object { - "x": 1607437350000, - "y": 1462272, - }, - Object { - "x": 1607437380000, - "y": 724992, - }, - Object { - "x": 1607437410000, - "y": 1335296, - }, - Object { - "x": 1607437440000, - "y": 329728, - }, - Object { - "x": 1607437470000, - "y": 1409008, - }, - Object { - "x": 1607437500000, - "y": 763904, - }, - Object { - "x": 1607437530000, - "y": null, - }, - Object { - "x": 1607437560000, - "y": 1474528, - }, - Object { - "x": 1607437590000, - "y": 598000, - }, - Object { - "x": 1607437620000, - "y": 1138688, - }, - Object { - "x": 1607437650000, - "y": 822272, - }, - ], - "p99": Array [ - Object { - "x": 1607435850000, - "y": null, - }, - Object { - "x": 1607435880000, - "y": 1032160, - }, - Object { - "x": 1607435910000, - "y": 1400704, - }, - Object { - "x": 1607435940000, - "y": 831360, - }, - Object { - "x": 1607435970000, - "y": 1118208, - }, - Object { - "x": 1607436000000, - "y": 921472, - }, - Object { - "x": 1607436030000, - "y": 995328, - }, - Object { - "x": 1607436060000, - "y": 1064960, - }, - Object { - "x": 1607436090000, - "y": 1560576, - }, - Object { - "x": 1607436120000, - "y": 610176, - }, - Object { - "x": 1607436150000, - "y": 1490912, - }, - Object { - "x": 1607436180000, - "y": 614400, - }, - Object { - "x": 1607436210000, - "y": 1286144, - }, - Object { - "x": 1607436240000, - "y": 1114096, - }, - Object { - "x": 1607436270000, - "y": 1843072, - }, - Object { - "x": 1607436300000, - "y": 1118208, - }, - Object { - "x": 1607436330000, - "y": 481152, - }, - Object { - "x": 1607436360000, - "y": 548848, - }, - Object { - "x": 1607436390000, - "y": 1695680, - }, - Object { - "x": 1607436420000, - "y": 1933312, - }, - Object { - "x": 1607436450000, - "y": 1429504, - }, - Object { - "x": 1607436480000, - "y": 1081216, - }, - Object { - "x": 1607436510000, - "y": 1572832, - }, - Object { - "x": 1607436540000, - "y": 1751040, - }, - Object { - "x": 1607436570000, - "y": 1087488, - }, - Object { - "x": 1607436600000, - "y": 1294320, - }, - Object { - "x": 1607436630000, - "y": 198528, - }, - Object { - "x": 1607436660000, - "y": 880640, - }, - Object { - "x": 1607436690000, - "y": 1257472, - }, - Object { - "x": 1607436720000, - "y": 180192, - }, - Object { - "x": 1607436750000, - "y": 1179520, - }, - Object { - "x": 1607436780000, - "y": 1556224, - }, - Object { - "x": 1607436810000, - "y": 37888, - }, - Object { - "x": 1607436840000, - "y": 1261504, - }, - Object { - "x": 1607436870000, - "y": null, - }, - Object { - "x": 1607436900000, - "y": 1087488, - }, - Object { - "x": 1607436930000, - "y": 581632, - }, - Object { - "x": 1607436960000, - "y": 294784, - }, - Object { - "x": 1607436990000, - "y": 1245152, - }, - Object { - "x": 1607437020000, - "y": 1654784, - }, - Object { - "x": 1607437050000, - "y": 1097728, - }, - Object { - "x": 1607437080000, - "y": 1433584, - }, - Object { - "x": 1607437110000, - "y": 925568, - }, - Object { - "x": 1607437140000, - "y": 919552, - }, - Object { - "x": 1607437170000, - "y": 1146880, - }, - Object { - "x": 1607437200000, - "y": 1507072, - }, - Object { - "x": 1607437230000, - "y": 1318880, - }, - Object { - "x": 1607437260000, - "y": 1867712, - }, - Object { - "x": 1607437290000, - "y": 210944, - }, - Object { - "x": 1607437320000, - "y": 1449952, - }, - Object { - "x": 1607437350000, - "y": 1462272, - }, - Object { - "x": 1607437380000, - "y": 724992, - }, - Object { - "x": 1607437410000, - "y": 1335296, - }, - Object { - "x": 1607437440000, - "y": 329728, - }, - Object { - "x": 1607437470000, - "y": 1466352, - }, - Object { - "x": 1607437500000, - "y": 763904, - }, - Object { - "x": 1607437530000, - "y": null, - }, - Object { - "x": 1607437560000, - "y": 1474528, - }, - Object { - "x": 1607437590000, - "y": 598000, - }, - Object { - "x": 1607437620000, - "y": 1138688, - }, - Object { - "x": 1607437650000, - "y": 822272, - }, - ], - }, - "tpmBuckets": Array [ - Object { - "avg": 3, - "dataPoints": Array [ - Object { - "x": 1607435850000, - "y": 0, - }, - Object { - "x": 1607435880000, - "y": 8, - }, - Object { - "x": 1607435910000, - "y": 4, - }, - Object { - "x": 1607435940000, - "y": 2, - }, - Object { - "x": 1607435970000, - "y": 0, - }, - Object { - "x": 1607436000000, - "y": 2, - }, - Object { - "x": 1607436030000, - "y": 0, - }, - Object { - "x": 1607436060000, - "y": 0, - }, - Object { - "x": 1607436090000, - "y": 0, - }, - Object { - "x": 1607436120000, - "y": 2, - }, - Object { - "x": 1607436150000, - "y": 10, - }, - Object { - "x": 1607436180000, - "y": 0, - }, - Object { - "x": 1607436210000, - "y": 0, - }, - Object { - "x": 1607436240000, - "y": 10, - }, - Object { - "x": 1607436270000, - "y": 2, - }, - Object { - "x": 1607436300000, - "y": 0, - }, - Object { - "x": 1607436330000, - "y": 4, - }, - Object { - "x": 1607436360000, - "y": 4, - }, - Object { - "x": 1607436390000, - "y": 6, - }, - Object { - "x": 1607436420000, - "y": 0, - }, - Object { - "x": 1607436450000, - "y": 0, - }, - Object { - "x": 1607436480000, - "y": 2, - }, - Object { - "x": 1607436510000, - "y": 6, - }, - Object { - "x": 1607436540000, - "y": 0, - }, - Object { - "x": 1607436570000, - "y": 0, - }, - Object { - "x": 1607436600000, - "y": 14, - }, - Object { - "x": 1607436630000, - "y": 8, - }, - Object { - "x": 1607436660000, - "y": 0, - }, - Object { - "x": 1607436690000, - "y": 0, - }, - Object { - "x": 1607436720000, - "y": 8, - }, - Object { - "x": 1607436750000, - "y": 2, - }, - Object { - "x": 1607436780000, - "y": 2, - }, - Object { - "x": 1607436810000, - "y": 2, - }, - Object { - "x": 1607436840000, - "y": 2, - }, - Object { - "x": 1607436870000, - "y": 0, - }, - Object { - "x": 1607436900000, - "y": 0, - }, - Object { - "x": 1607436930000, - "y": 0, - }, - Object { - "x": 1607436960000, - "y": 4, - }, - Object { - "x": 1607436990000, - "y": 8, - }, - Object { - "x": 1607437020000, - "y": 0, - }, - Object { - "x": 1607437050000, - "y": 0, - }, - Object { - "x": 1607437080000, - "y": 6, - }, - Object { - "x": 1607437110000, - "y": 6, - }, - Object { - "x": 1607437140000, - "y": 0, - }, - Object { - "x": 1607437170000, - "y": 0, - }, - Object { - "x": 1607437200000, - "y": 2, - }, - Object { - "x": 1607437230000, - "y": 14, - }, - Object { - "x": 1607437260000, - "y": 2, - }, - Object { - "x": 1607437290000, - "y": 0, - }, - Object { - "x": 1607437320000, - "y": 4, - }, - Object { - "x": 1607437350000, - "y": 0, - }, - Object { - "x": 1607437380000, - "y": 0, - }, - Object { - "x": 1607437410000, - "y": 0, - }, - Object { - "x": 1607437440000, - "y": 0, - }, - Object { - "x": 1607437470000, - "y": 22, - }, - Object { - "x": 1607437500000, - "y": 0, - }, - Object { - "x": 1607437530000, - "y": 0, - }, - Object { - "x": 1607437560000, - "y": 6, - }, - Object { - "x": 1607437590000, - "y": 6, - }, - Object { - "x": 1607437620000, - "y": 0, - }, - Object { - "x": 1607437650000, - "y": 0, - }, - ], - "key": "HTTP 2xx", - }, - Object { - "avg": 0.1, - "dataPoints": Array [ - Object { - "x": 1607435850000, - "y": 0, - }, - Object { - "x": 1607435880000, - "y": 0, - }, - Object { - "x": 1607435910000, - "y": 0, - }, - Object { - "x": 1607435940000, - "y": 0, - }, - Object { - "x": 1607435970000, - "y": 0, - }, - Object { - "x": 1607436000000, - "y": 0, - }, - Object { - "x": 1607436030000, - "y": 0, - }, - Object { - "x": 1607436060000, - "y": 0, - }, - Object { - "x": 1607436090000, - "y": 0, - }, - Object { - "x": 1607436120000, - "y": 0, - }, - Object { - "x": 1607436150000, - "y": 0, - }, - Object { - "x": 1607436180000, - "y": 0, - }, - Object { - "x": 1607436210000, - "y": 0, - }, - Object { - "x": 1607436240000, - "y": 0, - }, - Object { - "x": 1607436270000, - "y": 0, - }, - Object { - "x": 1607436300000, - "y": 0, - }, - Object { - "x": 1607436330000, - "y": 0, - }, - Object { - "x": 1607436360000, - "y": 0, - }, - Object { - "x": 1607436390000, - "y": 0, - }, - Object { - "x": 1607436420000, - "y": 0, - }, - Object { - "x": 1607436450000, - "y": 0, - }, - Object { - "x": 1607436480000, - "y": 0, - }, - Object { - "x": 1607436510000, - "y": 0, - }, - Object { - "x": 1607436540000, - "y": 0, - }, - Object { - "x": 1607436570000, - "y": 0, - }, - Object { - "x": 1607436600000, - "y": 0, - }, - Object { - "x": 1607436630000, - "y": 0, - }, - Object { - "x": 1607436660000, - "y": 0, - }, - Object { - "x": 1607436690000, - "y": 0, - }, - Object { - "x": 1607436720000, - "y": 0, - }, - Object { - "x": 1607436750000, - "y": 0, - }, - Object { - "x": 1607436780000, - "y": 0, - }, - Object { - "x": 1607436810000, - "y": 0, - }, - Object { - "x": 1607436840000, - "y": 0, - }, - Object { - "x": 1607436870000, - "y": 0, - }, - Object { - "x": 1607436900000, - "y": 0, - }, - Object { - "x": 1607436930000, - "y": 0, - }, - Object { - "x": 1607436960000, - "y": 0, - }, - Object { - "x": 1607436990000, - "y": 0, - }, - Object { - "x": 1607437020000, - "y": 0, - }, - Object { - "x": 1607437050000, - "y": 0, - }, - Object { - "x": 1607437080000, - "y": 0, - }, - Object { - "x": 1607437110000, - "y": 0, - }, - Object { - "x": 1607437140000, - "y": 0, - }, - Object { - "x": 1607437170000, - "y": 0, - }, - Object { - "x": 1607437200000, - "y": 0, - }, - Object { - "x": 1607437230000, - "y": 0, - }, - Object { - "x": 1607437260000, - "y": 0, - }, - Object { - "x": 1607437290000, - "y": 0, - }, - Object { - "x": 1607437320000, - "y": 2, - }, - Object { - "x": 1607437350000, - "y": 0, - }, - Object { - "x": 1607437380000, - "y": 0, - }, - Object { - "x": 1607437410000, - "y": 0, - }, - Object { - "x": 1607437440000, - "y": 0, - }, - Object { - "x": 1607437470000, - "y": 0, - }, - Object { - "x": 1607437500000, - "y": 0, - }, - Object { - "x": 1607437530000, - "y": 0, - }, - Object { - "x": 1607437560000, - "y": 0, - }, - Object { - "x": 1607437590000, - "y": 4, - }, - Object { - "x": 1607437620000, - "y": 0, - }, - Object { - "x": 1607437650000, - "y": 0, - }, - ], - "key": "HTTP 4xx", - }, - Object { - "avg": 0.0666666666666667, - "dataPoints": Array [ - Object { - "x": 1607435850000, - "y": 0, - }, - Object { - "x": 1607435880000, - "y": 0, - }, - Object { - "x": 1607435910000, - "y": 0, - }, - Object { - "x": 1607435940000, - "y": 0, - }, - Object { - "x": 1607435970000, - "y": 0, - }, - Object { - "x": 1607436000000, - "y": 0, - }, - Object { - "x": 1607436030000, - "y": 0, - }, - Object { - "x": 1607436060000, - "y": 0, - }, - Object { - "x": 1607436090000, - "y": 0, - }, - Object { - "x": 1607436120000, - "y": 0, - }, - Object { - "x": 1607436150000, - "y": 0, - }, - Object { - "x": 1607436180000, - "y": 0, - }, - Object { - "x": 1607436210000, - "y": 0, - }, - Object { - "x": 1607436240000, - "y": 0, - }, - Object { - "x": 1607436270000, - "y": 0, - }, - Object { - "x": 1607436300000, - "y": 0, - }, - Object { - "x": 1607436330000, - "y": 0, - }, - Object { - "x": 1607436360000, - "y": 0, - }, - Object { - "x": 1607436390000, - "y": 0, - }, - Object { - "x": 1607436420000, - "y": 0, - }, - Object { - "x": 1607436450000, - "y": 0, - }, - Object { - "x": 1607436480000, - "y": 0, - }, - Object { - "x": 1607436510000, - "y": 0, - }, - Object { - "x": 1607436540000, - "y": 0, - }, - Object { - "x": 1607436570000, - "y": 0, - }, - Object { - "x": 1607436600000, - "y": 4, - }, - Object { - "x": 1607436630000, - "y": 0, - }, - Object { - "x": 1607436660000, - "y": 0, - }, - Object { - "x": 1607436690000, - "y": 0, - }, - Object { - "x": 1607436720000, - "y": 0, - }, - Object { - "x": 1607436750000, - "y": 0, - }, - Object { - "x": 1607436780000, - "y": 0, - }, - Object { - "x": 1607436810000, - "y": 0, - }, - Object { - "x": 1607436840000, - "y": 0, - }, - Object { - "x": 1607436870000, - "y": 0, - }, - Object { - "x": 1607436900000, - "y": 0, - }, - Object { - "x": 1607436930000, - "y": 0, - }, - Object { - "x": 1607436960000, - "y": 0, - }, - Object { - "x": 1607436990000, - "y": 0, - }, - Object { - "x": 1607437020000, - "y": 0, - }, - Object { - "x": 1607437050000, - "y": 0, - }, - Object { - "x": 1607437080000, - "y": 0, - }, - Object { - "x": 1607437110000, - "y": 0, - }, - Object { - "x": 1607437140000, - "y": 0, - }, - Object { - "x": 1607437170000, - "y": 0, - }, - Object { - "x": 1607437200000, - "y": 0, - }, - Object { - "x": 1607437230000, - "y": 0, - }, - Object { - "x": 1607437260000, - "y": 0, - }, - Object { - "x": 1607437290000, - "y": 0, - }, - Object { - "x": 1607437320000, - "y": 0, - }, - Object { - "x": 1607437350000, - "y": 0, - }, - Object { - "x": 1607437380000, - "y": 0, - }, - Object { - "x": 1607437410000, - "y": 0, - }, - Object { - "x": 1607437440000, - "y": 0, - }, - Object { - "x": 1607437470000, - "y": 0, - }, - Object { - "x": 1607437500000, - "y": 0, - }, - Object { - "x": 1607437530000, - "y": 0, - }, - Object { - "x": 1607437560000, - "y": 0, - }, - Object { - "x": 1607437590000, - "y": 0, - }, - Object { - "x": 1607437620000, - "y": 0, - }, - Object { - "x": 1607437650000, - "y": 0, - }, - ], - "key": "HTTP 5xx", - }, - Object { - "avg": 4.26666666666667, - "dataPoints": Array [ - Object { - "x": 1607435850000, - "y": 0, - }, - Object { - "x": 1607435880000, - "y": 4, - }, - Object { - "x": 1607435910000, - "y": 8, - }, - Object { - "x": 1607435940000, - "y": 4, - }, - Object { - "x": 1607435970000, - "y": 6, - }, - Object { - "x": 1607436000000, - "y": 4, - }, - Object { - "x": 1607436030000, - "y": 4, - }, - Object { - "x": 1607436060000, - "y": 2, - }, - Object { - "x": 1607436090000, - "y": 6, - }, - Object { - "x": 1607436120000, - "y": 2, - }, - Object { - "x": 1607436150000, - "y": 4, - }, - Object { - "x": 1607436180000, - "y": 4, - }, - Object { - "x": 1607436210000, - "y": 2, - }, - Object { - "x": 1607436240000, - "y": 4, - }, - Object { - "x": 1607436270000, - "y": 8, - }, - Object { - "x": 1607436300000, - "y": 4, - }, - Object { - "x": 1607436330000, - "y": 4, - }, - Object { - "x": 1607436360000, - "y": 2, - }, - Object { - "x": 1607436390000, - "y": 6, - }, - Object { - "x": 1607436420000, - "y": 2, - }, - Object { - "x": 1607436450000, - "y": 6, - }, - Object { - "x": 1607436480000, - "y": 4, - }, - Object { - "x": 1607436510000, - "y": 6, - }, - Object { - "x": 1607436540000, - "y": 6, - }, - Object { - "x": 1607436570000, - "y": 6, - }, - Object { - "x": 1607436600000, - "y": 2, - }, - Object { - "x": 1607436630000, - "y": 4, - }, - Object { - "x": 1607436660000, - "y": 4, - }, - Object { - "x": 1607436690000, - "y": 8, - }, - Object { - "x": 1607436720000, - "y": 0, - }, - Object { - "x": 1607436750000, - "y": 8, - }, - Object { - "x": 1607436780000, - "y": 6, - }, - Object { - "x": 1607436810000, - "y": 0, - }, - Object { - "x": 1607436840000, - "y": 8, - }, - Object { - "x": 1607436870000, - "y": 0, - }, - Object { - "x": 1607436900000, - "y": 6, - }, - Object { - "x": 1607436930000, - "y": 2, - }, - Object { - "x": 1607436960000, - "y": 6, - }, - Object { - "x": 1607436990000, - "y": 4, - }, - Object { - "x": 1607437020000, - "y": 4, - }, - Object { - "x": 1607437050000, - "y": 2, - }, - Object { - "x": 1607437080000, - "y": 8, - }, - Object { - "x": 1607437110000, - "y": 2, - }, - Object { - "x": 1607437140000, - "y": 6, - }, - Object { - "x": 1607437170000, - "y": 2, - }, - Object { - "x": 1607437200000, - "y": 6, - }, - Object { - "x": 1607437230000, - "y": 4, - }, - Object { - "x": 1607437260000, - "y": 4, - }, - Object { - "x": 1607437290000, - "y": 4, - }, - Object { - "x": 1607437320000, - "y": 4, - }, - Object { - "x": 1607437350000, - "y": 8, - }, - Object { - "x": 1607437380000, - "y": 4, - }, - Object { - "x": 1607437410000, - "y": 4, - }, - Object { - "x": 1607437440000, - "y": 2, - }, - Object { - "x": 1607437470000, - "y": 4, - }, - Object { - "x": 1607437500000, - "y": 6, - }, - Object { - "x": 1607437530000, - "y": 0, - }, - Object { - "x": 1607437560000, - "y": 6, - }, - Object { - "x": 1607437590000, - "y": 4, - }, - Object { - "x": 1607437620000, - "y": 2, - }, - Object { - "x": 1607437650000, - "y": 4, - }, - ], - "key": "success", - }, - ], - }, -} -`; diff --git a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_charts.spec.snap b/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_charts.spec.snap deleted file mode 100644 index 2f78b03adbf4c..0000000000000 --- a/x-pack/test/apm_api_integration/tests/transactions/__snapshots__/transactions_charts.spec.snap +++ /dev/null @@ -1,61 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`APM Transaction Overview when data is loaded and fetching transaction charts with uiFilters when not defined environments selected should return the correct anomaly boundaries 1`] = ` -Array [ - Object { - "x": 1607436000000, - "y": 0, - "y0": 0, - }, - Object { - "x": 1607436900000, - "y": 0, - "y0": 0, - }, - Object { - "x": 1607437650000, - "y": 0, - "y0": 0, - }, -] -`; - -exports[`APM Transaction Overview when data is loaded and fetching transaction charts with uiFilters with environment selected and empty kuery filter should return a non-empty anomaly series 1`] = ` -Array [ - Object { - "x": 1607436000000, - "y": 1625128.56211579, - "y0": 7533.02707532227, - }, - Object { - "x": 1607436900000, - "y": 1660982.24115757, - "y0": 5732.00699123528, - }, - Object { - "x": 1607437650000, - "y": 1660982.24115757, - "y0": 5732.00699123528, - }, -] -`; - -exports[`APM Transaction Overview when data is loaded and fetching transaction charts with uiFilters with environment selected in uiFilters should return a non-empty anomaly series 1`] = ` -Array [ - Object { - "x": 1607436000000, - "y": 1625128.56211579, - "y0": 7533.02707532227, - }, - Object { - "x": 1607436900000, - "y": 1660982.24115757, - "y0": 5732.00699123528, - }, - Object { - "x": 1607437650000, - "y": 1660982.24115757, - "y0": 5732.00699123528, - }, -] -`; diff --git a/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts index 6b7848262c69f..d7cd6d5b87779 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/breakdown.spec.ts @@ -18,27 +18,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { const transactionType = 'request'; const transactionName = 'GET /api'; - registry.when('Breakdown 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}/transaction/charts/breakdown', - params: { - path: { serviceName: 'opbeans-node' }, - query: { - start, - end, - transactionType, - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }, - }); - - expect(response.status).to.be(200); - expect(response.body).to.eql({ timeseries: [] }); - }); - }); - registry.when( 'Breakdown when data is loaded', { config: 'basic', archives: [archiveName] }, diff --git a/x-pack/test/apm_api_integration/tests/transactions/error_rate.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/error_rate.spec.ts deleted file mode 100644 index 724390fdfa61f..0000000000000 --- a/x-pack/test/apm_api_integration/tests/transactions/error_rate.spec.ts +++ /dev/null @@ -1,433 +0,0 @@ -/* - * 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 { apm, timerange } from '@kbn/apm-synthtrace-client'; -import expect from '@kbn/expect'; -import { buildQueryFromFilters } from '@kbn/es-query'; -import { first, last } from 'lodash'; -import moment from 'moment'; -import { - APIClientRequestParamsOf, - APIReturnType, -} from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; -import { RecursivePartial } from '@kbn/apm-plugin/typings/common'; -import { ApmDocumentType } from '@kbn/apm-plugin/common/document_type'; -import { RollupInterval } from '@kbn/apm-plugin/common/rollup'; -import { FtrProviderContext } from '../../common/ftr_provider_context'; - -type ErrorRate = - APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate'>; - -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - const apmSynthtraceEsClient = getService('apmSynthtraceEsClient'); - - // url parameters - 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 fetchErrorCharts( - overrides?: RecursivePartial< - APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/transactions/charts/error_rate'>['params'] - > - ) { - return await apmApiClient.readUser({ - endpoint: `GET /internal/apm/services/{serviceName}/transactions/charts/error_rate`, - params: { - path: { serviceName: overrides?.path?.serviceName || 'opbeans-go' }, - query: { - start: new Date(start).toISOString(), - end: new Date(end).toISOString(), - transactionType: 'request', - environment: 'ENVIRONMENT_ALL', - kuery: '', - documentType: ApmDocumentType.TransactionMetric, - rollupInterval: RollupInterval.OneMinute, - bucketSizeInSeconds: 60, - ...overrides?.query, - }, - }, - }); - } - - registry.when('Error rate when data is not loaded', { config: 'basic', archives: [] }, () => { - it('handles the empty state', async () => { - const response = await fetchErrorCharts(); - expect(response.status).to.be(200); - - const body = response.body as ErrorRate; - expect(body).to.be.eql({ - currentPeriod: { timeseries: [], average: null }, - previousPeriod: { timeseries: [], average: null }, - }); - }); - - it('handles the empty state with comparison data', async () => { - const response = await fetchErrorCharts({ - query: { - start: moment(end).subtract(7, 'minutes').toISOString(), - offset: '7m', - }, - }); - expect(response.status).to.be(200); - - const body = response.body as ErrorRate; - expect(body).to.be.eql({ - currentPeriod: { timeseries: [], average: null }, - previousPeriod: { timeseries: [], average: null }, - }); - }); - }); - - // FLAKY: https://github.com/elastic/kibana/issues/177598 - registry.when('Error rate when data is loaded', { config: 'basic', archives: [] }, () => { - const config = { - firstTransaction: { - name: 'GET /apple 🍎 ', - successRate: 50, - failureRate: 50, - }, - secondTransaction: { - name: 'GET /pear 🍎 ', - successRate: 25, - failureRate: 75, - }, - }; - before(async () => { - const serviceGoProdInstance = apm - .service({ name: 'opbeans-go', environment: 'production', agentName: 'go' }) - .instance('instance-a'); - - const { firstTransaction, secondTransaction } = config; - - const documents = [ - timerange(start, end) - .ratePerMinute(firstTransaction.successRate) - .generator((timestamp) => - serviceGoProdInstance - .transaction({ transactionName: firstTransaction.name }) - .timestamp(timestamp) - .duration(1000) - .success() - ), - timerange(start, end) - .ratePerMinute(firstTransaction.failureRate) - .generator((timestamp) => - serviceGoProdInstance - .transaction({ transactionName: firstTransaction.name }) - .duration(1000) - .timestamp(timestamp) - .failure() - ), - timerange(start, end) - .ratePerMinute(secondTransaction.successRate) - .generator((timestamp) => - serviceGoProdInstance - .transaction({ transactionName: secondTransaction.name }) - .timestamp(timestamp) - .duration(1000) - .success() - ), - timerange(start, end) - .ratePerMinute(secondTransaction.failureRate) - .generator((timestamp) => - serviceGoProdInstance - .transaction({ transactionName: secondTransaction.name }) - .duration(1000) - .timestamp(timestamp) - .failure() - ), - ]; - await apmSynthtraceEsClient.index(documents); - }); - - after(() => apmSynthtraceEsClient.clean()); - - describe('returns the transaction error rate', () => { - let errorRateResponse: ErrorRate; - - before(async () => { - const response = await fetchErrorCharts({ - query: { transactionName: config.firstTransaction.name }, - }); - errorRateResponse = response.body; - }); - - it('returns some data', () => { - expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0); - expect(errorRateResponse.previousPeriod.average).to.be(null); - - expect(errorRateResponse.currentPeriod.timeseries).not.to.be.empty(); - expect(errorRateResponse.previousPeriod.timeseries).to.empty(); - - const nonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter( - ({ y }) => y !== null - ); - - expect(nonNullDataPoints).not.to.be.empty(); - }); - - it('has the correct start date', () => { - expect( - new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() - ).to.eql('2021-01-01T00:00:00.000Z'); - }); - - it('has the correct end date', () => { - expect( - new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() - ).to.eql('2021-01-01T00:14:00.000Z'); - }); - - it('has the correct number of buckets', () => { - expect(errorRateResponse.currentPeriod.timeseries.length).to.be.eql(15); - }); - - it('has the correct calculation for average', () => { - expect(errorRateResponse.currentPeriod.average).to.eql( - config.firstTransaction.failureRate / 100 - ); - }); - }); - - describe('returns the transaction error rate with comparison data per transaction name', () => { - let errorRateResponse: ErrorRate; - - before(async () => { - const query = { - transactionName: config.firstTransaction.name, - start: moment(end).subtract(7, 'minutes').toISOString(), - offset: '7m', - }; - - const response = await fetchErrorCharts({ query }); - - errorRateResponse = response.body; - }); - - it('returns some data', () => { - expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0); - expect(errorRateResponse.previousPeriod.average).to.be.greaterThan(0); - - expect(errorRateResponse.currentPeriod.timeseries).not.to.be.empty(); - expect(errorRateResponse.previousPeriod.timeseries).not.to.be.empty(); - - const currentPeriodNonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter( - ({ y }) => y !== null - ); - - const previousPeriodNonNullDataPoints = errorRateResponse.previousPeriod.timeseries.filter( - ({ y }) => y !== null - ); - - expect(currentPeriodNonNullDataPoints).not.to.be.empty(); - expect(previousPeriodNonNullDataPoints).not.to.be.empty(); - }); - - it('has the correct start date', () => { - expect( - new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() - ).to.eql('2021-01-01T00:07:00.000Z'); - expect( - new Date(first(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString() - ).to.eql('2021-01-01T00:07:00.000Z'); - }); - - it('has the correct end date', () => { - expect( - new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString() - ).to.eql('2021-01-01T00:14:00.000Z'); - expect( - new Date(last(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString() - ).to.eql('2021-01-01T00:14:00.000Z'); - }); - - it('has the correct number of buckets', () => { - expect(errorRateResponse.currentPeriod.timeseries.length).to.eql(8); - expect(errorRateResponse.previousPeriod.timeseries.length).to.eql(8); - }); - - it('has the correct calculation for average', () => { - expect(errorRateResponse.currentPeriod.average).to.eql( - config.firstTransaction.failureRate / 100 - ); - expect(errorRateResponse.previousPeriod.average).to.eql( - config.firstTransaction.failureRate / 100 - ); - }); - - it('matches x-axis on current period and previous period', () => { - expect(errorRateResponse.currentPeriod.timeseries.map(({ x }) => x)).to.be.eql( - errorRateResponse.previousPeriod.timeseries.map(({ x }) => x) - ); - }); - }); - - describe('returns the same error rate for tx metrics and service tx metrics ', () => { - let txMetricsErrorRateResponse: ErrorRate; - let serviceTxMetricsErrorRateResponse: ErrorRate; - - before(async () => { - const [txMetricsResponse, serviceTxMetricsResponse] = await Promise.all([ - fetchErrorCharts(), - fetchErrorCharts({ - query: { documentType: ApmDocumentType.ServiceTransactionMetric }, - }), - ]); - - txMetricsErrorRateResponse = txMetricsResponse.body; - serviceTxMetricsErrorRateResponse = serviceTxMetricsResponse.body; - }); - - describe('has the correct calculation for average', () => { - const expectedFailureRate = - (config.firstTransaction.failureRate + config.secondTransaction.failureRate) / 2 / 100; - - it('for tx metrics', () => { - expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); - }); - - it('for service tx metrics', () => { - expect(serviceTxMetricsErrorRateResponse.currentPeriod.average).to.eql( - expectedFailureRate - ); - }); - }); - }); - - describe('handles kuery', () => { - let txMetricsErrorRateResponse: ErrorRate; - - before(async () => { - const txMetricsResponse = await fetchErrorCharts({ - query: { - kuery: 'transaction.name : "GET /pear 🍎 "', - }, - }); - txMetricsErrorRateResponse = txMetricsResponse.body; - }); - - describe('has the correct calculation for average with kuery', () => { - const expectedFailureRate = config.secondTransaction.failureRate / 100; - - it('for tx metrics', () => { - expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); - }); - }); - }); - - describe('handles filters', () => { - const filters = [ - { - meta: { - disabled: false, - negate: false, - alias: null, - key: 'transaction.name', - params: ['GET /api/product/list'], - type: 'phrases', - }, - query: { - bool: { - minimum_should_match: 1, - should: { - match_phrase: { - 'transaction.name': 'GET /pear 🍎 ', - }, - }, - }, - }, - }, - ]; - const serializedFilters = JSON.stringify(buildQueryFromFilters(filters, undefined)); - let txMetricsErrorRateResponse: ErrorRate; - - before(async () => { - const txMetricsResponse = await fetchErrorCharts({ - query: { - filters: serializedFilters, - }, - }); - txMetricsErrorRateResponse = txMetricsResponse.body; - }); - - describe('has the correct calculation for average with filter', () => { - const expectedFailureRate = config.secondTransaction.failureRate / 100; - - it('for tx metrics', () => { - expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); - }); - }); - - describe('has the correct calculation for average with negate filter', () => { - const expectedFailureRate = config.secondTransaction.failureRate / 100; - - it('for tx metrics', () => { - expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); - }); - }); - }); - - describe('handles negate filters', () => { - const filters = [ - { - meta: { - disabled: false, - negate: true, - alias: null, - key: 'transaction.name', - params: ['GET /api/product/list'], - type: 'phrases', - }, - query: { - bool: { - minimum_should_match: 1, - should: { - match_phrase: { - 'transaction.name': 'GET /pear 🍎 ', - }, - }, - }, - }, - }, - ]; - const serializedFilters = JSON.stringify(buildQueryFromFilters(filters, undefined)); - let txMetricsErrorRateResponse: ErrorRate; - - before(async () => { - const txMetricsResponse = await fetchErrorCharts({ - query: { - filters: serializedFilters, - }, - }); - txMetricsErrorRateResponse = txMetricsResponse.body; - }); - - describe('has the correct calculation for average with filter', () => { - const expectedFailureRate = config.firstTransaction.failureRate / 100; - - it('for tx metrics', () => { - expect(txMetricsErrorRateResponse.currentPeriod.average).to.eql(expectedFailureRate); - }); - }); - }); - - describe('handles bad filters request', () => { - it('for tx metrics', async () => { - try { - await fetchErrorCharts({ - query: { - filters: '{}}}', - }, - }); - } catch (e) { - expect(e.res.status).to.eql(400); - } - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/tests/transactions/trace_samples.spec.ts b/x-pack/test/apm_api_integration/tests/transactions/trace_samples.spec.ts index 5edc1f5a1abc4..1aad31ecc4e55 100644 --- a/x-pack/test/apm_api_integration/tests/transactions/trace_samples.spec.ts +++ b/x-pack/test/apm_api_integration/tests/transactions/trace_samples.spec.ts @@ -16,33 +16,6 @@ export default function ApiTest({ getService }: FtrProviderContext) { const archiveName = 'apm_8.0.0'; const { start, end } = archives[archiveName]; - registry.when( - 'Transaction trace samples response structure when data is not loaded', - { config: 'basic', archives: [] }, - () => { - it('handles empty state', async () => { - const response = await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/transactions/traces/samples', - params: { - path: { serviceName: 'opbeans-java' }, - query: { - start, - end, - transactionType: 'request', - environment: 'ENVIRONMENT_ALL', - transactionName: 'APIRestController#stats', - kuery: '', - }, - }, - }); - - expect(response.status).to.be(200); - - expect(response.body.traceSamples.length).to.be(0); - }); - } - ); - registry.when( 'Transaction trace samples response structure when data is loaded', { config: 'basic', archives: [archiveName] },