DataLinks: Removes getDataSourceSettingsByUid from applyFieldOverrides (#29447)

* DataLinks: Removes getDataSourceSettingsByUid from applyFieldOverrides and data linking code

* Fixed test

* Fixed a few tests

* Fixed unit tests

* Removed old getDataSourceSettingsByUid from interface, still there for runtime backward compatability
pull/29508/head
Torkel Ödegaard 5 years ago committed by GitHub
parent 9913ac73fb
commit 34f2a72ff2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 8
      packages/grafana-data/src/field/fieldOverrides.test.ts
  2. 26
      packages/grafana-data/src/field/fieldOverrides.ts
  3. 1
      packages/grafana-data/src/field/getFieldDisplayValuesProxy.test.tsx
  4. 12
      packages/grafana-data/src/types/dataLink.ts
  5. 11
      packages/grafana-data/src/types/fieldOverrides.ts
  6. 37
      packages/grafana-data/src/utils/dataLinks.test.ts
  7. 40
      packages/grafana-data/src/utils/dataLinks.ts
  8. 6
      packages/grafana-runtime/src/services/dataSourceSrv.ts
  9. 1
      packages/grafana-ui/src/utils/storybook/data.ts
  10. 5
      public/app/features/alerting/getAlertingValidationMessage.test.ts
  11. 2
      public/app/features/dashboard/components/Inspector/InspectDataTab.tsx
  12. 7
      public/app/features/dashboard/state/PanelModel.test.ts
  13. 2
      public/app/features/dashboard/state/PanelModel.ts
  14. 2
      public/app/features/dashboard/utils/loadSnapshotData.ts
  15. 6
      public/app/features/explore/TraceView/createSpanLink.test.ts
  16. 11
      public/app/features/explore/TraceView/createSpanLink.tsx
  17. 2
      public/app/features/explore/state/main.ts
  18. 27
      public/app/features/explore/utils/links.test.ts
  19. 10
      public/app/features/explore/utils/links.ts
  20. 1
      public/app/features/panel/panellinks/linkSuppliers.test.ts
  21. 10
      public/app/features/query/state/PanelQueryRunner.test.ts
  22. 8
      public/app/plugins/datasource/elasticsearch/datasource.test.ts
  23. 60
      public/app/plugins/datasource/elasticsearch/datasource.ts
  24. 16
      public/app/plugins/datasource/loki/result_transformer.test.ts
  25. 7
      public/app/plugins/datasource/loki/result_transformer.ts
  26. 1
      public/app/plugins/panel/live/LivePanel.tsx

@ -183,7 +183,6 @@ describe('applyFieldOverrides', () => {
overrides: [],
},
replaceVariables: (value: any) => value,
getDataSourceSettingsByUid: undefined as any,
theme: getTestTheme(),
fieldConfigRegistry: new FieldConfigOptionsRegistry(),
});
@ -245,7 +244,6 @@ describe('applyFieldOverrides', () => {
overrides: [],
},
fieldConfigRegistry: customFieldRegistry,
getDataSourceSettingsByUid: undefined as any,
replaceVariables: v => v,
theme: getTestTheme(),
})[0];
@ -263,7 +261,6 @@ describe('applyFieldOverrides', () => {
data: [f0], // the frame
fieldConfig: src as FieldConfigSource, // defaults + overrides
replaceVariables: (undefined as any) as InterpolateFunction,
getDataSourceSettingsByUid: undefined as any,
theme: getTestTheme(),
fieldConfigRegistry: customFieldRegistry,
})[0];
@ -291,7 +288,6 @@ describe('applyFieldOverrides', () => {
data: [f0], // the frame
fieldConfig: src as FieldConfigSource, // defaults + overrides
replaceVariables: (undefined as any) as InterpolateFunction,
getDataSourceSettingsByUid: undefined as any,
theme: getTestTheme(),
})[0];
const valueColumn = data.fields[1];
@ -314,7 +310,6 @@ describe('applyFieldOverrides', () => {
replaceVariablesCalls.push(variables);
return value;
}) as InterpolateFunction,
getDataSourceSettingsByUid: undefined as any,
theme: getTestTheme(),
fieldConfigRegistry: customFieldRegistry,
})[0];
@ -565,7 +560,6 @@ describe('getLinksSupplier', () => {
{},
replaceSpy,
// this is used only for internal links so isn't needed here
() => ({} as any),
{
theme: getTestTheme(),
}
@ -598,6 +592,7 @@ describe('getLinksSupplier', () => {
title: '',
internal: {
datasourceUid: '0',
datasourceName: 'testDS',
query: '12345',
},
},
@ -613,7 +608,6 @@ describe('getLinksSupplier', () => {
{},
// We do not need to interpolate anything for this test
(value, vars, format) => value,
uid => ({ name: 'testDS' } as any),
{ theme: getTestTheme() }
);
const links = supplier({ valueRowIndex: 0 });

@ -2,7 +2,6 @@ import {
ApplyFieldOverrideOptions,
DataFrame,
DataLink,
DataSourceInstanceSettings,
DynamicConfigValue,
Field,
FieldColorModeId,
@ -130,7 +129,6 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
data: options.data!,
dataFrameIndex: index,
replaceVariables: options.replaceVariables,
getDataSourceSettingsByUid: options.getDataSourceSettingsByUid,
fieldConfigRegistry: fieldConfigRegistry,
};
@ -211,17 +209,10 @@ export function applyFieldOverrides(options: ApplyFieldOverrideOptions): DataFra
});
// Attach data links supplier
newField.getLinks = getLinksSupplier(
newFrame,
newField,
fieldScopedVars,
context.replaceVariables,
context.getDataSourceSettingsByUid,
{
theme: options.theme,
timeZone: options.timeZone,
}
);
newField.getLinks = getLinksSupplier(newFrame, newField, fieldScopedVars, context.replaceVariables, {
theme: options.theme,
timeZone: options.timeZone,
});
return newField;
});
@ -336,7 +327,6 @@ export const getLinksSupplier = (
field: Field,
fieldScopedVars: ScopedVars,
replaceVariables: InterpolateFunction,
getDataSourceSettingsByUid: (uid: string) => DataSourceInstanceSettings | undefined,
options: {
theme: GrafanaTheme;
timeZone?: TimeZone;
@ -401,9 +391,13 @@ export const getLinksSupplier = (
if (link.internal) {
// For internal links at the moment only destination is Explore.
return mapInternalLinkToExplore(link, variables, {} as any, field, {
return mapInternalLinkToExplore({
link,
internalLink: link.internal,
scopedVars: variables,
field,
range: {} as any,
replaceVariables,
getDataSourceSettingsByUid,
});
} else {
let href = locationUtil.assureBaseUrl(link.url.replace(/\n/g, ''));

@ -29,7 +29,6 @@ describe('getFieldDisplayValuesProxy', () => {
overrides: [],
},
replaceVariables: (val: string) => val,
getDataSourceSettingsByUid: (val: string) => ({} as any),
timeZone: 'utc',
theme: getTestTheme(),
})[0];

@ -36,10 +36,14 @@ export interface DataLink<T extends DataQuery = any> {
// datas ource that we want to show to the user. Usually this results in a link to explore but can also lead to
// more custom onClick behaviour if needed.
// @internal and subject to change in future releases
internal?: {
query: T;
datasourceUid: string;
};
internal?: InternalDataLink<T>;
}
/** @internal */
export interface InternalDataLink<T extends DataQuery = any> {
query: T;
datasourceUid: string;
datasourceName: string;
}
export type LinkTarget = '_blank' | '_self' | undefined;

@ -1,13 +1,5 @@
import { ComponentType } from 'react';
import {
MatcherConfig,
FieldConfig,
Field,
DataFrame,
GrafanaTheme,
TimeZone,
DataSourceInstanceSettings,
} from '../types';
import { MatcherConfig, FieldConfig, Field, DataFrame, GrafanaTheme, TimeZone } from '../types';
import { InterpolateFunction } from './panel';
import { StandardEditorProps, FieldConfigOptionsRegistry, StandardEditorContext } from '../field';
import { OptionsEditorItem } from './OptionsUIRegistryBuilder';
@ -114,7 +106,6 @@ export interface ApplyFieldOverrideOptions {
data?: DataFrame[];
fieldConfig: FieldConfigSource;
replaceVariables: InterpolateFunction;
getDataSourceSettingsByUid: (uid: string) => DataSourceInstanceSettings | undefined;
theme: GrafanaTheme;
timeZone?: TimeZone;
fieldConfigRegistry?: FieldConfigOptionsRegistry;

@ -4,33 +4,34 @@ import { ArrayVector } from '../vector';
describe('mapInternalLinkToExplore', () => {
it('creates internal link', () => {
const link = mapInternalLinkToExplore(
{
url: '',
title: '',
internal: {
datasourceUid: 'uid',
query: { query: '12344' },
},
const dataLink = {
url: '',
title: '',
internal: {
datasourceUid: 'uid',
datasourceName: 'dsName',
query: { query: '12344' },
},
{},
{} as any,
{
};
const link = mapInternalLinkToExplore({
link: dataLink,
internalLink: dataLink.internal,
scopedVars: {},
range: {} as any,
field: {
name: 'test',
type: FieldType.number,
config: {},
values: new ArrayVector([2]),
},
{
replaceVariables: val => val,
getDataSourceSettingsByUid: uid => ({ name: 'testDS' } as any),
}
);
replaceVariables: val => val,
});
expect(link).toEqual(
expect.objectContaining({
title: 'testDS',
href: '/explore?left={"datasource":"testDS","queries":[{"query":"12344"}]}',
title: 'dsName',
href: '/explore?left={"datasource":"dsName","queries":[{"query":"12344"}]}',
onClick: undefined,
})
);

@ -1,8 +1,8 @@
import {
DataLink,
DataQuery,
DataSourceInstanceSettings,
Field,
InternalDataLink,
InterpolateFunction,
LinkModel,
ScopedVars,
@ -27,41 +27,31 @@ export const DataLinkBuiltInVars = {
};
// We inject these because we cannot import them directly as they reside inside grafana main package.
type Options = {
export type LinkToExploreOptions = {
link: DataLink;
scopedVars: ScopedVars;
range: TimeRange;
field: Field;
internalLink: InternalDataLink;
onClickFn?: (options: { datasourceUid: string; query: any; range?: TimeRange }) => void;
replaceVariables: InterpolateFunction;
getDataSourceSettingsByUid: (uid: string) => DataSourceInstanceSettings | undefined;
};
export function mapInternalLinkToExplore(
link: DataLink,
scopedVars: ScopedVars,
range: TimeRange,
field: Field,
options: Options
): LinkModel<Field> {
if (!link.internal) {
throw new Error('Trying to map external link as internal');
}
const { onClickFn, replaceVariables, getDataSourceSettingsByUid } = options;
export function mapInternalLinkToExplore(options: LinkToExploreOptions): LinkModel<Field> {
const { onClickFn, replaceVariables, link, scopedVars, range, field, internalLink } = options;
const interpolatedQuery = interpolateQuery(link, scopedVars, replaceVariables);
return {
title: link.title
? replaceVariables(link.title || '', scopedVars)
: getDataSourceSettingsByUid(link.internal.datasourceUid)?.name || 'Unknown datasource',
const title = link.title ? link.title : internalLink.datasourceName;
return {
title: replaceVariables(title),
// In this case this is meant to be internal link (opens split view by default) the href will also points
// to explore but this way you can open it in new tab.
href: generateInternalHref(
getDataSourceSettingsByUid(link.internal.datasourceUid)?.name || 'unknown',
interpolatedQuery,
range
),
href: generateInternalHref(internalLink.datasourceName, interpolatedQuery, range),
onClick: onClickFn
? () => {
onClickFn?.({
datasourceUid: link.internal!.datasourceUid,
onClickFn({
datasourceUid: internalLink.datasourceUid,
query: interpolatedQuery,
range,
});

@ -15,12 +15,6 @@ export interface DataSourceSrv {
*/
get(name?: string | null, scopedVars?: ScopedVars): Promise<DataSourceApi>;
/**
* Returns metadata based on UID.
* @deprecated use getInstanceSettings
*/
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined;
/**
* Get all data sources
*/

@ -9,6 +9,5 @@ export function prepDataForStorybook(data: DataFrame[], theme: GrafanaTheme) {
},
theme,
replaceVariables: (value: string) => value,
getDataSourceSettingsByUid: (value: string) => ({} as any),
});
}

@ -22,7 +22,6 @@ describe('getAlertingValidationMessage', () => {
const getMock = jest.fn().mockResolvedValue(datasource);
const datasourceSrv: DataSourceSrv = {
get: getMock,
getDataSourceSettingsByUid(): any {},
getExternal(): DataSourceInstanceSettings[] {
return [];
},
@ -66,7 +65,6 @@ describe('getAlertingValidationMessage', () => {
return Promise.resolve(alertingDatasource);
},
getDataSourceSettingsByUid(): any {},
getInstanceSettings: (() => {}) as any,
getExternal(): DataSourceInstanceSettings[] {
return [];
@ -97,7 +95,6 @@ describe('getAlertingValidationMessage', () => {
const getMock = jest.fn().mockResolvedValue(datasource);
const datasourceSrv: DataSourceSrv = {
get: getMock,
getDataSourceSettingsByUid(): any {},
getInstanceSettings: (() => {}) as any,
getExternal(): DataSourceInstanceSettings[] {
return [];
@ -130,7 +127,6 @@ describe('getAlertingValidationMessage', () => {
const getMock = jest.fn().mockResolvedValue(datasource);
const datasourceSrv: DataSourceSrv = {
get: getMock,
getDataSourceSettingsByUid(): any {},
getInstanceSettings: (() => {}) as any,
getExternal(): DataSourceInstanceSettings[] {
return [];
@ -163,7 +159,6 @@ describe('getAlertingValidationMessage', () => {
const getMock = jest.fn().mockResolvedValue(datasource);
const datasourceSrv: DataSourceSrv = {
get: getMock,
getDataSourceSettingsByUid(): any {},
getInstanceSettings: (() => {}) as any,
getExternal(): DataSourceInstanceSettings[] {
return [];

@ -23,7 +23,6 @@ import { GetDataOptions } from '../../../query/state/PanelQueryRunner';
import { QueryOperationRow } from 'app/core/components/QueryOperationRow/QueryOperationRow';
import { PanelModel } from 'app/features/dashboard/state';
import { DetailText } from './DetailText';
import { getDatasourceSrv } from '../../../plugins/datasource_srv';
interface Props {
panel: PanelModel;
@ -125,7 +124,6 @@ export class InspectDataTab extends PureComponent<Props, State> {
replaceVariables: (value: string) => {
return value;
},
getDataSourceSettingsByUid: getDatasourceSrv().getDataSourceSettingsByUid,
});
}

@ -7,13 +7,11 @@ import {
standardEditorsRegistry,
standardFieldConfigEditorRegistry,
PanelData,
DataSourceInstanceSettings,
FieldColorModeId,
FieldColorConfigSettings,
} from '@grafana/data';
import { ComponentClass } from 'react';
import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { setDataSourceSrv } from '@grafana/runtime';
class TablePanelCtrl {}
@ -192,11 +190,6 @@ describe('PanelModel', () => {
});
it('should apply field config defaults', () => {
setDataSourceSrv({
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined {
return undefined;
},
} as any);
// default unit is overriden by model
expect(model.getFieldOverrideOptions().fieldConfig.defaults.unit).toBe('mpg');
// default decimals are aplied

@ -26,7 +26,6 @@ import {
import { EDIT_PANEL_ID } from 'app/core/constants';
import config from 'app/core/config';
import { PanelQueryRunner } from '../../query/state/PanelQueryRunner';
import { getDatasourceSrv } from '../../plugins/datasource_srv';
import { PanelOptionsChangedEvent, PanelQueriesChangedEvent, PanelTransformationsChangedEvent } from 'app/types/events';
export interface GridPos {
@ -462,7 +461,6 @@ export class PanelModel implements DataConfigSource {
return {
fieldConfig: this.fieldConfig,
replaceVariables: this.replaceVariables,
getDataSourceSettingsByUid: getDatasourceSrv().getDataSourceSettingsByUid.bind(getDatasourceSrv()),
fieldConfigRegistry: this.plugin.fieldConfigRegistry,
theme: config.theme,
};

@ -1,6 +1,5 @@
import { applyFieldOverrides, DefaultTimeRange, LoadingState, PanelData } from '@grafana/data';
import { config } from 'app/core/config';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { DashboardModel, PanelModel } from '../state';
import { getProcessedDataFrames } from '../../query/state/runRequest';
@ -17,7 +16,6 @@ export function loadSnapshotData(panel: PanelModel, dashboard: DashboardModel):
overrides: [],
},
replaceVariables: panel.replaceVariables,
getDataSourceSettingsByUid: getDatasourceSrv().getDataSourceSettingsByUid.bind(getDatasourceSrv()),
fieldConfigRegistry: panel.plugin!.fieldConfigRegistry,
theme: config.theme,
timeZone: dashboard.getTimezone(),

@ -41,10 +41,10 @@ describe('createSpanLinkFactory', () => {
} as DataSourceInstanceSettings,
];
},
getDataSourceSettingsByUid(uid: string): DataSourceInstanceSettings | undefined {
getInstanceSettings(uid: string): DataSourceInstanceSettings | undefined {
if (uid === 'lokiUid') {
return {
name: 'Loki1',
name: 'loki1',
} as any;
}
return undefined;
@ -82,7 +82,7 @@ describe('createSpanLinkFactory', () => {
} as any);
expect(linkDef.href).toBe(
`/explore?left={"range":{"from":"20201014T000000","to":"20201014T010006"},"datasource":"Loki1","queries":[{"expr":"{cluster=\\"cluster1\\", hostname=\\"hostname1\\"}","refId":""}]}`
`/explore?left={"range":{"from":"20201014T000000","to":"20201014T010006"},"datasource":"loki1","queries":[{"expr":"{cluster=\\"cluster1\\", hostname=\\"hostname1\\"}","refId":""}]}`
);
});
});

@ -34,17 +34,24 @@ export function createSpanLinkFactory(splitOpenFn: (options: { datasourceUid: st
url: '',
internal: {
datasourceUid: lokiDs.uid,
datasourceName: lokiDs.name,
query: {
expr: getLokiQueryFromSpan(span),
refId: '',
},
},
};
const link = mapInternalLinkToExplore(dataLink, {}, getTimeRangeFromSpan(span), {} as Field, {
const link = mapInternalLinkToExplore({
link: dataLink,
internalLink: dataLink.internal!,
scopedVars: {},
range: getTimeRangeFromSpan(span),
field: {} as Field,
onClickFn: splitOpenFn,
replaceVariables: getTemplateSrv().replace.bind(getTemplateSrv()),
getDataSourceSettingsByUid: getDataSourceSrv().getDataSourceSettingsByUid.bind(getDataSourceSrv()),
});
return {
href: link.href,
onClick: link.onClick,

@ -109,7 +109,7 @@ export function splitOpen<T extends DataQuery = any>(options?: {
} as DataQuery,
];
const dataSourceSettings = getDatasourceSrv().getDataSourceSettingsByUid(options.datasourceUid);
const dataSourceSettings = getDatasourceSrv().getInstanceSettings(options.datasourceUid);
await dispatch(changeDatasource(ExploreId.right, dataSourceSettings!.name));
await dispatch(setQueriesAction({ exploreId: ExploreId.right, queries }));

@ -1,17 +1,6 @@
import { getFieldLinksForExplore } from './links';
import {
ArrayVector,
DataLink,
DataSourceInstanceSettings,
dateTime,
Field,
FieldType,
LinkModel,
ScopedVars,
TimeRange,
} from '@grafana/data';
import { ArrayVector, DataLink, dateTime, Field, FieldType, LinkModel, ScopedVars, TimeRange } from '@grafana/data';
import { setLinkSrv } from '../../panel/panellinks/link_srv';
import { setDataSourceSrv } from '@grafana/runtime';
describe('getFieldLinksForExplore', () => {
it('returns correct link model for external link', () => {
@ -43,6 +32,7 @@ describe('getFieldLinksForExplore', () => {
internal: {
query: { query: 'query_1' },
datasourceUid: 'uid_1',
datasourceName: 'test_ds',
},
});
const splitfn = jest.fn();
@ -82,18 +72,7 @@ function setup(link: DataLink) {
return link.url;
},
});
setDataSourceSrv({
getDataSourceSettingsByUid(uid: string) {
return {
id: 1,
uid: 'uid_1',
type: 'metrics',
name: 'test_ds',
meta: {},
jsonData: {},
} as DataSourceInstanceSettings;
},
} as any);
const field: Field<string> = {
name: 'flux-dimensions',
type: FieldType.string,

@ -1,6 +1,6 @@
import { Field, LinkModel, TimeRange, mapInternalLinkToExplore } from '@grafana/data';
import { getLinkSrv } from '../../panel/panellinks/link_srv';
import { getDataSourceSrv, getTemplateSrv } from '@grafana/runtime';
import { getTemplateSrv } from '@grafana/runtime';
import { splitOpen } from '../state/main';
/**
@ -33,10 +33,14 @@ export const getFieldLinksForExplore = (
}
return linkModel;
} else {
return mapInternalLinkToExplore(link, scopedVars, range, field, {
return mapInternalLinkToExplore({
link,
internalLink: link.internal,
scopedVars: scopedVars,
range,
field,
onClickFn: splitOpenFn,
replaceVariables: getTemplateSrv().replace.bind(getTemplateSrv()),
getDataSourceSettingsByUid: getDataSourceSrv().getDataSourceSettingsByUid.bind(getDataSourceSrv()),
});
}
})

@ -90,7 +90,6 @@ describe('getFieldLinksSupplier', () => {
overrides: [],
},
replaceVariables: (val: string) => val,
getDataSourceSettingsByUid: (val: string) => ({} as any),
timeZone: 'utc',
theme: getTheme(),
})[0];

@ -88,11 +88,8 @@ function describeQueryRunnerScenario(description: string, scenarioFn: ScenarioFn
},
],
};
setDataSourceSrv({
getDataSourceSettingsByUid() {
return {} as any;
},
} as any);
setDataSourceSrv({} as any);
beforeEach(async () => {
setEchoSrv(new Echo());
@ -241,7 +238,6 @@ describe('PanelQueryRunner', () => {
overrides: [],
},
replaceVariables: v => v,
getDataSourceSettingsByUid: undefined as any,
theme: {} as GrafanaTheme,
}),
getTransformations: () => undefined,
@ -306,7 +302,6 @@ describe('PanelQueryRunner', () => {
overrides: [],
},
replaceVariables: v => v,
getDataSourceSettingsByUid: undefined as any,
theme: {} as GrafanaTheme,
}),
// @ts-ignore
@ -349,7 +344,6 @@ describe('PanelQueryRunner', () => {
overrides: [],
},
replaceVariables: v => v,
getDataSourceSettingsByUid: undefined as any,
theme: {} as GrafanaTheme,
}),
// @ts-ignore

@ -22,6 +22,13 @@ const ELASTICSEARCH_MOCK_URL = 'http://elasticsearch.local';
jest.mock('@grafana/runtime', () => ({
...((jest.requireActual('@grafana/runtime') as unknown) as object),
getBackendSrv: () => backendSrv,
getDataSourceSrv: () => {
return {
getInstanceSettings: () => {
return { name: 'elastic25' };
},
};
},
}));
describe('ElasticDatasource', function(this: any) {
@ -932,6 +939,7 @@ describe('enhanceDataFrame', () => {
url: '',
internal: {
query: { query: 'query' },
datasourceName: 'elastic25',
datasourceUid: 'dsUid',
},
});

@ -17,7 +17,7 @@ import { IndexPattern } from './index_pattern';
import { ElasticQueryBuilder } from './query_builder';
import { toUtc } from '@grafana/data';
import * as queryDef from './query_def';
import { getBackendSrv } from '@grafana/runtime';
import { getBackendSrv, getDataSourceSrv } from '@grafana/runtime';
import { getTemplateSrv, TemplateSrv } from 'app/features/templating/template_srv';
import { getTimeSrv, TimeSrv } from 'app/features/dashboard/services/TimeSrv';
import { DataLinkConfig, ElasticsearchOptions, ElasticsearchQuery } from './types';
@ -661,29 +661,41 @@ export class ElasticDatasource extends DataSourceApi<ElasticsearchQuery, Elastic
* Exported for tests.
*/
export function enhanceDataFrame(dataFrame: DataFrame, dataLinks: DataLinkConfig[]) {
if (dataLinks.length) {
for (const field of dataFrame.fields) {
const dataLinkConfig = dataLinks.find(dataLink => field.name && field.name.match(dataLink.field));
if (dataLinkConfig) {
let link: DataLink;
if (dataLinkConfig.datasourceUid) {
link = {
title: '',
url: '',
internal: {
query: { query: dataLinkConfig.url },
datasourceUid: dataLinkConfig.datasourceUid,
},
};
} else {
link = {
title: '',
url: dataLinkConfig.url,
};
}
field.config = field.config || {};
field.config.links = [...(field.config.links || []), link];
}
const dataSourceSrv = getDataSourceSrv();
if (!dataLinks.length) {
return;
}
for (const field of dataFrame.fields) {
const dataLinkConfig = dataLinks.find(dataLink => field.name && field.name.match(dataLink.field));
if (!dataLinkConfig) {
continue;
}
let link: DataLink;
if (dataLinkConfig.datasourceUid) {
const dsSettings = dataSourceSrv.getInstanceSettings(dataLinkConfig.datasourceUid);
link = {
title: '',
url: '',
internal: {
query: { query: dataLinkConfig.url },
datasourceUid: dataLinkConfig.datasourceUid,
datasourceName: dsSettings?.name ?? 'Data source not found',
},
};
} else {
link = {
title: '',
url: dataLinkConfig.url,
};
}
field.config = field.config || {};
field.config.links = [...(field.config.links || []), link];
}
}

@ -33,6 +33,18 @@ const lokiResponse: LokiStreamResponse = {
},
};
jest.mock('@grafana/runtime', () => ({
// @ts-ignore
...jest.requireActual('@grafana/runtime'),
getDataSourceSrv: () => {
return {
getInstanceSettings: () => {
return { name: 'Loki1' };
},
};
},
}));
describe('loki result transformer', () => {
beforeAll(() => {
setTemplateSrv(new TemplateSrv());
@ -167,12 +179,12 @@ describe('enhanceDataFrame', () => {
expect(fc.getFieldByName('trace2')!.config.links!.length).toBe(2);
expect(fc.getFieldByName('trace2')!.config.links![0]).toEqual({
title: '',
internal: { datasourceUid: 'uid', query: { query: 'test' } },
internal: { datasourceName: 'Loki1', datasourceUid: 'uid', query: { query: 'test' } },
url: '',
});
expect(fc.getFieldByName('trace2')!.config.links![1]).toEqual({
title: '',
internal: { datasourceUid: 'uid2', query: { query: 'test' } },
internal: { datasourceName: 'Loki1', datasourceUid: 'uid2', query: { query: 'test' } },
url: '',
});
});

@ -19,7 +19,7 @@ import {
ScopedVars,
} from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { getTemplateSrv, getDataSourceSrv } from '@grafana/runtime';
import TableModel from 'app/core/table_model';
import { formatQuery, getHighlighterExpressionsFromQuery } from './query_utils';
import {
@ -387,9 +387,13 @@ export const enhanceDataFrame = (dataFrame: DataFrame, config: LokiOptions | nul
* Transform derivedField config into dataframe field with config that contains link.
*/
function fieldFromDerivedFieldConfig(derivedFieldConfigs: DerivedFieldConfig[]): Field<any, ArrayVector> {
const dataSourceSrv = getDataSourceSrv();
const dataLinks = derivedFieldConfigs.reduce((acc, derivedFieldConfig) => {
// Having field.datasourceUid means it is an internal link.
if (derivedFieldConfig.datasourceUid) {
const dsSettings = dataSourceSrv.getInstanceSettings(derivedFieldConfig.datasourceUid);
acc.push({
// Will be filled out later
title: '',
@ -398,6 +402,7 @@ function fieldFromDerivedFieldConfig(derivedFieldConfigs: DerivedFieldConfig[]):
internal: {
query: { query: derivedFieldConfig.url },
datasourceUid: derivedFieldConfig.datasourceUid,
datasourceName: dsSettings?.name ?? 'Data source not found',
},
});
} else if (derivedFieldConfig.url) {

@ -174,7 +174,6 @@ export class LivePanel extends PureComponent<Props, State> {
series: applyFieldOverrides({
data: message.getData(),
theme: config.theme,
getDataSourceSettingsByUid: () => undefined,
replaceVariables: (v: string) => v,
fieldConfig: {
defaults: {},

Loading…
Cancel
Save