From e3c11d26826db3dfe44a1ae6879bb8dc06285095 Mon Sep 17 00:00:00 2001 From: Connor Lindsey Date: Thu, 9 Sep 2021 07:24:08 -0600 Subject: [PATCH] Explore: Add filter by trace and span ID to trace to logs feature (#38943) * Add filter by trace and span ID to trace to logs feature * Update settings screenshot --- docs/sources/datasources/jaeger.md | 4 +- docs/sources/datasources/tempo.md | 4 +- docs/sources/datasources/zipkin.md | 4 +- .../core/components/TraceToLogsSettings.tsx | 42 +++++++++++++++++- .../explore/TraceView/createSpanLink.test.ts | 44 +++++++++++++++++++ .../explore/TraceView/createSpanLink.tsx | 17 +++++-- 6 files changed, 108 insertions(+), 7 deletions(-) diff --git a/docs/sources/datasources/jaeger.md b/docs/sources/datasources/jaeger.md index 6b5c96e67b8..4139e33f219 100644 --- a/docs/sources/datasources/jaeger.md +++ b/docs/sources/datasources/jaeger.md @@ -34,8 +34,10 @@ This is a configuration for the [trace to logs feature]({{< relref "../explore/t - **Tags -** The tags that will be used in the Loki query. Default is `'cluster', 'hostname', 'namespace', 'pod'`. - **Span start time shift -** Shift in the start time for the Loki query based on the span start time. In order to extend to the past, you need to use a negative value. Use time interval units like 5s, 1m, 3h. The default is 0. - **Span end time shift -** Shift in the end time for the Loki query based on the span end time. Time units can be used here, for example, 5s, 1m, 3h. The default is 0. +- **Filter by Trace ID -** Toggle to append the trace ID to the Loki query. +- **Filter by Span ID -** Toggle to append the span ID to the Loki query. -![Trace to logs settings](/static/img/docs/explore/trace-to-logs-settings-8.png 'Screenshot of the trace to logs settings') +![Trace to logs settings](/static/img/docs/explore/trace-to-logs-settings-8-2.png 'Screenshot of the trace to logs settings') ## Query traces diff --git a/docs/sources/datasources/tempo.md b/docs/sources/datasources/tempo.md index fcb3bb45729..62993fb6180 100644 --- a/docs/sources/datasources/tempo.md +++ b/docs/sources/datasources/tempo.md @@ -33,8 +33,10 @@ This is a configuration for the [trace to logs feature]({{< relref "../explore/t - **Tags -** The tags that will be used in the Loki query. Default is `'cluster', 'hostname', 'namespace', 'pod'`. - **Span start time shift -** A shift in the start time for the Loki query based on the start time for the span. To extend the time to the past, use a negative value. You can use time units, for example, 5s, 1m, 3h. The default is 0. - **Span end time shift -** Shift in the end time for the Loki query based on the span end time. Time units can be used here, for example, 5s, 1m, 3h. The default is 0. +- **Filter by Trace ID -** Toggle to append the trace ID to the Loki query. +- **Filter by Span ID -** Toggle to append the span ID to the Loki query. -![Trace to logs settings](/static/img/docs/explore/trace-to-logs-settings-8.png 'Screenshot of the trace to logs settings') +![Trace to logs settings](/static/img/docs/explore/trace-to-logs-settings-8-2.png 'Screenshot of the trace to logs settings') ## Query traces diff --git a/docs/sources/datasources/zipkin.md b/docs/sources/datasources/zipkin.md index 70e8578f849..85504e86eeb 100644 --- a/docs/sources/datasources/zipkin.md +++ b/docs/sources/datasources/zipkin.md @@ -34,8 +34,10 @@ This is a configuration for the [trace to logs feature]({{< relref "../explore/t - **Tags -** The tags that will be used in the Loki query. Default is `'cluster', 'hostname', 'namespace', 'pod'`. - **Span start time shift -** Shift in the start time for the Loki query based on the span start time. In order to extend to the past, you need to use a negative value. Use time interval units like 5s, 1m, 3h. The default is 0. - **Span end time shift -** Shift in the end time for the Loki query based on the span end time. Time units can be used here, for example, 5s, 1m, 3h. The default is 0. +- **Filter by Trace ID -** Toggle to append the trace ID to the Loki query. +- **Filter by Span ID -** Toggle to append the span ID to the Loki query. -![Trace to logs settings](/static/img/docs/explore/trace-to-logs-settings-8.png 'Screenshot of the trace to logs settings') +![Trace to logs settings](/static/img/docs/explore/trace-to-logs-settings-8-2.png 'Screenshot of the trace to logs settings') ## Query traces diff --git a/public/app/core/components/TraceToLogsSettings.tsx b/public/app/core/components/TraceToLogsSettings.tsx index 742cd8e994f..64ab1668c17 100644 --- a/public/app/core/components/TraceToLogsSettings.tsx +++ b/public/app/core/components/TraceToLogsSettings.tsx @@ -6,7 +6,7 @@ import { updateDatasourcePluginJsonDataOption, } from '@grafana/data'; import { DataSourcePicker } from '@grafana/runtime'; -import { InlineField, InlineFieldRow, Input, TagsInput, useStyles } from '@grafana/ui'; +import { InlineField, InlineFieldRow, Input, TagsInput, useStyles, InlineSwitch } from '@grafana/ui'; import React from 'react'; export interface TraceToLogsOptions { @@ -14,6 +14,8 @@ export interface TraceToLogsOptions { tags?: string[]; spanStartTimeShift?: string; spanEndTimeShift?: string; + filterByTraceID?: boolean; + filterBySpanID?: boolean; } export interface TraceToLogsData extends DataSourceJsonData { @@ -112,6 +114,44 @@ export function TraceToLogsSettings({ options, onOptionsChange }: Props) { /> + + + + ) => + updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToLogs', { + ...options.jsonData.tracesToLogs, + filterByTraceID: event.currentTarget.checked, + }) + } + /> + + + + + + ) => + updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToLogs', { + ...options.jsonData.tracesToLogs, + filterBySpanID: event.currentTarget.checked, + }) + } + /> + + ); } diff --git a/public/app/features/explore/TraceView/createSpanLink.test.ts b/public/app/features/explore/TraceView/createSpanLink.test.ts index 912bb342d0e..715d8e615d6 100644 --- a/public/app/features/explore/TraceView/createSpanLink.test.ts +++ b/public/app/features/explore/TraceView/createSpanLink.test.ts @@ -174,5 +174,49 @@ describe('createSpanLinkFactory', () => { )}` ); }); + + it('filters by trace and span ID', () => { + const splitOpenFn = jest.fn(); + const createLink = createSpanLinkFactory(splitOpenFn, { + datasourceUid: 'lokiUid', + filterBySpanID: true, + filterByTraceID: true, + }); + expect(createLink).toBeDefined(); + const linkDef = createLink!({ + spanID: '6605c7b08e715d6c', + traceID: '7946b05c2e2e4e5a', + startTime: new Date('2020-10-14T01:00:00Z').valueOf() * 1000, + duration: 1000 * 1000, + tags: [ + { + key: 'host', + value: 'host', + }, + ], + process: { + tags: [ + { + key: 'cluster', + value: 'cluster1', + }, + { + key: 'hostname', + value: 'hostname1', + }, + { + key: 'label2', + value: 'val2', + }, + ], + } as any, + } as any); + + expect(linkDef.href).toBe( + `/explore?left=${encodeURIComponent( + '{"range":{"from":"2020-10-14T01:00:00.000Z","to":"2020-10-14T01:00:01.000Z"},"datasource":"loki1","queries":[{"expr":"{cluster=\\"cluster1\\", hostname=\\"hostname1\\"} |=\\"7946b05c2e2e4e5a\\" |=\\"6605c7b08e715d6c\\"","refId":""}]}' + )}` + ); + }); }); }); diff --git a/public/app/features/explore/TraceView/createSpanLink.tsx b/public/app/features/explore/TraceView/createSpanLink.tsx index 185a263d3d3..c2a5b7ee639 100644 --- a/public/app/features/explore/TraceView/createSpanLink.tsx +++ b/public/app/features/explore/TraceView/createSpanLink.tsx @@ -38,7 +38,7 @@ export function createSpanLinkFactory(splitOpenFn: SplitOpen, traceToLogsOptions datasourceUid: dataSourceSettings.uid, datasourceName: dataSourceSettings.name, query: { - expr: getLokiQueryFromSpan(span, traceToLogsOptions.tags), + expr: getLokiQueryFromSpan(span, traceToLogsOptions), refId: '', }, }, @@ -67,7 +67,8 @@ export function createSpanLinkFactory(splitOpenFn: SplitOpen, traceToLogsOptions */ const defaultKeys = ['cluster', 'hostname', 'namespace', 'pod']; -function getLokiQueryFromSpan(span: TraceSpan, keys?: string[]): string { +function getLokiQueryFromSpan(span: TraceSpan, options: TraceToLogsOptions): string { + const { tags: keys, filterByTraceID, filterBySpanID } = options; const keysToCheck = keys?.length ? keys : defaultKeys; const tags = [...span.process.tags, ...span.tags].reduce((acc, tag) => { if (keysToCheck.includes(tag.key)) { @@ -75,7 +76,17 @@ function getLokiQueryFromSpan(span: TraceSpan, keys?: string[]): string { } return acc; }, [] as string[]); - return `{${tags.join(', ')}}`; + + let query = `{${tags.join(', ')}}`; + + if (filterByTraceID && span.traceID) { + query += ` |="${span.traceID}"`; + } + if (filterBySpanID && span.spanID) { + query += ` |="${span.spanID}"`; + } + + return query; } /**