MixedDataSource.ts 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. import cloneDeep from 'lodash/cloneDeep';
  2. import groupBy from 'lodash/groupBy';
  3. import { from, of, Observable, merge } from 'rxjs';
  4. import { DataSourceApi, DataQuery, DataQueryRequest, DataQueryResponse, DataSourceInstanceSettings } from '@grafana/ui';
  5. import { getDataSourceSrv } from '@grafana/runtime';
  6. import { mergeMap, map, filter } from 'rxjs/operators';
  7. export const MIXED_DATASOURCE_NAME = '-- Mixed --';
  8. export class MixedDatasource extends DataSourceApi<DataQuery> {
  9. constructor(instanceSettings: DataSourceInstanceSettings) {
  10. super(instanceSettings);
  11. }
  12. query(request: DataQueryRequest<DataQuery>): Observable<DataQueryResponse> {
  13. // Remove any invalid queries
  14. const queries = request.targets.filter(t => {
  15. return t.datasource !== MIXED_DATASOURCE_NAME;
  16. });
  17. if (!queries.length) {
  18. return of({ data: [] } as DataQueryResponse); // nothing
  19. }
  20. const sets: { [key: string]: DataQuery[] } = groupBy(queries, 'datasource');
  21. const observables: Array<Observable<DataQueryResponse>> = [];
  22. for (const key in sets) {
  23. const targets = sets[key];
  24. const dsName = targets[0].datasource;
  25. const observable = from(getDataSourceSrv().get(dsName)).pipe(
  26. map((dataSourceApi: DataSourceApi) => {
  27. const datasourceRequest = cloneDeep(request);
  28. // Remove any unused hidden queries
  29. let newTargets = targets.slice();
  30. if (!dataSourceApi.meta.hiddenQueries) {
  31. newTargets = newTargets.filter((t: DataQuery) => !t.hide);
  32. }
  33. datasourceRequest.targets = newTargets;
  34. datasourceRequest.requestId = `${dsName}${datasourceRequest.requestId || ''}`;
  35. return {
  36. dataSourceApi,
  37. datasourceRequest,
  38. };
  39. })
  40. );
  41. const noTargets = observable.pipe(
  42. filter(({ datasourceRequest }) => datasourceRequest.targets.length === 0),
  43. mergeMap(() => {
  44. return of({ data: [] } as DataQueryResponse);
  45. })
  46. );
  47. const hasTargets = observable.pipe(
  48. filter(({ datasourceRequest }) => datasourceRequest.targets.length > 0),
  49. mergeMap(({ dataSourceApi, datasourceRequest }) => {
  50. return from(dataSourceApi.query(datasourceRequest)).pipe(
  51. map((response: DataQueryResponse) => {
  52. return {
  53. ...response,
  54. data: response.data || [],
  55. key: `${dsName}${response.key || ''}`,
  56. } as DataQueryResponse;
  57. })
  58. );
  59. })
  60. );
  61. observables.push(merge(noTargets, hasTargets));
  62. }
  63. return merge(...observables);
  64. }
  65. testDatasource() {
  66. return Promise.resolve({});
  67. }
  68. }