Skip to content

Commit 409874b

Browse files
hugohaggmarktorkelo
authored andcommitted
Explore: Introduces PanelData to ExploreItemState (grafana#18804)
* WIP: inital POC * Wip: Moving forward * Wip * Refactor: Makes loading indicator work for Prometheus * Refactor: Reverts prom observable queries because they did not work for multiple targets * Refactor: Transforms all epics into thunks * Fix: Fixes scanning * Fix: Fixes so that Instant and TimeSeries Prom query loads in parallel * Fix: Fixes negation logic error * Wip: Introduces PanelData as a carries for query responses * Refactor: Makes errors work again * Refactor: Simplifies code somewhat and removes comments * Tests: Fixes broken tests * Fix query latency * Remove unused code
1 parent 6912ed5 commit 409874b

File tree

15 files changed

+178
-433
lines changed

15 files changed

+178
-433
lines changed

emails/package.json

-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
"build": "grunt",
1313
"start": "grunt watch"
1414
},
15-
1615
"devDependencies": {
1716
"grunt": "^0.4.5",
1817
"grunt-premailer": "^1.1.10",

public/app/core/utils/explore.ts

+2-28
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
// Libraries
22
import _ from 'lodash';
3-
import { from } from 'rxjs';
43
import { isLive } from '@grafana/ui/src/components/RefreshPicker/RefreshPicker';
54
// Services & Utils
65
import {
@@ -9,25 +8,16 @@ import {
98
TimeRange,
109
RawTimeRange,
1110
TimeZone,
12-
IntervalValues,
1311
TimeFragment,
1412
LogRowModel,
1513
LogsModel,
1614
LogsDedupStrategy,
1715
} from '@grafana/data';
1816
import { renderUrl } from 'app/core/utils/url';
19-
import kbn from 'app/core/utils/kbn';
2017
import store from 'app/core/store';
2118
import { getNextRefIdChar } from './query';
2219
// Types
23-
import {
24-
DataQuery,
25-
DataSourceApi,
26-
DataQueryError,
27-
DataSourceJsonData,
28-
DataQueryRequest,
29-
DataStreamObserver,
30-
} from '@grafana/ui';
20+
import { DataQuery, DataSourceApi, DataQueryError } from '@grafana/ui';
3121
import {
3222
ExploreUrlState,
3323
HistoryItem,
@@ -321,14 +311,6 @@ export function hasNonEmptyQuery<TQuery extends DataQuery = any>(queries: TQuery
321311
);
322312
}
323313

324-
export function getIntervals(range: TimeRange, lowLimit: string, resolution: number): IntervalValues {
325-
if (!resolution) {
326-
return { interval: '1s', intervalMs: 1000 };
327-
}
328-
329-
return kbn.calculateInterval(range, resolution, lowLimit);
330-
}
331-
332314
/**
333315
* Update the query history. Side-effect: store history in local storage
334316
*/
@@ -448,7 +430,7 @@ export const getFirstQueryErrorWithoutRefId = (errors: DataQueryError[]) => {
448430
return null;
449431
}
450432

451-
return errors.filter(error => (error.refId ? false : true))[0];
433+
return errors.filter(error => (error && error.refId ? false : true))[0];
452434
};
453435

454436
export const getRefIds = (value: any): string[] => {
@@ -523,14 +505,6 @@ export const convertToWebSocketUrl = (url: string) => {
523505
return `${backend}${url}`;
524506
};
525507

526-
export const getQueryResponse = (
527-
datasourceInstance: DataSourceApi<DataQuery, DataSourceJsonData>,
528-
options: DataQueryRequest<DataQuery>,
529-
observer?: DataStreamObserver
530-
) => {
531-
return from(datasourceInstance.query(options, observer));
532-
};
533-
534508
export const stopQueryState = (queryState: PanelQueryState, reason: string) => {
535509
if (queryState && queryState.isStarted()) {
536510
queryState.cancel(reason);

public/app/features/dashboard/state/PanelQueryState.ts

+5-2
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,10 @@ export class PanelQueryState {
9595
}
9696

9797
execute(ds: DataSourceApi, req: DataQueryRequest): Promise<PanelData> {
98-
this.request = req;
98+
this.request = {
99+
...req,
100+
startTime: Date.now(),
101+
};
99102
this.datasource = ds;
100103

101104
// Return early if there are no queries to run
@@ -112,7 +115,7 @@ export class PanelQueryState {
112115
);
113116
}
114117

115-
// Set the loading state immediatly
118+
// Set the loading state immediately
116119
this.response.state = LoadingState.Loading;
117120
this.executor = new Promise<PanelData>((resolve, reject) => {
118121
this.rejector = reject;

public/app/features/explore/Explore.tsx

+8-15
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,17 @@ import React, { ComponentClass } from 'react';
33
import { hot } from 'react-hot-loader';
44
// @ts-ignore
55
import { connect } from 'react-redux';
6-
import _ from 'lodash';
76
import { AutoSizer } from 'react-virtualized';
87
import memoizeOne from 'memoize-one';
98

109
// Services & Utils
1110
import store from 'app/core/store';
12-
1311
// Components
14-
import { Alert } from '@grafana/ui';
12+
import { Alert, DataQuery, ExploreStartPageProps, DataSourceApi, PanelData } from '@grafana/ui';
1513
import { ErrorBoundary } from './ErrorBoundary';
1614
import LogsContainer from './LogsContainer';
1715
import QueryRows from './QueryRows';
1816
import TableContainer from './TableContainer';
19-
2017
// Actions
2118
import {
2219
changeSize,
@@ -29,11 +26,8 @@ import {
2926
updateTimeRange,
3027
toggleGraph,
3128
} from './state/actions';
32-
3329
// Types
34-
import { RawTimeRange, GraphSeriesXY, LoadingState, TimeZone, AbsoluteTimeRange } from '@grafana/data';
35-
36-
import { DataQuery, ExploreStartPageProps, DataSourceApi, DataQueryError } from '@grafana/ui';
30+
import { RawTimeRange, GraphSeriesXY, TimeZone, AbsoluteTimeRange } from '@grafana/data';
3731
import {
3832
ExploreItemState,
3933
ExploreUrlState,
@@ -86,7 +80,6 @@ interface ExploreProps {
8680
initialRange: RawTimeRange;
8781
mode: ExploreMode;
8882
initialUI: ExploreUIState;
89-
queryErrors: DataQueryError[];
9083
isLive: boolean;
9184
updateTimeRange: typeof updateTimeRange;
9285
graphResult?: GraphSeriesXY[];
@@ -97,6 +90,7 @@ interface ExploreProps {
9790
timeZone?: TimeZone;
9891
onHiddenSeriesChanged?: (hiddenSeries: string[]) => void;
9992
toggleGraph: typeof toggleGraph;
93+
queryResponse: PanelData;
10094
}
10195

10296
/**
@@ -243,14 +237,14 @@ export class Explore extends React.PureComponent<ExploreProps> {
243237
showingStartPage,
244238
split,
245239
queryKeys,
246-
queryErrors,
247240
mode,
248241
graphResult,
249242
loading,
250243
absoluteRange,
251244
showingGraph,
252245
showingTable,
253246
timeZone,
247+
queryResponse,
254248
} = this.props;
255249
const exploreClass = split ? 'explore explore-split' : 'explore';
256250

@@ -272,7 +266,7 @@ export class Explore extends React.PureComponent<ExploreProps> {
272266
{datasourceInstance && (
273267
<div className="explore-container">
274268
<QueryRows exploreEvents={this.exploreEvents} exploreId={exploreId} queryKeys={queryKeys} />
275-
<ErrorContainer queryErrors={queryErrors} />
269+
<ErrorContainer queryErrors={[queryResponse.error]} />
276270
<AutoSizer onResize={this.onResize} disableHeight>
277271
{({ width }) => {
278272
if (width === 0) {
@@ -347,15 +341,15 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
347341
queryKeys,
348342
urlState,
349343
update,
350-
queryErrors,
351344
isLive,
352345
supportedModes,
353346
mode,
354347
graphResult,
355-
loadingState,
348+
loading,
356349
showingGraph,
357350
showingTable,
358351
absoluteRange,
352+
queryResponse,
359353
} = item;
360354

361355
const { datasource, queries, range: urlRange, mode: urlMode, ui } = (urlState || {}) as ExploreUrlState;
@@ -380,7 +374,6 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
380374
}
381375

382376
const initialUI = ui || DEFAULT_UI_STATE;
383-
const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
384377

385378
return {
386379
StartPage,
@@ -398,13 +391,13 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
398391
initialRange,
399392
mode: newMode,
400393
initialUI,
401-
queryErrors,
402394
isLive,
403395
graphResult,
404396
loading,
405397
showingGraph,
406398
showingTable,
407399
absoluteRange,
400+
queryResponse,
408401
};
409402
}
410403

public/app/features/explore/ExploreToolbar.tsx

+2-3
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import memoizeOne from 'memoize-one';
55

66
import { ExploreId, ExploreMode } from 'app/types/explore';
77
import { DataSourceSelectItem, ToggleButtonGroup, ToggleButton } from '@grafana/ui';
8-
import { RawTimeRange, TimeZone, TimeRange, LoadingState, SelectableValue } from '@grafana/data';
8+
import { RawTimeRange, TimeZone, TimeRange, SelectableValue } from '@grafana/data';
99
import { DataSourcePicker } from 'app/core/components/Select/DataSourcePicker';
1010
import { StoreState } from 'app/types/store';
1111
import {
@@ -281,15 +281,14 @@ const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps
281281
exploreDatasources,
282282
range,
283283
refreshInterval,
284-
loadingState,
284+
loading,
285285
supportedModes,
286286
mode,
287287
isLive,
288288
} = exploreItem;
289289
const selectedDatasource = datasourceInstance
290290
? exploreDatasources.find(datasource => datasource.name === datasourceInstance.name)
291291
: undefined;
292-
const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
293292
const hasLiveOption =
294293
datasourceInstance && datasourceInstance.meta && datasourceInstance.meta.streaming ? true : false;
295294

public/app/features/explore/LogsContainer.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
LogsModel,
1212
LogRowModel,
1313
LogsDedupStrategy,
14-
LoadingState,
1514
TimeRange,
1615
} from '@grafana/data';
1716

@@ -143,14 +142,13 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
143142
const {
144143
logsHighlighterExpressions,
145144
logsResult,
146-
loadingState,
145+
loading,
147146
scanning,
148147
datasourceInstance,
149148
isLive,
150149
range,
151150
absoluteRange,
152151
} = item;
153-
const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
154152
const { dedupStrategy } = exploreItemUIStateSelector(item);
155153
const dedupedResult = deduplicatedLogsSelector(item);
156154
const timeZone = getTimeZone(state.user);

public/app/features/explore/QueryRow.tsx

+4-25
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,16 @@
22
import React, { PureComponent } from 'react';
33
import _ from 'lodash';
44
import { hot } from 'react-hot-loader';
5-
import memoizeOne from 'memoize-one';
65
// @ts-ignore
76
import { connect } from 'react-redux';
8-
97
// Components
108
import QueryEditor from './QueryEditor';
11-
129
// Actions
1310
import { changeQuery, modifyQueries, runQueries, addQueryRow } from './state/actions';
14-
1511
// Types
1612
import { StoreState } from 'app/types';
17-
import { TimeRange, AbsoluteTimeRange, toDataFrame, guessFieldTypes, GraphSeriesXY, LoadingState } from '@grafana/data';
18-
import { DataQuery, DataSourceApi, QueryFixAction, DataSourceStatus, PanelData, DataQueryError } from '@grafana/ui';
13+
import { TimeRange, AbsoluteTimeRange } from '@grafana/data';
14+
import { DataQuery, DataSourceApi, QueryFixAction, DataSourceStatus, PanelData } from '@grafana/ui';
1915
import { HistoryItem, ExploreItemState, ExploreId, ExploreMode } from 'app/types/explore';
2016
import { Emitter } from 'app/core/utils/emitter';
2117
import { highlightLogsExpressionAction, removeQueryRowAction } from './state/actionTypes';
@@ -44,7 +40,6 @@ interface QueryRowProps extends PropsFromParent {
4440
runQueries: typeof runQueries;
4541
queryResponse: PanelData;
4642
latency: number;
47-
queryErrors: DataQueryError[];
4843
mode: ExploreMode;
4944
}
5045

@@ -122,11 +117,11 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
122117
datasourceStatus,
123118
queryResponse,
124119
latency,
125-
queryErrors,
126120
mode,
127121
} = this.props;
128122
const canToggleEditorModes =
129123
mode === ExploreMode.Metrics && _.has(datasourceInstance, 'components.QueryCtrl.prototype.toggleEditorMode');
124+
const queryErrors = queryResponse.error && queryResponse.error.refId === query.refId ? [queryResponse.error] : [];
130125
let QueryField;
131126

132127
if (mode === ExploreMode.Metrics && datasourceInstance.components.ExploreMetricsQueryField) {
@@ -199,17 +194,6 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
199194
}
200195
}
201196

202-
const makeQueryResponseMemoized = memoizeOne(
203-
(graphResult: GraphSeriesXY[], error: DataQueryError, loadingState: LoadingState): PanelData => {
204-
const series = graphResult ? graphResult.map(serie => guessFieldTypes(toDataFrame(serie))) : []; // TODO: use DataFrame
205-
return {
206-
series,
207-
state: loadingState,
208-
error,
209-
};
210-
}
211-
);
212-
213197
function mapStateToProps(state: StoreState, { exploreId, index }: QueryRowProps) {
214198
const explore = state.explore;
215199
const item: ExploreItemState = explore[exploreId];
@@ -220,16 +204,12 @@ function mapStateToProps(state: StoreState, { exploreId, index }: QueryRowProps)
220204
range,
221205
absoluteRange,
222206
datasourceError,
223-
graphResult,
224-
loadingState,
225207
latency,
226-
queryErrors,
227208
mode,
209+
queryResponse,
228210
} = item;
229211
const query = queries[index];
230212
const datasourceStatus = datasourceError ? DataSourceStatus.Disconnected : DataSourceStatus.Connected;
231-
const error = queryErrors.filter(queryError => queryError.refId === query.refId)[0];
232-
const queryResponse = makeQueryResponseMemoized(graphResult, error, loadingState);
233213

234214
return {
235215
datasourceInstance,
@@ -240,7 +220,6 @@ function mapStateToProps(state: StoreState, { exploreId, index }: QueryRowProps)
240220
datasourceStatus,
241221
queryResponse,
242222
latency,
243-
queryErrors,
244223
mode,
245224
};
246225
}

public/app/features/explore/TableContainer.tsx

+2-6
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import React, { PureComponent } from 'react';
22
import { hot } from 'react-hot-loader';
33
import { connect } from 'react-redux';
4-
import { LoadingState } from '@grafana/data';
54
import { Collapse } from '@grafana/ui';
65

76
import { ExploreId, ExploreItemState } from 'app/types/explore';
@@ -40,11 +39,8 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
4039
const explore = state.explore;
4140
// @ts-ignore
4241
const item: ExploreItemState = explore[exploreId];
43-
const { loadingState, showingTable, tableResult } = item;
44-
const loading =
45-
tableResult && tableResult.rows.length > 0
46-
? false
47-
: loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
42+
const { loading: loadingInState, showingTable, tableResult } = item;
43+
const loading = tableResult && tableResult.rows.length > 0 ? false : loadingInState;
4844
return { loading, showingTable, tableResult };
4945
}
5046

0 commit comments

Comments
 (0)