MixedDatasource: Shows retrieved data even if a data source fails (#27024)

* MixedDatasource: Shows data for working data sources and error for erroneous

* Tests: remove funky import

* Tests: fixes types
This commit is contained in:
Hugo Häggmark
2020-08-18 23:52:40 -07:00
committed by GitHub
parent 3d18c4d614
commit 0755390286
3 changed files with 109 additions and 38 deletions

View File

@@ -1,17 +1,17 @@
import cloneDeep from 'lodash/cloneDeep';
import groupBy from 'lodash/groupBy';
import { from, of, Observable, forkJoin } from 'rxjs';
import { map, mergeMap, mergeAll } from 'rxjs/operators';
import { forkJoin, from, Observable, of } from 'rxjs';
import { catchError, map, mergeAll, mergeMap } from 'rxjs/operators';
import {
LoadingState,
DataSourceApi,
DataQuery,
DataQueryRequest,
DataQueryResponse,
DataSourceApi,
DataSourceInstanceSettings,
LoadingState,
} from '@grafana/data';
import { getDataSourceSrv } from '@grafana/runtime';
import { getDataSourceSrv, toDataQueryError } from '@grafana/runtime';
export const MIXED_DATASOURCE_NAME = '-- Mixed --';
@@ -68,13 +68,25 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
state: LoadingState.Loading,
key: `mixed-${i}-${response.key || ''}`,
} as DataQueryResponse;
}),
catchError(err => {
err = toDataQueryError(err);
err.message = `${api.name}: ${err.message}`;
return of({
data: [],
state: LoadingState.Error,
error: err,
key: `mixed-${i}-${dsRequest.requestId || ''}`,
});
})
);
})
)
);
return forkJoin(runningQueries).pipe(map(this.markAsDone), mergeAll());
return forkJoin(runningQueries).pipe(map(this.finalizeResponses), mergeAll());
}
testDatasource() {
@@ -85,14 +97,20 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
return query && Array.isArray(query.targets) && query.targets.length > 0;
}
private markAsDone(responses: DataQueryResponse[]): DataQueryResponse[] {
private finalizeResponses(responses: DataQueryResponse[]): DataQueryResponse[] {
const { length } = responses;
if (length === 0) {
return responses;
}
responses[length - 1].state = LoadingState.Done;
const error = responses.find(response => response.state === LoadingState.Error);
if (error) {
responses.push(error); // adds the first found error entry so error shows up in the panel
} else {
responses[length - 1].state = LoadingState.Done;
}
return responses;
}
}