Skip to content

Commit

Permalink
Merge branch 'master' into small_cases_bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
kibanamachine authored Apr 8, 2021
2 parents a3e60d0 + 9ec466e commit 057a6d5
Show file tree
Hide file tree
Showing 38 changed files with 372 additions and 4,477 deletions.
12 changes: 7 additions & 5 deletions docs/management/advanced-options.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -119,8 +119,12 @@ When date histograms use the `auto` interval, Kibana attempts to generate this
number of bars.

[[histogram-maxbars]]`histogram:maxBars`::
Date histograms are not generated with more bars than the value of this property,
scaling values when necessary.
To improve performance, limits the density of date and number histograms across {kib}
using a test query. When the test query contains too many buckets,
the interval between buckets increases. This setting applies separately
to each histogram aggregation, and does not apply to other types of aggregations.
To find the maximum value of this setting, divide the {es} `search.max_buckets`
value by the maximum number of aggregations in each visualization.

[[history-limit]]`history:limit`::
In fields that have history, such as query inputs, show this many recent values.
Expand All @@ -134,9 +138,7 @@ Fields that exist outside of `_source`. Kibana merges these fields into the
document when displaying it.

[[metrics-maxbuckets]]`metrics:max_buckets`::
The maximum numbers of buckets that a single data source can return. This might
arise when the user selects a short interval (for example, 1s) for a long time
period (1 year).
Affects the *TSVB* histogram density. Must be set higher than `histogram:maxBars`.

