Skip to content

Commit

Permalink
Fix service map for All environment single service (#93517) (#93534)
Browse files Browse the repository at this point in the history
Before we removed environment from the UI filters (#89647), the environment query parameter would be undefined if "All" was selected. Now we send ENVIRONMENT_ALL in as the query parameter.

Changes in https://github.com/elastic/kibana/blob/master/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts made it so no connections would be returned if ENVIRONMENT_ALL was selected, rather than all connections. Since no connections were being returned, no elements except the selected service would be returned in the API response.

This changes it so if ENVIRONMENT_ALL is selected, the connection will always be returned, just like what used to be the case when environment was undefined.

Add an API test for this case.

Fixes #93385.

Co-authored-by: Nathan L Smith <[email protected]>
  • Loading branch information
kibanamachine and smith authored Mar 4, 2021
1 parent faadbce commit da2a7fc
Show file tree
Hide file tree
Showing 2 changed files with 105 additions and 89 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,8 @@ export function getConnections({
if (!paths) {
return [];
}
const isEnvironmentSelected =
environment && environment !== ENVIRONMENT_ALL.value;

if (serviceName || isEnvironmentSelected) {
if (serviceName || environment) {
paths = paths.filter((path) => {
return (
path
Expand All @@ -46,7 +44,7 @@ export function getConnections({
return false;
}

if (!environment) {
if (!environment || environment === ENVIRONMENT_ALL.value) {
return true;
}

Expand Down
188 changes: 103 additions & 85 deletions x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
*/

import querystring from 'querystring';
import url from 'url';
import expect from '@kbn/expect';
import { isEmpty, uniq } from 'lodash';
import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata';
Expand Down Expand Up @@ -131,110 +132,127 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
expect(environments.has(ENVIRONMENT_NOT_DEFINED)).to.eql(true);
expectSnapshot(body).toMatch();
});
});

describe('/api/apm/service-map with ML data', () => {
describe('with the default apm user', () => {
let response: PromiseReturnType<typeof supertest.get>;

before(async () => {
response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`);
});
describe('with ML data', () => {
describe('with the default apm user', () => {
before(async () => {
response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`);
});

it('returns service map elements with anomaly stats', () => {
expect(response.status).to.be(200);
const dataWithAnomalies = response.body.elements.filter(
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
);
it('returns service map elements with anomaly stats', () => {
expect(response.status).to.be(200);
const dataWithAnomalies = response.body.elements.filter(
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
);

expect(dataWithAnomalies).to.not.empty();
expect(dataWithAnomalies).to.not.empty();

dataWithAnomalies.forEach(({ data }: any) => {
expect(
Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value))
).to.not.empty();
dataWithAnomalies.forEach(({ data }: any) => {
expect(
Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value))
).to.not.empty();
});
});
});

it('returns the correct anomaly stats', () => {
const dataWithAnomalies = response.body.elements.filter(
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
);

expectSnapshot(dataWithAnomalies.length).toMatchInline(`8`);
expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(`
Array [
Object {
"data": Object {
"agent.name": "python",
"id": "opbeans-python",
"service.name": "opbeans-python",
"serviceAnomalyStats": Object {
"actualValue": 24282.2352941176,
"anomalyScore": 0,
"healthStatus": "healthy",
"jobId": "apm-environment_not_defined-5626-high_mean_transaction_duration",
"serviceName": "opbeans-python",
"transactionType": "request",
it('returns the correct anomaly stats', () => {
const dataWithAnomalies = response.body.elements.filter(
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
);

expectSnapshot(dataWithAnomalies.length).toMatchInline(`8`);
expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(`
Array [
Object {
"data": Object {
"agent.name": "python",
"id": "opbeans-python",
"service.name": "opbeans-python",
"serviceAnomalyStats": Object {
"actualValue": 24282.2352941176,
"anomalyScore": 0,
"healthStatus": "healthy",
"jobId": "apm-environment_not_defined-5626-high_mean_transaction_duration",
"serviceName": "opbeans-python",
"transactionType": "request",
},
},
},
},
Object {
"data": Object {
"agent.name": "nodejs",
"id": "opbeans-node",
"service.environment": "testing",
"service.name": "opbeans-node",
"serviceAnomalyStats": Object {
"actualValue": 29300.5555555556,
"anomalyScore": 0,
"healthStatus": "healthy",
"jobId": "apm-testing-384f-high_mean_transaction_duration",
"serviceName": "opbeans-node",
"transactionType": "request",
Object {
"data": Object {
"agent.name": "nodejs",
"id": "opbeans-node",
"service.environment": "testing",
"service.name": "opbeans-node",
"serviceAnomalyStats": Object {
"actualValue": 29300.5555555556,
"anomalyScore": 0,
"healthStatus": "healthy",
"jobId": "apm-testing-384f-high_mean_transaction_duration",
"serviceName": "opbeans-node",
"transactionType": "request",
},
},
},
},
Object {
"data": Object {
"agent.name": "rum-js",
"id": "opbeans-rum",
"service.environment": "testing",
"service.name": "opbeans-rum",
"serviceAnomalyStats": Object {
"actualValue": 2386500,
"anomalyScore": 0,
"healthStatus": "healthy",
"jobId": "apm-testing-384f-high_mean_transaction_duration",
"serviceName": "opbeans-rum",
"transactionType": "page-load",
Object {
"data": Object {
"agent.name": "rum-js",
"id": "opbeans-rum",
"service.environment": "testing",
"service.name": "opbeans-rum",
"serviceAnomalyStats": Object {
"actualValue": 2386500,
"anomalyScore": 0,
"healthStatus": "healthy",
"jobId": "apm-testing-384f-high_mean_transaction_duration",
"serviceName": "opbeans-rum",
"transactionType": "page-load",
},
},
},
},
]
`);
]
`);

expectSnapshot(response.body).toMatch();
expectSnapshot(response.body).toMatch();
});
});
});

describe('with a user that does not have access to ML', () => {
let response: PromiseReturnType<typeof supertest.get>;
describe('with a user that does not have access to ML', () => {
before(async () => {
response = await supertestAsApmReadUserWithoutMlAccess.get(
`/api/apm/service-map?start=${start}&end=${end}`
);
});

before(async () => {
response = await supertestAsApmReadUserWithoutMlAccess.get(
`/api/apm/service-map?start=${start}&end=${end}`
);
});
it('returns service map elements without anomaly stats', () => {
expect(response.status).to.be(200);

it('returns service map elements without anomaly stats', () => {
expect(response.status).to.be(200);
const dataWithAnomalies = response.body.elements.filter(
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
);

const dataWithAnomalies = response.body.elements.filter(
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
);
expect(dataWithAnomalies).to.be.empty();
});
});
});

describe('with a single service', () => {
describe('when ENVIRONMENT_ALL is selected', () => {
it('returns service map elements', async () => {
response = await supertest.get(
url.format({
pathname: '/api/apm/service-map',
query: {
environment: 'ENVIRONMENT_ALL',
start: metadata.start,
end: metadata.end,
serviceName: 'opbeans-java',
},
})
);

expect(dataWithAnomalies).to.be.empty();
expect(response.status).to.be(200);
expect(response.body.elements.length).to.be.greaterThan(1);
});
});
});
});
Expand Down

0 comments on commit da2a7fc

Please sign in to comment.