[APM] Refactoring API test to use synthtrace (#142260) (#142502)

* error rate with synthtrace

* latency with synthtrace

* adding production env test

* addressing pr comments

(cherry picked from commit d675d91c94)

Co-authored-by: Cauê Marcondes <55978943+cauemarcondes@users.noreply.github.com>
This commit is contained in:
Kibana Machine 2022-10-03 11:37:19 -06:00 committed by GitHub
parent e91a5c3684
commit 92dd90d688
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 279 additions and 720 deletions

View file

@ -1,268 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate has the correct error rate 1`] = `
Array [
Object {
"x": 1627973400000,
"y": 0,
},
Object {
"x": 1627973460000,
"y": 0,
},
Object {
"x": 1627973520000,
"y": 0.333333333333333,
},
Object {
"x": 1627973580000,
"y": 0.181818181818182,
},
Object {
"x": 1627973640000,
"y": 0,
},
Object {
"x": 1627973700000,
"y": 0,
},
Object {
"x": 1627973760000,
"y": 0.166666666666667,
},
Object {
"x": 1627973820000,
"y": 0.181818181818182,
},
Object {
"x": 1627973880000,
"y": 0,
},
Object {
"x": 1627973940000,
"y": 0,
},
Object {
"x": 1627974000000,
"y": 0.0833333333333333,
},
Object {
"x": 1627974060000,
"y": 0.0769230769230769,
},
Object {
"x": 1627974120000,
"y": 0,
},
Object {
"x": 1627974180000,
"y": 0.1,
},
Object {
"x": 1627974240000,
"y": 0.153846153846154,
},
Object {
"x": 1627974300000,
"y": 0,
},
Object {
"x": 1627974360000,
"y": null,
},
Object {
"x": 1627974420000,
"y": 0,
},
Object {
"x": 1627974480000,
"y": 0,
},
Object {
"x": 1627974540000,
"y": 0,
},
Object {
"x": 1627974600000,
"y": 0.125,
},
Object {
"x": 1627974660000,
"y": 0.6,
},
Object {
"x": 1627974720000,
"y": 0.2,
},
Object {
"x": 1627974780000,
"y": 0,
},
Object {
"x": 1627974840000,
"y": 0,
},
Object {
"x": 1627974900000,
"y": 0.0666666666666667,
},
Object {
"x": 1627974960000,
"y": 0,
},
Object {
"x": 1627975020000,
"y": 0,
},
Object {
"x": 1627975080000,
"y": 0,
},
Object {
"x": 1627975140000,
"y": 0.181818181818182,
},
Object {
"x": 1627975200000,
"y": null,
},
]
`;
exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate with comparison data has the correct error rate 1`] = `
Array [
Object {
"x": 1627974300000,
"y": 0,
},
Object {
"x": 1627974360000,
"y": null,
},
Object {
"x": 1627974420000,
"y": 0,
},
Object {
"x": 1627974480000,
"y": 0,
},
Object {
"x": 1627974540000,
"y": 0,
},
Object {
"x": 1627974600000,
"y": 0.125,
},
Object {
"x": 1627974660000,
"y": 0.6,
},
Object {
"x": 1627974720000,
"y": 0.2,
},
Object {
"x": 1627974780000,
"y": 0,
},
Object {
"x": 1627974840000,
"y": 0,
},
Object {
"x": 1627974900000,
"y": 0.0666666666666667,
},
Object {
"x": 1627974960000,
"y": 0,
},
Object {
"x": 1627975020000,
"y": 0,
},
Object {
"x": 1627975080000,
"y": 0,
},
Object {
"x": 1627975140000,
"y": 0.181818181818182,
},
Object {
"x": 1627975200000,
"y": null,
},
]
`;
exports[`APM API tests basic apm_8.0.0 Error rate when data is loaded returns the transaction error rate with comparison data has the correct error rate 2`] = `
Array [
Object {
"x": 1627974300000,
"y": 0,
},
Object {
"x": 1627974360000,
"y": 0,
},
Object {
"x": 1627974420000,
"y": 0.333333333333333,
},
Object {
"x": 1627974480000,
"y": 0.181818181818182,
},
Object {
"x": 1627974540000,
"y": 0,
},
Object {
"x": 1627974600000,
"y": 0,
},
Object {
"x": 1627974660000,
"y": 0.166666666666667,
},
Object {
"x": 1627974720000,
"y": 0.181818181818182,
},
Object {
"x": 1627974780000,
"y": 0,
},
Object {
"x": 1627974840000,
"y": 0,
},
Object {
"x": 1627974900000,
"y": 0.0833333333333333,
},
Object {
"x": 1627974960000,
"y": 0.0769230769230769,
},
Object {
"x": 1627975020000,
"y": 0,
},
Object {
"x": 1627975080000,
"y": 0.1,
},
Object {
"x": 1627975140000,
"y": 0.153846153846154,
},
Object {
"x": 1627975200000,
"y": null,
},
]
`;

