Skip to content

Commit

Permalink
[8.x] [APM] Migrate /entities to deployment agnostic test (#199579) (
Browse files Browse the repository at this point in the history
…#199718)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[APM] Migrate `/entities` to deployment agnostic test
(#199579)](#199579)

<!--- Backport version: 8.9.8 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Sergi
Romeu","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-11-11T17:23:46Z","message":"[APM]
Migrate `/entities` to deployment agnostic test (#199579)\n\n##
Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/198968\r\nPart of
https://github.com/elastic/kibana/issues/193245\r\n\r\nThis PR contains
the changes to migrate `entities` test folder to\r\nDeployment-agnostic
testing strategy.\r\n\r\n### How to test\r\n\r\n-
Serverless\r\n\r\n```\r\nnode scripts/functional_tests_server --config
x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts\r\nnode
scripts/functional_test_runner --config
x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts
--grep=\"APM\"\r\n```\r\n\r\nIt's recommended to be run
against\r\n[MKI](https://github.com/crespocarlos/kibana/blob/main/x-pack/test_serverless/README.md#run-tests-on-mki)\r\n\r\n-
Stateful\r\n```\r\nnode scripts/functional_tests_server --config
x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts\r\nnode
scripts/functional_test_runner --config
x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts
--grep=\"APM\"\r\n```\r\n\r\n## Checks\r\n\r\n- [ ] (OPTIONAL, only if a
test has been unskipped) Run flaky test suite\r\n- [x] local run for
serverless\r\n- [x] local run for stateful\r\n- [x] MKI run for
serverless","sha":"c611e52309983ceaf1bd4cfafb612efcde253dc3","branchLabelMapping":{"^v9.0.0$":"main","^v8.17.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","v9.0.0","backport:prev-minor","ci:project-deploy-observability","Team:obs-ux-infra_services"],"number":199579,"url":"https://github.com/elastic/kibana/pull/199579","mergeCommit":{"message":"[APM]
Migrate `/entities` to deployment agnostic test (#199579)\n\n##
Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/198968\r\nPart of
https://github.com/elastic/kibana/issues/193245\r\n\r\nThis PR contains
the changes to migrate `entities` test folder to\r\nDeployment-agnostic
testing strategy.\r\n\r\n### How to test\r\n\r\n-
Serverless\r\n\r\n```\r\nnode scripts/functional_tests_server --config
x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts\r\nnode
scripts/functional_test_runner --config
x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts
--grep=\"APM\"\r\n```\r\n\r\nIt's recommended to be run
against\r\n[MKI](https://github.com/crespocarlos/kibana/blob/main/x-pack/test_serverless/README.md#run-tests-on-mki)\r\n\r\n-
Stateful\r\n```\r\nnode scripts/functional_tests_server --config
x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts\r\nnode
scripts/functional_test_runner --config
x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts
--grep=\"APM\"\r\n```\r\n\r\n## Checks\r\n\r\n- [ ] (OPTIONAL, only if a
test has been unskipped) Run flaky test suite\r\n- [x] local run for
serverless\r\n- [x] local run for stateful\r\n- [x] MKI run for
serverless","sha":"c611e52309983ceaf1bd4cfafb612efcde253dc3"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","labelRegex":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/199579","number":199579,"mergeCommit":{"message":"[APM]
Migrate `/entities` to deployment agnostic test (#199579)\n\n##
Summary\r\n\r\nCloses
https://github.com/elastic/kibana/issues/198968\r\nPart of
https://github.com/elastic/kibana/issues/193245\r\n\r\nThis PR contains
the changes to migrate `entities` test folder to\r\nDeployment-agnostic
testing strategy.\r\n\r\n### How to test\r\n\r\n-
Serverless\r\n\r\n```\r\nnode scripts/functional_tests_server --config
x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts\r\nnode
scripts/functional_test_runner --config
x-pack/test/api_integration/deployment_agnostic/configs/serverless/oblt.serverless.config.ts
--grep=\"APM\"\r\n```\r\n\r\nIt's recommended to be run
against\r\n[MKI](https://github.com/crespocarlos/kibana/blob/main/x-pack/test_serverless/README.md#run-tests-on-mki)\r\n\r\n-
Stateful\r\n```\r\nnode scripts/functional_tests_server --config
x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts\r\nnode
scripts/functional_test_runner --config
x-pack/test/api_integration/deployment_agnostic/configs/stateful/oblt.stateful.config.ts
--grep=\"APM\"\r\n```\r\n\r\n## Checks\r\n\r\n- [ ] (OPTIONAL, only if a
test has been unskipped) Run flaky test suite\r\n- [x] local run for
serverless\r\n- [x] local run for stateful\r\n- [x] MKI run for
serverless","sha":"c611e52309983ceaf1bd4cfafb612efcde253dc3"}}]}]
BACKPORT-->
  • Loading branch information
rmyz authored Nov 11, 2024
1 parent 48c81df commit ea033d8
Show file tree
Hide file tree
Showing 5 changed files with 220 additions and 196 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/*
* 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 { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';

export default function ({ loadTestFile }: DeploymentAgnosticFtrProviderContext) {
describe('entities', () => {
loadTestFile(require.resolve('./service_logs_error_rate_timeseries.spec.ts'));
loadTestFile(require.resolve('./service_logs_rate_timeseries.spec.ts'));
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ import { log, timerange } from '@kbn/apm-synthtrace-client';
import { first, last } from 'lodash';
import { RecursivePartial } from '@kbn/apm-plugin/typings/common';
import { APIClientRequestParamsOf } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
import { FtrProviderContext } from '../../../common/ftr_provider_context';
import { LogsSynthtraceEsClient } from '@kbn/apm-synthtrace';
import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';

export default function ApiTest({ getService }: FtrProviderContext) {
const registry = getService('registry');
const apmApiClient = getService('apmApiClient');
const logSynthtrace = getService('logSynthtraceEsClient');
export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) {
const apmApiClient = getService('apmApi');
const synthtrace = getService('synthtrace');

const serviceName = 'synth-go';
const start = new Date('2024-01-01T00:00:00.000Z').getTime();
Expand Down Expand Up @@ -45,25 +45,26 @@ export default function ApiTest({ getService }: FtrProviderContext) {
});
return response;
}
describe('logs error rate timeseries', () => {
describe('when data is not loaded', () => {
it('handles empty state', async () => {
const response = await getLogsErrorRateTimeseries();
expect(response.status).to.be(200);
expect(response.body.currentPeriod).to.empty();
});
});

registry.when(
'Logs error rate timeseries when data is not loaded',
{ config: 'basic', archives: [] },
() => {
describe('Logs error rate api', () => {
it('handles the empty state', async () => {
const response = await getLogsErrorRateTimeseries();
expect(response.status).to.be(200);
expect(response.body.currentPeriod).to.empty();
});
describe('when data loaded', () => {
let logSynthtrace: LogsSynthtraceEsClient;

before(async () => {
logSynthtrace = await synthtrace.createLogsSynthtraceEsClient();
});

after(async () => {
await logSynthtrace.clean();
});
}
);

registry.when(
'Logs error rate timeseries when data loaded',
{ config: 'basic', archives: [] },
() => {
describe('Logs without log level field', () => {
before(async () => {
return logSynthtrace.index([
Expand Down Expand Up @@ -170,6 +171,6 @@ export default function ApiTest({ getService }: FtrProviderContext) {
});
});
});
}
);
});
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
/*
* 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 { log, timerange } from '@kbn/apm-synthtrace-client';
import { RecursivePartial } from '@kbn/apm-plugin/typings/common';
import { APIClientRequestParamsOf } from '@kbn/apm-plugin/public/services/rest/create_call_apm_api';
import { first, last } from 'lodash';
import { LogsSynthtraceEsClient } from '@kbn/apm-synthtrace';
import type { DeploymentAgnosticFtrProviderContext } from '../../../../ftr_provider_context';

export default function ApiTest({ getService }: DeploymentAgnosticFtrProviderContext) {
const apmApiClient = getService('apmApi');
const synthtrace = getService('synthtrace');

const serviceName = 'synth-go';
const start = new Date('2024-01-01T00:00:00.000Z').getTime();
const end = new Date('2024-01-01T00:15:00.000Z').getTime() - 1;

const hostName = 'synth-host';

async function getLogsRateTimeseries(
overrides?: RecursivePartial<
APIClientRequestParamsOf<'GET /internal/apm/entities/services/{serviceName}/logs_rate_timeseries'>['params']
>
) {
const response = await apmApiClient.readUser({
endpoint: 'GET /internal/apm/entities/services/{serviceName}/logs_rate_timeseries',
params: {
path: {
serviceName: 'synth-go',
...overrides?.path,
},
query: {
start: new Date(start).toISOString(),
end: new Date(end).toISOString(),
environment: 'ENVIRONMENT_ALL',
kuery: '',
...overrides?.query,
},
},
});
return response;
}
describe('logs rate timeseries', () => {
describe('when data is not loaded', () => {
it('handles empty state', async () => {
const response = await getLogsRateTimeseries();
expect(response.status).to.be(200);
expect(response.body.currentPeriod).to.empty();
});
});

describe('when data loaded', () => {
let logSynthtrace: LogsSynthtraceEsClient;

before(async () => {
logSynthtrace = await synthtrace.createLogsSynthtraceEsClient();
});

after(async () => {
await logSynthtrace.clean();
});

describe('Logs without log level field', () => {
before(async () => {
return logSynthtrace.index([
timerange(start, end)
.interval('1m')
.rate(1)
.generator((timestamp) =>
log.create().message('This is a log message').timestamp(timestamp).defaults({
'log.file.path': '/my-service.log',
'service.name': serviceName,
'host.name': hostName,
})
),
]);
});
after(async () => {
await logSynthtrace.clean();
});

it('returns {} if log level is not available ', async () => {
const response = await getLogsRateTimeseries();
expect(response.status).to.be(200);
});
});

describe('Logs with log.level=error', () => {
before(async () => {
return logSynthtrace.index([
timerange(start, end)
.interval('1m')
.rate(1)
.generator((timestamp) =>
log
.create()
.message('This is a log message')
.logLevel('error')
.timestamp(timestamp)
.defaults({
'log.file.path': '/my-service.log',
'service.name': serviceName,
'host.name': hostName,
'service.environment': 'test',
})
),
timerange(start, end)
.interval('2m')
.rate(1)
.generator((timestamp) =>
log
.create()
.message('This is an error log message')
.logLevel('error')
.timestamp(timestamp)
.defaults({
'log.file.path': '/my-service.log',
'service.name': 'my-service',
'host.name': hostName,
'service.environment': 'production',
})
),
timerange(start, end)
.interval('5m')
.rate(1)
.generator((timestamp) =>
log
.create()
.message('This is an info message')
.logLevel('info')
.timestamp(timestamp)
.defaults({
'log.file.path': '/my-service.log',
'service.name': 'my-service',
'host.name': hostName,
'service.environment': 'production',
})
),
]);
});
after(async () => {
await logSynthtrace.clean();
});

it('returns log rate timeseries', async () => {
const response = await getLogsRateTimeseries();
expect(response.status).to.be(200);
expect(
response.body.currentPeriod[serviceName].every(({ y }) => y === 0.06666666666666667)
).to.be(true);
});

it('handles environment filter', async () => {
const response = await getLogsRateTimeseries({ query: { environment: 'foo' } });
expect(response.status).to.be(200);
expect(response.body.currentPeriod).to.empty();
});

describe('when my-service is selected', () => {
it('returns some data', async () => {
const response = await getLogsRateTimeseries({
path: { serviceName: 'my-service' },
});

expect(response.status).to.be(200);
expect(first(response.body.currentPeriod?.['my-service'])?.y).to.be(
0.18181818181818182
);
expect(last(response.body.currentPeriod?.['my-service'])?.y).to.be(0.09090909090909091);
});
});
});
});
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default function apmApiIntegrationTests({
loadTestFile(require.resolve('./agent_explorer'));
loadTestFile(require.resolve('./custom_dashboards'));
loadTestFile(require.resolve('./dependencies'));
loadTestFile(require.resolve('./entities'));
loadTestFile(require.resolve('./cold_start'));
});
}
Loading

0 comments on commit ea033d8

Please sign in to comment.