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
This commit is contained in:
@@ -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.
|
||||
|
||||

|
||||

|
||||
|
||||
## Query traces
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||

|
||||
|
||||
## Query traces
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||

|
||||

|
||||
|
||||
## Query traces
|
||||
|
||||
|
||||
@@ -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) {
|
||||
/>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
|
||||
<InlineFieldRow>
|
||||
<InlineField
|
||||
label="Filter by Trace ID"
|
||||
labelWidth={26}
|
||||
grow
|
||||
tooltip="Filters logs by Trace ID. Appends '|=<trace id>' to the query."
|
||||
>
|
||||
<InlineSwitch
|
||||
value={options.jsonData.tracesToLogs?.filterByTraceID}
|
||||
onChange={(event: React.SyntheticEvent<HTMLInputElement>) =>
|
||||
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToLogs', {
|
||||
...options.jsonData.tracesToLogs,
|
||||
filterByTraceID: event.currentTarget.checked,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
|
||||
<InlineFieldRow>
|
||||
<InlineField
|
||||
label="Filter by Span ID"
|
||||
labelWidth={26}
|
||||
grow
|
||||
tooltip="Filters logs by Span ID. Appends '|=<span id>' to the query."
|
||||
>
|
||||
<InlineSwitch
|
||||
value={options.jsonData.tracesToLogs?.filterBySpanID}
|
||||
onChange={(event: React.SyntheticEvent<HTMLInputElement>) =>
|
||||
updateDatasourcePluginJsonDataOption({ onOptionsChange, options }, 'tracesToLogs', {
|
||||
...options.jsonData.tracesToLogs,
|
||||
filterBySpanID: event.currentTarget.checked,
|
||||
})
|
||||
}
|
||||
/>
|
||||
</InlineField>
|
||||
</InlineFieldRow>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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":""}]}'
|
||||
)}`
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user