PanelData: move preProcessPanelData to @grafana/data (#63743)

This commit is contained in:
Torkel Ödegaard 2023-03-06 10:59:47 +01:00 committed by GitHub
parent 15fb7e99d9
commit 4bf23b7f5f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 42 additions and 63 deletions

View File

@ -20,6 +20,8 @@ import {
TIME_SERIES_VALUE_FIELD_NAME,
TIME_SERIES_TIME_FIELD_NAME,
DataQueryResponseData,
PanelData,
LoadingState,
} from '../types/index';
import { ArrayVector } from '../vector/ArrayVector';
import { SortedVector } from '../vector/SortedVector';
@ -537,3 +539,37 @@ export function getProcessedDataFrames(results?: DataQueryResponseData[]): DataF
return results.map((data) => getProcessedDataFrame(data));
}
/**
* Will process the panel data frames and in case of loading state with no data, will return the last result data but with loading state
* This is to have panels not flicker temporarily with "no data" while loading
*/
export function preProcessPanelData(data: PanelData, lastResult?: PanelData): PanelData {
const { series, annotations } = data;
// for loading states with no data, use last result
if (data.state === LoadingState.Loading && series.length === 0) {
if (!lastResult) {
lastResult = data;
}
return {
...lastResult,
state: LoadingState.Loading,
request: data.request,
};
}
// Make sure the data frames are properly formatted
const STARTTIME = performance.now();
const processedDataFrames = series.map((data) => getProcessedDataFrame(data));
const annotationsProcessed = getProcessedDataFrames(annotations);
const STOPTIME = performance.now();
return {
...data,
series: processedDataFrames,
annotations: annotationsProcessed,
timings: { dataProcessingTime: STOPTIME - STARTTIME },
};
}

View File

@ -11,13 +11,13 @@ import {
rangeUtil,
TimeRange,
withLoadingIndicator,
preProcessPanelData,
} from '@grafana/data';
import { FetchResponse, getDataSourceSrv, toDataQueryError } from '@grafana/runtime';
import { BackendSrv, getBackendSrv } from 'app/core/services/backend_srv';
import { isExpressionQuery } from 'app/features/expressions/guards';
import { cancelNetworkRequestsOnUnsubscribe } from 'app/features/query/state/processing/canceler';
import { setStructureRevision } from 'app/features/query/state/processing/revision';
import { preProcessPanelData } from 'app/features/query/state/runRequest';
import { AlertQuery } from 'app/types/unified-alerting-dto';
import { getTimeRangeForExpression } from '../utils/timeRange';

View File

@ -9,6 +9,7 @@ import {
getDisplayProcessor,
PanelData,
standardTransformers,
preProcessPanelData,
} from '@grafana/data';
import { config } from '@grafana/runtime';
import { DataQuery } from '@grafana/schema';
@ -19,7 +20,6 @@ import { ExplorePanelData } from '../../../types';
import { CorrelationData } from '../../correlations/useCorrelations';
import { attachCorrelationsToDataFrames } from '../../correlations/utils';
import { sortLogsResult } from '../../logs/utils';
import { preProcessPanelData } from '../../query/state/runRequest';
/**
* When processing response first we try to determine what kind of dataframes we got as one query can return multiple

View File

@ -25,6 +25,7 @@ import {
TimeZone,
toDataFrame,
transformDataFrame,
preProcessPanelData,
} from '@grafana/data';
import { getTemplateSrv, toDataQueryError } from '@grafana/runtime';
import { ExpressionDatasourceRef } from '@grafana/runtime/src/utils/DataSourceWithBackend';
@ -38,7 +39,7 @@ import { PanelModel } from '../../dashboard/state';
import { getDashboardQueryRunner } from './DashboardQueryRunner/DashboardQueryRunner';
import { mergePanelAndDashData } from './mergePanelAndDashData';
import { preProcessPanelData, runRequest } from './runRequest';
import { runRequest } from './runRequest';
export interface QueryRunnerOptions<
TQuery extends DataQuery = DataQuery,

View File

@ -13,13 +13,14 @@ import {
QueryRunner as QueryRunnerSrv,
LoadingState,
DataSourceRef,
preProcessPanelData,
} from '@grafana/data';
import { getTemplateSrv } from '@grafana/runtime';
import { getDatasourceSrv } from 'app/features/plugins/datasource_srv';
import { getNextRequestId } from './PanelQueryRunner';
import { setStructureRevision } from './processing/revision';
import { preProcessPanelData, runRequest } from './runRequest';
import { runRequest } from './runRequest';
export class QueryRunner implements QueryRunnerSrv {
private subject: ReplaySubject<PanelData>;

View File

@ -7,7 +7,6 @@ import { catchError, map, mapTo, share, takeUntil, tap } from 'rxjs/operators';
// Types
import {
CoreApp,
DataFrame,
DataQueryError,
DataQueryRequest,
DataQueryResponse,
@ -15,11 +14,9 @@ import {
DataSourceApi,
DataTopic,
dateMath,
guessFieldTypes,
LoadingState,
PanelData,
TimeRange,
toDataFrame,
} from '@grafana/data';
import { toDataQueryError } from '@grafana/runtime';
import { isExpressionReference } from '@grafana/runtime/src/utils/DataSourceWithBackend';
@ -204,59 +201,3 @@ export function callQueryMethod(
const returnVal = queryFunction ? queryFunction(request) : datasource.query(request);
return from(returnVal);
}
function getProcessedDataFrame(data: DataQueryResponseData): DataFrame {
const dataFrame = guessFieldTypes(toDataFrame(data));
if (dataFrame.fields && dataFrame.fields.length) {
// clear out the cached info
for (const field of dataFrame.fields) {
field.state = null;
}
}
return dataFrame;
}
/**
* All panels will be passed tables that have our best guess at column type set
*
* This is also used by PanelChrome for snapshot support
*/
export function getProcessedDataFrames(results?: DataQueryResponseData[]): DataFrame[] {
if (!results || !isArray(results)) {
return [];
}
return results.map((data) => getProcessedDataFrame(data));
}
export function preProcessPanelData(data: PanelData, lastResult?: PanelData): PanelData {
const { series, annotations } = data;
// for loading states with no data, use last result
if (data.state === LoadingState.Loading && series.length === 0) {
if (!lastResult) {
lastResult = data;
}
return {
...lastResult,
state: LoadingState.Loading,
request: data.request,
};
}
// Make sure the data frames are properly formatted
const STARTTIME = performance.now();
const processedDataFrames = series.map((data) => getProcessedDataFrame(data));
const annotationsProcessed = getProcessedDataFrames(annotations);
const STOPTIME = performance.now();
return {
...data,
series: processedDataFrames,
annotations: annotationsProcessed,
timings: { dataProcessingTime: STOPTIME - STARTTIME },
};
}