mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Revert "MixedDataSource: Support multi value data source variable that issues a query to each data source" (#87579)
Revert "MixedDataSource: Support multi value data source variable that issues…"
This reverts commit 700d378c98
.
This commit is contained in:
parent
a6a9ab4008
commit
979d87f46f
@ -2,11 +2,7 @@ import { lastValueFrom } from 'rxjs';
|
|||||||
import { getQueryOptions } from 'test/helpers/getQueryOptions';
|
import { getQueryOptions } from 'test/helpers/getQueryOptions';
|
||||||
import { DatasourceSrvMock, MockObservableDataSourceApi } from 'test/mocks/datasource_srv';
|
import { DatasourceSrvMock, MockObservableDataSourceApi } from 'test/mocks/datasource_srv';
|
||||||
|
|
||||||
import { DataQueryRequest, DataSourceInstanceSettings, DataSourceRef, LoadingState } from '@grafana/data';
|
import { DataQueryRequest, DataSourceInstanceSettings, LoadingState } from '@grafana/data';
|
||||||
import { DataSourceSrv, setDataSourceSrv, setTemplateSrv } from '@grafana/runtime';
|
|
||||||
import { CustomVariable, SceneFlexLayout, SceneVariableSet } from '@grafana/scenes';
|
|
||||||
|
|
||||||
import { TemplateSrv } from '../../../features/templating/template_srv';
|
|
||||||
|
|
||||||
import { MIXED_DATASOURCE_NAME } from './MixedDataSource';
|
import { MIXED_DATASOURCE_NAME } from './MixedDataSource';
|
||||||
import { MixedDatasource } from './module';
|
import { MixedDatasource } from './module';
|
||||||
@ -25,19 +21,13 @@ const datasourceSrv = new DatasourceSrvMock(defaultDS, {
|
|||||||
]),
|
]),
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('MixedDatasource', () => {
|
const getDataSourceSrvMock = jest.fn().mockReturnValue(datasourceSrv);
|
||||||
beforeEach(() => {
|
jest.mock('@grafana/runtime', () => ({
|
||||||
jest.clearAllMocks();
|
...jest.requireActual('@grafana/runtime'),
|
||||||
setDataSourceSrv({
|
getDataSourceSrv: () => getDataSourceSrvMock(),
|
||||||
...datasourceSrv,
|
}));
|
||||||
get: (uid: DataSourceRef) => datasourceSrv.get(uid),
|
|
||||||
getInstanceSettings: jest.fn().mockReturnValue({ meta: {} }),
|
|
||||||
getList: jest.fn(),
|
|
||||||
reload: jest.fn(),
|
|
||||||
});
|
|
||||||
setTemplateSrv(new TemplateSrv());
|
|
||||||
});
|
|
||||||
|
|
||||||
|
describe('MixedDatasource', () => {
|
||||||
describe('with no errors', () => {
|
describe('with no errors', () => {
|
||||||
it('direct query should return results', async () => {
|
it('direct query should return results', async () => {
|
||||||
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
|
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
|
||||||
@ -93,67 +83,6 @@ describe('MixedDatasource', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('with multi template variable', () => {
|
|
||||||
beforeAll(() => {
|
|
||||||
setDataSourceSrv({
|
|
||||||
getInstanceSettings() {
|
|
||||||
return {};
|
|
||||||
},
|
|
||||||
} as DataSourceSrv);
|
|
||||||
});
|
|
||||||
|
|
||||||
const scene = new SceneFlexLayout({
|
|
||||||
children: [],
|
|
||||||
$variables: new SceneVariableSet({
|
|
||||||
variables: [new CustomVariable({ name: 'ds', value: ['B', 'C'] })],
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should run query for each datasource when there is a multi value template variable', async () => {
|
|
||||||
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
|
|
||||||
|
|
||||||
const request = {
|
|
||||||
targets: [{ refId: 'AA', datasource: { uid: '$ds' } }],
|
|
||||||
scopedVars: {
|
|
||||||
__sceneObject: { value: scene },
|
|
||||||
},
|
|
||||||
} as unknown as DataQueryRequest;
|
|
||||||
|
|
||||||
await expect(ds.query(request)).toEmitValuesWith((results) => {
|
|
||||||
expect(results).toHaveLength(2);
|
|
||||||
expect(results[0].key).toBe('mixed-0-');
|
|
||||||
expect(results[0].state).toBe(LoadingState.Loading);
|
|
||||||
expect(results[1].key).toBe('mixed-1-');
|
|
||||||
expect(results[1].state).toBe(LoadingState.Done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should run query for picked datasource and template variable datasource', async () => {
|
|
||||||
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
|
|
||||||
const request = {
|
|
||||||
targets: [
|
|
||||||
{ refId: 'AA', datasource: { uid: '$ds' } },
|
|
||||||
{ refId: 'BB', datasource: { uid: 'Loki' } },
|
|
||||||
],
|
|
||||||
scopedVars: {
|
|
||||||
__sceneObject: { value: scene },
|
|
||||||
},
|
|
||||||
} as unknown as DataQueryRequest;
|
|
||||||
|
|
||||||
await expect(ds.query(request)).toEmitValuesWith((results) => {
|
|
||||||
expect(results).toHaveLength(4);
|
|
||||||
expect(results[0].key).toBe('mixed-0-');
|
|
||||||
expect(results[0].state).toBe(LoadingState.Loading);
|
|
||||||
expect(results[1].key).toBe('mixed-1-');
|
|
||||||
expect(results[1].state).toBe(LoadingState.Loading);
|
|
||||||
expect(results[2].key).toBe('mixed-2-A');
|
|
||||||
expect(results[2].state).toBe(LoadingState.Loading);
|
|
||||||
expect(results[3].key).toBe('mixed-2-B');
|
|
||||||
expect(results[3].state).toBe(LoadingState.Done);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should return both query results from the same data source', async () => {
|
it('should return both query results from the same data source', async () => {
|
||||||
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
|
const ds = new MixedDatasource({} as DataSourceInstanceSettings);
|
||||||
const request = {
|
const request = {
|
||||||
|
@ -10,10 +10,8 @@ import {
|
|||||||
DataSourceApi,
|
DataSourceApi,
|
||||||
DataSourceInstanceSettings,
|
DataSourceInstanceSettings,
|
||||||
LoadingState,
|
LoadingState,
|
||||||
ScopedVars,
|
|
||||||
} from '@grafana/data';
|
} from '@grafana/data';
|
||||||
import { getDataSourceSrv, getTemplateSrv, toDataQueryError } from '@grafana/runtime';
|
import { getDataSourceSrv, toDataQueryError } from '@grafana/runtime';
|
||||||
import { CustomFormatterVariable } from '@grafana/scenes';
|
|
||||||
|
|
||||||
export const MIXED_DATASOURCE_NAME = '-- Mixed --';
|
export const MIXED_DATASOURCE_NAME = '-- Mixed --';
|
||||||
|
|
||||||
@ -21,8 +19,7 @@ export const mixedRequestId = (queryIdx: number, requestId?: string) => `mixed-$
|
|||||||
|
|
||||||
export interface BatchedQueries {
|
export interface BatchedQueries {
|
||||||
datasource: Promise<DataSourceApi>;
|
datasource: Promise<DataSourceApi>;
|
||||||
queries: DataQuery[];
|
targets: DataQuery[];
|
||||||
scopedVars: ScopedVars;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export class MixedDatasource extends DataSourceApi<DataQuery> {
|
export class MixedDatasource extends DataSourceApi<DataQuery> {
|
||||||
@ -42,77 +39,23 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
|
|||||||
|
|
||||||
// Build groups of queries to run in parallel
|
// Build groups of queries to run in parallel
|
||||||
const sets: { [key: string]: DataQuery[] } = groupBy(queries, 'datasource.uid');
|
const sets: { [key: string]: DataQuery[] } = groupBy(queries, 'datasource.uid');
|
||||||
const batches: BatchedQueries[] = [];
|
const mixed: BatchedQueries[] = [];
|
||||||
|
|
||||||
for (const key in sets) {
|
for (const key in sets) {
|
||||||
batches.push(...this.getBatchesForQueries(sets[key], request));
|
const targets = sets[key];
|
||||||
}
|
|
||||||
|
|
||||||
// Missing UIDs?
|
mixed.push({
|
||||||
if (!batches.length) {
|
datasource: getDataSourceSrv().get(targets[0].datasource, request.scopedVars),
|
||||||
return of({ data: [] }); // nothing
|
targets,
|
||||||
}
|
|
||||||
|
|
||||||
return this.batchQueries(batches, request);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Almost always returns a single batch for each set of queries.
|
|
||||||
* Unless the query is using a multi value variable.
|
|
||||||
*/
|
|
||||||
private getBatchesForQueries(queries: DataQuery[], request: DataQueryRequest<DataQuery>) {
|
|
||||||
const dsRef = queries[0].datasource;
|
|
||||||
const batches: BatchedQueries[] = [];
|
|
||||||
|
|
||||||
// Using the templateSrv.replace function here with a custom formatter as that is the cleanest way
|
|
||||||
// to access the raw value or value array of a variable.
|
|
||||||
const datasourceUid = getTemplateSrv().replace(
|
|
||||||
dsRef?.uid,
|
|
||||||
request.scopedVars,
|
|
||||||
(value: string | string[], variable: CustomFormatterVariable) => {
|
|
||||||
// If it's not a data source variable, or single value
|
|
||||||
if (!Array.isArray(value)) {
|
|
||||||
batches.push({
|
|
||||||
datasource: getDataSourceSrv().get(queries[0].datasource, request.scopedVars),
|
|
||||||
queries,
|
|
||||||
scopedVars: request.scopedVars,
|
|
||||||
});
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const uid of value) {
|
|
||||||
if (uid === 'default') {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const dsSettings = getDataSourceSrv().getInstanceSettings(uid);
|
|
||||||
|
|
||||||
batches.push({
|
|
||||||
datasource: getDataSourceSrv().get(uid),
|
|
||||||
queries: cloneDeep(queries),
|
|
||||||
scopedVars: {
|
|
||||||
...request.scopedVars,
|
|
||||||
[variable.name]: { value: uid, text: dsSettings?.name },
|
|
||||||
},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
if (datasourceUid !== '') {
|
|
||||||
batches.push({
|
|
||||||
datasource: getDataSourceSrv().get(datasourceUid),
|
|
||||||
queries: cloneDeep(queries),
|
|
||||||
scopedVars: {
|
|
||||||
...request.scopedVars,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return batches;
|
// Missing UIDs?
|
||||||
|
if (!mixed.length) {
|
||||||
|
return of({ data: [] }); // nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.batchQueries(mixed, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
batchQueries(mixed: BatchedQueries[], request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
|
batchQueries(mixed: BatchedQueries[], request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
|
||||||
@ -121,8 +64,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
|
|||||||
mergeMap((api: DataSourceApi) => {
|
mergeMap((api: DataSourceApi) => {
|
||||||
const dsRequest = cloneDeep(request);
|
const dsRequest = cloneDeep(request);
|
||||||
dsRequest.requestId = mixedRequestId(i, dsRequest.requestId);
|
dsRequest.requestId = mixedRequestId(i, dsRequest.requestId);
|
||||||
dsRequest.targets = query.queries;
|
dsRequest.targets = query.targets;
|
||||||
dsRequest.scopedVars = query.scopedVars;
|
|
||||||
|
|
||||||
return from(api.query(dsRequest)).pipe(
|
return from(api.query(dsRequest)).pipe(
|
||||||
map((response) => {
|
map((response) => {
|
||||||
@ -160,7 +102,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private isQueryable(query: BatchedQueries): boolean {
|
private isQueryable(query: BatchedQueries): boolean {
|
||||||
return query && Array.isArray(query.queries) && query.queries.length > 0;
|
return query && Array.isArray(query.targets) && query.targets.length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
private finalizeResponses(responses: DataQueryResponse[]): DataQueryResponse[] {
|
private finalizeResponses(responses: DataQueryResponse[]): DataQueryResponse[] {
|
||||||
|
Loading…
Reference in New Issue
Block a user