Add advanced setting to turn off search on Discover's initial page load (#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.
This commit is contained in:
Matt Bargar 2019-07-31 18:59:41 -04:00 committed by GitHub
parent a8080b88c9
commit 90ec9bc6b6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 200 additions and 74 deletions

View file

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

View file

@ -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
@ -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 {
@ -41,11 +53,11 @@ discover-app {
padding-left: $euiSizeM;
.dscResultHits {
padding-left: $euiSizeXS;
padding-left: $euiSizeXS;
}
> .kuiLink {
padding-left: $euiSizeM;
padding-left: $euiSizeM;
}
}
@ -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;
}

View file

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

View file

@ -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) => {
@ -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 () {
@ -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([
@ -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;
}
@ -644,6 +662,10 @@ function discoverController(
init.complete = true;
$state.replace();
if (shouldSearchOnPageLoad()) {
$scope.fetch();
}
});
});
@ -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 }) {

View file

@ -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(
'discoverUnsupportedIndexPattern',
reactDirective => reactDirective(wrapInI18nContext(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
app.directive('discoverNoResults', reactDirective =>
reactDirective(wrapInI18nContext(DiscoverNoResults))
);
app.directive('discoverUninitialized', reactDirective =>
reactDirective(wrapInI18nContext(DiscoverUninitialized))
);
app.directive('discoverUnsupportedIndexPattern', reactDirective =>
reactDirective(wrapInI18nContext(DiscoverUnsupportedIndexPattern), ['unsupportedType'])
);

View file

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

View file

@ -1,7 +1,7 @@
<discover-app class="app-container">
<!-- Local nav. -->
<kbn-top-nav-v2
<kbn-top-nav-v2
app-name="'discover'"
config="topNavMenu"
show-search-bar="true"
@ -19,7 +19,7 @@
on-refresh-change="onRefreshChange"
>
</kbn-top-nav-v2>
<main class="container-fluid">
<div class="row">
<div class="col-md-2 sidebar-container collapsible-sidebar" id="discover-sidebar">
@ -39,48 +39,52 @@
</div>
<div class="dscWrapper col-md-10">
<div class="dscWrapper__content">
<discover-unsupported-index-pattern
ng-if="isUnsupportedIndexPattern"
unsupported-type="unsupportedIndexPatternType"
></discover-unsupported-index-pattern>
<discover-unsupported-index-pattern
ng-if="isUnsupportedIndexPattern"
unsupported-type="unsupportedIndexPatternType"
></discover-unsupported-index-pattern>
<discover-no-results
ng-show="resultState === 'none'"
shard-failures="failures"
time-field-name="opts.timefield"
query-language="state.query.language"
get-doc-link="getDocLink"
></discover-no-results>
<discover-no-results
ng-show="resultState === 'none'"
shard-failures="failures"
time-field-name="opts.timefield"
query-language="state.query.language"
get-doc-link="getDocLink"
></discover-no-results>
<!-- loading -->
<div ng-show="resultState === 'loading'">
<discover-fetch-error
ng-show="fetchError"
fetch-error="fetchError"
></discover-fetch-error>
<discover-uninitialized
ng-show="resultState === 'uninitialized'"
on-refresh="fetch"
></discover-uninitialized>
<!-- loading -->
<div ng-show="resultState === 'loading'">
<discover-fetch-error
ng-show="fetchError"
fetch-error="fetchError"
></discover-fetch-error>
<div ng-hide="fetchError" class="dscOverlay">
<h2
i18n-id="kbn.discover.searchingTitle"
i18n-default-message="Searching"
class="euiTitle euiTitle--small"
></h2>
<div class="euiSpacer euiSpacer--m"></div>
<div
ng-hide="fetchError"
class="dscOverlay"
>
<h2
i18n-id="kbn.discover.searchingTitle"
i18n-default-message="Searching"
class="euiTitle euiTitle--small"
></h2>
<div class="euiSpacer euiSpacer--m"></div>
<div class="euiLoadingSpinner euiLoadingSpinner--large" data-test-subj="loadingSpinner"></div>
</div>
class="euiLoadingSpinner euiLoadingSpinner--large"
data-test-subj="loadingSpinner"
></div>
</div>
</div>
<div class="dscWrapper__content" ng-show="resultState === 'ready'">
<!-- result -->
<div class="dscResults" ng-show="resultState === 'ready'">
<div class="dscResults">
<button
class="kuiButton kuiButton--basic kuiButton--iconText dscSkipButton"
ng-click="showAllRows(); scrollToBottom()"
>
<span class="kuiButton__inner">
<span aria-hidden="true" class="kuiButton__icon kuiIcon fa-chevron-down"></span>
<span
@ -98,14 +102,14 @@
i18n-default-message="{hits, plural, one {hit} other {hits}}"
i18n-values="{ hits }"
></span>
<button
<button
ng-if="opts.savedSearch.id"
class="kuiLink"
type="button"
id="reload_saved_search"
ng-click="resetQuery()"
>
{{::'kbn.discover.reloadSavedSearchButton' | i18n: {defaultMessage: 'Reset search'} }}
class="kuiLink"
type="button"
id="reload_saved_search"
ng-click="resetQuery()"
>
{{::'kbn.discover.reloadSavedSearchButton' | i18n: {defaultMessage: 'Reset search'} }}
</button>
</div>

View file

@ -298,6 +298,19 @@ export function getUiSettingDefaults() {
}),
category: ['discover'],
},
'discover:searchOnPageLoad': {
name: i18n.translate('kbn.advancedSettings.discover.searchOnPageLoadTitle', {
defaultMessage: 'Search on page load',
}),
value: true,
type: 'boolean',
description: i18n.translate('kbn.advancedSettings.discover.searchOnPageLoadText', {
defaultMessage:
'Controls whether a search is executed when Discover first loads. This setting does not ' +
'have an effect when loading a saved search.',
}),
category: ['discover'],
},
'doc_table:highlight': {
name: i18n.translate('kbn.advancedSettings.docTableHighlightTitle', {
defaultMessage: 'Highlight results',

View file

@ -111,8 +111,7 @@
}
.index-pattern-selection {
padding: $euiSizeS;
padding-bottom: 0;
padding: 0 $euiSizeS;
}
.index-pattern-selection .ui-select-choices {