diff --git a/public/app/features/explore/LogsContainer.tsx b/public/app/features/explore/LogsContainer.tsx index 5d6330caf01..31248415c76 100644 --- a/public/app/features/explore/LogsContainer.tsx +++ b/public/app/features/explore/LogsContainer.tsx @@ -102,7 +102,7 @@ export class LogsContainer extends PureComponent { }; getFieldLinks = (field: Field, rowIndex: number) => { - return getFieldLinksForExplore(field, rowIndex, this.props.splitOpen, this.props.range); + return getFieldLinksForExplore({ field, rowIndex, splitOpenFn: this.props.splitOpen, range: this.props.range }); }; render() { diff --git a/public/app/features/explore/TableContainer.tsx b/public/app/features/explore/TableContainer.tsx index 297a45a67b8..042acc58f42 100644 --- a/public/app/features/explore/TableContainer.tsx +++ b/public/app/features/explore/TableContainer.tsx @@ -48,7 +48,7 @@ export class TableContainer extends PureComponent { // differently and sidestep this getLinks API on a dataframe for (const field of tableResult.fields) { field.getLinks = (config: ValueLinkConfig) => { - return getFieldLinksForExplore(field, config.valueRowIndex!, splitOpen, range); + return getFieldLinksForExplore({ field, rowIndex: config.valueRowIndex!, splitOpenFn: splitOpen, range }); }; } } diff --git a/public/app/features/explore/utils/links.test.ts b/public/app/features/explore/utils/links.test.ts index ad071d82ce3..30898671cc4 100644 --- a/public/app/features/explore/utils/links.test.ts +++ b/public/app/features/explore/utils/links.test.ts @@ -17,7 +17,7 @@ describe('getFieldLinksForExplore', () => { title: 'external', url: 'http://regionalhost', }); - const links = getFieldLinksForExplore(field, 0, jest.fn(), range); + const links = getFieldLinksForExplore({ field, rowIndex: 0, splitOpenFn: jest.fn(), range }); expect(links[0].href).toBe('http://regionalhost'); expect(links[0].title).toBe('external'); @@ -28,7 +28,7 @@ describe('getFieldLinksForExplore', () => { title: '', url: 'http://regionalhost', }); - const links = getFieldLinksForExplore(field, 0, jest.fn(), range); + const links = getFieldLinksForExplore({ field, rowIndex: 0, splitOpenFn: jest.fn(), range }); expect(links[0].href).toBe('http://regionalhost'); expect(links[0].title).toBe('regionalhost'); @@ -45,7 +45,7 @@ describe('getFieldLinksForExplore', () => { }, }); const splitfn = jest.fn(); - const links = getFieldLinksForExplore(field, 0, splitfn, range); + const links = getFieldLinksForExplore({ field, rowIndex: 0, splitOpenFn: splitfn, range }); expect(links[0].href).toBe( '/explore?left={"range":{"from":"now-1h","to":"now"},"datasource":"test_ds","queries":[{"query":"query_1"}]}' diff --git a/public/app/features/explore/utils/links.ts b/public/app/features/explore/utils/links.ts index 478000a465f..a9c9e6ea4f5 100644 --- a/public/app/features/explore/utils/links.ts +++ b/public/app/features/explore/utils/links.ts @@ -1,6 +1,15 @@ -import { Field, LinkModel, TimeRange, mapInternalLinkToExplore, InterpolateFunction } from '@grafana/data'; +import { + Field, + LinkModel, + TimeRange, + mapInternalLinkToExplore, + InterpolateFunction, + ScopedVars, + DataFrame, + getFieldDisplayValuesProxy, +} from '@grafana/data'; import { getLinkSrv } from '../../panel/panellinks/link_srv'; -import { getTemplateSrv } from '@grafana/runtime'; +import { config, getTemplateSrv } from '@grafana/runtime'; import { splitOpen } from '../state/main'; /** @@ -10,13 +19,16 @@ import { splitOpen } from '../state/main'; * appropriately. This is for example used for transition from log with traceId to trace datasource to show that * trace. */ -export const getFieldLinksForExplore = ( - field: Field, - rowIndex: number, - splitOpenFn: typeof splitOpen, - range: TimeRange -): Array> => { - const scopedVars: any = {}; +export const getFieldLinksForExplore = (options: { + field: Field; + rowIndex: number; + splitOpenFn?: typeof splitOpen; + range: TimeRange; + vars?: ScopedVars; + dataFrame?: DataFrame; +}): Array> => { + const { field, vars, splitOpenFn, range, rowIndex, dataFrame } = options; + const scopedVars: any = { ...(vars || {}) }; scopedVars['__value'] = { value: { raw: field.values.get(rowIndex), @@ -24,6 +36,20 @@ export const getFieldLinksForExplore = ( text: 'Raw value', }; + // If we have a dataFrame we can allow referencing other columns and their values in the interpolation. + if (dataFrame) { + scopedVars['__data'] = { + value: { + name: dataFrame.name, + refId: dataFrame.refId, + fields: getFieldDisplayValuesProxy(dataFrame, rowIndex, { + theme: config.theme, + }), + }, + text: 'Data', + }; + } + return field.config.links ? field.config.links.map(link => { if (!link.internal) { diff --git a/public/app/plugins/datasource/loki/configuration/DebugSection.tsx b/public/app/plugins/datasource/loki/configuration/DebugSection.tsx index b03cfa06dde..5ee40127deb 100644 --- a/public/app/plugins/datasource/loki/configuration/DebugSection.tsx +++ b/public/app/plugins/datasource/loki/configuration/DebugSection.tsx @@ -95,8 +95,8 @@ function makeDebugFields(derivedFields: DerivedFieldConfig[], debugText: string) let link: LinkModel | null = null; if (field.url && value) { - link = getFieldLinksForExplore( - { + link = getFieldLinksForExplore({ + field: { name: '', type: FieldType.string, values: new ArrayVector([value]), @@ -104,10 +104,9 @@ function makeDebugFields(derivedFields: DerivedFieldConfig[], debugText: string) links: [{ title: '', url: field.url }], }, }, - 0, - (() => {}) as any, - {} as any - )[0]; + rowIndex: 0, + range: {} as any, + })[0]; } return {