David Kaltschmidt 7 лет назад
Родитель
Сommit
593cc38cfc

+ 24 - 10
public/app/features/explore/Explore.tsx

@@ -97,6 +97,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
    * Local ID cache to compare requested vs selected datasource
    */
   requestedDatasourceId: string;
+  scanTimer: NodeJS.Timer;
   /**
    * Timepicker to control scanning
    */
@@ -170,6 +171,10 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
     }
   }
 
+  componentWillUnmount() {
+    clearTimeout(this.scanTimer);
+  }
+
   async setDatasource(datasource: any, origin?: DataSource) {
     const supportsGraph = datasource.meta.metrics;
     const supportsLogs = datasource.meta.logs;
@@ -328,7 +333,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
       ...nextRange,
     };
     if (this.state.scanning && !scanning) {
-      this.stopScanOlder();
+      this.onStopScanning();
     }
     this.setState({ range, scanning }, () => this.onSubmit());
   };
@@ -505,16 +510,22 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
     );
   };
 
-  onStartScanOlder = () => {
-    this.setState({ scanning: true }, this.scanOlder);
+  onStartScanning = () => {
+    this.setState({ scanning: true }, this.scanPreviousRange);
   };
 
-  scanOlder = () => {
-    this.timepickerRef.current.move(-1, true);
+  scanPreviousRange = () => {
+    const scanRange = this.timepickerRef.current.move(-1, true);
+    this.setState({ scanRange });
   };
 
-  stopScanOlder = () => {
-    // Stop ongoing scan transactions
+  onStopScanning = () => {
+    clearTimeout(this.scanTimer);
+    this.setState(state => {
+      const { queryTransactions } = state;
+      const nextQueryTransactions = queryTransactions.filter(qt => qt.scanning && !qt.done);
+      return { queryTransactions: nextQueryTransactions, scanning: false, scanRange: undefined };
+    });
   };
 
   onSubmit = () => {
@@ -651,11 +662,11 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
 
       const nextHistory = updateHistory(history, datasourceId, queries);
 
+      // Keep scanning for results if this was the last scanning transaction
       if (_.size(result) === 0 && scanning) {
-        // Keep scanning if this was the last scanning transaction
         const other = nextQueryTransactions.find(qt => qt.scanning && !qt.done);
         if (!other) {
-          setTimeout(this.scanOlder, 1000);
+          this.scanTimer = setTimeout(this.scanPreviousRange, 1000);
         }
       }
 
@@ -771,6 +782,7 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
       queryTransactions,
       range,
       scanning,
+      scanRange,
       showingGraph,
       showingLogs,
       showingStartPage,
@@ -929,9 +941,11 @@ export class Explore extends React.PureComponent<ExploreProps, ExploreState> {
                           loading={logsLoading}
                           position={position}
                           onChangeTime={this.onChangeTime}
-                          onStartScanOlder={this.onStartScanOlder}
+                          onStartScanning={this.onStartScanning}
+                          onStopScanning={this.onStopScanning}
                           range={range}
                           scanning={scanning}
+                          scanRange={scanRange}
                         />
                       </Panel>
                     )}

+ 28 - 13
public/app/features/explore/Logs.tsx

@@ -1,6 +1,7 @@
 import React, { Fragment, PureComponent } from 'react';
 import Highlighter from 'react-highlight-words';
 
+import * as rangeUtil from 'app/core/utils/rangeutil';
 import { RawTimeRange } from 'app/types/series';
 import { LogsDedupStrategy, LogsModel, dedupLogRows, filterLogLevels, LogLevel } from 'app/core/logs_model';
 import { findHighlightChunksInText } from 'app/core/utils/text';
@@ -29,8 +30,10 @@ interface LogsProps {
   position: string;
   range?: RawTimeRange;
   scanning?: boolean;
+  scanRange?: RawTimeRange;
   onChangeTime?: (range: RawTimeRange) => void;
-  onStartScanOlder?: () => void;
+  onStartScanning?: () => void;
+  onStopScanning?: () => void;
 }
 
 interface LogsState {
@@ -85,13 +88,18 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
     this.setState({ hiddenLogLevels });
   };
 
-  onClickScanOlder = (event: React.SyntheticEvent) => {
+  onClickScan = (event: React.SyntheticEvent) => {
     event.preventDefault();
-    this.props.onStartScanOlder();
+    this.props.onStartScanning();
+  };
+
+  onClickStopScan = (event: React.SyntheticEvent) => {
+    event.preventDefault();
+    this.props.onStopScanning();
   };
 
   render() {
-    const { className = '', data, loading = false, position, range, scanning } = this.props;
+    const { className = '', data, loading = false, position, range, scanning, scanRange } = this.props;
     const { dedup, hiddenLogLevels, showLabels, showLocalTime, showUtc } = this.state;
     const hasData = data && data.rows && data.rows.length > 0;
     const filteredData = filterLogLevels(data, hiddenLogLevels);
@@ -118,6 +126,7 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
     const logEntriesStyle = {
       gridTemplateColumns: cssColumnSizes.join(' '),
     };
+    const scanText = scanRange ? `Scanning ${rangeUtil.describeTimeRange(scanRange)}` : 'Scanning...';
 
     return (
       <div className={`${className} logs`}>
@@ -208,18 +217,24 @@ export default class Logs extends PureComponent<LogsProps, LogsState> {
             ))}
         </div>
         {!loading &&
-          !hasData && (
-            <div>
+          !hasData &&
+          !scanning && (
+            <div className="logs-nodata">
               No logs found.
-              {scanning ? (
-                'Scanning...'
-              ) : (
-                <a className="link" onClick={this.onClickScanOlder}>
-                  Scan for older logs
-                </a>
-              )}
+              <a className="link" onClick={this.onClickScan}>
+                Scan for older logs
+              </a>
             </div>
           )}
+
+        {scanning && (
+          <div className="logs-nodata">
+            <span>{scanText}</span>
+            <a className="link" onClick={this.onClickStopScan}>
+              Stop scan
+            </a>
+          </div>
+        )}
       </div>
     );
   }

+ 3 - 1
public/app/features/explore/TimePicker.tsx

@@ -92,7 +92,7 @@ export default class TimePicker extends PureComponent<TimePickerProps, TimePicke
     };
   }
 
-  move(direction: number, scanning?: boolean) {
+  move(direction: number, scanning?: boolean): RawTimeRange {
     const { onChangeTime } = this.props;
     const { fromRaw, toRaw } = this.state;
     const from = dateMath.parse(fromRaw, false);
@@ -131,6 +131,8 @@ export default class TimePicker extends PureComponent<TimePickerProps, TimePicke
         onChangeTime(nextRange, scanning);
       }
     );
+
+    return nextRange;
   }
 
   handleChangeFrom = e => {

+ 1 - 0
public/app/types/explore.ts

@@ -164,6 +164,7 @@ export interface ExploreState {
   queryTransactions: QueryTransaction[];
   range: RawTimeRange;
   scanning?: boolean;
+  scanRange?: RawTimeRange;
   showingGraph: boolean;
   showingLogs: boolean;
   showingStartPage?: boolean;

+ 6 - 0
public/sass/pages/_explore.scss

@@ -267,6 +267,12 @@
       }
     }
 
+    .logs-nodata {
+      > * {
+        margin-left: 0.5em;
+      }
+    }
+
     .logs-meta {
       flex: 1;
       color: $text-color-weak;