Skip to content

Commit 4e21fae

Browse files
authored
Fix service map for All environment single service (#93517)
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.
1 parent a61e1dd commit 4e21fae

File tree

2 files changed

+105
-89
lines changed

2 files changed

+105
-89
lines changed

x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,8 @@ export function getConnections({
3030
if (!paths) {
3131
return [];
3232
}
33-
const isEnvironmentSelected =
34-
environment && environment !== ENVIRONMENT_ALL.value;
3533

36-
if (serviceName || isEnvironmentSelected) {
34+
if (serviceName || environment) {
3735
paths = paths.filter((path) => {
3836
return (
3937
path
@@ -46,7 +44,7 @@ export function getConnections({
4644
return false;
4745
}
4846

49-
if (!environment) {
47+
if (!environment || environment === ENVIRONMENT_ALL.value) {
5048
return true;
5149
}
5250

x-pack/test/apm_api_integration/tests/service_maps/service_maps.ts

Lines changed: 103 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
*/
77

88
import querystring from 'querystring';
9+
import url from 'url';
910
import expect from '@kbn/expect';
1011
import { isEmpty, uniq } from 'lodash';
1112
import archives_metadata from '../../common/fixtures/es_archiver/archives_metadata';
@@ -131,110 +132,127 @@ export default function serviceMapsApiTests({ getService }: FtrProviderContext)
131132
expect(environments.has(ENVIRONMENT_NOT_DEFINED)).to.eql(true);
132133
expectSnapshot(body).toMatch();
133134
});
134-
});
135-
136-
describe('/api/apm/service-map with ML data', () => {
137-
describe('with the default apm user', () => {
138-
let response: PromiseReturnType<typeof supertest.get>;
139135

140-
before(async () => {
141-
response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`);
142-
});
136+
describe('with ML data', () => {
137+
describe('with the default apm user', () => {
138+
before(async () => {
139+
response = await supertest.get(`/api/apm/service-map?start=${start}&end=${end}`);
140+
});
143141

144-
it('returns service map elements with anomaly stats', () => {
145-
expect(response.status).to.be(200);
146-
const dataWithAnomalies = response.body.elements.filter(
147-
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
148-
);
142+
it('returns service map elements with anomaly stats', () => {
143+
expect(response.status).to.be(200);
144+
const dataWithAnomalies = response.body.elements.filter(
145+
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
146+
);
149147

150-
expect(dataWithAnomalies).to.not.empty();
148+
expect(dataWithAnomalies).to.not.empty();
151149

152-
dataWithAnomalies.forEach(({ data }: any) => {
153-
expect(
154-
Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value))
155-
).to.not.empty();
150+
dataWithAnomalies.forEach(({ data }: any) => {
151+
expect(
152+
Object.values(data.serviceAnomalyStats).filter((value) => isEmpty(value))
153+
).to.not.empty();
154+
});
156155
});
157-
});
158156

159-
it('returns the correct anomaly stats', () => {
160-
const dataWithAnomalies = response.body.elements.filter(
161-
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
162-
);
163-
164-
expectSnapshot(dataWithAnomalies.length).toMatchInline(`8`);
165-
expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(`
166-
Array [
167-
Object {
168-
"data": Object {
169-
"agent.name": "python",
170-
"id": "opbeans-python",
171-
"service.name": "opbeans-python",
172-
"serviceAnomalyStats": Object {
173-
"actualValue": 24282.2352941176,
174-
"anomalyScore": 0,
175-
"healthStatus": "healthy",
176-
"jobId": "apm-environment_not_defined-5626-high_mean_transaction_duration",
177-
"serviceName": "opbeans-python",
178-
"transactionType": "request",
157+
it('returns the correct anomaly stats', () => {
158+
const dataWithAnomalies = response.body.elements.filter(
159+
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
160+
);
161+
162+
expectSnapshot(dataWithAnomalies.length).toMatchInline(`8`);
163+
expectSnapshot(dataWithAnomalies.slice(0, 3)).toMatchInline(`
164+
Array [
165+
Object {
166+
"data": Object {
167+
"agent.name": "python",
168+
"id": "opbeans-python",
169+
"service.name": "opbeans-python",
170+
"serviceAnomalyStats": Object {
171+
"actualValue": 24282.2352941176,
172+
"anomalyScore": 0,
173+
"healthStatus": "healthy",
174+
"jobId": "apm-environment_not_defined-5626-high_mean_transaction_duration",
175+
"serviceName": "opbeans-python",
176+
"transactionType": "request",
177+
},
179178
},
180179
},
181-
},
182-
Object {
183-
"data": Object {
184-
"agent.name": "nodejs",
185-
"id": "opbeans-node",
186-
"service.environment": "testing",
187-
"service.name": "opbeans-node",
188-
"serviceAnomalyStats": Object {
189-
"actualValue": 29300.5555555556,
190-
"anomalyScore": 0,
191-
"healthStatus": "healthy",
192-
"jobId": "apm-testing-384f-high_mean_transaction_duration",
193-
"serviceName": "opbeans-node",
194-
"transactionType": "request",
180+
Object {
181+
"data": Object {
182+
"agent.name": "nodejs",
183+
"id": "opbeans-node",
184+
"service.environment": "testing",
185+
"service.name": "opbeans-node",
186+
"serviceAnomalyStats": Object {
187+
"actualValue": 29300.5555555556,
188+
"anomalyScore": 0,
189+
"healthStatus": "healthy",
190+
"jobId": "apm-testing-384f-high_mean_transaction_duration",
191+
"serviceName": "opbeans-node",
192+
"transactionType": "request",
193+
},
195194
},
196195
},
197-
},
198-
Object {
199-
"data": Object {
200-
"agent.name": "rum-js",
201-
"id": "opbeans-rum",
202-
"service.environment": "testing",
203-
"service.name": "opbeans-rum",
204-
"serviceAnomalyStats": Object {
205-
"actualValue": 2386500,
206-
"anomalyScore": 0,
207-
"healthStatus": "healthy",
208-
"jobId": "apm-testing-384f-high_mean_transaction_duration",
209-
"serviceName": "opbeans-rum",
210-
"transactionType": "page-load",
196+
Object {
197+
"data": Object {
198+
"agent.name": "rum-js",
199+
"id": "opbeans-rum",
200+
"service.environment": "testing",
201+
"service.name": "opbeans-rum",
202+
"serviceAnomalyStats": Object {
203+
"actualValue": 2386500,
204+
"anomalyScore": 0,
205+
"healthStatus": "healthy",
206+
"jobId": "apm-testing-384f-high_mean_transaction_duration",
207+
"serviceName": "opbeans-rum",
208+
"transactionType": "page-load",
209+
},
211210
},
212211
},
213-
},
214-
]
215-
`);
212+
]
213+
`);
216214

217-
expectSnapshot(response.body).toMatch();
215+
expectSnapshot(response.body).toMatch();
216+
});
218217
});
219-
});
220218

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

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

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

233-
const dataWithAnomalies = response.body.elements.filter(
234-
(el: { data: { serviceAnomalyStats?: {} } }) => !isEmpty(el.data.serviceAnomalyStats)
235-
);
233+
expect(dataWithAnomalies).to.be.empty();
234+
});
235+
});
236+
});
237+
238+
describe('with a single service', () => {
239+
describe('when ENVIRONMENT_ALL is selected', () => {
240+
it('returns service map elements', async () => {
241+
response = await supertest.get(
242+
url.format({
243+
pathname: '/api/apm/service-map',
244+
query: {
245+
environment: 'ENVIRONMENT_ALL',
246+
start: metadata.start,
247+
end: metadata.end,
248+
serviceName: 'opbeans-java',
249+
},
250+
})
251+
);
236252

237-
expect(dataWithAnomalies).to.be.empty();
253+
expect(response.status).to.be(200);
254+
expect(response.body.elements.length).to.be.greaterThan(1);
255+
});
238256
});
239257
});
240258
});

0 commit comments

Comments
 (0)