2019-09-09 17:29:37 +08:00
|
|
|
import cloneDeep from 'lodash/cloneDeep';
|
|
|
|
|
import groupBy from 'lodash/groupBy';
|
2019-09-12 23:28:46 +08:00
|
|
|
import { from, of, Observable, merge } from 'rxjs';
|
2019-09-09 17:29:37 +08:00
|
|
|
|
2019-09-12 23:28:46 +08:00
|
|
|
import { DataSourceApi, DataQuery, DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/ui';
|
2019-09-09 17:29:37 +08:00
|
|
|
import { getDataSourceSrv } from '@grafana/runtime';
|
2019-09-12 23:28:46 +08:00
|
|
|
import { mergeMap, map, filter } from 'rxjs/operators';
|
2019-09-09 17:29:37 +08:00
|
|
|
|
|
|
|
|
export const MIXED_DATASOURCE_NAME = '-- Mixed --';
|
|
|
|
|
|
|
|
|
|
export class MixedDatasource extends DataSourceApi<DataQuery> {
|
|
|
|
|
constructor(instanceSettings: DataSourceInstanceSettings) {
|
|
|
|
|
super(instanceSettings);
|
|
|
|
|
}
|
|
|
|
|
|
2019-09-12 23:28:46 +08:00
|
|
|
query(request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
|
2019-09-09 17:29:37 +08:00
|
|
|
// Remove any invalid queries
|
|
|
|
|
const queries = request.targets.filter(t => {
|
|
|
|
|
return t.datasource !== MIXED_DATASOURCE_NAME;
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
if (!queries.length) {
|
2019-09-12 23:28:46 +08:00
|
|
|
return of({ data: [] } as DataQueryResponse); // nothing
|
2019-09-09 17:29:37 +08:00
|
|
|
}
|
|
|
|
|
|
2019-09-12 23:28:46 +08:00
|
|
|
const sets: { [key: string]: DataQuery[] } = groupBy(queries, 'datasource');
|
|
|
|
|
const observables: Array<Observable<DataQueryResponse>> = [];
|
2019-09-09 17:29:37 +08:00
|
|
|
|
2019-09-12 23:28:46 +08:00
|
|
|
for (const key in sets) {
|
|
|
|
|
const targets = sets[key];
|
2019-09-09 17:29:37 +08:00
|
|
|
const dsName = targets[0].datasource;
|
2019-09-12 23:28:46 +08:00
|
|
|
|
|
|
|
|
const observable = from(getDataSourceSrv().get(dsName)).pipe(
|
|
|
|
|
map((dataSourceApi: DataSourceApi) => {
|
|
|
|
|
const datasourceRequest = cloneDeep(request);
|
2019-09-09 17:29:37 +08:00
|
|
|
|
|
|
|
|
// Remove any unused hidden queries
|
2019-09-12 23:28:46 +08:00
|
|
|
let newTargets = targets.slice();
|
|
|
|
|
if (!dataSourceApi.meta.hiddenQueries) {
|
|
|
|
|
newTargets = newTargets.filter((t: DataQuery) => !t.hide);
|
2019-09-09 17:29:37 +08:00
|
|
|
}
|
|
|
|
|
|
2019-09-12 23:28:46 +08:00
|
|
|
datasourceRequest.targets = newTargets;
|
|
|
|
|
datasourceRequest.requestId = `${dsName}${datasourceRequest.requestId || ''}`;
|
|
|
|
|
return {
|
|
|
|
|
dataSourceApi,
|
|
|
|
|
datasourceRequest,
|
|
|
|
|
};
|
|
|
|
|
})
|
|
|
|
|
);
|
2019-09-09 17:29:37 +08:00
|
|
|
|
2019-09-12 23:28:46 +08:00
|
|
|
const noTargets = observable.pipe(
|
|
|
|
|
filter(({ datasourceRequest }) => datasourceRequest.targets.length === 0),
|
|
|
|
|
mergeMap(() => {
|
|
|
|
|
return of({ data: [] } as DataQueryResponse);
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
const hasTargets = observable.pipe(
|
|
|
|
|
filter(({ datasourceRequest }) => datasourceRequest.targets.length > 0),
|
|
|
|
|
mergeMap(({ dataSourceApi, datasourceRequest }) => {
|
|
|
|
|
return from(dataSourceApi.query(datasourceRequest)).pipe(
|
|
|
|
|
map((response: DataQueryResponse) => {
|
|
|
|
|
return {
|
|
|
|
|
...response,
|
|
|
|
|
data: response.data || [],
|
|
|
|
|
key: `${dsName}${response.key || ''}`,
|
|
|
|
|
} as DataQueryResponse;
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
})
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
observables.push(merge(noTargets, hasTargets));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return merge(...observables);
|
2019-09-09 17:29:37 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
testDatasource() {
|
|
|
|
|
return Promise.resolve({});
|
|
|
|
|
}
|
|
|
|
|
}
|