View file

@ -1,131 +0,0 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`APM API tests basic apm_8.0.0 Latency with a basic license when data is loaded time comparison returns some data 1`] = `
Array [
Object {
"x": 1627974300000,
"y": 22799,
},
Object {
"x": 1627974360000,
"y": 3227391,
},
Object {
"x": 1627974420000,
"y": 15565.2222222222,
},
Object {
"x": 1627974480000,
"y": 54307.5714285714,
},
Object {
"x": 1627974540000,
"y": 16655,
},
Object {
"x": 1627974600000,
"y": 9453,
},
Object {
"x": 1627974660000,
"y": 31119,
},
Object {
"x": 1627974720000,
"y": 15282.2,
},
Object {
"x": 1627974780000,
"y": 18709,
},
Object {
"x": 1627974840000,
"y": 12095,
},
Object {
"x": 1627974900000,
"y": 16291,
},
Object {
"x": 1627974960000,
"y": 13444.3333333333,
},
Object {
"x": 1627975020000,
"y": 13241.6666666667,
},
Object {
"x": 1627975080000,
"y": 25535,
},
Object {
"x": 1627975140000,
"y": 11024.6,
},
]
`;
exports[`APM API tests basic apm_8.0.0 Latency with a basic license when data is loaded time comparison returns some data 2`] = `
Array [
Object {
"x": 1627974300000,
"y": 34866.2,
},
Object {
"x": 1627974360000,
"y": 104799,
},
Object {
"x": 1627974420000,
"y": 36247,
},
Object {
"x": 1627974480000,
"y": 22207,
},
Object {
"x": 1627974540000,
"y": 80191,
},
Object {
"x": 1627974600000,
"y": 11520.4545454545,
},
Object {
"x": 1627974660000,
"y": 47031.8888888889,
},
Object {
"x": 1627974720000,
"y": 30249.6666666667,
},
Object {
"x": 1627974780000,
"y": 14868.3333333333,
},
Object {
"x": 1627974840000,
"y": 17199,
},
Object {
"x": 1627974900000,
"y": 19837.2222222222,
},
Object {
"x": 1627974960000,
"y": 19397.6666666667,
},
Object {
"x": 1627975020000,
"y": 22473.6666666667,
},
Object {
"x": 1627975080000,
"y": 11362.2,
},
Object {
"x": 1627975140000,
"y": 26319,
},
]
`;

View file

