diff --git a/x-pack/plugins/apm/server/lib/service_map/__snapshots__/get_service_map_from_trace_ids.test.ts.snap b/x-pack/plugins/apm/server/lib/service_map/__snapshots__/get_service_map_from_trace_ids.test.ts.snap deleted file mode 100644 index b3cd91fd05a34..0000000000000 --- a/x-pack/plugins/apm/server/lib/service_map/__snapshots__/get_service_map_from_trace_ids.test.ts.snap +++ /dev/null @@ -1,270 +0,0 @@ -// Jest Snapshot v1, https://goo.gl/fbAQLP - -exports[`getConnections if neither service name or environment is given includes all connections 1`] = ` -Array [ - Object { - "destination": Object { - "agent.name": "java", - "service.environment": "testing", - "service.name": "opbeans-java", - }, - "source": Object { - "agent.name": "go", - "service.environment": "testing", - "service.name": "opbeans-go", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "172.18.0.6:3000", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "java", - "service.environment": "testing", - "service.name": "opbeans-java", - }, - }, - Object { - "destination": Object { - "agent.name": "nodejs", - "service.environment": null, - "service.name": "opbeans-node", - }, - "source": Object { - "agent.name": "python", - "service.environment": null, - "service.name": "opbeans-python", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "172.18.0.6:3000", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": null, - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "source": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "172.18.0.6:3000", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - "source": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - "source": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - }, - Object { - "destination": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "opbeans-python:3000", - "span.subtype": "http_rb", - "span.type": "ext", - }, - "source": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - }, - Object { - "destination": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - "source": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "opbeans-node:3000", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "172.18.0.7:3000", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - "source": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "opbeans-ruby:3000", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - "source": Object { - "agent.name": "python", - "service.environment": "production", - "service.name": "opbeans-python", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "opbeans-node:3000", - "span.subtype": "http_rb", - "span.type": "ext", - }, - "source": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "postgresql", - "span.subtype": "postgresql", - "span.type": "db", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "93.184.216.34:80", - "span.subtype": "http", - "span.type": "external", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "opbeans-ruby:3000", - "span.subtype": "http_rb", - "span.type": "ext", - }, - "source": Object { - "agent.name": "ruby", - "service.environment": "production", - "service.name": "opbeans-ruby", - }, - }, - Object { - "destination": Object { - "span.destination.service.resource": "redis", - "span.subtype": "redis", - "span.type": "cache", - }, - "source": Object { - "agent.name": "nodejs", - "service.environment": "production", - "service.name": "opbeans-node", - }, - }, -] -`; diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.test.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.test.ts index 1661aa6e89789..48ba41c650dcf 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.test.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.test.ts @@ -9,6 +9,20 @@ import serviceMapFromTraceIdsScriptResponse from './mock_responses/get_service_m import serviceMapFromTraceIdsScriptResponseEnvNotDefined from './mock_responses/get_service_map_from_trace_ids_script_response_env_not_defined.json'; import { PromiseReturnType } from '../../../typings/common'; import { fetchServicePathsFromTraceIds } from './fetch_service_paths_from_trace_ids'; +import { Connection } from '../../../common/service_map'; + +function getConnectionsPairs(connections: Connection[]) { + return connections + .map((conn) => { + const source = `${conn.source['service.name']}:${conn.source['service.environment']}`; + const destination = `${conn.destination['service.name']}:${conn.destination['service.environment']}`; + if (conn.destination['service.name']) { + return `${source} -> ${destination}`; + } + }) + .filter((_) => _) + .sort(); +} describe('getConnections', () => { describe('if neither service name or environment is given', () => { @@ -17,97 +31,146 @@ describe('getConnections', () => { typeof fetchServicePathsFromTraceIds >; - const connections = getConnections( - response.aggregations?.service_map.value.paths - ); - - expect(connections).toMatchSnapshot(); + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: undefined, + environment: undefined, + }); + const connectionsPairs = getConnectionsPairs(connections); + expect(connectionsPairs).toEqual([ + 'opbeans-go:testing -> opbeans-java:testing', + 'opbeans-node:production -> opbeans-python:production', + 'opbeans-node:production -> opbeans-ruby:production', + 'opbeans-python:null -> opbeans-node:null', + 'opbeans-python:production -> opbeans-node:production', + 'opbeans-python:production -> opbeans-ruby:production', + 'opbeans-ruby:production -> opbeans-node:production', + 'opbeans-ruby:production -> opbeans-python:production', + ]); }); }); describe('if service name and environment are given', () => { - it('excludes connections with different service name and environment', () => { + it('shows all connections for opbeans-node and production', () => { const response = serviceMapFromTraceIdsScriptResponse as PromiseReturnType< typeof fetchServicePathsFromTraceIds >; - const serviceName = 'opbeans-node'; - const environment = 'production'; - const connections = getConnections( - response.aggregations?.service_map.value.paths, - serviceName, - environment - ); - expect( - connections.every( - (conn) => conn.source['service.environment'] === environment - ) - ).toBeTruthy(); - const serviceNames = new Set(); - connections.forEach((conn) => - serviceNames.add(conn.source['service.name']) - ); - ['opbeans-python', 'opbeans-node', 'opbeans-ruby'].forEach((name) => - expect(serviceNames.has(name)).toBeTruthy() - ); + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: 'opbeans-node', + environment: 'production', + }); + + const connectionsPairs = getConnectionsPairs(connections); + + expect(connectionsPairs).toEqual([ + 'opbeans-node:production -> opbeans-python:production', + 'opbeans-node:production -> opbeans-ruby:production', + 'opbeans-python:production -> opbeans-node:production', + 'opbeans-python:production -> opbeans-ruby:production', + 'opbeans-ruby:production -> opbeans-node:production', + 'opbeans-ruby:production -> opbeans-python:production', + ]); + }); + + it('shows all connections for opbeans-go and testing', () => { + const response = serviceMapFromTraceIdsScriptResponse as PromiseReturnType< + typeof fetchServicePathsFromTraceIds + >; + + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: 'opbeans-go', + environment: 'testing', + }); + + const connectionsPairs = getConnectionsPairs(connections); + + expect(connectionsPairs).toEqual([ + 'opbeans-go:testing -> opbeans-java:testing', + ]); }); }); describe('if service name is given', () => { - it('excludes connections with different service name', () => { + it('shows all connections for opbeans-node', () => { const response = serviceMapFromTraceIdsScriptResponse as PromiseReturnType< typeof fetchServicePathsFromTraceIds >; - const serviceName = 'opbeans-node'; - const connections = getConnections( - response.aggregations?.service_map.value.paths, - serviceName - ); - - const serviceNames = new Set(); - connections.forEach((conn) => - serviceNames.add(conn.source['service.name']) - ); - ['opbeans-python', 'opbeans-node', 'opbeans-ruby'].forEach((name) => - expect(serviceNames.has(name)).toBeTruthy() - ); + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: 'opbeans-node', + environment: undefined, + }); + + const connectionsPairs = getConnectionsPairs(connections); + + expect(connectionsPairs).toEqual([ + 'opbeans-node:production -> opbeans-python:production', + 'opbeans-node:production -> opbeans-ruby:production', + 'opbeans-python:null -> opbeans-node:null', + 'opbeans-python:production -> opbeans-node:production', + 'opbeans-python:production -> opbeans-ruby:production', + 'opbeans-ruby:production -> opbeans-node:production', + 'opbeans-ruby:production -> opbeans-python:production', + ]); }); }); describe('if environment is given', () => { - it('excludes connections with different environment', () => { + it('shows all connections for testing environment', () => { const response = serviceMapFromTraceIdsScriptResponse as PromiseReturnType< typeof fetchServicePathsFromTraceIds >; - const environment = 'testing'; - const connections = getConnections( - response.aggregations?.service_map.value.paths, - undefined, - environment - ); + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: undefined, + environment: 'testing', + }); - expect( - connections.every( - (conn) => conn.source['service.environment'] === environment - ) - ).toBeTruthy(); + const connectionsPairs = getConnectionsPairs(connections); + + expect(connectionsPairs).toEqual([ + 'opbeans-go:testing -> opbeans-java:testing', + ]); + }); + it('shows all connections for production environment', () => { + const response = serviceMapFromTraceIdsScriptResponse as PromiseReturnType< + typeof fetchServicePathsFromTraceIds + >; + + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: undefined, + environment: 'production', + }); + + const connectionsPairs = getConnectionsPairs(connections); + + expect(connectionsPairs).toEqual([ + 'opbeans-node:production -> opbeans-python:production', + 'opbeans-node:production -> opbeans-ruby:production', + 'opbeans-python:production -> opbeans-node:production', + 'opbeans-python:production -> opbeans-ruby:production', + 'opbeans-ruby:production -> opbeans-node:production', + 'opbeans-ruby:production -> opbeans-python:production', + ]); }); }); describe('if environment is "not defined"', () => { - it('excludes connections with source environment set', () => { + it('shows all connections where environment is not set', () => { const response = serviceMapFromTraceIdsScriptResponseEnvNotDefined as PromiseReturnType< typeof fetchServicePathsFromTraceIds >; - const environment = 'ENVIRONMENT_NOT_DEFINED'; - - const connections = getConnections( - response.aggregations?.service_map.value.paths, - undefined, - environment - ); + const connections = getConnections({ + paths: response.aggregations?.service_map.value.paths, + serviceName: undefined, + environment: 'ENVIRONMENT_NOT_DEFINED', + }); const environments = new Set(); diff --git a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts b/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts index 7108b4c93a8d5..595c12bb424bd 100644 --- a/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts +++ b/x-pack/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts @@ -13,11 +13,15 @@ import { Connection, ConnectionNode } from '../../../common/service_map'; import { Setup } from '../helpers/setup_request'; import { fetchServicePathsFromTraceIds } from './fetch_service_paths_from_trace_ids'; -export function getConnections( - paths?: ConnectionNode[][], - serviceName?: string, - environment?: string -) { +export function getConnections({ + paths, + serviceName, + environment, +}: { + paths: ConnectionNode[][] | undefined; + serviceName: string | undefined; + environment: string | undefined; +}) { if (!paths) { return []; } @@ -82,11 +86,11 @@ export async function getServiceMapFromTraceIds({ serviceMapFromTraceIdsScriptResponse.aggregations?.service_map.value; return { - connections: getConnections( - serviceMapScriptedAggValue?.paths, + connections: getConnections({ + paths: serviceMapScriptedAggValue?.paths, serviceName, - environment - ), + environment, + }), discoveredServices: serviceMapScriptedAggValue?.discoveredServices ?? [], }; }