From fdad7113316b3ba9f4dfd71663a7f8b9a1295711 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Thu, 12 Dec 2024 02:59:21 +1100 Subject: [PATCH] [8.17] [ObsUX][APM] Migrate Service Overview archiver test cases to synthtrace (#201407) (#201536) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit # Backport This will backport the following commits from `main` to `8.17`: - [[ObsUX][APM] Migrate Service Overview archiver test cases to synthtrace (#201407)](https://github.com/elastic/kibana/pull/201407) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Gonçalo Rica Pais da Silva --- .../observability/apm/dependencies/index.ts | 1 - .../dependencies/service_dependencies.spec.ts | 72 --- .../instances_detailed_statistics.spec.snap | 568 +++++++++--------- .../dependencies/index.spec.ts | 523 ++++++++-------- .../apm/service_overview/generate_data.ts | 110 ++++ .../instances_detailed_statistics.spec.ts | 174 +++++- .../dependencies/index.spec.ts | 253 -------- .../service_overview/get_service_node_ids.ts | 42 -- .../instances_detailed_statistics.spec.ts | 179 ------ 9 files changed, 841 insertions(+), 1081 deletions(-) delete mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/service_dependencies.spec.ts rename x-pack/test/{apm_api_integration/tests => api_integration/deployment_agnostic/apis/observability/apm}/service_overview/__snapshots__/instances_detailed_statistics.spec.snap (71%) create mode 100644 x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/generate_data.ts delete mode 100644 x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.spec.ts delete mode 100644 x-pack/test/apm_api_integration/tests/service_overview/get_service_node_ids.ts delete mode 100644 x-pack/test/apm_api_integration/tests/service_overview/instances_detailed_statistics.spec.ts diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/index.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/index.ts index 46ad399380550..617f9bcae89b1 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/index.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/index.ts @@ -11,7 +11,6 @@ export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) describe('custom_dashboards', () => { loadTestFile(require.resolve('./dependency_metrics.spec.ts')); loadTestFile(require.resolve('./metadata.spec.ts')); - loadTestFile(require.resolve('./service_dependencies.spec.ts')); loadTestFile(require.resolve('./top_dependencies.spec.ts')); loadTestFile(require.resolve('./top_operations.spec.ts')); loadTestFile(require.resolve('./top_spans.spec.ts')); diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/service_dependencies.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/service_dependencies.spec.ts deleted file mode 100644 index 4105989e5509b..0000000000000 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/dependencies/service_dependencies.spec.ts +++ /dev/null @@ -1,72 +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 expect from '@kbn/expect'; -import { DependencyNode } from '@kbn/apm-plugin/common/connections'; -import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; -import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; -import { generateData } from './generate_data'; - -export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { - const apmApiClient = getService('apmApi'); - const synthtrace = getService('synthtrace'); - const start = new Date('2021-01-01T00:00:00.000Z').getTime(); - const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; - const dependencyName = 'elasticsearch'; - const serviceName = 'synth-go'; - - async function callApi() { - return await apmApiClient.readUser({ - endpoint: 'GET /internal/apm/services/{serviceName}/dependencies', - params: { - path: { serviceName }, - query: { - environment: 'production', - numBuckets: 20, - offset: '1d', - start: new Date(start).toISOString(), - end: new Date(end).toISOString(), - }, - }, - }); - } - - describe('Dependency for service', () => { - describe('when data is not loaded', () => { - it('handles empty state #1', async () => { - const { status, body } = await callApi(); - - expect(status).to.be(200); - expect(body.serviceDependencies).to.empty(); - }); - }); - - describe('when data is loaded', () => { - let apmSynthtraceEsClient: ApmSynthtraceEsClient; - - before(async () => { - apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); - await generateData({ apmSynthtraceEsClient, start, end }); - }); - after(() => apmSynthtraceEsClient.clean()); - - it('returns a list of dependencies for a service', async () => { - const { status, body } = await callApi(); - - expect(status).to.be(200); - expect( - body.serviceDependencies.map( - ({ location }) => (location as DependencyNode).dependencyName - ) - ).to.eql([dependencyName]); - - const currentStatsLatencyValues = - body.serviceDependencies[0].currentStats.latency.timeseries; - expect(currentStatsLatencyValues.every(({ y }) => y === 1000000)).to.be(true); - }); - }); - }); -} diff --git a/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.spec.snap b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/__snapshots__/instances_detailed_statistics.spec.snap similarity index 71% rename from x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.spec.snap rename to x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/__snapshots__/instances_detailed_statistics.spec.snap index a5444cc6a6e32..dfea3c44472a8 100644 --- a/x-pack/test/apm_api_integration/tests/service_overview/__snapshots__/instances_detailed_statistics.spec.snap +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/__snapshots__/instances_detailed_statistics.spec.snap @@ -1,69 +1,69 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`APM API tests service_overview/instances_detailed_statistics.spec.ts basic apm_8.0.0 Service overview instances detailed statistics when data is loaded fetching data with comparison returns the right data for current and previous periods 5`] = ` +exports[`Deployment-agnostic APM API integration tests APM service_overview Service Overview Instances detailed statistics when data is loaded fetching data with comparison returns the right data for current and previous periods 5`] = ` Object { "currentPeriod": Object { - "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad": Object { + "instance-a": Object { "cpuUsage": Array [ Object { "x": 1627974300000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974360000, - "y": 0.001, + "y": 0.5, }, Object { "x": 1627974420000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974480000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974540000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974600000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974660000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974720000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974780000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974840000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974900000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974960000, - "y": 0.001, + "y": 0.5, }, Object { "x": 1627975020000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627975080000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627975140000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627975200000, @@ -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.125, + "y": 0, }, Object { "x": 1627974660000, - "y": 0.6, + "y": 0, }, Object { "x": 1627974720000, - "y": 0.2, + "y": 0, }, Object { "x": 1627974780000, @@ -113,7 +113,7 @@ Object { }, Object { "x": 1627974900000, - "y": 0.0666666666666667, + "y": 0, }, Object { "x": 1627974960000, @@ -129,7 +129,7 @@ Object { }, Object { "x": 1627975140000, - "y": 0.181818181818182, + "y": 0, }, Object { "x": 1627975200000, @@ -139,63 +139,63 @@ Object { "latency": Array [ Object { "x": 1627974300000, - "y": 34887.8888888889, + "y": null, }, Object { "x": 1627974360000, - "y": null, + "y": 1000000, }, Object { "x": 1627974420000, - "y": 4983, + "y": 1000000, }, Object { "x": 1627974480000, - "y": 41285.4, + "y": 1000000, }, Object { "x": 1627974540000, - "y": 13820.3333333333, + "y": 1000000, }, Object { "x": 1627974600000, - "y": 13782, + "y": 1000000, }, Object { "x": 1627974660000, - "y": 13392.6, + "y": 1000000, }, Object { "x": 1627974720000, - "y": 6991, + "y": 1000000, }, Object { "x": 1627974780000, - "y": 6885.85714285714, + "y": 1000000, }, Object { "x": 1627974840000, - "y": 7935, + "y": 1000000, }, Object { "x": 1627974900000, - "y": 10828.3333333333, + "y": 1000000, }, Object { "x": 1627974960000, - "y": 6079, + "y": 1000000, }, Object { "x": 1627975020000, - "y": 5217, + "y": 1000000, }, Object { "x": 1627975080000, - "y": 8477.76923076923, + "y": 1000000, }, Object { "x": 1627975140000, - "y": 5937.18181818182, + "y": 1000000, }, Object { "x": 1627975200000, @@ -205,130 +205,130 @@ Object { "memoryUsage": Array [ Object { "x": 1627974300000, - "y": 0.786640167236328, + "y": 0.416666666666667, }, Object { "x": 1627974360000, - "y": 0.786666870117188, + "y": 0.416666666666667, }, Object { "x": 1627974420000, - "y": 0.786960601806641, + "y": 0.416666666666667, }, Object { "x": 1627974480000, - "y": 0.787132263183594, + "y": 0.416666666666667, }, Object { "x": 1627974540000, - "y": 0.787441253662109, + "y": 0.416666666666667, }, Object { "x": 1627974600000, - "y": 0.787555694580078, + "y": 0.416666666666667, }, Object { "x": 1627974660000, - "y": 0.788524627685547, + "y": 0.416666666666667, }, Object { "x": 1627974720000, - "y": 0.788822174072266, + "y": 0.416666666666667, }, Object { "x": 1627974780000, - "y": 0.789054870605469, + "y": 0.416666666666667, }, Object { "x": 1627974840000, - "y": 0.78936767578125, + "y": 0.416666666666667, }, Object { "x": 1627974900000, - "y": 0.789985656738281, + "y": 0.416666666666667, }, Object { "x": 1627974960000, - "y": 0.790130615234375, + "y": 0.416666666666667, }, Object { "x": 1627975020000, - "y": 0.790508270263672, + "y": 0.416666666666667, }, Object { "x": 1627975080000, - "y": 0.791069030761719, + "y": 0.416666666666667, }, Object { "x": 1627975140000, - "y": 0.791587829589844, + "y": 0.416666666666667, }, Object { "x": 1627975200000, "y": null, }, ], - "serviceNodeName": "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad", + "serviceNodeName": "instance-a", "throughput": Array [ Object { "x": 1627974300000, - "y": 9, + "y": 0, }, Object { "x": 1627974360000, - "y": 0, + "y": 20, }, Object { "x": 1627974420000, - "y": 4, + "y": 20, }, Object { "x": 1627974480000, - "y": 5, + "y": 20, }, Object { "x": 1627974540000, - "y": 6, + "y": 20, }, Object { "x": 1627974600000, - "y": 8, + "y": 20, }, Object { "x": 1627974660000, - "y": 5, + "y": 20, }, Object { "x": 1627974720000, - "y": 5, + "y": 20, }, Object { "x": 1627974780000, - "y": 7, + "y": 20, }, Object { "x": 1627974840000, - "y": 2, + "y": 20, }, Object { "x": 1627974900000, - "y": 15, + "y": 20, }, Object { "x": 1627974960000, - "y": 3, + "y": 20, }, Object { "x": 1627975020000, - "y": 8, + "y": 20, }, Object { "x": 1627975080000, - "y": 13, + "y": 20, }, Object { "x": 1627975140000, - "y": 11, + "y": 20, }, Object { "x": 1627975200000, @@ -338,77 +338,77 @@ Object { }, }, "previousPeriod": Object { - "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad": Object { + "instance-a": Object { "cpuUsage": Array [ Object { "x": 1627974300000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974360000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974420000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974480000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974540000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974600000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974660000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974720000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974780000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974840000, - "y": 0.0045, + "y": 0.5, }, Object { "x": 1627974900000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974960000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627975020000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627975080000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627975140000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627975200000, - "y": null, + "y": 0.5, }, ], "errorRate": Array [ Object { "x": 1627974300000, - "y": 0, + "y": null, }, Object { "x": 1627974360000, @@ -416,11 +416,11 @@ Object { }, Object { "x": 1627974420000, - "y": 0.333333333333333, + "y": 0, }, Object { "x": 1627974480000, - "y": 0.181818181818182, + "y": 0, }, Object { "x": 1627974540000, @@ -432,11 +432,11 @@ Object { }, Object { "x": 1627974660000, - "y": 0.166666666666667, + "y": 0, }, Object { "x": 1627974720000, - "y": 0.181818181818182, + "y": 0, }, Object { "x": 1627974780000, @@ -448,11 +448,11 @@ Object { }, Object { "x": 1627974900000, - "y": 0.0833333333333333, + "y": 0, }, Object { "x": 1627974960000, - "y": 0.0769230769230769, + "y": 0, }, Object { "x": 1627975020000, @@ -460,214 +460,214 @@ Object { }, Object { "x": 1627975080000, - "y": 0.1, + "y": 0, }, Object { "x": 1627975140000, - "y": 0.153846153846154, + "y": 0, }, Object { "x": 1627975200000, - "y": null, + "y": 0, }, ], "latency": Array [ Object { "x": 1627974300000, - "y": 11839, + "y": null, }, Object { "x": 1627974360000, - "y": 7407, + "y": 1000000, }, Object { "x": 1627974420000, - "y": 1925569.66666667, + "y": 1000000, }, Object { "x": 1627974480000, - "y": 9017.18181818182, + "y": 1000000, }, Object { "x": 1627974540000, - "y": 63575, + "y": 1000000, }, Object { "x": 1627974600000, - "y": 7577.66666666667, + "y": 1000000, }, Object { "x": 1627974660000, - "y": 6844.33333333333, + "y": 1000000, }, Object { "x": 1627974720000, - "y": 503471, + "y": 1000000, }, Object { "x": 1627974780000, - "y": 6247.8, + "y": 1000000, }, Object { "x": 1627974840000, - "y": 1137247, + "y": 1000000, }, Object { "x": 1627974900000, - "y": 27951.6666666667, + "y": 1000000, }, Object { "x": 1627974960000, - "y": 10248.8461538462, + "y": 1000000, }, Object { "x": 1627975020000, - "y": 13529, + "y": 1000000, }, Object { "x": 1627975080000, - "y": 6691247.8, + "y": 1000000, }, Object { "x": 1627975140000, - "y": 12098.6923076923, + "y": 1000000, }, Object { "x": 1627975200000, - "y": null, + "y": 1000000, }, ], "memoryUsage": Array [ Object { "x": 1627974300000, - "y": 0.780715942382813, + "y": 0.416666666666667, }, Object { "x": 1627974360000, - "y": 0.780921936035156, + "y": 0.416666666666667, }, Object { "x": 1627974420000, - "y": 0.781166076660156, + "y": 0.416666666666667, }, Object { "x": 1627974480000, - "y": 0.781524658203125, + "y": 0.416666666666667, }, Object { "x": 1627974540000, - "y": 0.781723022460938, + "y": 0.416666666666667, }, Object { "x": 1627974600000, - "y": 0.782463073730469, + "y": 0.416666666666667, }, Object { "x": 1627974660000, - "y": 0.782634735107422, + "y": 0.416666666666667, }, Object { "x": 1627974720000, - "y": 0.782939910888672, + "y": 0.416666666666667, }, Object { "x": 1627974780000, - "y": 0.783458709716797, + "y": 0.416666666666667, }, Object { "x": 1627974840000, - "y": 0.783935546875, + "y": 0.416666666666667, }, Object { "x": 1627974900000, - "y": 0.784690856933594, + "y": 0.416666666666667, }, Object { "x": 1627974960000, - "y": 0.785182952880859, + "y": 0.416666666666667, }, Object { "x": 1627975020000, - "y": 0.785446166992188, + "y": 0.416666666666667, }, Object { "x": 1627975080000, - "y": 0.786224365234375, + "y": 0.416666666666667, }, Object { "x": 1627975140000, - "y": 0.786415100097656, + "y": 0.416666666666667, }, Object { "x": 1627975200000, - "y": null, + "y": 0.416666666666667, }, ], - "serviceNodeName": "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad", + "serviceNodeName": "instance-a", "throughput": Array [ Object { "x": 1627974300000, - "y": 4, + "y": 0, }, Object { "x": 1627974360000, - "y": 2, + "y": 20, }, Object { "x": 1627974420000, - "y": 3, + "y": 20, }, Object { "x": 1627974480000, - "y": 11, + "y": 20, }, Object { "x": 1627974540000, - "y": 4, + "y": 20, }, Object { "x": 1627974600000, - "y": 6, + "y": 20, }, Object { "x": 1627974660000, - "y": 6, + "y": 20, }, Object { "x": 1627974720000, - "y": 11, + "y": 20, }, Object { "x": 1627974780000, - "y": 10, + "y": 20, }, Object { "x": 1627974840000, - "y": 10, + "y": 20, }, Object { "x": 1627974900000, - "y": 12, + "y": 20, }, Object { "x": 1627974960000, - "y": 13, + "y": 20, }, Object { "x": 1627975020000, - "y": 8, + "y": 20, }, Object { "x": 1627975080000, - "y": 10, + "y": 20, }, Object { "x": 1627975140000, - "y": 13, + "y": 20, }, Object { "x": 1627975200000, - "y": 0, + "y": 20, }, ], }, @@ -675,130 +675,130 @@ Object { } `; -exports[`APM API tests service_overview/instances_detailed_statistics.spec.ts basic apm_8.0.0 Service overview instances detailed statistics when data is loaded fetching data without comparison returns the right data 3`] = ` +exports[`Deployment-agnostic APM API integration tests APM service_overview Service Overview Instances detailed statistics when data is loaded fetching data without comparison returns the right data 3`] = ` Object { "currentPeriod": Object { - "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad": Object { + "instance-a": Object { "cpuUsage": Array [ Object { "x": 1627973400000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627973460000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627973520000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627973580000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627973640000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627973700000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627973760000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627973820000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627973880000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627973940000, - "y": 0.0045, + "y": 0.5, }, Object { "x": 1627974000000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974060000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974120000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974180000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974240000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974300000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974360000, - "y": 0.001, + "y": 0.5, }, Object { "x": 1627974420000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974480000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974540000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974600000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974660000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974720000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974780000, - "y": 0.0015, + "y": 0.5, }, Object { "x": 1627974840000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627974900000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627974960000, - "y": 0.001, + "y": 0.5, }, Object { "x": 1627975020000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627975080000, - "y": 0.002, + "y": 0.5, }, Object { "x": 1627975140000, - "y": 0.0025, + "y": 0.5, }, Object { "x": 1627975200000, @@ -808,7 +808,7 @@ Object { "errorRate": Array [ Object { "x": 1627973400000, - "y": 0, + "y": null, }, Object { "x": 1627973460000, @@ -816,11 +816,11 @@ Object { }, Object { "x": 1627973520000, - "y": 0.333333333333333, + "y": 0, }, Object { "x": 1627973580000, - "y": 0.181818181818182, + "y": 0, }, Object { "x": 1627973640000, @@ -832,11 +832,11 @@ Object { }, Object { "x": 1627973760000, - "y": 0.166666666666667, + "y": 0, }, Object { "x": 1627973820000, - "y": 0.181818181818182, + "y": 0, }, Object { "x": 1627973880000, @@ -848,11 +848,11 @@ Object { }, Object { "x": 1627974000000, - "y": 0.0833333333333333, + "y": 0, }, Object { "x": 1627974060000, - "y": 0.0769230769230769, + "y": 0, }, Object { "x": 1627974120000, @@ -860,11 +860,11 @@ Object { }, Object { "x": 1627974180000, - "y": 0.1, + "y": 0, }, Object { "x": 1627974240000, - "y": 0.153846153846154, + "y": 0, }, 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.125, + "y": 0, }, Object { "x": 1627974660000, - "y": 0.6, + "y": 0, }, Object { "x": 1627974720000, - "y": 0.2, + "y": 0, }, Object { "x": 1627974780000, @@ -908,7 +908,7 @@ Object { }, Object { "x": 1627974900000, - "y": 0.0666666666666667, + "y": 0, }, Object { "x": 1627974960000, @@ -924,7 +924,7 @@ Object { }, Object { "x": 1627975140000, - "y": 0.181818181818182, + "y": 0, }, Object { "x": 1627975200000, @@ -934,123 +934,123 @@ Object { "latency": Array [ Object { "x": 1627973400000, - "y": 11839, + "y": null, }, Object { "x": 1627973460000, - "y": 7407, + "y": 1000000, }, Object { "x": 1627973520000, - "y": 1925569.66666667, + "y": 1000000, }, Object { "x": 1627973580000, - "y": 9017.18181818182, + "y": 1000000, }, Object { "x": 1627973640000, - "y": 63575, + "y": 1000000, }, Object { "x": 1627973700000, - "y": 7577.66666666667, + "y": 1000000, }, Object { "x": 1627973760000, - "y": 6844.33333333333, + "y": 1000000, }, Object { "x": 1627973820000, - "y": 503471, + "y": 1000000, }, Object { "x": 1627973880000, - "y": 6247.8, + "y": 1000000, }, Object { "x": 1627973940000, - "y": 1137247, + "y": 1000000, }, Object { "x": 1627974000000, - "y": 27951.6666666667, + "y": 1000000, }, Object { "x": 1627974060000, - "y": 10248.8461538462, + "y": 1000000, }, Object { "x": 1627974120000, - "y": 13529, + "y": 1000000, }, Object { "x": 1627974180000, - "y": 6691247.8, + "y": 1000000, }, Object { "x": 1627974240000, - "y": 12098.6923076923, + "y": 1000000, }, Object { "x": 1627974300000, - "y": 34887.8888888889, + "y": 1000000, }, Object { "x": 1627974360000, - "y": null, + "y": 1000000, }, Object { "x": 1627974420000, - "y": 4983, + "y": 1000000, }, Object { "x": 1627974480000, - "y": 41285.4, + "y": 1000000, }, Object { "x": 1627974540000, - "y": 13820.3333333333, + "y": 1000000, }, Object { "x": 1627974600000, - "y": 13782, + "y": 1000000, }, Object { "x": 1627974660000, - "y": 13392.6, + "y": 1000000, }, Object { "x": 1627974720000, - "y": 6991, + "y": 1000000, }, Object { "x": 1627974780000, - "y": 6885.85714285714, + "y": 1000000, }, Object { "x": 1627974840000, - "y": 7935, + "y": 1000000, }, Object { "x": 1627974900000, - "y": 10828.3333333333, + "y": 1000000, }, Object { "x": 1627974960000, - "y": 6079, + "y": 1000000, }, Object { "x": 1627975020000, - "y": 5217, + "y": 1000000, }, Object { "x": 1627975080000, - "y": 8477.76923076923, + "y": 1000000, }, Object { "x": 1627975140000, - "y": 5937.18181818182, + "y": 1000000, }, Object { "x": 1627975200000, @@ -1060,250 +1060,250 @@ Object { "memoryUsage": Array [ Object { "x": 1627973400000, - "y": 0.780715942382813, + "y": 0.416666666666667, }, Object { "x": 1627973460000, - "y": 0.780921936035156, + "y": 0.416666666666667, }, Object { "x": 1627973520000, - "y": 0.781166076660156, + "y": 0.416666666666667, }, Object { "x": 1627973580000, - "y": 0.781524658203125, + "y": 0.416666666666667, }, Object { "x": 1627973640000, - "y": 0.781723022460938, + "y": 0.416666666666667, }, Object { "x": 1627973700000, - "y": 0.782463073730469, + "y": 0.416666666666667, }, Object { "x": 1627973760000, - "y": 0.782634735107422, + "y": 0.416666666666667, }, Object { "x": 1627973820000, - "y": 0.782939910888672, + "y": 0.416666666666667, }, Object { "x": 1627973880000, - "y": 0.783458709716797, + "y": 0.416666666666667, }, Object { "x": 1627973940000, - "y": 0.783935546875, + "y": 0.416666666666667, }, Object { "x": 1627974000000, - "y": 0.784690856933594, + "y": 0.416666666666667, }, Object { "x": 1627974060000, - "y": 0.785182952880859, + "y": 0.416666666666667, }, Object { "x": 1627974120000, - "y": 0.785446166992188, + "y": 0.416666666666667, }, Object { "x": 1627974180000, - "y": 0.786224365234375, + "y": 0.416666666666667, }, Object { "x": 1627974240000, - "y": 0.786415100097656, + "y": 0.416666666666667, }, Object { "x": 1627974300000, - "y": 0.786640167236328, + "y": 0.416666666666667, }, Object { "x": 1627974360000, - "y": 0.786666870117188, + "y": 0.416666666666667, }, Object { "x": 1627974420000, - "y": 0.786960601806641, + "y": 0.416666666666667, }, Object { "x": 1627974480000, - "y": 0.787132263183594, + "y": 0.416666666666667, }, Object { "x": 1627974540000, - "y": 0.787441253662109, + "y": 0.416666666666667, }, Object { "x": 1627974600000, - "y": 0.787555694580078, + "y": 0.416666666666667, }, Object { "x": 1627974660000, - "y": 0.788524627685547, + "y": 0.416666666666667, }, Object { "x": 1627974720000, - "y": 0.788822174072266, + "y": 0.416666666666667, }, Object { "x": 1627974780000, - "y": 0.789054870605469, + "y": 0.416666666666667, }, Object { "x": 1627974840000, - "y": 0.78936767578125, + "y": 0.416666666666667, }, Object { "x": 1627974900000, - "y": 0.789985656738281, + "y": 0.416666666666667, }, Object { "x": 1627974960000, - "y": 0.790130615234375, + "y": 0.416666666666667, }, Object { "x": 1627975020000, - "y": 0.790508270263672, + "y": 0.416666666666667, }, Object { "x": 1627975080000, - "y": 0.791069030761719, + "y": 0.416666666666667, }, Object { "x": 1627975140000, - "y": 0.791587829589844, + "y": 0.416666666666667, }, Object { "x": 1627975200000, "y": null, }, ], - "serviceNodeName": "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad", + "serviceNodeName": "instance-a", "throughput": Array [ Object { "x": 1627973400000, - "y": 4, + "y": 0, }, Object { "x": 1627973460000, - "y": 2, + "y": 20, }, Object { "x": 1627973520000, - "y": 3, + "y": 20, }, Object { "x": 1627973580000, - "y": 11, + "y": 20, }, Object { "x": 1627973640000, - "y": 4, + "y": 20, }, Object { "x": 1627973700000, - "y": 6, + "y": 20, }, Object { "x": 1627973760000, - "y": 6, + "y": 20, }, Object { "x": 1627973820000, - "y": 11, + "y": 20, }, Object { "x": 1627973880000, - "y": 10, + "y": 20, }, Object { "x": 1627973940000, - "y": 10, + "y": 20, }, Object { "x": 1627974000000, - "y": 12, + "y": 20, }, Object { "x": 1627974060000, - "y": 13, + "y": 20, }, Object { "x": 1627974120000, - "y": 8, + "y": 20, }, Object { "x": 1627974180000, - "y": 10, + "y": 20, }, Object { "x": 1627974240000, - "y": 13, + "y": 20, }, Object { "x": 1627974300000, - "y": 9, + "y": 20, }, Object { "x": 1627974360000, - "y": 0, + "y": 20, }, Object { "x": 1627974420000, - "y": 4, + "y": 20, }, Object { "x": 1627974480000, - "y": 5, + "y": 20, }, Object { "x": 1627974540000, - "y": 6, + "y": 20, }, Object { "x": 1627974600000, - "y": 8, + "y": 20, }, Object { "x": 1627974660000, - "y": 5, + "y": 20, }, Object { "x": 1627974720000, - "y": 5, + "y": 20, }, Object { "x": 1627974780000, - "y": 7, + "y": 20, }, Object { "x": 1627974840000, - "y": 2, + "y": 20, }, Object { "x": 1627974900000, - "y": 15, + "y": 20, }, Object { "x": 1627974960000, - "y": 3, + "y": 20, }, Object { "x": 1627975020000, - "y": 8, + "y": 20, }, Object { "x": 1627975080000, - "y": 13, + "y": 20, }, Object { "x": 1627975140000, - "y": 11, + "y": 20, }, Object { "x": 1627975200000, diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/dependencies/index.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/dependencies/index.spec.ts index cb7f81304c3b0..a579e196e7aa4 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/dependencies/index.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/dependencies/index.spec.ts @@ -4,301 +4,328 @@ * 2.0; you may not use this file except in compliance with the Elastic License * 2.0. */ - import expect from '@kbn/expect'; import { last, pick } from 'lodash'; +import { DependencyNode } from '@kbn/apm-plugin/common/connections'; import type { ValuesType } from 'utility-types'; +import type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import type { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; import { type Node, NodeType } from '@kbn/apm-plugin/common/connections'; import { ENVIRONMENT_ALL, ENVIRONMENT_NOT_DEFINED, } from '@kbn/apm-plugin/common/environment_filter_values'; -import type { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; -import { roundNumber } from '../../utils/common'; import type { DeploymentAgnosticFtrProviderContext } from '../../../../../ftr_provider_context'; +import { roundNumber } from '../../utils/common'; +import { generateDependencyData } from '../generate_data'; import { apmDependenciesMapping, createServiceDependencyDocs } from './es_utils'; export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); const es = getService('es'); - - const { start, end } = { - start: '2021-08-03T06:50:15.910Z', - end: '2021-08-03T07:20:15.910Z', - }; + const start = new Date('2021-01-01T00:00:00.000Z').getTime(); + const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1; + const dependencyName = 'elasticsearch'; + const serviceName = 'synth-go'; function getName(node: Node) { return node.type === NodeType.service ? node.serviceName : node.dependencyName; } - describe('Service Overview', () => { - describe('Dependencies', () => { - describe('when data is not loaded', () => { - it('handles the empty state', async () => { - const response = await apmApiClient.readUser({ - endpoint: `GET /internal/apm/services/{serviceName}/dependencies`, - params: { - path: { serviceName: 'opbeans-java' }, - query: { - start, - end, - numBuckets: 20, - environment: ENVIRONMENT_ALL.value, - }, - }, - }); + async function callApi() { + return await apmApiClient.readUser({ + endpoint: 'GET /internal/apm/services/{serviceName}/dependencies', + params: { + path: { serviceName }, + query: { + environment: 'production', + numBuckets: 20, + offset: '1d', + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + }, + }, + }); + } - expect(response.status).to.be(200); - expect(response.body.serviceDependencies).to.eql([]); - }); + describe('Dependency for service', () => { + describe('when data is not loaded', () => { + it('handles empty state #1', async () => { + const { status, body } = await callApi(); + + expect(status).to.be(200); + expect(body.serviceDependencies).to.be.empty(); }); + }); - describe('when specific data is loaded', () => { - let response: { - status: number; - body: APIReturnType<'GET /internal/apm/services/{serviceName}/dependencies'>; - }; + describe('when specific data is loaded', () => { + let response: { + status: number; + body: APIReturnType<'GET /internal/apm/services/{serviceName}/dependencies'>; + }; + + const indices = { + metric: 'apm-dependencies-metric', + transaction: 'apm-dependencies-transaction', + span: 'apm-dependencies-span', + }; + + const startTime = new Date(start).getTime(); + const endTime = new Date(end).getTime(); + + after(async () => { + const allIndices = Object.values(indices).join(','); + const indexExists = await es.indices.exists({ index: allIndices }); + if (indexExists) { + await es.indices.delete({ + index: allIndices, + }); + } + }); - const indices = { - metric: 'apm-dependencies-metric', - transaction: 'apm-dependencies-transaction', - span: 'apm-dependencies-span', - }; + before(async () => { + await es.indices.create({ + index: indices.metric, + body: { + mappings: apmDependenciesMapping, + }, + }); - const startTime = new Date(start).getTime(); - const endTime = new Date(end).getTime(); - - after(async () => { - const allIndices = Object.values(indices).join(','); - const indexExists = await es.indices.exists({ index: allIndices }); - if (indexExists) { - await es.indices.delete({ - index: allIndices, - }); - } + await es.indices.create({ + index: indices.transaction, + body: { + mappings: apmDependenciesMapping, + }, }); - before(async () => { - await es.indices.create({ - index: indices.metric, - body: { - mappings: apmDependenciesMapping, - }, - }); + await es.indices.create({ + index: indices.span, + body: { + mappings: apmDependenciesMapping, + }, + }); - await es.indices.create({ - index: indices.transaction, - body: { - mappings: apmDependenciesMapping, + const docs = [ + ...createServiceDependencyDocs({ + service: { + name: 'opbeans-java', + environment: 'production', }, - }); - - await es.indices.create({ - index: indices.span, - body: { - mappings: apmDependenciesMapping, + agentName: 'java', + span: { + type: 'external', + subtype: 'http', }, - }); - - const docs = [ - ...createServiceDependencyDocs({ - service: { - name: 'opbeans-java', - environment: 'production', - }, - agentName: 'java', - span: { - type: 'external', - subtype: 'http', - }, - resource: 'opbeans-node:3000', - outcome: 'success', - responseTime: { - count: 2, - sum: 10, - }, - time: startTime, - to: { - service: { - name: 'opbeans-node', - }, - agentName: 'nodejs', - }, - }), - ...createServiceDependencyDocs({ - service: { - name: 'opbeans-java', - environment: 'production', - }, - agentName: 'java', - span: { - type: 'external', - subtype: 'http', - }, - resource: 'opbeans-node:3000', - outcome: 'failure', - responseTime: { - count: 1, - sum: 10, - }, - time: startTime, - }), - ...createServiceDependencyDocs({ + resource: 'opbeans-node:3000', + outcome: 'success', + responseTime: { + count: 2, + sum: 10, + }, + time: startTime, + to: { service: { - name: 'opbeans-java', - environment: 'production', - }, - agentName: 'java', - span: { - type: 'external', - subtype: 'http', - }, - resource: 'postgres', - outcome: 'success', - responseTime: { - count: 1, - sum: 3, + name: 'opbeans-node', }, - time: startTime, - }), - ...createServiceDependencyDocs({ + agentName: 'nodejs', + }, + }), + ...createServiceDependencyDocs({ + service: { + name: 'opbeans-java', + environment: 'production', + }, + agentName: 'java', + span: { + type: 'external', + subtype: 'http', + }, + resource: 'opbeans-node:3000', + outcome: 'failure', + responseTime: { + count: 1, + sum: 10, + }, + time: startTime, + }), + ...createServiceDependencyDocs({ + service: { + name: 'opbeans-java', + environment: 'production', + }, + agentName: 'java', + span: { + type: 'external', + subtype: 'http', + }, + resource: 'postgres', + outcome: 'success', + responseTime: { + count: 1, + sum: 3, + }, + time: startTime, + }), + ...createServiceDependencyDocs({ + service: { + name: 'opbeans-java', + environment: 'production', + }, + agentName: 'java', + span: { + type: 'external', + subtype: 'http', + }, + resource: 'opbeans-node-via-proxy', + outcome: 'success', + responseTime: { + count: 1, + sum: 1, + }, + time: endTime - 1, + to: { service: { - name: 'opbeans-java', - environment: 'production', - }, - agentName: 'java', - span: { - type: 'external', - subtype: 'http', - }, - resource: 'opbeans-node-via-proxy', - outcome: 'success', - responseTime: { - count: 1, - sum: 1, + name: 'opbeans-node', }, - time: endTime - 1, - to: { - service: { - name: 'opbeans-node', - }, - agentName: 'nodejs', - }, - }), - ]; - - const bulkActions = docs.reduce( - (prev, doc) => { - return [...prev, { index: { _index: indices[doc.processor.event] } }, doc]; + agentName: 'nodejs', }, - [] as Array< - | { - index: { - _index: string; - }; - } - | ValuesType - > - ); - - await es.bulk({ - body: bulkActions, - refresh: 'wait_for', - }); + }), + ]; + + const bulkActions = docs.reduce( + (prev, doc) => { + return [...prev, { index: { _index: indices[doc.processor.event] } }, doc]; + }, + [] as Array< + | { + index: { + _index: string; + }; + } + | ValuesType + > + ); + + await es.bulk({ + body: bulkActions, + refresh: 'wait_for', + }); - response = await apmApiClient.readUser({ - endpoint: `GET /internal/apm/services/{serviceName}/dependencies`, - params: { - path: { serviceName: 'opbeans-java' }, - query: { - start, - end, - numBuckets: 20, - environment: ENVIRONMENT_ALL.value, - }, + response = await apmApiClient.readUser({ + endpoint: `GET /internal/apm/services/{serviceName}/dependencies`, + params: { + path: { serviceName: 'opbeans-java' }, + query: { + start: new Date(start).toISOString(), + end: new Date(end).toISOString(), + numBuckets: 20, + environment: ENVIRONMENT_ALL.value, }, - }); + }, }); + }); - it('returns a 200', () => { - expect(response.status).to.be(200); - }); + it('returns a 200', () => { + expect(response.status).to.be(200); + }); - it('returns two dependencies', () => { - expect(response.body.serviceDependencies.length).to.be(2); - }); + it('returns two dependencies', () => { + expect(response.body.serviceDependencies.length).to.be(2); + }); - it('returns opbeans-node as a dependency', () => { - const opbeansNode = response.body.serviceDependencies.find( - (item) => getName(item.location) === 'opbeans-node' - ); - - expect(opbeansNode !== undefined).to.be(true); - - const values = { - latency: roundNumber(opbeansNode?.currentStats.latency.value), - throughput: roundNumber(opbeansNode?.currentStats.throughput.value), - errorRate: roundNumber(opbeansNode?.currentStats.errorRate.value), - impact: opbeansNode?.currentStats.impact, - ...pick(opbeansNode?.location, 'serviceName', 'type', 'agentName', 'environment'), - }; - - const count = 4; - const sum = 21; - const errors = 1; - - expect(values).to.eql({ - agentName: 'nodejs', - environment: ENVIRONMENT_NOT_DEFINED.value, - serviceName: 'opbeans-node', - type: 'service', - errorRate: roundNumber(errors / count), - latency: roundNumber(sum / count), - throughput: roundNumber(count / ((endTime - startTime) / 1000 / 60)), - impact: 100, - }); + it('returns opbeans-node as a dependency', () => { + const opbeansNode = response.body.serviceDependencies.find( + (item) => getName(item.location) === 'opbeans-node' + ); - const firstValue = roundNumber(opbeansNode?.currentStats.latency.timeseries[0].y); - const lastValue = roundNumber(last(opbeansNode?.currentStats.latency.timeseries)?.y); + expect(opbeansNode !== undefined).to.be(true); - expect(firstValue).to.be(roundNumber(20 / 3)); - expect(lastValue).to.be(1); + const values = { + latency: roundNumber(opbeansNode?.currentStats.latency.value), + throughput: roundNumber(opbeansNode?.currentStats.throughput.value), + errorRate: roundNumber(opbeansNode?.currentStats.errorRate.value), + impact: opbeansNode?.currentStats.impact, + ...pick(opbeansNode?.location, 'serviceName', 'type', 'agentName', 'environment'), + }; + + const count = 4; + const sum = 21; + const errors = 1; + + expect(values).to.eql({ + agentName: 'nodejs', + environment: ENVIRONMENT_NOT_DEFINED.value, + serviceName: 'opbeans-node', + type: 'service', + errorRate: roundNumber(errors / count), + latency: roundNumber(sum / count), + throughput: roundNumber(count / ((endTime - startTime) / 1000 / 60)), + impact: 100, }); - it('returns postgres as an external dependency', () => { - const postgres = response.body.serviceDependencies.find( - (item) => getName(item.location) === 'postgres' - ); - - expect(postgres !== undefined).to.be(true); - - const values = { - latency: roundNumber(postgres?.currentStats.latency.value), - throughput: roundNumber(postgres?.currentStats.throughput.value), - errorRate: roundNumber(postgres?.currentStats.errorRate.value), - impact: postgres?.currentStats.impact, - ...pick(postgres?.location, 'spanType', 'spanSubtype', 'dependencyName', 'type'), - }; - - const count = 1; - const sum = 3; - const errors = 0; - - expect(values).to.eql({ - spanType: 'external', - spanSubtype: 'http', - dependencyName: 'postgres', - type: 'dependency', - errorRate: roundNumber(errors / count), - latency: roundNumber(sum / count), - throughput: roundNumber(count / ((endTime - startTime) / 1000 / 60)), - impact: 0, - }); + const firstValue = roundNumber(opbeansNode?.currentStats.latency.timeseries[0].y); + const lastValue = roundNumber(last(opbeansNode?.currentStats.latency.timeseries)?.y); + + expect(firstValue).to.be(roundNumber(20 / 3)); + expect(lastValue).to.be(1); + }); + + it('returns postgres as an external dependency', () => { + const postgres = response.body.serviceDependencies.find( + (item) => getName(item.location) === 'postgres' + ); + + expect(postgres !== undefined).to.be(true); + + const values = { + latency: roundNumber(postgres?.currentStats.latency.value), + throughput: roundNumber(postgres?.currentStats.throughput.value), + errorRate: roundNumber(postgres?.currentStats.errorRate.value), + impact: postgres?.currentStats.impact, + ...pick(postgres?.location, 'spanType', 'spanSubtype', 'dependencyName', 'type'), + }; + + const count = 1; + const sum = 3; + const errors = 0; + + expect(values).to.eql({ + spanType: 'external', + spanSubtype: 'http', + dependencyName: 'postgres', + type: 'dependency', + errorRate: roundNumber(errors / count), + latency: roundNumber(sum / count), + throughput: roundNumber(count / ((endTime - startTime) / 1000 / 60)), + impact: 0, }); }); + }); - // UNSUPPORTED TEST CASES - when data is loaded - // TODO: These tests should be migrated to use synthtrace: https://github.com/elastic/kibana/issues/200743 + describe('when data is loaded', () => { + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); + await generateDependencyData({ apmSynthtraceEsClient, start, end }); + }); + after(() => apmSynthtraceEsClient.clean()); + + it('returns a list of dependencies for a service', async () => { + const { status, body } = await callApi(); + + expect(status).to.be(200); + expect( + body.serviceDependencies.map( + ({ location }) => (location as DependencyNode).dependencyName + ) + ).to.eql([dependencyName]); + + const currentStatsLatencyValues = + body.serviceDependencies[0].currentStats.latency.timeseries; + expect(currentStatsLatencyValues.every(({ y }) => y === 1000000)).to.be(true); + }); }); }); } diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/generate_data.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/generate_data.ts new file mode 100644 index 0000000000000..150a3ff00fde3 --- /dev/null +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/generate_data.ts @@ -0,0 +1,110 @@ +/* + * 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 type { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; + +export const dataConfig = { + rate: 20, + transaction: { + name: 'GET /api/product/list', + duration: 1000, + }, + span: { + name: 'GET apm-*/_search', + type: 'db', + subType: 'elasticsearch', + destination: 'elasticsearch', + }, +} as const; + +export async function generateServiceData({ + apmSynthtraceEsClient, + start, + end, + name, + environment, + agentName, +}: { + apmSynthtraceEsClient: ApmSynthtraceEsClient; + start: number; + end: number; + name: string; + environment: string; + agentName: string; +}) { + const instance = apm.service({ name, environment, agentName }).instance('instance-a'); + const { rate, transaction, span } = dataConfig; + + await apmSynthtraceEsClient.index([ + timerange(start, end) + .interval('1m') + .rate(rate) + .generator((timestamp) => + instance + .transaction({ transactionName: transaction.name }) + .timestamp(timestamp) + .duration(transaction.duration) + .success() + .children( + instance + .span({ spanName: span.name, spanType: span.type, spanSubtype: span.subType }) + .duration(transaction.duration) + .success() + .destination(span.destination) + .timestamp(timestamp) + ) + ), + timerange(start, end) + .interval('1m') + .rate(rate) + .generator((timestamp) => + instance + .appMetrics({ + 'system.process.cpu.total.norm.pct': 0.5, + 'system.memory.total': 120000, + 'system.process.cgroup.memory.mem.usage.bytes': 50000, + }) + .timestamp(timestamp) + ), + ]); +} + +export async function generateDependencyData({ + apmSynthtraceEsClient, + start, + end, +}: { + apmSynthtraceEsClient: ApmSynthtraceEsClient; + start: number; + end: number; +}) { + const instance = apm + .service({ name: 'synth-go', environment: 'production', agentName: 'go' }) + .instance('instance-a'); + const { rate, transaction, span } = dataConfig; + + await apmSynthtraceEsClient.index( + timerange(start, end) + .interval('1m') + .rate(rate) + .generator((timestamp) => + instance + .transaction({ transactionName: transaction.name }) + .timestamp(timestamp) + .duration(transaction.duration) + .success() + .children( + instance + .span({ spanName: span.name, spanType: span.type, spanSubtype: span.subType }) + .duration(transaction.duration) + .success() + .destination(span.destination) + .timestamp(timestamp) + ) + ) + ); +} diff --git a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/instances_detailed_statistics.spec.ts b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/instances_detailed_statistics.spec.ts index b2596ae43c956..7fd39b650b716 100644 --- a/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/instances_detailed_statistics.spec.ts +++ b/x-pack/test/api_integration/deployment_agnostic/apis/observability/apm/service_overview/instances_detailed_statistics.spec.ts @@ -6,12 +6,19 @@ */ import expect from '@kbn/expect'; +import moment from 'moment'; +import type { Coordinate } from '@kbn/apm-plugin/typings/timeseries'; import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregation_types'; +import { ApmSynthtraceEsClient } from '@kbn/apm-synthtrace'; +import type { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; +import { isFiniteNumber } from '@kbn/apm-plugin/common/utils/is_finite_number'; import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context'; import { getServiceNodeIds } from './get_service_node_ids'; +import { generateServiceData } from './generate_data'; export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) { const apmApiClient = getService('apmApi'); + const synthtrace = getService('synthtrace'); const serviceName = 'opbeans-java'; @@ -20,6 +27,11 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon end: '2021-08-03T07:20:15.910Z', }; + interface Response { + status: number; + body: APIReturnType<'GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics'>; + } + describe('Service Overview', () => { describe('Instances detailed statistics', () => { describe('when data is not loaded', () => { @@ -49,8 +61,166 @@ export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderCon }); }); - // UNSUPPORTED TEST CASES - when data is loaded - // TODO: These tests should be migrated to use synthtrace: https://github.com/elastic/kibana/issues/200743 + describe('when data is loaded', () => { + let apmSynthtraceEsClient: ApmSynthtraceEsClient; + + before(async () => { + apmSynthtraceEsClient = await synthtrace.createApmSynthtraceEsClient(); + await generateServiceData({ + apmSynthtraceEsClient, + start: new Date(start).getTime(), + end: new Date(end).getTime(), + name: serviceName, + environment: 'ENVIRONMENT_ALL', + agentName: 'java', + }); + }); + + after(() => apmSynthtraceEsClient.clean()); + + describe('fetching data without comparison', () => { + let response: Response; + let serviceNodeIds: string[]; + + beforeEach(async () => { + serviceNodeIds = await getServiceNodeIds({ + apmApiClient, + start, + end, + }); + + response = await apmApiClient.readUser({ + endpoint: + 'GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics', + params: { + path: { serviceName }, + query: { + latencyAggregationType: LatencyAggregationType.avg, + start, + end, + numBuckets: 20, + transactionType: 'request', + serviceNodeIds: JSON.stringify(serviceNodeIds), + environment: 'ENVIRONMENT_ALL', + kuery: '', + }, + }, + }); + }); + + it('returns a service node item', () => { + expect(Object.values(response.body.currentPeriod).length).to.be.greaterThan(0); + expect(Object.values(response.body.previousPeriod)).to.eql(0); + }); + + it('returns statistics for each service node', () => { + const item = response.body.currentPeriod[serviceNodeIds[0]]; + + expect(item?.cpuUsage?.some((point) => isFiniteNumber(point.y))).to.be(true); + expect(item?.memoryUsage?.some((point) => isFiniteNumber(point.y))).to.be(true); + expect(item?.errorRate?.some((point) => isFiniteNumber(point.y))).to.be(true); + expect(item?.throughput?.some((point) => isFiniteNumber(point.y))).to.be(true); + expect(item?.latency?.some((point) => isFiniteNumber(point.y))).to.be(true); + }); + + it('returns the right data', () => { + expectSnapshot(Object.values(response.body.currentPeriod).length).toMatchInline(`1`); + + expectSnapshot(Object.keys(response.body.currentPeriod)).toMatchInline(` + Array [ + "instance-a", + ] + `); + + expectSnapshot(response.body).toMatch(); + }); + }); + + describe('fetching data with comparison', () => { + let response: Response; + let serviceNodeIds: string[]; + + beforeEach(async () => { + serviceNodeIds = await getServiceNodeIds({ + apmApiClient, + start, + end, + }); + response = await apmApiClient.readUser({ + endpoint: + 'GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics', + params: { + path: { serviceName }, + query: { + latencyAggregationType: LatencyAggregationType.avg, + numBuckets: 20, + transactionType: 'request', + serviceNodeIds: JSON.stringify(serviceNodeIds), + start: moment(end).subtract(15, 'minutes').toISOString(), + end, + offset: '15m', + environment: 'ENVIRONMENT_ALL', + kuery: '', + }, + }, + }); + }); + + it('returns a service node item for current and previous periods', () => { + expect(Object.values(response.body.currentPeriod).length).to.be.greaterThan(0); + expect(Object.values(response.body.previousPeriod).length).to.be.greaterThan(0); + }); + + it('returns statistics for current and previous periods', () => { + const currentPeriodItem = response.body.currentPeriod[serviceNodeIds[0]]; + + function hasValidYCoordinate(point: Coordinate) { + return isFiniteNumber(point.y); + } + + expect(currentPeriodItem?.cpuUsage?.some(hasValidYCoordinate)).to.be(true); + expect(currentPeriodItem?.memoryUsage?.some(hasValidYCoordinate)).to.be(true); + expect(currentPeriodItem?.errorRate?.some(hasValidYCoordinate)).to.be(true); + expect(currentPeriodItem?.throughput?.some(hasValidYCoordinate)).to.be(true); + expect(currentPeriodItem?.latency?.some(hasValidYCoordinate)).to.be(true); + + const previousPeriodItem = response.body.previousPeriod[serviceNodeIds[0]]; + + expect(previousPeriodItem?.cpuUsage?.some(hasValidYCoordinate)).to.be(true); + expect(previousPeriodItem?.memoryUsage?.some(hasValidYCoordinate)).to.be(true); + expect(previousPeriodItem?.errorRate?.some(hasValidYCoordinate)).to.be(true); + expect(previousPeriodItem?.throughput?.some(hasValidYCoordinate)).to.be(true); + expect(previousPeriodItem?.latency?.some(hasValidYCoordinate)).to.be(true); + }); + + it('returns the right data for current and previous periods', () => { + expectSnapshot(Object.values(response.body.currentPeriod).length).toMatchInline(`1`); + expectSnapshot(Object.values(response.body.previousPeriod).length).toMatchInline(`1`); + + expectSnapshot(Object.keys(response.body.currentPeriod)).toMatchInline(` + Array [ + "instance-a", + ] + `); + expectSnapshot(Object.keys(response.body.previousPeriod)).toMatchInline(` + Array [ + "instance-a", + ] + `); + + expectSnapshot(response.body).toMatch(); + }); + + it('matches x-axis on current period and previous period', () => { + const currentLatencyItems = response.body.currentPeriod[serviceNodeIds[0]]?.latency; + const previousLatencyItems = response.body.previousPeriod[serviceNodeIds[0]]?.latency; + + expect(currentLatencyItems?.map(({ x }) => x)).to.be.eql( + previousLatencyItems?.map(({ x }) => x) + ); + }); + }); + }); }); }); } diff --git a/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.spec.ts b/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.spec.ts deleted file mode 100644 index fd06ee9f95266..0000000000000 --- a/x-pack/test/apm_api_integration/tests/service_overview/dependencies/index.spec.ts +++ /dev/null @@ -1,253 +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 expect from '@kbn/expect'; -import { omit, sortBy } from 'lodash'; -import { type Node, NodeType } from '@kbn/apm-plugin/common/connections'; -import { ENVIRONMENT_ALL } from '@kbn/apm-plugin/common/environment_filter_values'; -import type { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; -import archives from '../../../common/fixtures/es_archiver/archives_metadata'; -import type { FtrProviderContext } from '../../../common/ftr_provider_context'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - - const archiveName = 'apm_8.0.0'; - const { start, end } = archives[archiveName]; - - function getName(node: Node) { - return node.type === NodeType.service ? node.serviceName : node.dependencyName; - } - - registry.when( - 'Service overview dependencies when data is loaded', - { config: 'basic', archives: [archiveName] }, - () => { - let response: { - status: number; - body: APIReturnType<'GET /internal/apm/services/{serviceName}/dependencies'>; - }; - - before(async () => { - response = await apmApiClient.readUser({ - endpoint: `GET /internal/apm/services/{serviceName}/dependencies`, - params: { - path: { serviceName: 'opbeans-python' }, - query: { - start, - end, - numBuckets: 20, - environment: ENVIRONMENT_ALL.value, - }, - }, - }); - }); - - it('returns a successful response', () => { - expect(response.status).to.be(200); - }); - - it('returns at least one item', () => { - expect(response.body.serviceDependencies.length).to.be.greaterThan(0); - - expectSnapshot(response.body.serviceDependencies.length).toMatchInline(`4`); - - const { currentStats, ...firstItem } = sortBy( - response.body.serviceDependencies, - 'currentStats.impact' - ).reverse()[0]; - - expectSnapshot(firstItem.location).toMatchInline(` - Object { - "agentName": "dotnet", - "dependencyName": "opbeans:3000", - "environment": "production", - "id": "5948c153c2d8989f92a9c75ef45bb845f53e200d", - "serviceName": "opbeans-dotnet", - "type": "service", - } - `); - - expectSnapshot( - omit(currentStats, [ - 'errorRate.timeseries', - 'throughput.timeseries', - 'latency.timeseries', - 'totalTime.timeseries', - ]) - ).toMatchInline(` - Object { - "errorRate": Object { - "value": 0.163636363636364, - }, - "impact": 100, - "latency": Object { - "value": 1117085.74545455, - }, - "throughput": Object { - "value": 1.83333333333333, - }, - "totalTime": Object { - "value": 61439716, - }, - } - `); - }); - - it('returns the right names', () => { - const names = response.body.serviceDependencies.map((item) => getName(item.location)); - expectSnapshot(names.sort()).toMatchInline(` - Array [ - "elasticsearch", - "opbeans-dotnet", - "postgresql", - "redis", - ] - `); - }); - - it('returns the right service names', () => { - const serviceNames = response.body.serviceDependencies - .map((item) => - item.location.type === NodeType.service ? getName(item.location) : undefined - ) - .filter(Boolean); - - expectSnapshot(serviceNames.sort()).toMatchInline(` - Array [ - "opbeans-dotnet", - ] - `); - }); - - it('returns the right latency values', () => { - const latencyValues = sortBy( - response.body.serviceDependencies.map((item) => ({ - name: getName(item.location), - latency: item.currentStats.latency.value, - })), - 'name' - ); - - expectSnapshot(latencyValues).toMatchInline(` - Array [ - Object { - "latency": 9496.32291666667, - "name": "elasticsearch", - }, - Object { - "latency": 1117085.74545455, - "name": "opbeans-dotnet", - }, - Object { - "latency": 27826.9968314322, - "name": "postgresql", - }, - Object { - "latency": 1468.27242524917, - "name": "redis", - }, - ] - `); - }); - - it('returns the right throughput values', () => { - const throughputValues = sortBy( - response.body.serviceDependencies.map((item) => ({ - name: getName(item.location), - throughput: item.currentStats.throughput.value, - })), - 'name' - ); - - expectSnapshot(throughputValues).toMatchInline(` - Array [ - Object { - "name": "elasticsearch", - "throughput": 3.2, - }, - Object { - "name": "opbeans-dotnet", - "throughput": 1.83333333333333, - }, - Object { - "name": "postgresql", - "throughput": 52.6, - }, - Object { - "name": "redis", - "throughput": 40.1333333333333, - }, - ] - `); - }); - - it('returns the right impact values', () => { - const impactValues = sortBy( - response.body.serviceDependencies.map((item) => ({ - name: getName(item.location), - impact: item.currentStats.impact, - })), - 'name' - ); - - expectSnapshot(impactValues).toMatchInline(` - Array [ - Object { - "impact": 0, - "name": "elasticsearch", - }, - Object { - "impact": 100, - "name": "opbeans-dotnet", - }, - Object { - "impact": 71.0403531954737, - "name": "postgresql", - }, - Object { - "impact": 1.41447268043525, - "name": "redis", - }, - ] - `); - }); - - it('returns the right totalTime values', () => { - const totalTimeValues = sortBy( - response.body.serviceDependencies.map((item) => ({ - name: getName(item.location), - totalTime: item.currentStats.totalTime.value, - })), - 'name' - ); - - expectSnapshot(totalTimeValues).toMatchInline(` - Array [ - Object { - "name": "elasticsearch", - "totalTime": 911647, - }, - Object { - "name": "opbeans-dotnet", - "totalTime": 61439716, - }, - Object { - "name": "postgresql", - "totalTime": 43911001, - }, - Object { - "name": "redis", - "totalTime": 1767800, - }, - ] - `); - }); - } - ); -} diff --git a/x-pack/test/apm_api_integration/tests/service_overview/get_service_node_ids.ts b/x-pack/test/apm_api_integration/tests/service_overview/get_service_node_ids.ts deleted file mode 100644 index 751f772fb7507..0000000000000 --- a/x-pack/test/apm_api_integration/tests/service_overview/get_service_node_ids.ts +++ /dev/null @@ -1,42 +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 { take } from 'lodash'; -import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregation_types'; -import type { ApmServices } from '../../common/config'; - -export async function getServiceNodeIds({ - apmApiClient, - start, - end, - serviceName = 'opbeans-java', - count = 1, -}: { - apmApiClient: Awaited>; - start: string; - end: string; - serviceName?: string; - count?: number; -}) { - const { body } = await apmApiClient.readUser({ - endpoint: `GET /internal/apm/services/{serviceName}/service_overview_instances/main_statistics`, - params: { - path: { serviceName }, - query: { - latencyAggregationType: LatencyAggregationType.avg, - start, - end, - transactionType: 'request', - environment: 'ENVIRONMENT_ALL', - kuery: '', - sortField: 'throughput', - sortDirection: 'desc', - }, - }, - }); - - return take(body.currentPeriod.map((item) => item.serviceNodeName).sort(), count); -} diff --git a/x-pack/test/apm_api_integration/tests/service_overview/instances_detailed_statistics.spec.ts b/x-pack/test/apm_api_integration/tests/service_overview/instances_detailed_statistics.spec.ts deleted file mode 100644 index af28697a254c2..0000000000000 --- a/x-pack/test/apm_api_integration/tests/service_overview/instances_detailed_statistics.spec.ts +++ /dev/null @@ -1,179 +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 expect from '@kbn/expect'; -import moment from 'moment'; -import type { Coordinate } from '@kbn/apm-plugin/typings/timeseries'; -import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregation_types'; -import { isFiniteNumber } from '@kbn/apm-plugin/common/utils/is_finite_number'; -import type { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api'; -import type { FtrProviderContext } from '../../common/ftr_provider_context'; -import archives from '../../common/fixtures/es_archiver/archives_metadata'; -import { getServiceNodeIds } from './get_service_node_ids'; - -export default function ApiTest({ getService }: FtrProviderContext) { - const registry = getService('registry'); - const apmApiClient = getService('apmApiClient'); - - const serviceName = 'opbeans-java'; - const archiveName = 'apm_8.0.0'; - const { start, end } = archives[archiveName]; - - interface Response { - status: number; - body: APIReturnType<'GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics'>; - } - - registry.when( - 'Service overview instances detailed statistics when data is loaded', - { config: 'basic', archives: [archiveName] }, - () => { - describe('fetching data without comparison', () => { - let response: Response; - let serviceNodeIds: string[]; - - beforeEach(async () => { - serviceNodeIds = await getServiceNodeIds({ - apmApiClient, - start, - end, - }); - - response = await apmApiClient.readUser({ - endpoint: - 'GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics', - params: { - path: { serviceName }, - query: { - latencyAggregationType: LatencyAggregationType.avg, - start, - end, - numBuckets: 20, - transactionType: 'request', - serviceNodeIds: JSON.stringify(serviceNodeIds), - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }, - }); - }); - - it('returns a service node item', () => { - expect(Object.values(response.body.currentPeriod).length).to.be.greaterThan(0); - expect(Object.values(response.body.previousPeriod)).to.eql(0); - }); - - it('returns statistics for each service node', async () => { - const item = response.body.currentPeriod[serviceNodeIds[0]]; - - expect(item?.cpuUsage?.some((point) => isFiniteNumber(point.y))).to.be(true); - expect(item?.memoryUsage?.some((point) => isFiniteNumber(point.y))).to.be(true); - expect(item?.errorRate?.some((point) => isFiniteNumber(point.y))).to.be(true); - expect(item?.throughput?.some((point) => isFiniteNumber(point.y))).to.be(true); - expect(item?.latency?.some((point) => isFiniteNumber(point.y))).to.be(true); - }); - - it('returns the right data', () => { - expectSnapshot(Object.values(response.body.currentPeriod).length).toMatchInline(`1`); - - expectSnapshot(Object.keys(response.body.currentPeriod)).toMatchInline(` - Array [ - "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad", - ] - `); - - expectSnapshot(response.body).toMatch(); - }); - }); - - describe('fetching data with comparison', () => { - let response: Response; - let serviceNodeIds: string[]; - - beforeEach(async () => { - serviceNodeIds = await getServiceNodeIds({ - apmApiClient, - start, - end, - }); - response = await apmApiClient.readUser({ - endpoint: - 'GET /internal/apm/services/{serviceName}/service_overview_instances/detailed_statistics', - params: { - path: { serviceName }, - query: { - latencyAggregationType: LatencyAggregationType.avg, - numBuckets: 20, - transactionType: 'request', - serviceNodeIds: JSON.stringify(serviceNodeIds), - start: moment(end).subtract(15, 'minutes').toISOString(), - end, - offset: '15m', - environment: 'ENVIRONMENT_ALL', - kuery: '', - }, - }, - }); - }); - - it('returns a service node item for current and previous periods', () => { - expect(Object.values(response.body.currentPeriod).length).to.be.greaterThan(0); - expect(Object.values(response.body.previousPeriod).length).to.be.greaterThan(0); - }); - - it('returns statistics for current and previous periods', () => { - const currentPeriodItem = response.body.currentPeriod[serviceNodeIds[0]]; - - function hasValidYCoordinate(point: Coordinate) { - return isFiniteNumber(point.y); - } - - expect(currentPeriodItem?.cpuUsage?.some(hasValidYCoordinate)).to.be(true); - expect(currentPeriodItem?.memoryUsage?.some(hasValidYCoordinate)).to.be(true); - expect(currentPeriodItem?.errorRate?.some(hasValidYCoordinate)).to.be(true); - expect(currentPeriodItem?.throughput?.some(hasValidYCoordinate)).to.be(true); - expect(currentPeriodItem?.latency?.some(hasValidYCoordinate)).to.be(true); - - const previousPeriodItem = response.body.previousPeriod[serviceNodeIds[0]]; - - expect(previousPeriodItem?.cpuUsage?.some(hasValidYCoordinate)).to.be(true); - expect(previousPeriodItem?.memoryUsage?.some(hasValidYCoordinate)).to.be(true); - expect(previousPeriodItem?.errorRate?.some(hasValidYCoordinate)).to.be(true); - expect(previousPeriodItem?.throughput?.some(hasValidYCoordinate)).to.be(true); - expect(previousPeriodItem?.latency?.some(hasValidYCoordinate)).to.be(true); - }); - - it('returns the right data for current and previous periods', () => { - expectSnapshot(Object.values(response.body.currentPeriod).length).toMatchInline(`1`); - expectSnapshot(Object.values(response.body.previousPeriod).length).toMatchInline(`1`); - - expectSnapshot(Object.keys(response.body.currentPeriod)).toMatchInline(` - Array [ - "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad", - ] - `); - expectSnapshot(Object.keys(response.body.previousPeriod)).toMatchInline(` - Array [ - "31651f3c624b81c55dd4633df0b5b9f9ab06b151121b0404ae796632cd1f87ad", - ] - `); - - expectSnapshot(response.body).toMatch(); - }); - - it('matches x-axis on current period and previous period', () => { - const currentLatencyItems = response.body.currentPeriod[serviceNodeIds[0]]?.latency; - const previousLatencyItems = response.body.previousPeriod[serviceNodeIds[0]]?.latency; - - expect(currentLatencyItems?.map(({ x }) => x)).to.be.eql( - previousLatencyItems?.map(({ x }) => x) - ); - }); - }); - } - ); -}