@ -4,12 +4,15 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { apm, timerange } from '@kbn/apm-synthtrace';
import expect from '@kbn/expect';
import { first, last } from 'lodash';
import moment from 'moment';
import { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata';
import {
APIClientRequestParamsOf,
APIReturnType,
} from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
import { RecursivePartial } from '@kbn/apm-plugin/typings/common';
import { FtrProviderContext } from '../../common/ftr_provider_context';
type ErrorRate =
@ -18,48 +21,36 @@ type ErrorRate =
export default function ApiTest({ getService }: FtrProviderContext) {
const registry = getService('registry');
const apmApiClient = getService('apmApiClient');
const archiveName = 'apm_8.0.0';
const synthtraceEsClient = getService('synthtraceEsClient');
// url parameters
const { start, end } = archives_metadata[archiveName];
const transactionType = 'request';
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({
serviceName,
query,
}: {
serviceName: string;
query: {
start: string;
end: string;
transactionType: string;
environment: string;
kuery: string;
offset?: string;
};
}) {
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 },
query,
path: { serviceName: overrides?.path?.serviceName || 'opbeans-go' },
query: {
start: new Date(start).toISOString(),
end: new Date(end).toISOString(),
transactionType: 'request',
environment: 'ENVIRONMENT_ALL',
kuery: '',
...overrides?.query,
},
},
});
}
registry.when('Error rate when data is not loaded', { config: 'basic', archives: [] }, () => {
it('handles the empty state', async () => {
const response = await fetchErrorCharts({
serviceName: 'opbeans-java',
query: {
start,
end,
transactionType,
environment: 'ENVIRONMENT_ALL',
kuery: '',
},
});
const response = await fetchErrorCharts();
expect(response.status).to.be(200);
const body = response.body as ErrorRate;
@ -71,14 +62,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
it('handles the empty state with comparison data', async () => {
const response = await fetchErrorCharts({
serviceName: 'opbeans-java',
query: {
transactionType,
start: moment(end).subtract(15, 'minutes').toISOString(),
end,
offset: '15m',
environment: 'ENVIRONMENT_ALL',
kuery: '',
start: moment(end).subtract(7, 'minutes').toISOString(),
offset: '7m',
},
});
expect(response.status).to.be(200);
@ -91,149 +77,174 @@ export default function ApiTest({ getService }: FtrProviderContext) {
});
});
registry.when(
'Error rate when data is loaded',
{ config: 'basic', archives: [archiveName] },
() => {
describe('returns the transaction error rate', () => {
let errorRateResponse: ErrorRate;
registry.when('Error rate when data is loaded', { config: 'basic', archives: [] }, () => {
const config = {
firstTransaction: {
name: 'GET /apple 🍎 ',
successRate: 50,
failureRate: 50,
},
};
before(async () => {
const serviceGoProdInstance = apm
.service({ name: 'opbeans-go', environment: 'production', agentName: 'go' })
.instance('instance-a');
before(async () => {
const response = await fetchErrorCharts({
serviceName: 'opbeans-java',
query: {
start,
end,
transactionType,
environment: 'ENVIRONMENT_ALL',
kuery: '',
},
});
const { firstTransaction } = config;
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.length).to.be.greaterThan(0);
expect(errorRateResponse.previousPeriod.timeseries).to.empty();
const nonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter(
({ y }) => y !== null
);
expect(nonNullDataPoints.length).to.be.greaterThan(0);
});
it('has the correct start date', () => {
expectSnapshot(
new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString()
).toMatchInline(`"2021-08-03T06:50:00.000Z"`);
});
it('has the correct end date', () => {
expectSnapshot(
new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString()
).toMatchInline(`"2021-08-03T07:20:00.000Z"`);
});
it('has the correct number of buckets', () => {
expectSnapshot(errorRateResponse.currentPeriod.timeseries.length).toMatchInline(`31`);
});
it('has the correct calculation for average', () => {
expectSnapshot(errorRateResponse.currentPeriod.average).toMatchInline(
`0.0848214285714286`
);
});
it('has the correct error rate', () => {
expectSnapshot(errorRateResponse.currentPeriod.timeseries).toMatch();
const documents = timerange(start, end)
.ratePerMinute(firstTransaction.successRate)
.generator((timestamp) =>
serviceGoProdInstance
.transaction({ transactionName: firstTransaction.name })
.timestamp(timestamp)
.duration(1000)
.success()
)
.merge(
timerange(start, end)
.ratePerMinute(firstTransaction.failureRate)
.generator((timestamp) =>
serviceGoProdInstance
.transaction({ transactionName: firstTransaction.name })
.errors(
serviceGoProdInstance
.error({
message: 'Error 1',
type: firstTransaction.name,
groupingName: 'Error test',
})
.timestamp(timestamp)
)
.duration(1000)
.timestamp(timestamp)
.failure()
)
);
await synthtraceEsClient.index(documents);
});
after(() => synthtraceEsClient.clean());
describe('returns the transaction error rate', () => {
let errorRateResponse: ErrorRate;
before(async () => {
const response = await fetchErrorCharts({
query: { transactionName: config.firstTransaction.name },
});
errorRateResponse = response.body;
});
describe('returns the transaction error rate with comparison data', () => {
let errorRateResponse: ErrorRate;
it('returns some data', () => {
expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0);
expect(errorRateResponse.previousPeriod.average).to.be(null);
before(async () => {
const response = await fetchErrorCharts({
serviceName: 'opbeans-java',
query: {
transactionType,
start: moment(end).subtract(15, 'minutes').toISOString(),
end,
offset: '15m',
environment: 'ENVIRONMENT_ALL',
kuery: '',
},
});
expect(errorRateResponse.currentPeriod.timeseries).not.to.be.empty();
expect(errorRateResponse.previousPeriod.timeseries).to.empty();
errorRateResponse = response.body;
});
const nonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter(
({ y }) => y !== null
);
it('returns some data', () => {
expect(errorRateResponse.currentPeriod.average).to.be.greaterThan(0);
expect(errorRateResponse.previousPeriod.average).to.be.greaterThan(0);
expect(errorRateResponse.currentPeriod.timeseries.length).to.be.greaterThan(0);
expect(errorRateResponse.previousPeriod.timeseries.length).to.be.greaterThan(0);
const currentPeriodNonNullDataPoints = errorRateResponse.currentPeriod.timeseries.filter(
({ y }) => y !== null
);
const previousPeriodNonNullDataPoints =
errorRateResponse.previousPeriod.timeseries.filter(({ y }) => y !== null);
expect(currentPeriodNonNullDataPoints.length).to.be.greaterThan(0);
expect(previousPeriodNonNullDataPoints.length).to.be.greaterThan(0);
});
it('has the correct start date', () => {
expectSnapshot(
new Date(first(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString()
).toMatchInline(`"2021-08-03T07:05:00.000Z"`);
expectSnapshot(
new Date(first(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString()
).toMatchInline(`"2021-08-03T07:05:00.000Z"`);
});
it('has the correct end date', () => {
expectSnapshot(
new Date(last(errorRateResponse.currentPeriod.timeseries)?.x ?? NaN).toISOString()
).toMatchInline(`"2021-08-03T07:20:00.000Z"`);
expectSnapshot(
new Date(last(errorRateResponse.previousPeriod.timeseries)?.x ?? NaN).toISOString()
).toMatchInline(`"2021-08-03T07:20:00.000Z"`);
});
it('has the correct number of buckets', () => {
expectSnapshot(errorRateResponse.currentPeriod.timeseries.length).toMatchInline(`16`);
expectSnapshot(errorRateResponse.previousPeriod.timeseries.length).toMatchInline(`16`);
});
it('has the correct calculation for average', () => {
expectSnapshot(errorRateResponse.currentPeriod.average).toMatchInline(
`0.0792079207920792`
);
expectSnapshot(errorRateResponse.previousPeriod.average).toMatchInline(
`0.0894308943089431`
);
});
it('has the correct error rate', () => {
expectSnapshot(errorRateResponse.currentPeriod.timeseries).toMatch();
expectSnapshot(errorRateResponse.previousPeriod.timeseries).toMatch();
});
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)
);
});
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', () => {
let errorRateResponse: ErrorRate;
before(async () => {
const response = await fetchErrorCharts({
query: {
transactionName: config.firstTransaction.name,
start: moment(end).subtract(7, 'minutes').toISOString(),
offset: '7m',
},
});
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)
);
});
});
});
}

View file

@ -4,13 +4,17 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { apm, timerange } from '@kbn/apm-synthtrace';
import expect from '@kbn/expect';
import moment from 'moment';
import { APIReturnType } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
import {
APIClientRequestParamsOf,
APIReturnType,
} from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
import { LatencyAggregationType } from '@kbn/apm-plugin/common/latency_aggregation_types';
import { RecursivePartial } from '@kbn/apm-plugin/typings/common';
import { meanBy } from 'lodash';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata';
type LatencyChartReturnType =
APIReturnType<'GET /internal/apm/services/{serviceName}/transactions/charts/latency'>;
@ -18,31 +22,30 @@ type LatencyChartReturnType =
export default function ApiTest({ getService }: FtrProviderContext) {
const registry = getService('registry');
const apmApiClient = getService('apmApiClient');
const synthtraceEsClient = getService('synthtraceEsClient');
const archiveName = 'apm_8.0.0';
const serviceName = 'synth-go';
const start = new Date('2021-01-01T00:00:00.000Z').getTime();
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
const { start, end } = archives_metadata[archiveName];
async function fetchLatencyCharts({
serviceName,
query,
}: {
serviceName: string;
query: {
start: string;
end: string;
latencyAggregationType: LatencyAggregationType;
transactionType: string;
environment: string;
kuery: string;
offset?: string;
};
}) {
async function fetchLatencyCharts(
overrides?: RecursivePartial<
APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/transactions/charts/latency'>['params']
>
) {
return await apmApiClient.readUser({
endpoint: `GET /internal/apm/services/{serviceName}/transactions/charts/latency`,
params: {
path: { serviceName },
query,
path: { serviceName: overrides?.path?.serviceName || serviceName },
query: {
start: new Date(start).toISOString(),
end: new Date(end).toISOString(),
latencyAggregationType: LatencyAggregationType.avg,
transactionType: 'request',
environment: 'ENVIRONMENT_ALL',
kuery: '',
...overrides?.query,
},
},
});
}
@ -52,20 +55,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
{ config: 'basic', archives: [] },
() => {
it('handles the empty state', async () => {
const response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.avg,
transactionType: 'request',
environment: 'testing',
kuery: '',
},
});
const response = await fetchLatencyCharts();
expect(response.status).to.be(200);
const latencyChartReturn = response.body as LatencyChartReturnType;
expect(latencyChartReturn.currentPeriod.overallAvgDuration).to.be(null);
@ -77,73 +68,90 @@ export default function ApiTest({ getService }: FtrProviderContext) {
registry.when(
'Latency with a basic license when data is loaded',
{ config: 'basic', archives: [archiveName] },
{ config: 'basic', archives: [] },
() => {
const GO_PROD_RATE = 80;
const GO_DEV_RATE = 20;
const GO_PROD_DURATION = 1000;
const GO_DEV_DURATION = 500;
before(async () => {
const serviceGoProdInstance = apm
.service({ name: serviceName, environment: 'production', agentName: 'go' })
.instance('instance-a');
const serviceGoDevInstance = apm
.service({ name: serviceName, environment: 'development', agentName: 'go' })
.instance('instance-b');
await synthtraceEsClient.index([
timerange(start, end)
.ratePerMinute(GO_PROD_RATE)
.generator((timestamp) =>
serviceGoProdInstance
.transaction({ transactionName: 'GET /api/product/list' })
.duration(GO_PROD_DURATION)
.timestamp(timestamp)
),
timerange(start, end)
.ratePerMinute(GO_DEV_RATE)
.generator((timestamp) =>
serviceGoDevInstance
.transaction({ transactionName: 'GET /api/product/:id' })
.duration(GO_DEV_DURATION)
.timestamp(timestamp)
),
]);
});
after(() => synthtraceEsClient.clean());
const expectedLatencyAvgValueMs =
((GO_PROD_RATE * GO_PROD_DURATION + GO_DEV_RATE * GO_DEV_DURATION) /
(GO_PROD_RATE + GO_DEV_RATE)) *
1000;
describe('average latency type', () => {
it('returns average duration and timeseries', async () => {
const response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.avg,
transactionType: 'request',
environment: 'testing',
kuery: '',
},
});
const response = await fetchLatencyCharts();
expect(response.status).to.be(200);
const latencyChartReturn = response.body as LatencyChartReturnType;
expect(latencyChartReturn.currentPeriod.overallAvgDuration).not.to.be(null);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(31);
expect(latencyChartReturn.currentPeriod.overallAvgDuration).to.be(
expectedLatencyAvgValueMs
);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(15);
});
});
describe('95th percentile latency type', () => {
it('returns average duration and timeseries', async () => {
const response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.p95,
transactionType: 'request',
environment: 'testing',
kuery: '',
},
query: { latencyAggregationType: LatencyAggregationType.p95 },
});
expect(response.status).to.be(200);
const latencyChartReturn = response.body as LatencyChartReturnType;
expect(latencyChartReturn.currentPeriod.overallAvgDuration).not.to.be(null);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(31);
expect(latencyChartReturn.currentPeriod.overallAvgDuration).to.be(
expectedLatencyAvgValueMs
);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(15);
});
});
describe('99th percentile latency type', () => {
it('returns average duration and timeseries', async () => {
const response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.p99,
transactionType: 'request',
environment: 'testing',
kuery: '',
},
});
expect(response.status).to.be(200);
const latencyChartReturn = response.body as LatencyChartReturnType;
expect(latencyChartReturn.currentPeriod.overallAvgDuration).not.to.be(null);
expectSnapshot(latencyChartReturn.currentPeriod.overallAvgDuration).toMatchInline(
`53906.6603773585`
expect(latencyChartReturn.currentPeriod.overallAvgDuration).to.be(
expectedLatencyAvgValueMs
);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(31);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(15);
});
});
@ -152,14 +160,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
before(async () => {
response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
latencyAggregationType: LatencyAggregationType.avg,
transactionType: 'request',
start: moment(end).subtract(15, 'minutes').toISOString(),
end,
offset: '15m',
environment: 'ENVIRONMENT_ALL',
start: moment(end).subtract(7, 'minutes').toISOString(),
offset: '7m',
kuery: '',
},
});
@ -175,8 +178,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
latencyChartReturn.previousPeriod.latencyTimeseries.filter(({ y }) => y !== null);
expect(previousPeriodNonNullDataPoints.length).to.be.greaterThan(0);
expectSnapshot(currentPeriodNonNullDataPoints).toMatch();
expectSnapshot(previousPeriodNonNullDataPoints).toMatch();
expect(meanBy(currentPeriodNonNullDataPoints, 'y')).to.eql(expectedLatencyAvgValueMs);
expect(meanBy(previousPeriodNonNullDataPoints, 'y')).to.eql(expectedLatencyAvgValueMs);
});
it('matches x-axis on current period and previous period', () => {
@ -192,14 +195,8 @@ export default function ApiTest({ getService }: FtrProviderContext) {
before(async () => {
response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.avg,
transactionType: 'request',
environment: 'does-not-exist',
kuery: '',
},
});
});
@ -216,74 +213,24 @@ export default function ApiTest({ getService }: FtrProviderContext) {
expect(currentPeriodNonNullDataPoints).to.be.empty();
});
});
}
);
registry.when(
'Transaction latency with a trial license when data is loaded',
{ config: 'trial', archives: [archiveName] },
() => {
let response: Awaited<ReturnType<typeof fetchLatencyCharts>>;
describe('with production environment', () => {
let response: Awaited<ReturnType<typeof fetchLatencyCharts>>;
const transactionType = 'request';
describe('without an environment', () => {
before(async () => {
response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.avg,
transactionType,
environment: 'ENVIRONMENT_ALL',
kuery: '',
},
});
});
it('returns an ok response', () => {
expect(response.status).to.eql(200);
});
});
describe('with environment selected', () => {
before(async () => {
response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.avg,
transactionType,
environment: 'production',
kuery: '',
},
});
});
it('should have a successful response', () => {
expect(response.status).to.eql(200);
});
});
describe('with all environments selected', () => {
before(async () => {
response = await fetchLatencyCharts({
serviceName: 'opbeans-node',
query: {
start,
end,
latencyAggregationType: LatencyAggregationType.avg,
transactionType,
environment: 'ENVIRONMENT_ALL',
kuery: '',
},
});
});
it('should have a successful response', () => {
expect(response.status).to.eql(200);
it('returns average duration and timeseries', async () => {
const latencyChartReturn = response.body as LatencyChartReturnType;
expect(latencyChartReturn.currentPeriod.overallAvgDuration).to.be(
GO_PROD_DURATION * 1000
);
expect(latencyChartReturn.currentPeriod.latencyTimeseries.length).to.be.eql(15);
});
});
}