Explorar el Código

Explore: Add memoization and remove unused props (#18775)

Andrej Ocenas hace 6 años
padre
commit
6402391638

+ 1 - 0
package.json

@@ -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",

+ 7 - 2
public/app/features/explore/ElapsedTime.tsx

@@ -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();
     }

+ 6 - 2
public/app/features/explore/Explore.tsx

@@ -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) {

+ 37 - 26
public/app/features/explore/ExploreToolbar.tsx

@@ -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,

+ 2 - 21
public/app/features/explore/LiveLogs.tsx

@@ -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}

+ 0 - 1
public/app/features/explore/Logs.tsx

@@ -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;

+ 0 - 5
public/app/features/explore/LogsContainer.tsx

@@ -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,

+ 14 - 7
public/app/features/explore/QueryRow.tsx

@@ -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,

+ 5 - 4
yarn.lock

@@ -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"