diff --git a/public/app/features/explore/TraceView/components/model/transform-trace-data.test.ts b/public/app/features/explore/TraceView/components/model/transform-trace-data.test.ts index 7ff8742e335..53d3f3b696d 100644 --- a/public/app/features/explore/TraceView/components/model/transform-trace-data.test.ts +++ b/public/app/features/explore/TraceView/components/model/transform-trace-data.test.ts @@ -143,58 +143,6 @@ describe('transformTraceData()', () => { expect(transformTraceData(traceData)).toEqual(null); }); - it('should return null for any span without a spanID', () => { - const traceData = { - traceID, - processes, - spans: [ - { - traceID, - operationName: 'rootOperation', - references: [ - { - refType: 'CHILD_OF', - traceID, - spanID: rootSpanID, - }, - ], - startTime, - duration, - tags: [], - processID: 'p1', - }, - ], - } as unknown as TraceResponse; - - expect(transformTraceData(traceData)).toEqual(null); - }); - - it('should return null for any span without a processID', () => { - const traceData = { - traceID, - processes, - spans: [ - { - traceID, - spanID: '41f71485ed2593e4', - operationName: 'rootOperation', - references: [ - { - refType: 'CHILD_OF', - traceID, - spanID: rootSpanID, - }, - ], - startTime, - duration, - tags: [], - }, - ], - } as unknown as TraceResponse; - - expect(transformTraceData(traceData)).toEqual(null); - }); - it('should return trace data with correct traceName based on root span with missing ref', () => { const traceData = { traceID, diff --git a/public/app/features/explore/TraceView/components/model/transform-trace-data.tsx b/public/app/features/explore/TraceView/components/model/transform-trace-data.tsx index fef8f4fcf8e..ccd1905bd77 100644 --- a/public/app/features/explore/TraceView/components/model/transform-trace-data.tsx +++ b/public/app/features/explore/TraceView/components/model/transform-trace-data.tsx @@ -74,7 +74,7 @@ export function orderTags(tags: TraceKeyValuePair[], topPrefixes?: string[]) { * generally requires. */ export default function transformTraceData(data: TraceResponse | undefined): Trace | null { - if (!data?.traceID || data?.spans.some((x) => !x.processID || !x.spanID)) { + if (!data?.traceID) { return null; } const traceID = data.traceID.toLowerCase(); diff --git a/public/app/features/explore/TraceView/utils/transform.test.ts b/public/app/features/explore/TraceView/utils/transform.test.ts new file mode 100644 index 00000000000..dc92293493e --- /dev/null +++ b/public/app/features/explore/TraceView/utils/transform.test.ts @@ -0,0 +1,45 @@ +import { createDataFrame } from '@grafana/data'; + +import { transformTraceDataFrame } from './transform'; + +describe('transformTraceDataFrame()', () => { + const fields = [ + { name: 'traceID', values: ['trace1'] }, + { name: 'operationName', values: ['operation1'] }, + { name: 'kind', values: ['server'] }, + { name: 'tags', values: [[{ key: 'key1', value: 'value1' }]] }, + ]; + + it('should return transformed data', () => { + const dummyDataFrame = createDataFrame({ + fields: fields.concat([...fields, { name: 'spanID', values: ['span1'] }]), + }); + expect(transformTraceDataFrame(dummyDataFrame)).toEqual({ + processes: { span1: { serviceName: undefined, tags: undefined } }, + spans: [ + { + dataFrameRowIndex: 0, + duration: NaN, + flags: 0, + kind: 'server', + logs: [], + operationName: 'operation1', + processID: 'span1', + references: [], + spanID: 'span1', + startTime: NaN, + tags: [{ key: 'key1', value: 'value1' }], + traceID: 'trace1', + }, + ], + traceID: 'trace1', + }); + }); + + it('should return null for any span without a spanID', () => { + const dummyDataFrame = createDataFrame({ + fields: fields, + }); + expect(transformTraceDataFrame(dummyDataFrame)).toEqual(null); + }); +}); diff --git a/public/app/features/explore/TraceView/utils/transform.ts b/public/app/features/explore/TraceView/utils/transform.ts index 07f5d2a144e..f731ac653da 100644 --- a/public/app/features/explore/TraceView/utils/transform.ts +++ b/public/app/features/explore/TraceView/utils/transform.ts @@ -6,19 +6,26 @@ export function transformDataFrames(frame?: DataFrame): Trace | null { if (!frame) { return null; } - let data: TraceResponse = + let data: TraceResponse | null = frame.fields.length === 1 ? // For backward compatibility when we sent whole json response in a single field/value frame.fields[0].values[0] : transformTraceDataFrame(frame); + + if (!data) { + return null; + } return transformTraceData(data); } -function transformTraceDataFrame(frame: DataFrame): TraceResponse { +export function transformTraceDataFrame(frame: DataFrame): TraceResponse | null { const view = new DataFrameView(frame); const processes: Record = {}; for (let i = 0; i < view.length; i++) { const span = view.get(i); + if (!span.spanID) { + return null; + } if (!processes[span.spanID]) { processes[span.spanID] = { serviceName: span.serviceName,