diff --git a/public/app/plugins/datasource/zipkin/types.ts b/public/app/plugins/datasource/zipkin/types.ts index cc0d2de4c69..98d8c1e5483 100644 --- a/public/app/plugins/datasource/zipkin/types.ts +++ b/public/app/plugins/datasource/zipkin/types.ts @@ -5,16 +5,20 @@ export type ZipkinSpan = { id: string; timestamp: number; duration: number; - localEndpoint: { - serviceName: string; - ipv4: string; - port?: number; - }; + localEndpoint?: ZipkinEndpoint; + remoteEndpoint?: ZipkinEndpoint; annotations?: ZipkinAnnotation[]; tags?: { [key: string]: string }; kind?: 'CLIENT' | 'SERVER' | 'PRODUCER' | 'CONSUMER'; }; +export type ZipkinEndpoint = { + serviceName: string; + ipv4?: string; + ipv6?: string; + port?: number; +}; + export type ZipkinAnnotation = { timestamp: number; value: string; diff --git a/public/app/plugins/datasource/zipkin/utils/testData.ts b/public/app/plugins/datasource/zipkin/utils/testData.ts index ecaae2d5f40..dc2d9ece27a 100644 --- a/public/app/plugins/datasource/zipkin/utils/testData.ts +++ b/public/app/plugins/datasource/zipkin/utils/testData.ts @@ -45,6 +45,18 @@ export const zipkinResponse: ZipkinSpan[] = [ error: '404', }, }, + { + traceId: 'trace_id', + parentId: 'span 1 id', + name: 'span 3', + id: 'span 3 id', + timestamp: 6, + duration: 7, + remoteEndpoint: { + serviceName: 'spanstore-jdbc', + ipv6: '127.0.0.1', + }, + }, ]; export const jaegerTrace: TraceData & { spans: SpanData[] } = { @@ -74,6 +86,16 @@ export const jaegerTrace: TraceData & { spans: SpanData[] } = { }, ], }, + 'spanstore-jdbc': { + serviceName: 'spanstore-jdbc', + tags: [ + { + key: 'ipv6', + type: 'string', + value: '127.0.0.1', + }, + ], + }, }, traceID: 'trace_id', warnings: null, @@ -141,5 +163,24 @@ export const jaegerTrace: TraceData & { spans: SpanData[] } = { }, ], }, + { + duration: 7, + flags: 1, + logs: [], + operationName: 'span 3', + processID: 'spanstore-jdbc', + startTime: 6, + tags: [], + spanID: 'span 3 id', + traceID: 'trace_id', + warnings: null as any, + references: [ + { + refType: 'CHILD_OF', + spanID: 'span 1 id', + traceID: 'trace_id', + }, + ], + }, ], }; diff --git a/public/app/plugins/datasource/zipkin/utils/transforms.ts b/public/app/plugins/datasource/zipkin/utils/transforms.ts index 78df970ea76..16e65e1dad7 100644 --- a/public/app/plugins/datasource/zipkin/utils/transforms.ts +++ b/public/app/plugins/datasource/zipkin/utils/transforms.ts @@ -1,6 +1,6 @@ import { identity } from 'lodash'; import { keyBy } from 'lodash'; -import { ZipkinAnnotation, ZipkinSpan } from '../types'; +import { ZipkinAnnotation, ZipkinEndpoint, ZipkinSpan } from '../types'; import { KeyValuePair, Log, Process, SpanData, TraceData } from '@jaegertracing/jaeger-ui-components'; /** @@ -22,7 +22,7 @@ function transformSpan(span: ZipkinSpan): SpanData { flags: 1, logs: span.annotations?.map(transformAnnotation) ?? [], operationName: span.name, - processID: span.localEndpoint.serviceName, + processID: span.localEndpoint?.serviceName || span.remoteEndpoint?.serviceName || 'unknown', startTime: span.timestamp, spanID: span.id, traceID: span.traceId, @@ -77,22 +77,36 @@ function transformAnnotation(annotation: ZipkinAnnotation): Log { } function gatherProcesses(zSpans: ZipkinSpan[]): Record { - const processes = zSpans.map(span => ({ - serviceName: span.localEndpoint.serviceName, - tags: [ - { - key: 'ipv4', - type: 'string', - value: span.localEndpoint.ipv4, - }, - span.localEndpoint.port - ? { - key: 'port', - type: 'number', - value: span.localEndpoint.port, - } - : undefined, - ].filter(identity) as KeyValuePair[], - })); + const processes = zSpans.reduce((acc, span) => { + if (span.localEndpoint) { + acc.push(endpointToProcess(span.localEndpoint)); + } + if (span.remoteEndpoint) { + acc.push(endpointToProcess(span.remoteEndpoint)); + } + return acc; + }, [] as Process[]); return keyBy(processes, 'serviceName'); } + +function endpointToProcess(endpoint: ZipkinEndpoint): Process { + return { + serviceName: endpoint.serviceName, + tags: [ + valueToTag('ipv4', endpoint.ipv4, 'string'), + valueToTag('ipv6', endpoint.ipv6, 'string'), + valueToTag('port', endpoint.port, 'number'), + ].filter(identity) as KeyValuePair[], + }; +} + +function valueToTag(key: string, value: string | number | undefined, type: string): KeyValuePair | undefined { + if (!value) { + return undefined; + } + return { + key, + type, + value, + }; +}