mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Tempo: Don't show error when running query without traceId (#43676)
* Check for traceId and return EMPTY observable if no value * Make sure we change status on complete * Add tests * Fix test
This commit is contained in:
parent
bac9253fdc
commit
88d17c4998
@ -13,7 +13,7 @@ import {
|
||||
storeLogsVolumeDataProviderAction,
|
||||
} from './query';
|
||||
import { ExploreId, ExploreItemState, StoreState, ThunkDispatch } from 'app/types';
|
||||
import { interval, Observable, of } from 'rxjs';
|
||||
import { EMPTY, interval, Observable, of } from 'rxjs';
|
||||
import {
|
||||
ArrayVector,
|
||||
DataFrame,
|
||||
@ -91,10 +91,8 @@ function setupQueryResponse(state: StoreState) {
|
||||
|
||||
describe('runQueries', () => {
|
||||
it('should pass dataFrames to state even if there is error in response', async () => {
|
||||
setTimeSrv({
|
||||
init() {},
|
||||
} as any);
|
||||
const { dispatch, getState }: { dispatch: ThunkDispatch; getState: () => StoreState } = configureStore({
|
||||
setTimeSrv({ init() {} } as any);
|
||||
const { dispatch, getState } = configureStore({
|
||||
...(defaultInitialState as any),
|
||||
});
|
||||
setupQueryResponse(getState());
|
||||
@ -102,6 +100,17 @@ describe('runQueries', () => {
|
||||
expect(getState().explore[ExploreId.left].showMetrics).toBeTruthy();
|
||||
expect(getState().explore[ExploreId.left].graphResult).toBeDefined();
|
||||
});
|
||||
|
||||
it('should set state to done if query completes without emitting', async () => {
|
||||
setTimeSrv({ init() {} } as any);
|
||||
const { dispatch, getState } = configureStore({
|
||||
...(defaultInitialState as any),
|
||||
});
|
||||
(getState().explore[ExploreId.left].datasourceInstance?.query as Mock).mockReturnValueOnce(EMPTY);
|
||||
await dispatch(runQueries(ExploreId.left));
|
||||
await new Promise((resolve) => setTimeout(() => resolve(''), 500));
|
||||
expect(getState().explore[ExploreId.left].queryResponse.state).toBe(LoadingState.Done);
|
||||
});
|
||||
});
|
||||
|
||||
describe('running queries', () => {
|
||||
|
@ -449,8 +449,8 @@ export const runQueries = (
|
||||
)
|
||||
)
|
||||
)
|
||||
.subscribe(
|
||||
(data) => {
|
||||
.subscribe({
|
||||
next(data) {
|
||||
dispatch(queryStreamUpdatedAction({ exploreId, response: data }));
|
||||
|
||||
// Keep scanning for results if this was the last scanning transaction
|
||||
@ -465,12 +465,15 @@ export const runQueries = (
|
||||
}
|
||||
}
|
||||
},
|
||||
(error) => {
|
||||
error(error) {
|
||||
dispatch(notifyApp(createErrorNotification('Query processing error', error)));
|
||||
dispatch(changeLoadingStateAction({ exploreId, loadingState: LoadingState.Error }));
|
||||
console.error(error);
|
||||
}
|
||||
);
|
||||
},
|
||||
complete() {
|
||||
dispatch(changeLoadingStateAction({ exploreId, loadingState: LoadingState.Done }));
|
||||
},
|
||||
});
|
||||
|
||||
if (live) {
|
||||
dispatch(
|
||||
|
@ -16,6 +16,15 @@ import { DEFAULT_LIMIT, TempoJsonData, TempoDatasource, TempoQuery } from './dat
|
||||
import mockJson from './mockJsonResponse.json';
|
||||
|
||||
describe('Tempo data source', () => {
|
||||
it('returns empty response when traceId is empty', async () => {
|
||||
const ds = new TempoDatasource(defaultSettings);
|
||||
const response = await lastValueFrom(
|
||||
ds.query({ targets: [{ refId: 'refid1', queryType: 'traceId', query: '' } as Partial<TempoQuery>] } as any),
|
||||
{ defaultValue: 'empty' }
|
||||
);
|
||||
expect(response).toBe('empty');
|
||||
});
|
||||
|
||||
it('parses json fields from backend', async () => {
|
||||
setupBackendSrv(
|
||||
new MutableDataFrame({
|
||||
@ -34,7 +43,7 @@ describe('Tempo data source', () => {
|
||||
})
|
||||
);
|
||||
const ds = new TempoDatasource(defaultSettings);
|
||||
const response = await lastValueFrom(ds.query({ targets: [{ refId: 'refid1' }] } as any));
|
||||
const response = await lastValueFrom(ds.query({ targets: [{ refId: 'refid1', query: '12345' }] } as any));
|
||||
|
||||
expect(
|
||||
(response.data[0] as DataFrame).fields.map((f) => ({
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { from, merge, Observable, of, throwError } from 'rxjs';
|
||||
import { EMPTY, from, merge, Observable, of, throwError } from 'rxjs';
|
||||
import { catchError, map, mergeMap, toArray } from 'rxjs/operators';
|
||||
import {
|
||||
DataQuery,
|
||||
@ -41,7 +41,7 @@ export interface TempoJsonData extends DataSourceJsonData {
|
||||
nodeGraph?: NodeGraphOptions;
|
||||
}
|
||||
|
||||
export type TempoQuery = {
|
||||
export interface TempoQuery extends DataQuery {
|
||||
query: string;
|
||||
// Query to find list of traces, e.g., via Loki
|
||||
linkedQuery?: LokiQuery;
|
||||
@ -53,7 +53,7 @@ export type TempoQuery = {
|
||||
maxDuration?: string;
|
||||
limit?: number;
|
||||
serviceMapQuery?: string;
|
||||
} & DataQuery;
|
||||
}
|
||||
|
||||
export const DEFAULT_LIMIT = 20;
|
||||
|
||||
@ -152,22 +152,38 @@ export class TempoDatasource extends DataSourceWithBackend<TempoQuery, TempoJson
|
||||
}
|
||||
|
||||
if (targets.traceId?.length > 0) {
|
||||
const traceRequest: DataQueryRequest<TempoQuery> = { ...options, targets: targets.traceId };
|
||||
subQueries.push(
|
||||
super.query(traceRequest).pipe(
|
||||
map((response) => {
|
||||
if (response.error) {
|
||||
return response;
|
||||
}
|
||||
return transformTrace(response, this.nodeGraph?.enabled);
|
||||
})
|
||||
)
|
||||
);
|
||||
subQueries.push(this.handleTraceIdQuery(options, targets.traceId));
|
||||
}
|
||||
|
||||
return merge(...subQueries);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the simplest of the queries where we have just a trace id and return trace data for it.
|
||||
* @param options
|
||||
* @param targets
|
||||
* @private
|
||||
*/
|
||||
private handleTraceIdQuery(
|
||||
options: DataQueryRequest<TempoQuery>,
|
||||
targets: TempoQuery[]
|
||||
): Observable<DataQueryResponse> {
|
||||
const validTargets = targets.filter((t) => t.query);
|
||||
if (!validTargets.length) {
|
||||
return EMPTY;
|
||||
}
|
||||
|
||||
const traceRequest: DataQueryRequest<TempoQuery> = { ...options, targets: validTargets };
|
||||
return super.query(traceRequest).pipe(
|
||||
map((response) => {
|
||||
if (response.error) {
|
||||
return response;
|
||||
}
|
||||
return transformTrace(response, this.nodeGraph?.enabled);
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async metadataRequest(url: string, params = {}) {
|
||||
return await this._request(url, params, { method: 'GET', hideFromInspector: true }).toPromise();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user