diff --git a/public/app/features/explore/Explore.tsx b/public/app/features/explore/Explore.tsx index d451dc6ea56..44380877c34 100644 --- a/public/app/features/explore/Explore.tsx +++ b/public/app/features/explore/Explore.tsx @@ -97,6 +97,7 @@ export class Explore extends React.PureComponent { * 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 { } } + 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 { ...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 { ); }; - 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 { 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 { queryTransactions, range, scanning, + scanRange, showingGraph, showingLogs, showingStartPage, @@ -929,9 +941,11 @@ export class Explore extends React.PureComponent { loading={logsLoading} position={position} onChangeTime={this.onChangeTime} - onStartScanOlder={this.onStartScanOlder} + onStartScanning={this.onStartScanning} + onStopScanning={this.onStopScanning} range={range} scanning={scanning} + scanRange={scanRange} /> )} diff --git a/public/app/features/explore/Logs.tsx b/public/app/features/explore/Logs.tsx index 37feb719f63..58965df4514 100644 --- a/public/app/features/explore/Logs.tsx +++ b/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 { 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 { const logEntriesStyle = { gridTemplateColumns: cssColumnSizes.join(' '), }; + const scanText = scanRange ? `Scanning ${rangeUtil.describeTimeRange(scanRange)}` : 'Scanning...'; return (
@@ -208,18 +217,24 @@ export default class Logs extends PureComponent { ))}
{!loading && - !hasData && ( -
+ !hasData && + !scanning && ( +
No logs found. - {scanning ? ( - 'Scanning...' - ) : ( - - Scan for older logs - - )} + + Scan for older logs +
)} + + {scanning && ( +
+ {scanText} + + Stop scan + +
+ )}
); } diff --git a/public/app/features/explore/TimePicker.tsx b/public/app/features/explore/TimePicker.tsx index ebfb23087d2..47c52b07292 100644 --- a/public/app/features/explore/TimePicker.tsx +++ b/public/app/features/explore/TimePicker.tsx @@ -92,7 +92,7 @@ export default class TimePicker extends PureComponent { diff --git a/public/app/types/explore.ts b/public/app/types/explore.ts index 3aef458bd54..d9ace7b74c0 100644 --- a/public/app/types/explore.ts +++ b/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; diff --git a/public/sass/pages/_explore.scss b/public/sass/pages/_explore.scss index 23c6fbf0916..5c2848d018b 100644 --- a/public/sass/pages/_explore.scss +++ b/public/sass/pages/_explore.scss @@ -267,6 +267,12 @@ } } + .logs-nodata { + > * { + margin-left: 0.5em; + } + } + .logs-meta { flex: 1; color: $text-color-weak;