From 78c23d8dabe7e96d4fe031cffcc6d6b49ff95a29 Mon Sep 17 00:00:00 2001 From: Connor Lindsey Date: Wed, 23 Mar 2022 10:48:11 -0600 Subject: [PATCH] Tracing: Prevent createSpanLink from returning an invalid Loki query (#46864) --- .../explore/TraceView/createSpanLink.test.ts | 19 +++++++++++++++++++ .../explore/TraceView/createSpanLink.tsx | 16 +++++++++++++--- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/public/app/features/explore/TraceView/createSpanLink.test.ts b/public/app/features/explore/TraceView/createSpanLink.test.ts index eb98f159813..9ace5203e94 100644 --- a/public/app/features/explore/TraceView/createSpanLink.test.ts +++ b/public/app/features/explore/TraceView/createSpanLink.test.ts @@ -195,6 +195,25 @@ describe('createSpanLinkFactory', () => { )}` ); }); + + it('handles empty queries', () => { + const createLink = setupSpanLinkFactory({ + tags: [], + }); + expect(createLink).toBeDefined(); + const linkDef = createLink!( + createTraceSpan({ + process: { + serviceName: 'service', + tags: [ + { key: 'service.name', value: 'serviceName' }, + { key: 'k8s.pod.name', value: 'podName' }, + ], + }, + }) + ); + expect(linkDef).toBeUndefined(); + }); }); }); diff --git a/public/app/features/explore/TraceView/createSpanLink.tsx b/public/app/features/explore/TraceView/createSpanLink.tsx index 5170eb41236..5c74fecb728 100644 --- a/public/app/features/explore/TraceView/createSpanLink.tsx +++ b/public/app/features/explore/TraceView/createSpanLink.tsx @@ -75,12 +75,17 @@ function legacyCreateSpanLinkFactory(splitOpenFn: SplitOpen, traceToLogsOptions? return undefined; } - return function SpanLink(span: TraceSpan): SpanLinkDef { + return function SpanLink(span: TraceSpan): SpanLinkDef | undefined { // This is reusing existing code from derived fields which may not be ideal match so some data is a bit faked at // the moment. Issue is that the trace itself isn't clearly mapped to dataFrame (right now it's just a json blob // inside a single field) so the dataLinks as config of that dataFrame abstraction breaks down a bit and we do // it manually here instead of leaving it for the data source to supply the config. + const expr = getLokiQueryFromSpan(span, traceToLogsOptions); + if (!expr) { + return undefined; + } + const dataLink: DataLink = { title: dataSourceSettings.name, url: '', @@ -88,7 +93,7 @@ function legacyCreateSpanLinkFactory(splitOpenFn: SplitOpen, traceToLogsOptions? datasourceUid: dataSourceSettings.uid, datasourceName: dataSourceSettings.name, query: { - expr: getLokiQueryFromSpan(span, traceToLogsOptions), + expr, refId: '', }, }, @@ -122,7 +127,7 @@ function legacyCreateSpanLinkFactory(splitOpenFn: SplitOpen, traceToLogsOptions? */ const defaultKeys = ['cluster', 'hostname', 'namespace', 'pod']; -function getLokiQueryFromSpan(span: TraceSpan, options: TraceToLogsOptions): string { +function getLokiQueryFromSpan(span: TraceSpan, options: TraceToLogsOptions): string | undefined { const { tags: keys, filterByTraceID, filterBySpanID, mapTagNamesEnabled, mappedTags } = options; // In order, try to use mapped tags -> tags -> default tags @@ -143,6 +148,11 @@ function getLokiQueryFromSpan(span: TraceSpan, options: TraceToLogsOptions): str return acc; }, [] as string[]); + // If no tags found, return undefined to prevent an invalid Loki query + if (!tags.length) { + return undefined; + } + let query = `{${tags.join(', ')}}`; if (filterByTraceID && span.traceID) {