mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Only update pane's instance of Inspector (#80106)
* send instance ID to query inspector, ensure requestId match before updating data * Extract logic for mixed request ID, use in Explore prefix when appropriate * Change query inspector to get passed request ID * Fix test
This commit is contained in:
parent
9e04fd0fb7
commit
7b4dd4fe47
@ -55,11 +55,16 @@ export interface FolderRequestOptions {
|
||||
|
||||
const GRAFANA_TRACEID_HEADER = 'grafana-trace-id';
|
||||
|
||||
export interface InspectorStream {
|
||||
response: FetchResponse | FetchError;
|
||||
requestId?: string;
|
||||
}
|
||||
|
||||
export class BackendSrv implements BackendService {
|
||||
private inFlightRequests: Subject<string> = new Subject<string>();
|
||||
private HTTP_REQUEST_CANCELED = -1;
|
||||
private noBackendCache: boolean;
|
||||
private inspectorStream: Subject<FetchResponse | FetchError> = new Subject<FetchResponse | FetchError>();
|
||||
private inspectorStream: Subject<InspectorStream> = new Subject<InspectorStream>();
|
||||
private readonly fetchQueue: FetchQueue;
|
||||
private readonly responseQueue: ResponseQueue;
|
||||
private _tokenRotationInProgress?: Observable<FetchResponse> | null = null;
|
||||
@ -333,7 +338,7 @@ export class BackendSrv implements BackendService {
|
||||
}, 50);
|
||||
}
|
||||
|
||||
this.inspectorStream.next(err);
|
||||
this.inspectorStream.next({ response: err, requestId: options.requestId });
|
||||
return err;
|
||||
}
|
||||
|
||||
@ -356,7 +361,7 @@ export class BackendSrv implements BackendService {
|
||||
}),
|
||||
tap((response) => {
|
||||
this.showSuccessAlert(response);
|
||||
this.inspectorStream.next(response);
|
||||
this.inspectorStream.next({ response: response, requestId: options.requestId });
|
||||
})
|
||||
);
|
||||
}
|
||||
@ -446,7 +451,7 @@ export class BackendSrv implements BackendService {
|
||||
);
|
||||
}
|
||||
|
||||
getInspectorStream(): Observable<FetchResponse | FetchError> {
|
||||
getInspectorStream(): Observable<InspectorStream> {
|
||||
return this.inspectorStream;
|
||||
}
|
||||
|
||||
|
@ -664,7 +664,7 @@ describe('backendSrv', () => {
|
||||
|
||||
let inspectorPacket: FetchResponse | FetchError;
|
||||
backendSrv.getInspectorStream().subscribe({
|
||||
next: (rsp) => (inspectorPacket = rsp),
|
||||
next: (rsp) => (inspectorPacket = rsp.response),
|
||||
});
|
||||
|
||||
await backendSrv.datasourceRequest(options).catch((error) => {
|
||||
|
@ -101,6 +101,10 @@ export async function getExploreUrl(args: GetExploreUrlArguments): Promise<strin
|
||||
return urlUtil.renderUrl('/explore', { panes: exploreState, schemaVersion: 1 });
|
||||
}
|
||||
|
||||
export function requestIdGenerator(exploreId: string) {
|
||||
return `explore_${exploreId}`;
|
||||
}
|
||||
|
||||
export function buildQueryTransaction(
|
||||
exploreId: string,
|
||||
queries: DataQuery[],
|
||||
@ -123,7 +127,7 @@ export function buildQueryTransaction(
|
||||
panelId,
|
||||
targets: queries, // Datasources rely on DataQueries being passed under the targets key.
|
||||
range,
|
||||
requestId: 'explore_' + exploreId,
|
||||
requestId: requestIdGenerator(exploreId),
|
||||
rangeRaw: range.raw,
|
||||
scopedVars: {
|
||||
__interval: { text: interval, value: interval },
|
||||
|
@ -682,6 +682,7 @@ export class Explore extends React.PureComponent<Props, ExploreState> {
|
||||
width={width}
|
||||
onClose={this.toggleShowQueryInspector}
|
||||
timeZone={timeZone}
|
||||
isMixed={datasourceInstance.meta.mixed || false}
|
||||
/>
|
||||
)}
|
||||
</ErrorBoundaryAlert>
|
||||
|
@ -4,6 +4,7 @@ import AutoSizer from 'react-virtualized-auto-sizer';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
import { LoadingState, InternalTimeZones, getDefaultTimeRange } from '@grafana/data';
|
||||
import { InspectorStream } from 'app/core/services/backend_srv';
|
||||
|
||||
import { ExploreQueryInspector } from './ExploreQueryInspector';
|
||||
|
||||
@ -50,6 +51,7 @@ const setup = (propOverrides = {}) => {
|
||||
exploreId: 'left',
|
||||
onClose: jest.fn(),
|
||||
timeZone: InternalTimeZones.utc,
|
||||
isMixed: false,
|
||||
queryResponse: {
|
||||
state: LoadingState.Done,
|
||||
series: [],
|
||||
@ -143,15 +145,16 @@ describe('ExploreQueryInspector', () => {
|
||||
});
|
||||
});
|
||||
|
||||
const response = (hideFromInspector = false) => ({
|
||||
const response = (hideFromInspector = false): InspectorStream => {
|
||||
return {
|
||||
response: {
|
||||
status: 1,
|
||||
statusText: '',
|
||||
ok: true,
|
||||
headers: {},
|
||||
headers: new Headers(),
|
||||
redirected: false,
|
||||
type: 'basic',
|
||||
url: '',
|
||||
request: {},
|
||||
data: {
|
||||
test: {
|
||||
testKey: 'Very unique test value',
|
||||
@ -161,4 +164,7 @@ const response = (hideFromInspector = false) => ({
|
||||
url: '',
|
||||
hideFromInspector,
|
||||
},
|
||||
});
|
||||
},
|
||||
requestId: 'explore_left',
|
||||
};
|
||||
};
|
||||
|
@ -5,12 +5,14 @@ import { CoreApp, LoadingState } from '@grafana/data';
|
||||
import { reportInteraction } from '@grafana/runtime/src';
|
||||
import { defaultTimeZone, TimeZone } from '@grafana/schema';
|
||||
import { TabbedContainer, TabConfig } from '@grafana/ui';
|
||||
import { requestIdGenerator } from 'app/core/utils/explore';
|
||||
import { ExploreDrawer } from 'app/features/explore/ExploreDrawer';
|
||||
import { InspectDataTab } from 'app/features/inspector/InspectDataTab';
|
||||
import { InspectErrorTab } from 'app/features/inspector/InspectErrorTab';
|
||||
import { InspectJSONTab } from 'app/features/inspector/InspectJSONTab';
|
||||
import { InspectStatsTab } from 'app/features/inspector/InspectStatsTab';
|
||||
import { QueryInspector } from 'app/features/inspector/QueryInspector';
|
||||
import { mixedRequestId } from 'app/plugins/datasource/mixed/MixedDataSource';
|
||||
import { StoreState, ExploreItemState } from 'app/types';
|
||||
|
||||
import { GetDataOptions } from '../query/state/PanelQueryRunner';
|
||||
@ -22,12 +24,13 @@ interface DispatchProps {
|
||||
exploreId: string;
|
||||
timeZone: TimeZone;
|
||||
onClose: () => void;
|
||||
isMixed: boolean;
|
||||
}
|
||||
|
||||
type Props = DispatchProps & ConnectedProps<typeof connector>;
|
||||
|
||||
export function ExploreQueryInspector(props: Props) {
|
||||
const { width, onClose, queryResponse, timeZone } = props;
|
||||
const { width, onClose, queryResponse, timeZone, isMixed, exploreId } = props;
|
||||
const [dataOptions, setDataOptions] = useState<GetDataOptions>({
|
||||
withTransforms: false,
|
||||
withFieldConfig: true,
|
||||
@ -79,7 +82,11 @@ export function ExploreQueryInspector(props: Props) {
|
||||
value: 'query',
|
||||
icon: 'info-circle',
|
||||
content: (
|
||||
<QueryInspector data={queryResponse} onRefreshQuery={() => props.runQueries({ exploreId: props.exploreId })} />
|
||||
<QueryInspector
|
||||
instanceId={isMixed ? mixedRequestId(0, requestIdGenerator(exploreId)) : requestIdGenerator(exploreId)}
|
||||
data={queryResponse}
|
||||
onRefreshQuery={() => props.runQueries({ exploreId })}
|
||||
/>
|
||||
),
|
||||
};
|
||||
|
||||
|
@ -19,6 +19,7 @@ interface ExecutedQueryInfo {
|
||||
}
|
||||
|
||||
interface Props {
|
||||
instanceId?: string; // Must match the prefix of the requestId of the query being inspected. For updating only one instance of the inspector in case of multiple instances, ie Explore split view
|
||||
data: PanelData;
|
||||
onRefreshQuery: () => void;
|
||||
}
|
||||
@ -49,7 +50,15 @@ export class QueryInspector extends PureComponent<Props, State> {
|
||||
componentDidMount() {
|
||||
this.subs.add(
|
||||
backendSrv.getInspectorStream().subscribe({
|
||||
next: (response) => this.onDataSourceResponse(response),
|
||||
next: (response) => {
|
||||
let update = true;
|
||||
if (this.props.instanceId && response?.requestId) {
|
||||
update = response.requestId.startsWith(this.props.instanceId);
|
||||
}
|
||||
if (update) {
|
||||
return this.onDataSourceResponse(response.response);
|
||||
}
|
||||
},
|
||||
})
|
||||
);
|
||||
}
|
||||
|
@ -15,6 +15,8 @@ import { getDataSourceSrv, toDataQueryError } from '@grafana/runtime';
|
||||
|
||||
export const MIXED_DATASOURCE_NAME = '-- Mixed --';
|
||||
|
||||
export const mixedRequestId = (queryIdx: number, requestId?: string) => `mixed-${queryIdx}-${requestId || ''}`;
|
||||
|
||||
export interface BatchedQueries {
|
||||
datasource: Promise<DataSourceApi>;
|
||||
targets: DataQuery[];
|
||||
@ -61,7 +63,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
|
||||
from(query.datasource).pipe(
|
||||
mergeMap((api: DataSourceApi) => {
|
||||
const dsRequest = cloneDeep(request);
|
||||
dsRequest.requestId = `mixed-${i}-${dsRequest.requestId || ''}`;
|
||||
dsRequest.requestId = mixedRequestId(i, dsRequest.requestId);
|
||||
dsRequest.targets = query.targets;
|
||||
|
||||
return from(api.query(dsRequest)).pipe(
|
||||
@ -70,7 +72,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
|
||||
...response,
|
||||
data: response.data || [],
|
||||
state: LoadingState.Loading,
|
||||
key: `mixed-${i}-${response.key || ''}`,
|
||||
key: mixedRequestId(i, response.key),
|
||||
};
|
||||
}),
|
||||
toArray(),
|
||||
@ -83,7 +85,7 @@ export class MixedDatasource extends DataSourceApi<DataQuery> {
|
||||
data: [],
|
||||
state: LoadingState.Error,
|
||||
error: err,
|
||||
key: `mixed-${i}-${dsRequest.requestId || ''}`,
|
||||
key: mixedRequestId(i, dsRequest.requestId),
|
||||
},
|
||||
]);
|
||||
})
|
||||
|
Loading…
Reference in New Issue
Block a user