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:
parent
a8080b88c9
commit
90ec9bc6b6
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 }) {
|
||||
|
|
|
@ -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'])
|
||||
);
|
||||
|
|
|
@ -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>
|
||||
);
|
||||
};
|
|
@ -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
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -111,8 +111,7 @@
|
|||
}
|
||||
|
||||
.index-pattern-selection {
|
||||
padding: $euiSizeS;
|
||||
padding-bottom: 0;
|
||||
padding: 0 $euiSizeS;
|
||||
}
|
||||
|
||||
.index-pattern-selection .ui-select-choices {
|
||||
|
|
Loading…
Reference in a new issue