diff --git a/x-pack/legacy/plugins/apm/common/service_map.ts b/x-pack/legacy/plugins/apm/common/service_map.ts index 464182467d540..fbaa489c45039 100644 --- a/x-pack/legacy/plugins/apm/common/service_map.ts +++ b/x-pack/legacy/plugins/apm/common/service_map.ts @@ -11,6 +11,8 @@ export interface ServiceConnectionNode { } export interface ExternalConnectionNode { 'destination.address': string; + 'span.type': string; + 'span.subtype': string; } export type ConnectionNode = ServiceConnectionNode | ExternalConnectionNode; diff --git a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts index bc4cff21ad234..c9caa27af41c5 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts +++ b/x-pack/legacy/plugins/apm/public/components/app/ServiceMap/get_cytoscape_elements.ts @@ -4,12 +4,8 @@ * you may not use this file except in compliance with the Elastic License. */ import { ValuesType } from 'utility-types'; -import { sortBy } from 'lodash'; -import { - Connection, - ConnectionNode, - ServiceConnectionNode -} from '../../../../common/service_map'; +import { sortBy, isEqual } from 'lodash'; +import { Connection, ConnectionNode } from '../../../../common/service_map'; import { ServiceMapAPIResponse } from '../../../../server/lib/service_map/get_service_map'; import { getAPMHref } from '../../shared/Links/apm/APMLink'; @@ -30,12 +26,9 @@ export function getCytoscapeElements( responses: ServiceMapAPIResponse[], search: string ) { - const destMap = responses.reduce((prev, response) => { - return { - ...prev, - ...response.destinationMap - }; - }, {} as Record); + const discoveredServices = responses.flatMap( + response => response.discoveredServices + ); const serviceNodes = responses .flatMap(response => response.services) @@ -46,9 +39,15 @@ export function getCytoscapeElements( // maps destination.address to service.name if possible function getConnectionNode(node: ConnectionNode) { - const mappedNode = - ('destination.address' in node && destMap[node['destination.address']]) || - node; + let mappedNode: ConnectionNode | undefined; + + if ('destination.address' in node) { + mappedNode = discoveredServices.find(map => isEqual(map.from, node))?.to; + } + + if (!mappedNode) { + mappedNode = node; + } return { ...mappedNode, diff --git a/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map.ts b/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map.ts index dda74cba880fd..04e2a43a4b8f1 100644 --- a/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map.ts +++ b/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map.ts @@ -46,7 +46,7 @@ async function getConnectionData({ environment, traceIds }) - : { connections: [], destinationMap: {} }; + : { connections: [], discoveredServices: [] }; return { after: nextAfter, diff --git a/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts b/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts index 1b70753909048..df76f54a00cab 100644 --- a/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts +++ b/x-pack/legacy/plugins/apm/server/lib/service_map/get_service_map_from_trace_ids.ts @@ -12,7 +12,8 @@ import { import { Connection, ServiceConnectionNode, - ConnectionNode + ConnectionNode, + ExternalConnectionNode } from '../../../common/service_map'; export async function getServiceMapFromTraceIds({ @@ -66,6 +67,7 @@ export async function getServiceMapFromTraceIds({ 'trace.id', 'processor.event', 'span.type', + 'span.subtype', 'agent.name' }; state.fieldsToCopy = fieldsToCopy;` @@ -96,7 +98,16 @@ export async function getServiceMapFromTraceIds({ }, reduce_script: { lang: 'painless', - source: `def processAndReturnEvent(def context, def eventId) { + source: ` + def getDestination ( def event ) { + def destination = new HashMap(); + destination['destination.address'] = event['destination.address']; + destination['span.type'] = event['span.type']; + destination['span.subtype'] = event['span.subtype']; + return destination; + } + + def processAndReturnEvent(def context, def eventId) { if (context.processedEvents[eventId] != null) { return context.processedEvents[eventId]; } @@ -135,7 +146,8 @@ export async function getServiceMapFromTraceIds({ || parent['service.environment'] != event['service.environment'] ) ) { - context.externalToServiceMap[parent['destination.address']] = service; + def parentDestination = getDestination(parent); + context.externalToServiceMap.put(parentDestination, service); } } } @@ -151,8 +163,7 @@ export async function getServiceMapFromTraceIds({ /* if there is an outgoing span, create a new path */ if (event['destination.address'] != null && event['destination.address'] != '') { - def outgoingLocation = new HashMap(); - outgoingLocation['destination.address'] = event['destination.address']; + def outgoingLocation = getDestination(event); def outgoingPath = new ArrayList(basePath); outgoingPath.add(outgoingLocation); context.paths.add(outgoingPath); @@ -191,8 +202,17 @@ export async function getServiceMapFromTraceIds({ def response = new HashMap(); response.paths = paths; - response.externalToServiceMap = context.externalToServiceMap; - + + def discoveredServices = new HashSet(); + + for(entry in context.externalToServiceMap.entrySet()) { + def map = new HashMap(); + map.from = entry.getKey(); + map.to = entry.getValue(); + discoveredServices.add(map); + } + response.discoveredServices = discoveredServices; + return response;` } } @@ -205,7 +225,10 @@ export async function getServiceMapFromTraceIds({ const scriptResponse = serviceMapResponse.aggregations?.service_map.value as { paths: ConnectionNode[][]; - externalToServiceMap: Record; + discoveredServices: Array<{ + from: ExternalConnectionNode; + to: ServiceConnectionNode; + }>; }; let paths = scriptResponse.paths; @@ -251,6 +274,6 @@ export async function getServiceMapFromTraceIds({ return { connections, - destinationMap: scriptResponse.externalToServiceMap + discoveredServices: scriptResponse.discoveredServices }; }