[APM] Adding api tests for error group (#116771)

* adding api tests for error group

* addresing pr changes
This commit is contained in:
Cauê Marcondes 2021-11-01 12:31:06 -04:00 committed by GitHub
parent 4feeeeb34f
commit f2402cef37
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 172 additions and 53 deletions

View file

@ -4,7 +4,6 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { service, timerange } from '@elastic/apm-synthtrace';
import expect from '@kbn/expect';
import { first, last, sumBy } from 'lodash';
import { isFiniteNumber } from '../../../../plugins/apm/common/utils/is_finite_number';
@ -15,6 +14,7 @@ import {
import { RecursivePartial } from '../../../../plugins/apm/typings/common';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import { registry } from '../../common/registry';
import { config, generateData } from './generate_data';
type ErrorsDistribution =
APIReturnType<'GET /internal/apm/services/{serviceName}/errors/distribution'>;
@ -65,59 +65,9 @@ export default function ApiTest({ getService }: FtrProviderContext) {
{ config: 'basic', archives: ['apm_mappings_only_8.0.0'] },
() => {
describe('errors distribution', () => {
const appleTransaction = {
name: 'GET /apple 🍎 ',
successRate: 75,
failureRate: 25,
};
const bananaTransaction = {
name: 'GET /banana 🍌',
successRate: 50,
failureRate: 50,
};
const { appleTransaction, bananaTransaction } = config;
before(async () => {
const serviceGoProdInstance = service(serviceName, 'production', 'go').instance(
'instance-a'
);
const interval = '1m';
const indices = [appleTransaction, bananaTransaction]
.map((transaction, index) => {
return [
...timerange(start, end)
.interval(interval)
.rate(transaction.successRate)
.flatMap((timestamp) =>
serviceGoProdInstance
.transaction(transaction.name)
.timestamp(timestamp)
.duration(1000)
.success()
.serialize()
),
...timerange(start, end)
.interval(interval)
.rate(transaction.failureRate)
.flatMap((timestamp) =>
serviceGoProdInstance
.transaction(transaction.name)
.errors(
serviceGoProdInstance
.error(`Error ${index}`, transaction.name)
.timestamp(timestamp)
)
.duration(1000)
.timestamp(timestamp)
.failure()
.serialize()
),
];
})
.flatMap((_) => _);
await synthtraceEsClient.index(indices);
await generateData({ serviceName, start, end, synthtraceEsClient });
});
after(() => synthtraceEsClient.clean());

View file

@ -0,0 +1,73 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { service, timerange } from '@elastic/apm-synthtrace';
import type { SynthtraceEsClient } from '../../common/synthtrace_es_client';
export const config = {
appleTransaction: {
name: 'GET /apple 🍎 ',
successRate: 75,
failureRate: 25,
},
bananaTransaction: {
name: 'GET /banana 🍌',
successRate: 50,
failureRate: 50,
},
};
export async function generateData({
synthtraceEsClient,
serviceName,
start,
end,
}: {
synthtraceEsClient: SynthtraceEsClient;
serviceName: string;
start: number;
end: number;
}) {
const serviceGoProdInstance = service(serviceName, 'production', 'go').instance('instance-a');
const interval = '1m';
const { bananaTransaction, appleTransaction } = config;
const documents = [appleTransaction, bananaTransaction]
.map((transaction, index) => {
return [
...timerange(start, end)
.interval(interval)
.rate(transaction.successRate)
.flatMap((timestamp) =>
serviceGoProdInstance
.transaction(transaction.name)
.timestamp(timestamp)
.duration(1000)
.success()
.serialize()
),
...timerange(start, end)
.interval(interval)
.rate(transaction.failureRate)
.flatMap((timestamp) =>
serviceGoProdInstance
.transaction(transaction.name)
.errors(
serviceGoProdInstance.error(`Error ${index}`, transaction.name).timestamp(timestamp)
)
.duration(1000)
.timestamp(timestamp)
.failure()
.serialize()
),
];
})
.flatMap((_) => _);
await synthtraceEsClient.index(documents);
}

View file

@ -0,0 +1,92 @@
/*
* 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 {
APIClientRequestParamsOf,
APIReturnType,
} from '../../../../plugins/apm/public/services/rest/createCallApmApi';
import { RecursivePartial } from '../../../../plugins/apm/typings/common';
import { FtrProviderContext } from '../../common/ftr_provider_context';
import { registry } from '../../common/registry';
import { config, generateData } from './generate_data';
type ErrorsDistribution =
APIReturnType<'GET /internal/apm/services/{serviceName}/errors/{groupId}'>;
export default function ApiTest({ getService }: FtrProviderContext) {
const apmApiClient = getService('apmApiClient');
const synthtraceEsClient = getService('synthtraceEsClient');
const serviceName = 'synth-go';
const start = new Date('2021-01-01T00:00:00.000Z').getTime();
const end = new Date('2021-01-01T00:15:00.000Z').getTime() - 1;
async function callApi(
overrides?: RecursivePartial<
APIClientRequestParamsOf<'GET /internal/apm/services/{serviceName}/errors/{groupId}'>['params']
>
) {
const response = await apmApiClient.readUser({
endpoint: 'GET /internal/apm/services/{serviceName}/errors/{groupId}',
params: {
path: {
serviceName,
groupId: 'foo',
...overrides?.path,
},
query: {
start: new Date(start).toISOString(),
end: new Date(end).toISOString(),
environment: 'ENVIRONMENT_ALL',
kuery: '',
...overrides?.query,
},
},
});
return response;
}
registry.when('when data is not loaded', { config: 'basic', archives: [] }, () => {
it('handles the empty state', async () => {
const response = await callApi();
expect(response.status).to.be(200);
expect(response.body.occurrencesCount).to.be(0);
});
});
registry.when(
'when data is loaded',
{ config: 'basic', archives: ['apm_mappings_only_8.0.0'] },
() => {
const { bananaTransaction } = config;
describe('error group id', () => {
before(async () => {
await generateData({ serviceName, start, end, synthtraceEsClient });
});
after(() => synthtraceEsClient.clean());
describe('return correct data', () => {
let errorsDistribution: ErrorsDistribution;
before(async () => {
const response = await callApi({
path: { groupId: '0000000000000000000000000Error 1' },
});
errorsDistribution = response.body;
});
it('displays correct number of occurrences', () => {
const numberOfBuckets = 15;
expect(errorsDistribution.occurrencesCount).to.equal(
bananaTransaction.failureRate * numberOfBuckets
);
});
});
});
}
);
}

View file

@ -241,6 +241,10 @@ export default function apmApiIntegrationTests(providerContext: FtrProviderConte
loadTestFile(require.resolve('./latency/service_apis'));
});
describe('errors/group_id', function () {
loadTestFile(require.resolve('./errors/group_id'));
});
describe('errors/distribution', function () {
loadTestFile(require.resolve('./errors/distribution'));
});