[[query-allowleadingwildcards]]`query:allowLeadingWildcards`::
Allows a wildcard (*) as the first character in a query clause. Only applies
Expand Down
16 changes: 11 additions & 5 deletions src/plugins/data/server/ui_settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -304,23 +304,29 @@ export function getUiSettings(): Record<string, UiSettingsParams<unknown>> {
},
[UI_SETTINGS.HISTOGRAM_BAR_TARGET]: {
name: i18n.translate('data.advancedSettings.histogram.barTargetTitle', {
defaultMessage: 'Target bars',
defaultMessage: 'Target buckets',
}),
value: 50,
description: i18n.translate('data.advancedSettings.histogram.barTargetText', {
defaultMessage:
'Attempt to generate around this many bars when using "auto" interval in date histograms',
'Attempt to generate around this many buckets when using "auto" interval in date and numeric histograms',
}),
schema: schema.number(),
},
[UI_SETTINGS.HISTOGRAM_MAX_BARS]: {
name: i18n.translate('data.advancedSettings.histogram.maxBarsTitle', {
defaultMessage: 'Maximum bars',
defaultMessage: 'Maximum buckets',
}),
value: 100,
description: i18n.translate('data.advancedSettings.histogram.maxBarsText', {
defaultMessage:
'Never show more than this many bars in date histograms, scale values if needed',
defaultMessage: `
Limits the density of date and number histograms across Kibana
for better performance using a test query. If the test query would too many buckets,
the interval between buckets will be increased. This setting applies separately
to each histogram aggregation, and does not apply to other types of aggregation.
To find the maximum value of this setting, divide the Elasticsearch 'search.max_buckets'
value by the maximum number of aggregations in each visualization.
`,
}),
schema: schema.number(),
},
Expand Down
5 changes: 3 additions & 2 deletions src/plugins/vis_type_timeseries/server/ui_settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,12 @@ import { MAX_BUCKETS_SETTING } from '../common/constants';
export const uiSettings: Record<string, UiSettingsParams> = {
[MAX_BUCKETS_SETTING]: {
name: i18n.translate('visTypeTimeseries.advancedSettings.maxBucketsTitle', {
defaultMessage: 'Maximum buckets',
defaultMessage: 'TSVB buckets limit',
}),
value: 2000,
description: i18n.translate('visTypeTimeseries.advancedSettings.maxBucketsText', {
defaultMessage: 'The maximum number of buckets a single datasource can return',
defaultMessage:
'Affects the TSVB histogram density. Must be set higher than "histogram:maxBars".',
}),
schema: schema.number(),
},
Expand Down
2 changes: 2 additions & 0 deletions test/common/services/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { RetryProvider } from './retry';
import { RandomnessProvider } from './randomness';
import { SecurityServiceProvider } from './security';
import { EsDeleteAllIndicesProvider } from './es_delete_all_indices';
import { SavedObjectInfoProvider } from './saved_object_info';

export const services = {
deployment: DeploymentProvider,
Expand All @@ -26,4 +27,5 @@ export const services = {
randomness: RandomnessProvider,
security: SecurityServiceProvider,
esDeleteAllIndices: EsDeleteAllIndicesProvider,
savedObjectInfo: SavedObjectInfoProvider,
};
53 changes: 53 additions & 0 deletions test/common/services/saved_object_info.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/

import { Client } from '@elastic/elasticsearch';
import url from 'url';
import { Either, fromNullable, chain, getOrElse } from 'fp-ts/Either';
import { flow } from 'fp-ts/function';
import { FtrProviderContext } from '../ftr_provider_context';

const pluck = (key: string) => (obj: any): Either<Error, string> =>
fromNullable(new Error(`Missing ${key}`))(obj[key]);

const types = (node: string) => async (index: string = '.kibana') => {
let res: unknown;
try {
const { body } = await new Client({ node }).search({
index,
body: {
aggs: {
savedobjs: {
terms: {
field: 'type',
},
},
},
},
});

res = flow(
pluck('aggregations'),
chain(pluck('savedobjs')),
chain(pluck('buckets')),
getOrElse((err) => `${err.message}`)
)(body);
} catch (err) {
throw new Error(`Error while searching for saved object types: ${err}`);
}

return res;
};

export const SavedObjectInfoProvider: any = ({ getService }: FtrProviderContext) => {
const config = getService('config');

return {
types: types(url.format(config.get('servers.elasticsearch'))),
};
};
4 changes: 4 additions & 0 deletions test/functional/apps/discover/_discover.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import expect from '@kbn/expect';
import { FtrProviderContext } from '../../ftr_provider_context';

export default function ({ getService, getPageObjects }: FtrProviderContext) {
const savedObjectInfo = getService('savedObjectInfo');
const browser = getService('browser');
const log = getService('log');
const retry = getService('retry');
Expand All @@ -31,6 +32,9 @@ export default function ({ getService, getPageObjects }: FtrProviderContext) {

await kibanaServer.savedObjects.clean({ types: ['search'] });
await kibanaServer.importExport.load('discover');
log.info(
`\n### SAVED OBJECT TYPES IN index: [.kibana]: \n\t${await savedObjectInfo.types()}`
);

// and load a set of makelogs data
await esArchiver.loadIfNeeded('logstash_functional');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,20 @@ jest.mock('../../../contexts/kibana', () => ({
useMlKibana: () => {
return {
services: {
uiSettings: { get: jest.fn() },
uiSettings: {
get: jest.fn().mockReturnValue([
{
from: 'now/d',
to: 'now/d',
display: 'Today',
},
{
from: 'now/w',
to: 'now/w',
display: 'This week',
},
]),
},
data: {
query: {
timefilter: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,17 +5,24 @@
* 2.0.
*/

import React, { FC, useCallback, useEffect, useState } from 'react';
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
import { Subscription } from 'rxjs';
import { debounce } from 'lodash';

import { EuiSuperDatePicker, OnRefreshProps } from '@elastic/eui';
import { TimeHistoryContract, TimeRange } from 'src/plugins/data/public';
import { UI_SETTINGS } from '../../../../../../../../src/plugins/data/common';

import { mlTimefilterRefresh$ } from '../../../services/timefilter_refresh_service';
import { useUrlState } from '../../../util/url_state';
import { useMlKibana } from '../../../contexts/kibana';

interface TimePickerQuickRange {
from: string;
to: string;
display: string;
}

interface Duration {
start: string;
end: string;
Expand Down Expand Up @@ -71,6 +78,19 @@ export const DatePickerWrapper: FC = () => {
);

const dateFormat = config.get('dateFormat');
const timePickerQuickRanges = config.get<TimePickerQuickRange[]>(
UI_SETTINGS.TIMEPICKER_QUICK_RANGES
);

const commonlyUsedRanges = useMemo(
() =>
timePickerQuickRanges.map(({ from, to, display }) => ({
start: from,
end: to,
label: display,
})),
[timePickerQuickRanges]
);

useEffect(() => {
const subscriptions = new Subscription();
Expand Down Expand Up @@ -141,6 +161,7 @@ export const DatePickerWrapper: FC = () => {
onRefreshChange={updateInterval}
recentlyUsedRanges={recentlyUsedRanges}
dateFormat={dateFormat}
commonlyUsedRanges={commonlyUsedRanges}
/>
</div>
) : null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,11 @@
* 2.0.
*/

import { dataPluginMock } from '../../../../../../../../src/plugins/data/public/mocks';

export const kibanaContextMock = {
services: {
uiSettings: { get: jest.fn() },
chrome: { recentlyAccessed: { add: jest.fn() } },
application: { navigateToApp: jest.fn() },
http: {
Expand All @@ -17,6 +20,7 @@ export const kibanaContextMock = {
share: {
urlGenerators: { getUrlGenerator: jest.fn() },
},
data: dataPluginMock.createStartContract(),
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -480,23 +480,25 @@ describe('<EditRolePage />', () => {
});
});

it('can render if features are not available', async () => {
const { http } = coreMock.createStart();
http.get.mockImplementation(async (path: any) => {
if (path === '/api/features') {
const error = { response: { status: 404 } };
throw error;
}
it('registers fatal error if features endpoint fails unexpectedly', async () => {
const error = { response: { status: 500 } };
const getFeatures = jest.fn().mockRejectedValue(error);
const props = getProps({ action: 'edit' });
const wrapper = mountWithIntl(<EditRolePage {...props} getFeatures={getFeatures} />);

if (path === '/api/spaces/space') {
return buildSpaces();
}
});
await waitForRender(wrapper);
expect(props.fatalErrors.add).toHaveBeenLastCalledWith(error);
expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(0);
});

const wrapper = mountWithIntl(<EditRolePage {...{ ...getProps({ action: 'edit' }), http }} />);
it('can render if features call is not allowed', async () => {
const error = { response: { status: 403 } };
const getFeatures = jest.fn().mockRejectedValue(error);
const props = getProps({ action: 'edit' });
const wrapper = mountWithIntl(<EditRolePage {...props} getFeatures={getFeatures} />);

await waitForRender(wrapper);

expect(props.fatalErrors.add).not.toHaveBeenCalled();
expect(wrapper.find(SpaceAwarePrivilegeSection)).toHaveLength(1);
expect(wrapper.find('[data-test-subj="userCannotManageSpacesCallout"]')).toHaveLength(0);
expectSaveFormButtons(wrapper);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,12 @@ function useFeatures(
// possible that a user with `manage_security` will attempt to visit the role management page without the
// correct Kibana privileges. If that's the case, then they receive a partial view of the role, and the UI does
// not allow them to make changes to that role's kibana privileges. When this user visits the edit role page,
// this API endpoint will throw a 404, which causes view to fail completely. So we instead attempt to detect the
// 404 here, and respond in a way that still allows the UI to render itself.
const unauthorizedForFeatures = err.response?.status === 404;
// this API endpoint will throw a 403, which causes view to fail completely. So we instead attempt to detect the
// 403 here, and respond in a way that still allows the UI to render itself.
const unauthorizedForFeatures = err.response?.status === 403;
if (unauthorizedForFeatures) {
return [] as KibanaFeature[];
}

fatalErrors.add(err);
})
.then((retrievedFeatures) => {
Expand Down Expand Up @@ -296,7 +295,6 @@ export const EditRolePage: FunctionComponent<Props> = ({
// We should keep the same mutable instance of Validator for every re-render since we'll
// eventually enable validation after the first time user tries to save a role.
const { current: validator } = useRef(new RoleValidator({ shouldValidate: false }));

const [formError, setFormError] = useState<RoleValidationResult | null>(null);
const runAsUsers = useRunAsUsers(userAPIClient, fatalErrors);
const indexPatternsTitles = useIndexPatternsTitles(indexPatterns, fatalErrors, notifications);
Expand Down
Loading

0 comments on commit 057a6d5

Please sign in to comment.