Skip to content

Commit

Permalink
Add advanced setting to turn off search on Discover's initial page lo…
Browse files Browse the repository at this point in the history
…ad (elastic#42036)

Discover currently executes a search as soon as it loads. For some users this is useful. But for others it may return worthless results at the expense of extra load on their ES cluster and increased page load times, making it harder to get to the data they actually want. This PR adds an advanced setting allowing users to turn off the "search on page load" functionality in Discover.
  • Loading branch information
Bargs committed Jul 31, 2019
1 parent 5da63f9 commit d9af45a
Show file tree
Hide file tree
Showing 9 changed files with 202 additions and 76 deletions.
2 changes: 2 additions & 0 deletions docs/management/advanced-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ The default is `_source`.
the Visualize button in the field drop down. The default is `20`.
`discover:sampleSize`:: The number of rows to show in the Discover table.
`discover:sort:defaultOrder`:: The default sort direction for time-based index patterns.
`discover:searchOnPageLoad`:: Controls whether a search is executed when Discover first loads.
This setting does not have an effect when loading a saved search.
`doc_table:hideTimeColumn`:: Hides the "Time" column in Discover and in all saved searches on dashboards.
`doc_table:highlight`:: Highlights results in Discover and saved searches on dashboards.
Highlighting slows requests when
Expand Down
28 changes: 20 additions & 8 deletions src/legacy/core_plugins/kibana/public/discover/_discover.scss
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
@import 'node_modules/@elastic/eui/src/components/panel/mixins';

discover-app {
background-color: $euiColorEmptyShade;
flex-grow: 1;

.sidebar-container {
background-color: transparent;
}
}

// SASSTODO: replace the margin-top value with a variable
Expand All @@ -14,14 +20,20 @@ discover-app {

// SASSTODO: replace the z-index value with a variable
.dscWrapper {
padding-right: 0;
padding-right: $euiSizeS;
padding-left: 21px;
z-index: 1
z-index: 1;
}

@include euiPanel('dscWrapper__content');

.dscWrapper__content {
padding-right: $euiSize;
clear: both;
padding-top: $euiSizeXS;
background-color: $euiColorEmptyShade;

.kbn-table {
margin-bottom: 0;
}
}

.dscTimechart {
Expand All @@ -41,11 +53,11 @@ discover-app {
padding-left: $euiSizeM;

.dscResultHits {
padding-left: $euiSizeXS;
padding-left: $euiSizeXS;
}

> .kuiLink {
padding-left: $euiSizeM;
padding-left: $euiSizeM;
}
}

Expand Down Expand Up @@ -136,7 +148,7 @@ discover-app {
// SASSTODO: replace the padding value with a variable
.dscFieldDetails {
padding: 10px;
background-color: shade($euiColorLightestShade, 5%);
background-color: $euiColorLightestShade;
color: $euiTextColor;
}

Expand Down
3 changes: 1 addition & 2 deletions src/legacy/core_plugins/kibana/public/discover/_hacks.scss
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// SASSTODO: the classname is dinamically generated with ng-class
// SASSTODO: the classname is dynamically generated with ng-class
.tab-discover {
overflow: hidden;
background: $euiColorEmptyShade;
}

// SASSTODO: these are Angular Bootstrap classes. Will be replaced by EUI
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,14 @@ function discoverController(
indexPatternList: $route.current.locals.ip.list,
};

const shouldSearchOnPageLoad = () => {
// A saved search is created on every page load, so we check the ID to see if we're loading a
// previously saved search or if it is just transient
return config.get('discover:searchOnPageLoad')
|| savedSearch.id !== undefined
|| _.get($scope, 'refreshInterval.pause') === false;
};

const init = _.once(function () {
stateMonitor = stateMonitorFactory.create($state, getStateDefaults());
stateMonitor.onChange((status) => {
Expand Down Expand Up @@ -577,8 +585,10 @@ function discoverController(
$scope.enableTimeRangeSelector = !!timefield;
});

$scope.$watch('state.interval', function () {
$scope.fetch();
$scope.$watch('state.interval', function (newInterval, oldInterval) {
if (newInterval !== oldInterval) {
$scope.fetch();
}
});

$scope.$watch('vis.aggs', function () {
Expand All @@ -592,9 +602,11 @@ function discoverController(
}
});

$scope.$watch('state.query', (newQuery) => {
const query = migrateLegacyQuery(newQuery);
$scope.updateQueryAndFetch({ query });
$scope.$watch('state.query', (newQuery, oldQuery) => {
if (!_.isEqual(newQuery, oldQuery)) {
const query = migrateLegacyQuery(newQuery);
$scope.updateQueryAndFetch({ query });
}
});

$scope.$watchMulti([
Expand All @@ -603,19 +615,25 @@ function discoverController(
], (function updateResultState() {
let prev = {};
const status = {
UNINITIALIZED: 'uninitialized',
LOADING: 'loading', // initial data load
READY: 'ready', // results came back
NO_RESULTS: 'none' // no results came back
};

function pick(rows, oldRows, fetchStatus) {
// initial state, pretend we are loading
if (rows == null && oldRows == null) return status.LOADING;
// initial state, pretend we're already loading if we're about to execute a search so
// that the uninitilized message doesn't flash on screen
if (rows == null && oldRows == null && shouldSearchOnPageLoad()) {
return status.LOADING;
}

if (fetchStatus === fetchStatuses.UNINITIALIZED) {
return status.UNINITIALIZED;
}

const rowsEmpty = _.isEmpty(rows);
const preparingForFetch = fetchStatus === fetchStatuses.UNINITIALIZED;
if (preparingForFetch) return status.LOADING;
else if (rowsEmpty && fetchStatus === fetchStatuses.LOADING) return status.LOADING;
if (rowsEmpty && fetchStatus === fetchStatuses.LOADING) return status.LOADING;
else if (!rowsEmpty) return status.READY;
else return status.NO_RESULTS;
}
Expand Down Expand Up @@ -644,6 +662,10 @@ function discoverController(

init.complete = true;
$state.replace();

if (shouldSearchOnPageLoad()) {
$scope.fetch();
}
});
});

Expand Down Expand Up @@ -807,7 +829,14 @@ function discoverController(
};

$scope.updateRefreshInterval = function () {
$scope.refreshInterval = timefilter.getRefreshInterval();
const newInterval = timefilter.getRefreshInterval();
const shouldFetch = _.get($scope, 'refreshInterval.pause') === true && newInterval.pause === false;

$scope.refreshInterval = newInterval;

if (shouldFetch) {
$scope.fetch();
}
};

$scope.onRefreshChange = function ({ isPaused, refreshInterval }) {
Expand Down
23 changes: 13 additions & 10 deletions src/legacy/core_plugins/kibana/public/discover/directives/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,24 @@ import 'ngreact';
import { wrapInI18nContext } from 'ui/i18n';
import { uiModules } from 'ui/modules';

import {
DiscoverNoResults,
} from './no_results';
import { DiscoverNoResults } from './no_results';

import {
DiscoverUnsupportedIndexPattern,
} from './unsupported_index_pattern';
import { DiscoverUninitialized } from './uninitialized';

import { DiscoverUnsupportedIndexPattern } from './unsupported_index_pattern';

import './timechart';

const app = uiModules.get('apps/discover', ['react']);

app.directive('discoverNoResults', reactDirective => reactDirective(wrapInI18nContext(DiscoverNoResults)));
app.directive('discoverNoResults', reactDirective =>
reactDirective(wrapInI18nContext(DiscoverNoResults))
);

app.directive('discoverUninitialized', reactDirective =>
reactDirective(wrapInI18nContext(DiscoverUninitialized))
);

app.directive(
'discoverUnsupportedIndexPattern',
reactDirective => reactDirective(wrapInI18nContext(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
app.directive('discoverUnsupportedIndexPattern', reactDirective =>
reactDirective(wrapInI18nContext(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/

import React from 'react';
import { FormattedMessage } from '@kbn/i18n/react';

import { EuiButton, EuiEmptyPrompt, EuiPage, EuiPageBody, EuiPageContent } from '@elastic/eui';

interface Props {
onRefresh: () => void;
}

export const DiscoverUninitialized = ({ onRefresh }: Props) => {
return (
<EuiPage>
<EuiPageBody>
<EuiPageContent horizontalPosition="center">
<EuiEmptyPrompt
iconType="discoverApp"
title={
<h2>
<FormattedMessage
id="kbn.discover.uninitializedTitle"
defaultMessage="Start searching"
/>
</h2>
}
body={
<p>
<FormattedMessage
id="kbn.discover.uninitializedText"
defaultMessage="Write a query, add some filters, or simply hit Refresh to retrieve results for the current query."
/>
</p>
}
actions={
<EuiButton color="primary" fill onClick={onRefresh}>
<FormattedMessage
id="kbn.discover.uninitializedRefreshButtonText"
defaultMessage="Refresh data"
/>
</EuiButton>
}
/>
</EuiPageContent>
</EuiPageBody>
</EuiPage>
);
};
Loading

0 comments on commit d9af45a

Please sign in to comment.