From b2f028a8b9c2c59bec4837e1021a9564096d4813 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 25 Jun 2019 12:28:11 +0200 Subject: [PATCH] Add dateHistogramInterval utility (#39091) (#39563) * Add dateHistogramInterval utility * Fix editor bug * Fix tests * FIx imports to temporary solution * Remove wrongly merged translations * Remove old static.ts file --- src/dev/jest/config.js | 2 +- .../common/date_histogram_interval.test.ts | 50 +++++++++++++++++++ .../data/common/date_histogram_interval.ts | 49 ++++++++++++++++++ src/legacy/core_plugins/data/common/index.ts | 29 +++++++++++ .../data/common}/parse_es_interval/index.ts | 1 + .../invalid_es_calendar_interval_error.ts | 2 +- .../invalid_es_interval_format_error.ts | 2 +- .../parse_es_interval/is_valid_es_interval.ts | 38 ++++++++++++++ .../parse_es_interval.test.ts | 0 .../parse_es_interval/parse_es_interval.ts | 0 src/legacy/core_plugins/data/public/index.ts | 11 ++++ src/legacy/core_plugins/data/server/index.ts | 30 +++++++++++ .../tabify/__tests__/_get_columns.js | 26 +++++----- .../buckets/date_histogram/_params.js | 29 +++++++---- .../__tests__/metrics/sibling_pipeline.js | 6 +-- .../agg_types/buckets/date_histogram.js | 15 +++++- src/legacy/ui/public/agg_types/utils.ts | 4 +- src/legacy/ui/public/notify/fatal_error.ts | 6 +-- .../ui/public/utils/parse_es_interval.ts | 27 ++++++++++ .../ui/public/vis/__tests__/_agg_configs.js | 7 +-- x-pack/dev-tools/jest/create_jest_config.js | 2 + .../translations/translations/ja-JP.json | 4 +- .../translations/translations/zh-CN.json | 4 +- 23 files changed, 299 insertions(+), 45 deletions(-) create mode 100644 src/legacy/core_plugins/data/common/date_histogram_interval.test.ts create mode 100644 src/legacy/core_plugins/data/common/date_histogram_interval.ts create mode 100644 src/legacy/core_plugins/data/common/index.ts rename src/legacy/{ui/public/utils => core_plugins/data/common}/parse_es_interval/index.ts (94%) rename src/legacy/{ui/public/utils => core_plugins/data/common}/parse_es_interval/invalid_es_calendar_interval_error.ts (95%) rename src/legacy/{ui/public/utils => core_plugins/data/common}/parse_es_interval/invalid_es_interval_format_error.ts (94%) create mode 100644 src/legacy/core_plugins/data/common/parse_es_interval/is_valid_es_interval.ts rename src/legacy/{ui/public/utils => core_plugins/data/common}/parse_es_interval/parse_es_interval.test.ts (100%) rename src/legacy/{ui/public/utils => core_plugins/data/common}/parse_es_interval/parse_es_interval.ts (100%) create mode 100644 src/legacy/core_plugins/data/server/index.ts create mode 100644 src/legacy/ui/public/utils/parse_es_interval.ts diff --git a/src/dev/jest/config.js b/src/dev/jest/config.js index 31203725f5af8..582cad37b2791 100644 --- a/src/dev/jest/config.js +++ b/src/dev/jest/config.js @@ -53,7 +53,7 @@ export default { '!src/legacy/core_plugins/**/__snapshots__/**/*', ], moduleNameMapper: { - '^plugins/([^\/.]*)/(.*)': '/src/legacy/core_plugins/$1/public/$2', + '^plugins/([^\/.]*)(.*)': '/src/legacy/core_plugins/$1/public$2', '^ui/(.*)': '/src/legacy/ui/public/$1', '^uiExports/(.*)': '/src/dev/jest/mocks/file_mock.js', '^test_utils/(.*)': '/src/test_utils/public/$1', diff --git a/src/legacy/core_plugins/data/common/date_histogram_interval.test.ts b/src/legacy/core_plugins/data/common/date_histogram_interval.test.ts new file mode 100644 index 0000000000000..7ae1e580c28b3 --- /dev/null +++ b/src/legacy/core_plugins/data/common/date_histogram_interval.test.ts @@ -0,0 +1,50 @@ +/* + * 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 { dateHistogramInterval } from './date_histogram_interval'; + +describe('dateHistogramInterval', () => { + it('should return calender_interval key for calendar intervals', () => { + expect(dateHistogramInterval('1m')).toEqual({ calendar_interval: '1m' }); + expect(dateHistogramInterval('1h')).toEqual({ calendar_interval: '1h' }); + expect(dateHistogramInterval('1d')).toEqual({ calendar_interval: '1d' }); + expect(dateHistogramInterval('1w')).toEqual({ calendar_interval: '1w' }); + expect(dateHistogramInterval('1M')).toEqual({ calendar_interval: '1M' }); + expect(dateHistogramInterval('1y')).toEqual({ calendar_interval: '1y' }); + }); + + it('should return fixed_interval key for fixed intervals', () => { + expect(dateHistogramInterval('1ms')).toEqual({ fixed_interval: '1ms' }); + expect(dateHistogramInterval('42ms')).toEqual({ fixed_interval: '42ms' }); + expect(dateHistogramInterval('1s')).toEqual({ fixed_interval: '1s' }); + expect(dateHistogramInterval('42s')).toEqual({ fixed_interval: '42s' }); + expect(dateHistogramInterval('42m')).toEqual({ fixed_interval: '42m' }); + expect(dateHistogramInterval('42h')).toEqual({ fixed_interval: '42h' }); + expect(dateHistogramInterval('42d')).toEqual({ fixed_interval: '42d' }); + }); + + it('should throw an error on invalid intervals', () => { + expect(() => dateHistogramInterval('2w')).toThrow(); + expect(() => dateHistogramInterval('2M')).toThrow(); + expect(() => dateHistogramInterval('2y')).toThrow(); + expect(() => dateHistogramInterval('2')).toThrow(); + expect(() => dateHistogramInterval('y')).toThrow(); + expect(() => dateHistogramInterval('0.5h')).toThrow(); + }); +}); diff --git a/src/legacy/core_plugins/data/common/date_histogram_interval.ts b/src/legacy/core_plugins/data/common/date_histogram_interval.ts new file mode 100644 index 0000000000000..4a6905bbf0562 --- /dev/null +++ b/src/legacy/core_plugins/data/common/date_histogram_interval.ts @@ -0,0 +1,49 @@ +/* + * 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 { parseEsInterval } from './parse_es_interval'; + +type Interval = { fixed_interval: string } | { calendar_interval: string }; + +/** + * Checks whether a given Elasticsearch interval is a calendar or fixed interval + * and returns an object containing the appropriate date_histogram property for that + * interval. So it will return either an object containing the fixed_interval key for + * that interval or a calendar_interval. If the specified interval was not a valid Elasticsearch + * interval this method will throw an error. + * + * You can simply spread the returned value of this method into your date_histogram. + * @example + * const aggregation = { + * date_histogram: { + * field: 'date', + * ...dateHistogramInterval('24h'), + * } + * }; + * + * @param interval The interval string to return the appropriate date_histogram key for. + */ +export function dateHistogramInterval(interval: string): Interval { + const { type } = parseEsInterval(interval); + if (type === 'calendar') { + return { calendar_interval: interval }; + } else { + return { fixed_interval: interval }; + } +} diff --git a/src/legacy/core_plugins/data/common/index.ts b/src/legacy/core_plugins/data/common/index.ts new file mode 100644 index 0000000000000..403ea4821ffbc --- /dev/null +++ b/src/legacy/core_plugins/data/common/index.ts @@ -0,0 +1,29 @@ +/* + * 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. + */ + +/** @public static code */ +export { dateHistogramInterval } from './date_histogram_interval'; +/** @public static code */ +export { + isValidEsInterval, + InvalidEsCalendarIntervalError, + InvalidEsIntervalFormatError, + parseEsInterval, + ParsedInterval, +} from './parse_es_interval'; diff --git a/src/legacy/ui/public/utils/parse_es_interval/index.ts b/src/legacy/core_plugins/data/common/parse_es_interval/index.ts similarity index 94% rename from src/legacy/ui/public/utils/parse_es_interval/index.ts rename to src/legacy/core_plugins/data/common/parse_es_interval/index.ts index 152037138072f..9c2c546af40d4 100644 --- a/src/legacy/ui/public/utils/parse_es_interval/index.ts +++ b/src/legacy/core_plugins/data/common/parse_es_interval/index.ts @@ -20,3 +20,4 @@ export { parseEsInterval, ParsedInterval } from './parse_es_interval'; export { InvalidEsCalendarIntervalError } from './invalid_es_calendar_interval_error'; export { InvalidEsIntervalFormatError } from './invalid_es_interval_format_error'; +export { isValidEsInterval } from './is_valid_es_interval'; diff --git a/src/legacy/ui/public/utils/parse_es_interval/invalid_es_calendar_interval_error.ts b/src/legacy/core_plugins/data/common/parse_es_interval/invalid_es_calendar_interval_error.ts similarity index 95% rename from src/legacy/ui/public/utils/parse_es_interval/invalid_es_calendar_interval_error.ts rename to src/legacy/core_plugins/data/common/parse_es_interval/invalid_es_calendar_interval_error.ts index 7c794ef61a989..ef2a39b9e2004 100644 --- a/src/legacy/ui/public/utils/parse_es_interval/invalid_es_calendar_interval_error.ts +++ b/src/legacy/core_plugins/data/common/parse_es_interval/invalid_es_calendar_interval_error.ts @@ -28,7 +28,7 @@ export class InvalidEsCalendarIntervalError extends Error { public readonly type: string ) { super( - i18n.translate('common.ui.parseEsInterval.invalidEsCalendarIntervalErrorMessage', { + i18n.translate('data.parseEsInterval.invalidEsCalendarIntervalErrorMessage', { defaultMessage: 'Invalid calendar interval: {interval}, value must be 1', values: { interval }, }) diff --git a/src/legacy/ui/public/utils/parse_es_interval/invalid_es_interval_format_error.ts b/src/legacy/core_plugins/data/common/parse_es_interval/invalid_es_interval_format_error.ts similarity index 94% rename from src/legacy/ui/public/utils/parse_es_interval/invalid_es_interval_format_error.ts rename to src/legacy/core_plugins/data/common/parse_es_interval/invalid_es_interval_format_error.ts index ac6b85f447b29..e1bbfcfe5e78e 100644 --- a/src/legacy/ui/public/utils/parse_es_interval/invalid_es_interval_format_error.ts +++ b/src/legacy/core_plugins/data/common/parse_es_interval/invalid_es_interval_format_error.ts @@ -22,7 +22,7 @@ import { i18n } from '@kbn/i18n'; export class InvalidEsIntervalFormatError extends Error { constructor(public readonly interval: string) { super( - i18n.translate('common.ui.parseEsInterval.invalidEsIntervalFormatErrorMessage', { + i18n.translate('data.parseEsInterval.invalidEsIntervalFormatErrorMessage', { defaultMessage: 'Invalid interval format: {interval}', values: { interval }, }) diff --git a/src/legacy/core_plugins/data/common/parse_es_interval/is_valid_es_interval.ts b/src/legacy/core_plugins/data/common/parse_es_interval/is_valid_es_interval.ts new file mode 100644 index 0000000000000..5ab561c98ec29 --- /dev/null +++ b/src/legacy/core_plugins/data/common/parse_es_interval/is_valid_es_interval.ts @@ -0,0 +1,38 @@ +/* + * 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 { parseEsInterval } from './parse_es_interval'; + +/** + * Checks whether a given interval string (e.g. 1w, 24h, ...) is a valid Elasticsearch interval. + * Will return false if the interval is not valid in Elasticsearch, otherwise true. + * Invalid intervals might be: 2f, since there is no unit 'f'; 2w, since weeks and month intervals + * are only allowed with a value of 1, etc. + * + * @param interval The interval string like 1w, 24h + * @returns True if the interval is valid for Elasticsearch + */ +export function isValidEsInterval(interval: string): boolean { + try { + parseEsInterval(interval); + return true; + } catch { + return false; + } +} diff --git a/src/legacy/ui/public/utils/parse_es_interval/parse_es_interval.test.ts b/src/legacy/core_plugins/data/common/parse_es_interval/parse_es_interval.test.ts similarity index 100% rename from src/legacy/ui/public/utils/parse_es_interval/parse_es_interval.test.ts rename to src/legacy/core_plugins/data/common/parse_es_interval/parse_es_interval.test.ts diff --git a/src/legacy/ui/public/utils/parse_es_interval/parse_es_interval.ts b/src/legacy/core_plugins/data/common/parse_es_interval/parse_es_interval.ts similarity index 100% rename from src/legacy/ui/public/utils/parse_es_interval/parse_es_interval.ts rename to src/legacy/core_plugins/data/common/parse_es_interval/parse_es_interval.ts diff --git a/src/legacy/core_plugins/data/public/index.ts b/src/legacy/core_plugins/data/public/index.ts index 679a835a0477e..d762af70d2088 100644 --- a/src/legacy/core_plugins/data/public/index.ts +++ b/src/legacy/core_plugins/data/public/index.ts @@ -87,3 +87,14 @@ export { ExpressionRenderer, ExpressionRendererProps, ExpressionRunner } from '. /** @public types */ export { IndexPattern, StaticIndexPattern, StaticIndexPatternField, Field } from './index_patterns'; export { Query } from './query'; + +/** @public static code */ +export { dateHistogramInterval } from '../common/date_histogram_interval'; +/** @public static code */ +export { + isValidEsInterval, + InvalidEsCalendarIntervalError, + InvalidEsIntervalFormatError, + parseEsInterval, + ParsedInterval, +} from '../common/parse_es_interval'; diff --git a/src/legacy/core_plugins/data/server/index.ts b/src/legacy/core_plugins/data/server/index.ts new file mode 100644 index 0000000000000..f3310bb0cb20f --- /dev/null +++ b/src/legacy/core_plugins/data/server/index.ts @@ -0,0 +1,30 @@ +/* + * 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. + */ + +/** @public static code */ +export { dateHistogramInterval } from '../common/date_histogram_interval'; + +/** @public static code */ +export { + isValidEsInterval, + InvalidEsCalendarIntervalError, + InvalidEsIntervalFormatError, + parseEsInterval, + ParsedInterval, +} from '../common/parse_es_interval'; diff --git a/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js b/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js index 4e15f8cc4e619..27b390ed7e471 100644 --- a/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js +++ b/src/legacy/ui/public/agg_response/tabify/__tests__/_get_columns.js @@ -48,7 +48,7 @@ describe('get columns', function () { const vis = new Vis(indexPattern, { type: 'pie', aggs: [ - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } } + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } } ] }); @@ -63,10 +63,10 @@ describe('get columns', function () { const vis = new Vis(indexPattern, { type: 'pie', aggs: [ - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } } + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } } ] }); @@ -83,12 +83,12 @@ describe('get columns', function () { const vis = new Vis(indexPattern, { type: 'pie', aggs: [ - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } } + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } } ] }); @@ -119,12 +119,12 @@ describe('get columns', function () { const vis = new Vis(indexPattern, { type: 'histogram', aggs: [ - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } } + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } } ] }); diff --git a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js index ff45d8cfef519..e972f14b85b21 100644 --- a/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js +++ b/src/legacy/ui/public/agg_types/__tests__/buckets/date_histogram/_params.js @@ -35,6 +35,7 @@ describe('date_histogram params', function () { let paramWriter; let writeInterval; + let write; let getTimeBounds; let timeField; @@ -50,6 +51,9 @@ describe('date_histogram params', function () { writeInterval = function (interval, timeRange) { return paramWriter.write({ interval: interval, field: timeField, timeRange: timeRange }); }; + write = (params) => { + return paramWriter.write({ interval: '10s', ...params }); + }; const now = moment(); getTimeBounds = function (n, units) { @@ -63,9 +67,14 @@ describe('date_histogram params', function () { })); describe('interval', function () { - it('accepts a valid interval', function () { + it('accepts a valid calendar interval', function () { const output = writeInterval('d'); - expect(output.params).to.have.property('interval', '1d'); + expect(output.params).to.have.property('calendar_interval', '1d'); + }); + + it('accepts a valid fixed interval', () => { + const output = writeInterval('100s'); + expect(output.params).to.have.property('fixed_interval', '100s'); }); it('throws error when interval is invalid', function () { @@ -75,13 +84,13 @@ describe('date_histogram params', function () { it('automatically picks an interval', function () { const timeBounds = getTimeBounds(15, 'm'); const output = writeInterval('auto', timeBounds); - expect(output.params.interval).to.be('30s'); + expect(output.params).to.have.property('fixed_interval', '30s'); }); it('scales up the interval if it will make too many buckets', function () { const timeBounds = getTimeBounds(30, 'm'); const output = writeInterval('s', timeBounds); - expect(output.params.interval).to.be('10s'); + expect(output.params).to.have.property('fixed_interval', '10s'); expect(output.metricScaleText).to.be('second'); expect(output.metricScale).to.be(0.1); }); @@ -89,7 +98,7 @@ describe('date_histogram params', function () { it('does not scale down the interval', function () { const timeBounds = getTimeBounds(1, 'm'); const output = writeInterval('h', timeBounds); - expect(output.params.interval).to.be('1h'); + expect(output.params).to.have.property('calendar_interval', '1h'); expect(output.metricScaleText).to.be(undefined); expect(output.metricScale).to.be(undefined); }); @@ -140,20 +149,20 @@ describe('date_histogram params', function () { }); it('should use the specified time_zone', () => { - const output = paramWriter.write({ time_zone: 'Europe/Kiev' }); + const output = write({ time_zone: 'Europe/Kiev' }); expect(output.params).to.have.property('time_zone', 'Europe/Kiev'); }); it('should use the Kibana time_zone if no parameter specified', () => { config.isDefault.withArgs('dateFormat:tz').returns(false); config.get.withArgs('dateFormat:tz').returns('Europe/Riga'); - const output = paramWriter.write({}); + const output = write({}); expect(output.params).to.have.property('time_zone', 'Europe/Riga'); }); it('should use the fixed time_zone from the index pattern typeMeta', () => { _.set(paramWriter.indexPattern, ['typeMeta', 'aggs', 'date_histogram', timeField, 'time_zone'], 'Europe/Rome'); - const output = paramWriter.write({ field: timeField }); + const output = write({ field: timeField }); expect(output.params).to.have.property('time_zone', 'Europe/Rome'); }); @@ -167,7 +176,7 @@ describe('date_histogram params', function () { it('should write a long value if a moment passed in', function () { const then = moment(0); const now = moment(500); - const output = paramWriter.write({ + const output = write({ extended_bounds: { min: then, max: now @@ -185,7 +194,7 @@ describe('date_histogram params', function () { it('should write a long if a long is passed', function () { const then = 0; const now = 500; - const output = paramWriter.write({ + const output = write({ extended_bounds: { min: then, max: now diff --git a/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js b/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js index c80f7f6a9ad2c..9d0e6802ec12b 100644 --- a/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js +++ b/src/legacy/ui/public/agg_types/__tests__/metrics/sibling_pipeline.js @@ -60,7 +60,7 @@ describe('sibling pipeline aggs', function () { id: '6', type: 'date_histogram', schema: 'bucket', - params: { field: '@timestamp' } + params: { field: '@timestamp', interval: '10s' } } }; @@ -115,7 +115,7 @@ describe('sibling pipeline aggs', function () { id: '6', type: 'date_histogram', schema: 'bucket', - params: { field: '@timestamp' }, + params: { field: '@timestamp', interval: '10s', }, } }); expect(aggDsl[metric.name].buckets_path).to.be('2-bucket>2-metric'); @@ -135,7 +135,7 @@ describe('sibling pipeline aggs', function () { id: '6', type: 'date_histogram', schema: 'bucket', - params: { field: '@timestamp' }, + params: { field: '@timestamp', interval: '10s' }, } }); expect(metricAgg.getFormat(aggConfig).type.id).to.be('bytes'); diff --git a/src/legacy/ui/public/agg_types/buckets/date_histogram.js b/src/legacy/ui/public/agg_types/buckets/date_histogram.js index 5a59b11274030..89fe25ec1b8a9 100644 --- a/src/legacy/ui/public/agg_types/buckets/date_histogram.js +++ b/src/legacy/ui/public/agg_types/buckets/date_histogram.js @@ -27,6 +27,7 @@ import { intervalOptions } from './_interval_options'; import { TimeIntervalParamEditor } from '../controls/time_interval'; import { timefilter } from '../../timefilter'; import { DropPartialsParamEditor } from '../controls/drop_partials'; +import { dateHistogramInterval } from '../../../../core_plugins/data/common'; import { i18n } from '@kbn/i18n'; const config = chrome.getUiSettingsClient(); @@ -140,7 +141,19 @@ export const dateHistogramBucketAgg = new BucketAggType({ const { useNormalizedEsInterval } = agg.params; const interval = agg.buckets.getInterval(useNormalizedEsInterval); output.bucketInterval = interval; - output.params.interval = interval.expression; + if (interval.expression === '0ms') { + // We are hitting this code a couple of times while configuring in editor + // with an interval of 0ms because the overall time range has not yet been + // set. Since 0ms is not a valid ES interval, we cannot pass it through dateHistogramInterval + // below, since it would throw an exception. So in the cases we still have an interval of 0ms + // here we simply skip the rest of the method and never write an interval into the DSL, since + // this DSL will anyway not be used before we're passing this code with an actual interval. + return; + } + output.params = { + ...output.params, + ...dateHistogramInterval(interval.expression), + }; const scaleMetrics = interval.scaled && interval.scale < 1; if (scaleMetrics && aggs) { diff --git a/src/legacy/ui/public/agg_types/utils.ts b/src/legacy/ui/public/agg_types/utils.ts index 66fc5d85d7ab7..c6452cf46e0c0 100644 --- a/src/legacy/ui/public/agg_types/utils.ts +++ b/src/legacy/ui/public/agg_types/utils.ts @@ -17,7 +17,7 @@ * under the License. */ -import { parseInterval } from '../utils/parse_interval'; +import { isValidEsInterval } from '../../../core_plugins/data/common'; import { leastCommonInterval } from '../vis/lib/least_common_interval'; /** @@ -53,7 +53,7 @@ function isValidInterval(value: string, baseInterval: string) { if (baseInterval) { return _parseWithBase(value, baseInterval); } else { - return parseInterval(value) !== null; + return isValidEsInterval(value); } } diff --git a/src/legacy/ui/public/notify/fatal_error.ts b/src/legacy/ui/public/notify/fatal_error.ts index f3f05bdf793a2..4c02322bae492 100644 --- a/src/legacy/ui/public/notify/fatal_error.ts +++ b/src/legacy/ui/public/notify/fatal_error.ts @@ -24,10 +24,8 @@ import { isAngularHttpError, } from './lib/format_angular_http_error'; -const newPlatformFatalErrors = npSetup.core.fatalErrors; - export function addFatalErrorCallback(callback: () => void) { - newPlatformFatalErrors.get$().subscribe(() => { + npSetup.core.fatalErrors.get$().subscribe(() => { callback(); }); } @@ -38,5 +36,5 @@ export function fatalError(error: AngularHttpError | Error | string, location?: error = formatAngularHttpError(error); } - newPlatformFatalErrors.add(error, location); + npSetup.core.fatalErrors.add(error, location); } diff --git a/src/legacy/ui/public/utils/parse_es_interval.ts b/src/legacy/ui/public/utils/parse_es_interval.ts new file mode 100644 index 0000000000000..58b1974bb241d --- /dev/null +++ b/src/legacy/ui/public/utils/parse_es_interval.ts @@ -0,0 +1,27 @@ +/* + * 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. + */ + +// Those exports are kept here for now, so we can move over imports +// step by step into the data plugin. +export { + parseEsInterval, + ParsedInterval, + InvalidEsCalendarIntervalError, + InvalidEsIntervalFormatError, +} from '../../../core_plugins/data/common'; diff --git a/src/legacy/ui/public/vis/__tests__/_agg_configs.js b/src/legacy/ui/public/vis/__tests__/_agg_configs.js index 2c663800a4d28..8da8095fd4712 100644 --- a/src/legacy/ui/public/vis/__tests__/_agg_configs.js +++ b/src/legacy/ui/public/vis/__tests__/_agg_configs.js @@ -276,7 +276,7 @@ describe('AggConfigs', function () { const vis = new Vis(indexPattern, { type: 'histogram', aggs: [ - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, { type: 'count', schema: 'metric' } ] }); @@ -295,7 +295,7 @@ describe('AggConfigs', function () { const vis = new Vis(indexPattern, { type: 'histogram', aggs: [ - { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp' } }, + { type: 'date_histogram', schema: 'segment', params: { field: '@timestamp', interval: '10s' } }, { type: 'avg', schema: 'metric', params: { field: 'bytes' } }, { type: 'sum', schema: 'metric', params: { field: 'bytes' } }, { type: 'min', schema: 'metric', params: { field: 'bytes' } }, @@ -368,7 +368,8 @@ describe('AggConfigs', function () { type: 'date_histogram', schema: 'bucketAgg', params: { - field: '@timestamp' + field: '@timestamp', + interval: '10s', } }, customMetric: { diff --git a/x-pack/dev-tools/jest/create_jest_config.js b/x-pack/dev-tools/jest/create_jest_config.js index ff90f8d253cd7..2d9eec59e286e 100644 --- a/x-pack/dev-tools/jest/create_jest_config.js +++ b/x-pack/dev-tools/jest/create_jest_config.js @@ -22,7 +22,9 @@ export function createJestConfig({ ], moduleNameMapper: { '^ui/(.*)': `${kibanaDirectory}/src/legacy/ui/public/$1`, + 'uiExports/(.*)': `${kibanaDirectory}/src/dev/jest/mocks/file_mocks.js`, '^src/core/(.*)': `${kibanaDirectory}/src/core/$1`, + '^plugins/([^\/.]*)(.*)': `${kibanaDirectory}/src/legacy/core_plugins/$1/public$2`, '^plugins/xpack_main/(.*);': `${xPackKibanaDirectory}/legacy/plugins/xpack_main/public/$1`, '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$': `${kibanaDirectory}/src/dev/jest/mocks/file_mock.js`, diff --git a/x-pack/legacy/plugins/translations/translations/ja-JP.json b/x-pack/legacy/plugins/translations/translations/ja-JP.json index a53f4f3b056f0..fbad2f17e76f6 100644 --- a/x-pack/legacy/plugins/translations/translations/ja-JP.json +++ b/x-pack/legacy/plugins/translations/translations/ja-JP.json @@ -509,8 +509,6 @@ "common.ui.paginateSelectableList.sortByButtonLabeDescendingScreenReaderOnly": "降順", "common.ui.paginateSelectableList.sortByButtonLabel": "名前", "common.ui.paginateSelectableList.sortByButtonLabelScreenReaderOnly": "並べ替え基準", - "common.ui.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "無効なカレンダー間隔: {interval}、1 よりも大きな値が必要です", - "common.ui.parseEsInterval.invalidEsIntervalFormatErrorMessage": "無効な間隔のフォーマット: {interval}", "common.ui.recentLinks.linkItem.screenReaderLabel": "{recentlyAccessedItemLinklabel}、タイプ: {pageType}", "common.ui.savedObjectFinder.addNewItemButtonLabel": "新規 {item} を追加", "common.ui.savedObjectFinder.manageItemsButtonLabel": "{items} の管理", @@ -9921,4 +9919,4 @@ "xpack.watcher.watchActionsTitle": "条件が満たされた際に {watchActionsCount, plural, one{# アクション} other {# アクション}} を実行します", "xpack.watcher.watcherDescription": "アラートの作成、管理、監視によりデータへの変更を検知します。" } -} +} \ No newline at end of file diff --git a/x-pack/legacy/plugins/translations/translations/zh-CN.json b/x-pack/legacy/plugins/translations/translations/zh-CN.json index 211de1593cb15..ccf4e22bf1136 100644 --- a/x-pack/legacy/plugins/translations/translations/zh-CN.json +++ b/x-pack/legacy/plugins/translations/translations/zh-CN.json @@ -508,8 +508,6 @@ "common.ui.paginateSelectableList.sortByButtonLabeDescendingScreenReaderOnly": "降序", "common.ui.paginateSelectableList.sortByButtonLabel": "名称", "common.ui.paginateSelectableList.sortByButtonLabelScreenReaderOnly": "排序依据", - "common.ui.parseEsInterval.invalidEsCalendarIntervalErrorMessage": "无效的日历时间间隔:{interval},值必须为 1", - "common.ui.parseEsInterval.invalidEsIntervalFormatErrorMessage": "无效的时间间隔格式:{interval}", "common.ui.recentLinks.linkItem.screenReaderLabel": "{recentlyAccessedItemLinklabel},类型:{pageType}", "common.ui.savedObjectFinder.addNewItemButtonLabel": "添加新的 {item}", "common.ui.savedObjectFinder.manageItemsButtonLabel": "管理 {items}", @@ -9923,4 +9921,4 @@ "xpack.watcher.watchActionsTitle": "满足后将执行 {watchActionsCount, plural, one{# 个操作} other {# 个操作}}", "xpack.watcher.watcherDescription": "通过创建、管理和监测警报来检测数据中的更改。" } -} \ No newline at end of file +}