mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
Explore: Add memoization and remove unused props (#18775)
This commit is contained in:
parent
3aa3a45372
commit
6402391638
@ -208,6 +208,7 @@
|
||||
"jquery": "3.4.1",
|
||||
"lodash": "4.17.14",
|
||||
"marked": "0.6.2",
|
||||
"memoize-one": "5.1.1",
|
||||
"moment": "2.24.0",
|
||||
"mousetrap": "1.6.3",
|
||||
"mousetrap-global-bind": "1.1.0",
|
||||
|
@ -5,7 +5,9 @@ const INTERVAL = 150;
|
||||
|
||||
export interface Props {
|
||||
time?: number;
|
||||
renderCount?: number;
|
||||
// Use this to reset the timer. Any value is allowed just need to be !== from the previous.
|
||||
// Keep in mind things like [] !== [] or {} !== {}.
|
||||
resetKey?: any;
|
||||
className?: string;
|
||||
humanize?: boolean;
|
||||
}
|
||||
@ -14,6 +16,9 @@ export interface State {
|
||||
elapsed: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows an incremental time ticker of elapsed time from some event.
|
||||
*/
|
||||
export default class ElapsedTime extends PureComponent<Props, State> {
|
||||
offset: number;
|
||||
timer: number;
|
||||
@ -40,7 +45,7 @@ export default class ElapsedTime extends PureComponent<Props, State> {
|
||||
this.start();
|
||||
}
|
||||
|
||||
if (nextProps.renderCount) {
|
||||
if (nextProps.resetKey !== this.props.resetKey) {
|
||||
clearInterval(this.timer);
|
||||
this.start();
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { hot } from 'react-hot-loader';
|
||||
import { connect } from 'react-redux';
|
||||
import _ from 'lodash';
|
||||
import { AutoSizer } from 'react-virtualized';
|
||||
import memoizeOne from 'memoize-one';
|
||||
|
||||
// Services & Utils
|
||||
import store from 'app/core/store';
|
||||
@ -327,6 +328,9 @@ export class Explore extends React.PureComponent<ExploreProps> {
|
||||
}
|
||||
}
|
||||
|
||||
const ensureQueriesMemoized = memoizeOne(ensureQueries);
|
||||
const getTimeRangeFromUrlMemoized = memoizeOne(getTimeRangeFromUrl);
|
||||
|
||||
function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
|
||||
const explore = state.explore;
|
||||
const { split } = explore;
|
||||
@ -356,8 +360,8 @@ function mapStateToProps(state: StoreState, { exploreId }: ExploreProps) {
|
||||
|
||||
const { datasource, queries, range: urlRange, mode: urlMode, ui } = (urlState || {}) as ExploreUrlState;
|
||||
const initialDatasource = datasource || store.get(lastUsedDatasourceKeyForOrgId(state.user.orgId));
|
||||
const initialQueries: DataQuery[] = ensureQueries(queries);
|
||||
const initialRange = urlRange ? getTimeRangeFromUrl(urlRange, timeZone).raw : DEFAULT_RANGE;
|
||||
const initialQueries: DataQuery[] = ensureQueriesMemoized(queries);
|
||||
const initialRange = urlRange ? getTimeRangeFromUrlMemoized(urlRange, timeZone).raw : DEFAULT_RANGE;
|
||||
|
||||
let newMode: ExploreMode;
|
||||
if (supportedModes.length) {
|
||||
|
@ -1,6 +1,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import { connect } from 'react-redux';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import memoizeOne from 'memoize-one';
|
||||
|
||||
import { ExploreId, ExploreMode } from 'app/types/explore';
|
||||
import { DataSourceSelectItem, ToggleButtonGroup, ToggleButton } from '@grafana/ui';
|
||||
@ -236,6 +237,41 @@ export class UnConnectedExploreToolbar extends PureComponent<Props, {}> {
|
||||
}
|
||||
}
|
||||
|
||||
const getModeOptionsMemoized = memoizeOne(
|
||||
(
|
||||
supportedModes: ExploreMode[],
|
||||
mode: ExploreMode
|
||||
): [Array<SelectableValue<ExploreMode>>, SelectableValue<ExploreMode>] => {
|
||||
const supportedModeOptions: Array<SelectableValue<ExploreMode>> = [];
|
||||
let selectedModeOption = null;
|
||||
for (const supportedMode of supportedModes) {
|
||||
switch (supportedMode) {
|
||||
case ExploreMode.Metrics:
|
||||
const option1 = {
|
||||
value: ExploreMode.Metrics,
|
||||
label: ExploreMode.Metrics,
|
||||
};
|
||||
supportedModeOptions.push(option1);
|
||||
if (mode === ExploreMode.Metrics) {
|
||||
selectedModeOption = option1;
|
||||
}
|
||||
break;
|
||||
case ExploreMode.Logs:
|
||||
const option2 = {
|
||||
value: ExploreMode.Logs,
|
||||
label: ExploreMode.Logs,
|
||||
};
|
||||
supportedModeOptions.push(option2);
|
||||
if (mode === ExploreMode.Logs) {
|
||||
selectedModeOption = option2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [supportedModeOptions, selectedModeOption];
|
||||
}
|
||||
);
|
||||
|
||||
const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps => {
|
||||
const splitted = state.explore.split;
|
||||
const exploreItem = state.explore[exploreId];
|
||||
@ -257,32 +293,7 @@ const mapStateToProps = (state: StoreState, { exploreId }: OwnProps): StateProps
|
||||
const hasLiveOption =
|
||||
datasourceInstance && datasourceInstance.meta && datasourceInstance.meta.streaming ? true : false;
|
||||
|
||||
const supportedModeOptions: Array<SelectableValue<ExploreMode>> = [];
|
||||
let selectedModeOption = null;
|
||||
for (const supportedMode of supportedModes) {
|
||||
switch (supportedMode) {
|
||||
case ExploreMode.Metrics:
|
||||
const option1 = {
|
||||
value: ExploreMode.Metrics,
|
||||
label: ExploreMode.Metrics,
|
||||
};
|
||||
supportedModeOptions.push(option1);
|
||||
if (mode === ExploreMode.Metrics) {
|
||||
selectedModeOption = option1;
|
||||
}
|
||||
break;
|
||||
case ExploreMode.Logs:
|
||||
const option2 = {
|
||||
value: ExploreMode.Logs,
|
||||
label: ExploreMode.Logs,
|
||||
};
|
||||
supportedModeOptions.push(option2);
|
||||
if (mode === ExploreMode.Logs) {
|
||||
selectedModeOption = option2;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
const [supportedModeOptions, selectedModeOption] = getModeOptionsMemoized(supportedModes, mode);
|
||||
|
||||
return {
|
||||
datasourceMissing,
|
||||
|
@ -40,28 +40,10 @@ export interface Props extends Themeable {
|
||||
stopLive: () => void;
|
||||
}
|
||||
|
||||
export interface State {
|
||||
renderCount: number;
|
||||
}
|
||||
|
||||
class LiveLogs extends PureComponent<Props, State> {
|
||||
class LiveLogs extends PureComponent<Props> {
|
||||
private liveEndDiv: HTMLDivElement = null;
|
||||
|
||||
constructor(props: Props) {
|
||||
super(props);
|
||||
this.state = { renderCount: 0 };
|
||||
}
|
||||
|
||||
componentDidUpdate(prevProps: Props) {
|
||||
const prevRows: LogRowModel[] = prevProps.logsResult ? prevProps.logsResult.rows : [];
|
||||
const rows: LogRowModel[] = this.props.logsResult ? this.props.logsResult.rows : [];
|
||||
|
||||
if (prevRows !== rows) {
|
||||
this.setState({
|
||||
renderCount: this.state.renderCount + 1,
|
||||
});
|
||||
}
|
||||
|
||||
if (this.liveEndDiv) {
|
||||
this.liveEndDiv.scrollIntoView(false);
|
||||
}
|
||||
@ -69,7 +51,6 @@ class LiveLogs extends PureComponent<Props, State> {
|
||||
|
||||
render() {
|
||||
const { theme, timeZone } = this.props;
|
||||
const { renderCount } = this.state;
|
||||
const styles = getStyles(theme);
|
||||
const rowsToRender: LogRowModel[] = this.props.logsResult ? this.props.logsResult.rows : [];
|
||||
const showUtc = timeZone === 'utc';
|
||||
@ -109,7 +90,7 @@ class LiveLogs extends PureComponent<Props, State> {
|
||||
</div>
|
||||
<div className={cx([styles.logsRowsIndicator])}>
|
||||
<span>
|
||||
Last line received: <ElapsedTime renderCount={renderCount} humanize={true} /> ago
|
||||
Last line received: <ElapsedTime resetKey={this.props.logsResult} humanize={true} /> ago
|
||||
</span>
|
||||
<LinkButton
|
||||
onClick={this.props.stopLive}
|
||||
|
@ -39,7 +39,6 @@ interface Props {
|
||||
scanning?: boolean;
|
||||
scanRange?: RawTimeRange;
|
||||
dedupStrategy: LogsDedupStrategy;
|
||||
hiddenLogLevels: Set<LogLevel>;
|
||||
onChangeTime: (range: AbsoluteTimeRange) => void;
|
||||
onClickLabel?: (label: string, value: string) => void;
|
||||
onStartScanning?: () => void;
|
||||
|
@ -43,7 +43,6 @@ interface LogsContainerProps {
|
||||
toggleLogLevelAction: typeof toggleLogLevelAction;
|
||||
changeDedupStrategy: typeof changeDedupStrategy;
|
||||
dedupStrategy: LogsDedupStrategy;
|
||||
hiddenLogLevels: Set<LogLevel>;
|
||||
width: number;
|
||||
isLive: boolean;
|
||||
stopLive: typeof changeRefreshIntervalAction;
|
||||
@ -100,7 +99,6 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
||||
scanning,
|
||||
range,
|
||||
width,
|
||||
hiddenLogLevels,
|
||||
isLive,
|
||||
} = this.props;
|
||||
|
||||
@ -131,7 +129,6 @@ export class LogsContainer extends PureComponent<LogsContainerProps> {
|
||||
scanning={scanning}
|
||||
scanRange={range.raw}
|
||||
width={width}
|
||||
hiddenLogLevels={hiddenLogLevels}
|
||||
getRowContext={this.getLogRowContext}
|
||||
/>
|
||||
</Collapse>
|
||||
@ -155,7 +152,6 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
|
||||
} = item;
|
||||
const loading = loadingState === LoadingState.Loading || loadingState === LoadingState.Streaming;
|
||||
const { dedupStrategy } = exploreItemUIStateSelector(item);
|
||||
const hiddenLogLevels = new Set(item.hiddenLogLevels);
|
||||
const dedupedResult = deduplicatedLogsSelector(item);
|
||||
const timeZone = getTimeZone(state.user);
|
||||
|
||||
@ -166,7 +162,6 @@ function mapStateToProps(state: StoreState, { exploreId }: { exploreId: string }
|
||||
scanning,
|
||||
timeZone,
|
||||
dedupStrategy,
|
||||
hiddenLogLevels,
|
||||
dedupedResult,
|
||||
datasourceInstance,
|
||||
isLive,
|
||||
|
@ -2,6 +2,7 @@
|
||||
import React, { PureComponent } from 'react';
|
||||
import _ from 'lodash';
|
||||
import { hot } from 'react-hot-loader';
|
||||
import memoizeOne from 'memoize-one';
|
||||
// @ts-ignore
|
||||
import { connect } from 'react-redux';
|
||||
|
||||
@ -13,7 +14,7 @@ import { changeQuery, modifyQueries, runQueries, addQueryRow } from './state/act
|
||||
|
||||
// Types
|
||||
import { StoreState } from 'app/types';
|
||||
import { TimeRange, AbsoluteTimeRange, toDataFrame, guessFieldTypes } from '@grafana/data';
|
||||
import { TimeRange, AbsoluteTimeRange, toDataFrame, guessFieldTypes, GraphSeriesXY, LoadingState } from '@grafana/data';
|
||||
import { DataQuery, DataSourceApi, QueryFixAction, DataSourceStatus, PanelData, DataQueryError } from '@grafana/ui';
|
||||
import { HistoryItem, ExploreItemState, ExploreId, ExploreMode } from 'app/types/explore';
|
||||
import { Emitter } from 'app/core/utils/emitter';
|
||||
@ -198,6 +199,17 @@ export class QueryRow extends PureComponent<QueryRowProps, QueryRowState> {
|
||||
}
|
||||
}
|
||||
|
||||
const makeQueryResponseMemoized = memoizeOne(
|
||||
(graphResult: GraphSeriesXY[], error: DataQueryError, loadingState: LoadingState): PanelData => {
|
||||
const series = graphResult ? graphResult.map(serie => guessFieldTypes(toDataFrame(serie))) : []; // TODO: use DataFrame
|
||||
return {
|
||||
series,
|
||||
state: loadingState,
|
||||
error,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function mapStateToProps(state: StoreState, { exploreId, index }: QueryRowProps) {
|
||||
const explore = state.explore;
|
||||
const item: ExploreItemState = explore[exploreId];
|
||||
@ -217,12 +229,7 @@ function mapStateToProps(state: StoreState, { exploreId, index }: QueryRowProps)
|
||||
const query = queries[index];
|
||||
const datasourceStatus = datasourceError ? DataSourceStatus.Disconnected : DataSourceStatus.Connected;
|
||||
const error = queryErrors.filter(queryError => queryError.refId === query.refId)[0];
|
||||
const series = graphResult ? graphResult.map(serie => guessFieldTypes(toDataFrame(serie))) : []; // TODO: use DataFrame
|
||||
const queryResponse: PanelData = {
|
||||
series,
|
||||
state: loadingState,
|
||||
error,
|
||||
};
|
||||
const queryResponse = makeQueryResponseMemoized(graphResult, error, loadingState);
|
||||
|
||||
return {
|
||||
datasourceInstance,
|
||||
|
@ -11741,6 +11741,11 @@ mem@^4.0.0:
|
||||
mimic-fn "^2.0.0"
|
||||
p-is-promise "^2.0.0"
|
||||
|
||||
memoize-one@5.1.1:
|
||||
version "5.1.1"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.1.1.tgz#047b6e3199b508eaec03504de71229b8eb1d75c0"
|
||||
integrity sha512-HKeeBpWvqiVJD57ZUAsJNm71eHTykffzcLZVYWiVfQeI1rJtuEaS7hQiEpWfVVk18donPwJEcFKIkCmPJNOhHA==
|
||||
|
||||
"memoize-one@>=3.1.1 <6", memoize-one@^5.0.0:
|
||||
version "5.0.4"
|
||||
resolved "https://registry.yarnpkg.com/memoize-one/-/memoize-one-5.0.4.tgz#005928aced5c43d890a4dfab18ca908b0ec92cbc"
|
||||
@ -15485,10 +15490,6 @@ redux-mock-store@1.5.3:
|
||||
dependencies:
|
||||
lodash.isplainobject "^4.0.6"
|
||||
|
||||
redux-observable@1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/redux-observable/-/redux-observable-1.1.0.tgz#323a8fe53e89fdb519be2807b55f08e21c13e6f1"
|
||||
|
||||
redux-thunk@2.3.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/redux-thunk/-/redux-thunk-2.3.0.tgz#51c2c19a185ed5187aaa9a2d08b666d0d6467622"
|
||||
|
Loading…
Reference in New Issue
Block a user