diff --git a/src/plugins/data/common/search/aggs/agg_config.ts b/src/plugins/data/common/search/aggs/agg_config.ts index f62fedc13b32a0..a237f5dfc43b50 100644 --- a/src/plugins/data/common/search/aggs/agg_config.ts +++ b/src/plugins/data/common/search/aggs/agg_config.ts @@ -437,10 +437,14 @@ export class AggConfig { } fieldIsTimeField() { - const indexPattern = this.getIndexPattern(); - if (!indexPattern) return false; - const timeFieldName = indexPattern.timeFieldName; - return timeFieldName && this.fieldName() === timeFieldName; + const defaultTimeField = this.getIndexPattern()?.getTimeField?.()?.name; + const defaultTimeFields = defaultTimeField ? [defaultTimeField] : []; + const allTimeFields = + this.aggConfigs.timeFields && this.aggConfigs.timeFields.length > 0 + ? this.aggConfigs.timeFields + : defaultTimeFields; + const currentFieldName = this.fieldName(); + return allTimeFields.includes(currentFieldName); } public get type() { diff --git a/src/plugins/data/common/search/aggs/agg_configs.ts b/src/plugins/data/common/search/aggs/agg_configs.ts index c9986b7e93bed2..ea42d0641f374b 100644 --- a/src/plugins/data/common/search/aggs/agg_configs.ts +++ b/src/plugins/data/common/search/aggs/agg_configs.ts @@ -57,6 +57,7 @@ export type IAggConfigs = AggConfigs; export class AggConfigs { public indexPattern: IndexPattern; public timeRange?: TimeRange; + public timeFields?: string[]; private readonly typesRegistry: AggTypesRegistryStart; aggs: IAggConfig[]; @@ -76,6 +77,10 @@ export class AggConfigs { configStates.forEach((params: any) => this.createAggConfig(params)); } + setTimeFields(timeFields: string[] | undefined) { + this.timeFields = timeFields; + } + setTimeRange(timeRange: TimeRange) { this.timeRange = timeRange; diff --git a/src/plugins/data/common/search/aggs/aggs_service.test.ts b/src/plugins/data/common/search/aggs/aggs_service.test.ts index 92e6168b169c6c..14e4f7932e9c15 100644 --- a/src/plugins/data/common/search/aggs/aggs_service.test.ts +++ b/src/plugins/data/common/search/aggs/aggs_service.test.ts @@ -192,9 +192,8 @@ describe('Aggs service', () => { describe('start()', () => { test('exposes proper contract', () => { const start = service.start(startDeps); - expect(Object.keys(start).length).toBe(5); + expect(Object.keys(start).length).toBe(4); expect(start).toHaveProperty('calculateAutoTimeExpression'); - expect(start).toHaveProperty('getDateMetaByDatatableColumn'); expect(start).toHaveProperty('createAggConfigs'); expect(start).toHaveProperty('types'); expect(start).toHaveProperty('datatableUtilities'); diff --git a/src/plugins/data/common/search/aggs/aggs_service.ts b/src/plugins/data/common/search/aggs/aggs_service.ts index c5543e5037fc6c..86bda5019a4961 100644 --- a/src/plugins/data/common/search/aggs/aggs_service.ts +++ b/src/plugins/data/common/search/aggs/aggs_service.ts @@ -17,7 +17,6 @@ import { getCalculateAutoTimeExpression, } from './'; import { AggsCommonSetup, AggsCommonStart } from './types'; -import { getDateMetaByDatatableColumn } from './utils/time_column_meta'; import { getDatatableColumnUtilities } from './utils/datatable_column_meta'; /** @internal */ @@ -89,12 +88,6 @@ export class AggsCommonService { return { calculateAutoTimeExpression, - getDateMetaByDatatableColumn: getDateMetaByDatatableColumn({ - calculateAutoTimeExpression, - getIndexPattern, - getConfig, - isDefaultTimezone, - }), datatableUtilities: getDatatableColumnUtilities({ getIndexPattern, createAggConfigs, diff --git a/src/plugins/data/common/search/aggs/buckets/date_histogram.ts b/src/plugins/data/common/search/aggs/buckets/date_histogram.ts index 61ad66d7efdc9a..4fa4d4f213ca28 100644 --- a/src/plugins/data/common/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/common/search/aggs/buckets/date_histogram.ts @@ -64,7 +64,9 @@ export interface AggParamsDateHistogram extends BaseAggParams { useNormalizedEsInterval?: boolean; scaleMetricValues?: boolean; interval?: string; + used_interval?: string; time_zone?: string; + used_time_zone?: string; drop_partials?: boolean; format?: string; min_doc_count?: number; @@ -220,6 +222,22 @@ export const getDateHistogramBucketAgg = ({ } }, }, + { + name: 'used_interval', + default: autoInterval, + shouldShow() { + return false; + }, + write: () => {}, + serialize(val, agg) { + if (!agg) return undefined; + updateTimeBuckets(agg, calculateBounds); + const { useNormalizedEsInterval } = agg.params; + const interval = agg.buckets.getInterval(useNormalizedEsInterval); + return interval.expression; + }, + toExpressionAst: () => undefined, + }, { name: 'time_zone', default: undefined, @@ -232,6 +250,18 @@ export const getDateHistogramBucketAgg = ({ output.params.time_zone = tz; }, }, + { + name: 'used_timezone', + shouldShow() { + return false; + }, + write: () => {}, + serialize(val, agg) { + if (!agg) return undefined; + return inferTimeZone(agg.params, agg.getIndexPattern(), isDefaultTimezone, getConfig); + }, + toExpressionAst: () => undefined, + }, { name: 'drop_partials', default: false, diff --git a/src/plugins/data/common/search/aggs/types.ts b/src/plugins/data/common/search/aggs/types.ts index 48ded7fa7a7fcf..a4e51efc0f6094 100644 --- a/src/plugins/data/common/search/aggs/types.ts +++ b/src/plugins/data/common/search/aggs/types.ts @@ -9,7 +9,6 @@ import { Assign } from '@kbn/utility-types'; import { DatatableColumn } from 'src/plugins/expressions'; import { IndexPattern } from '../../index_patterns/index_patterns/index_pattern'; -import { TimeRange } from '../../query'; import { aggAvg, aggBucketAvg, @@ -104,19 +103,6 @@ export interface AggsCommonSetup { /** @internal */ export interface AggsCommonStart { calculateAutoTimeExpression: ReturnType; - /** - * Helper function returning meta data about use date intervals for a data table column. - * If the column is not a column created by a date histogram aggregation of the esaggs data source, - * this function will return undefined. - * - * Otherwise, it will return the following attributes in an object: - * * `timeZone` time zone used to create the buckets (important e.g. for DST), - * * `timeRange` total time range of the fetch data (to infer partial buckets at the beginning and end of the data) - * * `interval` Interval used on elasticsearch (`auto` resolved to the actual interval) - */ - getDateMetaByDatatableColumn: ( - column: DatatableColumn - ) => Promise; datatableUtilities: { getIndexPattern: (column: DatatableColumn) => Promise; getAggConfig: (column: DatatableColumn) => Promise; diff --git a/src/plugins/data/common/search/aggs/utils/get_date_histogram_meta.ts b/src/plugins/data/common/search/aggs/utils/get_date_histogram_meta.ts new file mode 100644 index 00000000000000..86631c24f58ad2 --- /dev/null +++ b/src/plugins/data/common/search/aggs/utils/get_date_histogram_meta.ts @@ -0,0 +1,35 @@ +/* + * 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 { DatatableColumn } from 'src/plugins/expressions/common'; +import { TimeRange } from '../../../types'; +import type { AggParamsDateHistogram } from '../buckets'; +import { BUCKET_TYPES } from '../buckets/bucket_agg_types'; + +/** + * Helper function returning the used interval for data table column created by the histogramm agg type. + * "auto" will get expanded to the actually used interval. + * If the column is not a column created by a histogram aggregation of the esaggs data source, + * this function will return undefined. + */ +export const getDateHistogramMetaDataByDatatableColumn = (column: DatatableColumn) => { + if (column.meta.source !== 'esaggs') return; + if (column.meta.sourceParams?.type !== BUCKET_TYPES.DATE_HISTOGRAM) return; + const params = (column.meta.sourceParams.params as unknown) as AggParamsDateHistogram; + + let interval: string | undefined; + if (params.used_interval && params.used_interval !== 'auto') { + interval = params.used_interval; + } + + return { + interval, + timeZone: params.used_time_zone, + timeRange: column.meta.sourceParams.appliedTimeRange as TimeRange | undefined, + }; +}; diff --git a/src/plugins/data/common/search/aggs/utils/index.ts b/src/plugins/data/common/search/aggs/utils/index.ts index f90e8f88546f46..c92653e8432336 100644 --- a/src/plugins/data/common/search/aggs/utils/index.ts +++ b/src/plugins/data/common/search/aggs/utils/index.ts @@ -8,6 +8,7 @@ export * from './calculate_auto_time_expression'; export { getNumberHistogramIntervalByDatatableColumn } from './get_number_histogram_interval'; +export { getDateHistogramMetaDataByDatatableColumn } from './get_date_histogram_meta'; export * from './date_interval_utils'; export * from './get_format_with_aggs'; export * from './ipv4_address'; diff --git a/src/plugins/data/common/search/aggs/utils/time_column_meta.test.ts b/src/plugins/data/common/search/aggs/utils/time_column_meta.test.ts deleted file mode 100644 index d9527ecd92a128..00000000000000 --- a/src/plugins/data/common/search/aggs/utils/time_column_meta.test.ts +++ /dev/null @@ -1,147 +0,0 @@ -/* - * 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 { BUCKET_TYPES } from '../buckets'; -import { DateMetaByColumnDeps, getDateMetaByDatatableColumn } from './time_column_meta'; - -describe('getDateMetaByDatatableColumn', () => { - let params: DateMetaByColumnDeps; - beforeEach(() => { - params = { - calculateAutoTimeExpression: jest.fn().mockReturnValue('5m'), - getIndexPattern: jest.fn().mockResolvedValue({}), - isDefaultTimezone: jest.fn().mockReturnValue(true), - getConfig: jest.fn(), - }; - }); - - it('returns nothing on column from other data source', async () => { - expect( - await getDateMetaByDatatableColumn(params)({ - id: 'test', - name: 'test', - meta: { - type: 'date', - source: 'essql', - }, - }) - ).toEqual(undefined); - }); - - it('returns nothing on non date histogram column', async () => { - expect( - await getDateMetaByDatatableColumn(params)({ - id: 'test', - name: 'test', - meta: { - type: 'date', - source: 'esaggs', - sourceParams: { - type: BUCKET_TYPES.TERMS, - }, - }, - }) - ).toEqual(undefined); - }); - - it('returns time range, time zone and interval', async () => { - expect( - await getDateMetaByDatatableColumn(params)({ - id: 'test', - name: 'test', - meta: { - type: 'date', - source: 'esaggs', - sourceParams: { - type: BUCKET_TYPES.DATE_HISTOGRAM, - params: { - time_zone: 'UTC', - interval: '1h', - }, - appliedTimeRange: { - from: 'now-5d', - to: 'now', - }, - }, - }, - }) - ).toEqual({ - timeZone: 'UTC', - timeRange: { - from: 'now-5d', - to: 'now', - }, - interval: '1h', - }); - }); - - it('throws if unable to resolve interval', async () => { - await expect( - getDateMetaByDatatableColumn(params)({ - id: 'test', - name: 'test', - meta: { - type: 'date', - source: 'esaggs', - sourceParams: { - type: BUCKET_TYPES.DATE_HISTOGRAM, - params: { - time_zone: 'UTC', - interval: 'auto', - }, - }, - }, - }) - ).rejects.toBeDefined(); - - await expect( - getDateMetaByDatatableColumn(params)({ - id: 'test', - name: 'test', - meta: { - type: 'date', - source: 'esaggs', - sourceParams: { - type: BUCKET_TYPES.DATE_HISTOGRAM, - params: { - time_zone: 'UTC', - }, - }, - }, - }) - ).rejects.toBeDefined(); - }); - - it('returns resolved auto interval', async () => { - expect( - await getDateMetaByDatatableColumn(params)({ - id: 'test', - name: 'test', - meta: { - type: 'date', - source: 'esaggs', - sourceParams: { - type: BUCKET_TYPES.DATE_HISTOGRAM, - params: { - time_zone: 'UTC', - interval: 'auto', - }, - appliedTimeRange: { - from: '2020-10-05T00:00:00.000Z', - to: '2020-10-10T00:00:00.000Z', - }, - }, - }, - }) - ).toEqual( - expect.objectContaining({ - interval: '5m', - }) - ); - }); -}); diff --git a/src/plugins/data/common/search/aggs/utils/time_column_meta.ts b/src/plugins/data/common/search/aggs/utils/time_column_meta.ts deleted file mode 100644 index b0912803908cc4..00000000000000 --- a/src/plugins/data/common/search/aggs/utils/time_column_meta.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * 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 { DatatableColumn } from 'src/plugins/expressions/common'; -import { IndexPattern } from '../../../index_patterns'; - -import { TimeRange } from '../../../types'; -import { AggParamsDateHistogram, BUCKET_TYPES } from '../buckets'; -import { inferTimeZone } from './infer_time_zone'; - -export interface DateMetaByColumnDeps { - calculateAutoTimeExpression: (range: TimeRange) => string | undefined; - getIndexPattern: (id: string) => Promise; - isDefaultTimezone: () => boolean; - getConfig: (key: string) => T; -} - -export const getDateMetaByDatatableColumn = ({ - calculateAutoTimeExpression, - getIndexPattern, - isDefaultTimezone, - getConfig, -}: DateMetaByColumnDeps) => async ( - column: DatatableColumn -): Promise => { - if (column.meta.source !== 'esaggs') return; - if (column.meta.sourceParams?.type !== BUCKET_TYPES.DATE_HISTOGRAM) return; - const params = column.meta.sourceParams.params as AggParamsDateHistogram; - const appliedTimeRange = column.meta.sourceParams.appliedTimeRange as TimeRange | undefined; - - const tz = inferTimeZone( - params, - await getIndexPattern(column.meta.sourceParams.indexPatternId as string), - isDefaultTimezone, - getConfig - ); - - const interval = - params.interval === 'auto' && appliedTimeRange - ? calculateAutoTimeExpression(appliedTimeRange) - : params.interval; - - if (!interval || interval === 'auto') { - throw new Error('time interval could not be determined'); - } - - return { - timeZone: tz, - timeRange: appliedTimeRange, - interval, - }; -}; diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts index f8604266cd6e0d..7580032b0dd851 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.test.ts @@ -33,6 +33,7 @@ describe('esaggs expression function - public', () => { setTimeRange: jest.fn(), toDsl: jest.fn().mockReturnValue({ aggs: {} }), onSearchRequestStart: jest.fn(), + setTimeFields: jest.fn(), } as unknown) as jest.Mocked, filters: undefined, indexPattern: ({ id: 'logstash-*' } as unknown) as jest.Mocked, diff --git a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts index e2ee1a31757cb7..72d9cc40955700 100644 --- a/src/plugins/data/common/search/expressions/esaggs/request_handler.ts +++ b/src/plugins/data/common/search/expressions/esaggs/request_handler.ts @@ -73,6 +73,7 @@ export const handleRequest = async ({ const requestSearchSource = timeFilterSearchSource.createChild({ callParentStartHandlers: true }); aggs.setTimeRange(timeRange as TimeRange); + aggs.setTimeFields(timeFields); // For now we need to mirror the history of the passed search source, since // the request inspector wouldn't work otherwise. diff --git a/src/plugins/data/public/index.ts b/src/plugins/data/public/index.ts index 1838ca43e8c231..c47cd6cd9740db 100644 --- a/src/plugins/data/public/index.ts +++ b/src/plugins/data/public/index.ts @@ -313,6 +313,7 @@ import { toAbsoluteDates, boundsDescendingRaw, getNumberHistogramIntervalByDatatableColumn, + getDateHistogramMetaDataByDatatableColumn, // expressions utils getRequestInspectorStats, getResponseInspectorStats, @@ -423,6 +424,7 @@ export const search = { toAbsoluteDates, boundsDescendingRaw, getNumberHistogramIntervalByDatatableColumn, + getDateHistogramMetaDataByDatatableColumn, }, getRequestInspectorStats, getResponseInspectorStats, diff --git a/src/plugins/data/public/search/aggs/aggs_service.test.ts b/src/plugins/data/public/search/aggs/aggs_service.test.ts index 63c27eeaf0b11b..3d17565efbc5f6 100644 --- a/src/plugins/data/public/search/aggs/aggs_service.test.ts +++ b/src/plugins/data/public/search/aggs/aggs_service.test.ts @@ -79,9 +79,8 @@ describe('AggsService - public', () => { describe('start()', () => { test('exposes proper contract', () => { const start = service.start(startDeps); - expect(Object.keys(start).length).toBe(5); + expect(Object.keys(start).length).toBe(4); expect(start).toHaveProperty('calculateAutoTimeExpression'); - expect(start).toHaveProperty('getDateMetaByDatatableColumn'); expect(start).toHaveProperty('createAggConfigs'); expect(start).toHaveProperty('types'); expect(start).toHaveProperty('datatableUtilities'); diff --git a/src/plugins/data/public/search/aggs/aggs_service.ts b/src/plugins/data/public/search/aggs/aggs_service.ts index 26f19ca7eaef4d..f603bd733f6014 100644 --- a/src/plugins/data/public/search/aggs/aggs_service.ts +++ b/src/plugins/data/public/search/aggs/aggs_service.ts @@ -91,16 +91,13 @@ export class AggsService { public start({ fieldFormats, uiSettings, indexPatterns }: AggsStartDependencies): AggsStart { const isDefaultTimezone = () => uiSettings.isDefault('dateFormat:tz'); - const { - calculateAutoTimeExpression, - getDateMetaByDatatableColumn, - datatableUtilities, - types, - } = this.aggsCommonService.start({ - getConfig: this.getConfig!, - getIndexPattern: indexPatterns.get, - isDefaultTimezone, - }); + const { calculateAutoTimeExpression, datatableUtilities, types } = this.aggsCommonService.start( + { + getConfig: this.getConfig!, + getIndexPattern: indexPatterns.get, + isDefaultTimezone, + } + ); const aggTypesDependencies: AggTypesDependencies = { calculateBounds: this.calculateBounds, @@ -140,7 +137,6 @@ export class AggsService { return { calculateAutoTimeExpression, - getDateMetaByDatatableColumn, datatableUtilities, createAggConfigs: (indexPattern, configStates = []) => { return new AggConfigs(indexPattern, configStates, { typesRegistry }); diff --git a/src/plugins/data/public/search/aggs/mocks.ts b/src/plugins/data/public/search/aggs/mocks.ts index 9c90af801bdac4..fb50058f083489 100644 --- a/src/plugins/data/public/search/aggs/mocks.ts +++ b/src/plugins/data/public/search/aggs/mocks.ts @@ -56,7 +56,6 @@ export const searchAggsSetupMock = (): AggsSetup => ({ export const searchAggsStartMock = (): AggsStart => ({ calculateAutoTimeExpression: getCalculateAutoTimeExpression(getConfig), - getDateMetaByDatatableColumn: jest.fn(), datatableUtilities: { isFilterable: jest.fn(), getAggConfig: jest.fn(), diff --git a/src/plugins/data/server/search/aggs/aggs_service.ts b/src/plugins/data/server/search/aggs/aggs_service.ts index ac81c5b0d5df41..96927728f2f2f5 100644 --- a/src/plugins/data/server/search/aggs/aggs_service.ts +++ b/src/plugins/data/server/search/aggs/aggs_service.ts @@ -74,7 +74,6 @@ export class AggsService { const { calculateAutoTimeExpression, - getDateMetaByDatatableColumn, datatableUtilities, types, } = this.aggsCommonService.start({ @@ -119,7 +118,6 @@ export class AggsService { return { calculateAutoTimeExpression, - getDateMetaByDatatableColumn, datatableUtilities, createAggConfigs: (indexPattern, configStates = []) => { return new AggConfigs(indexPattern, configStates, { typesRegistry }); diff --git a/src/plugins/data/server/search/aggs/mocks.ts b/src/plugins/data/server/search/aggs/mocks.ts index 70864d57b3565f..3644a3c13c48d7 100644 --- a/src/plugins/data/server/search/aggs/mocks.ts +++ b/src/plugins/data/server/search/aggs/mocks.ts @@ -58,7 +58,6 @@ export const searchAggsSetupMock = (): AggsSetup => ({ const commonStartMock = (): AggsCommonStart => ({ calculateAutoTimeExpression: getCalculateAutoTimeExpression(getConfig), - getDateMetaByDatatableColumn: jest.fn(), datatableUtilities: { getIndexPattern: jest.fn(), getAggConfig: jest.fn(), diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.test.ts index 2e4de8b52dacb3..34579927cfe195 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.test.ts @@ -7,7 +7,7 @@ import moment from 'moment'; import { Datatable } from 'src/plugins/expressions/public'; -import { DataPublicPluginStart } from 'src/plugins/data/public'; +import { DataPublicPluginStart, TimeRange } from 'src/plugins/data/public'; import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; import { functionWrapper } from 'src/plugins/expressions/common/expression_functions/specs/tests/utils'; import { getTimeScaleFunction, TimeScaleArgs } from './time_scale'; @@ -44,9 +44,25 @@ describe('time_scale', () => { targetUnit: 'h', }; + function setDateHistogramMeta(options: { + timeZone: string; + timeRange: TimeRange; + interval: string; + }) { + emptyTable.columns[0].meta.source = 'esaggs'; + emptyTable.columns[0].meta.sourceParams = { + type: 'date_histogram', + params: { + used_interval: options.interval, + used_time_zone: options.timeZone, + }, + appliedTimeRange: options.timeRange, + }; + } + beforeEach(() => { dataMock = dataPluginMock.createStartContract(); - (dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({ + setDateHistogramMeta({ timeZone: 'UTC', timeRange: { from: '2020-10-05T00:00:00.000Z', @@ -156,7 +172,7 @@ describe('time_scale', () => { }); it('should be able to scale up as well', async () => { - (dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({ + setDateHistogramMeta({ timeZone: 'UTC', timeRange: { from: '2020-10-05T12:00:00.000Z', @@ -196,7 +212,7 @@ describe('time_scale', () => { }); it('can scale starting from unit multiple target intervals', async () => { - (dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({ + setDateHistogramMeta({ timeZone: 'UTC', timeRange: { from: '2020-10-05T13:00:00.000Z', @@ -238,7 +254,7 @@ describe('time_scale', () => { }); it('take start and end of timerange into account', async () => { - (dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({ + setDateHistogramMeta({ timeZone: 'UTC', timeRange: { from: '2020-10-05T12:00:00.000Z', @@ -283,7 +299,7 @@ describe('time_scale', () => { }); it('should respect DST switches', async () => { - (dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({ + setDateHistogramMeta({ timeZone: 'Europe/Berlin', timeRange: { from: '2020-10-23T00:00:00.000+02:00', @@ -323,7 +339,7 @@ describe('time_scale', () => { }); it('take leap years into account', async () => { - (dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({ + setDateHistogramMeta({ timeZone: 'UTC', timeRange: { from: '2010-01-01T00:00:00.000Z', diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.ts b/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.ts index 33395de389125f..368e06110efc98 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/time_scale.ts @@ -97,8 +97,8 @@ export function getTimeScaleFunction(data: DataPublicPluginStart) { } const targetUnitInMs = unitInMs[targetUnit]; - const timeInfo = await data.search.aggs.getDateMetaByDatatableColumn(dateColumnDefinition); - const intervalDuration = timeInfo && search.aggs.parseInterval(timeInfo.interval); + const timeInfo = search.aggs.getDateHistogramMetaDataByDatatableColumn(dateColumnDefinition); + const intervalDuration = timeInfo?.interval && search.aggs.parseInterval(timeInfo.interval); if (!timeInfo || !intervalDuration) { throw new Error( diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx index c3ce391f4469d4..2487ddf32cd1f9 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.test.tsx @@ -1894,10 +1894,14 @@ describe('xy_expression', () => { xyProps.args.layers[0].xScaleType = 'time'; }); it('should use first valid layer and determine interval', async () => { - const result = await calculateMinInterval( - xyProps, - jest.fn().mockResolvedValue({ interval: '5m' }) - ); + xyProps.data.tables.first.columns[2].meta.source = 'esaggs'; + xyProps.data.tables.first.columns[2].meta.sourceParams = { + type: 'date_histogram', + params: { + used_interval: '5m', + }, + }; + const result = await calculateMinInterval(xyProps); expect(result).toEqual(5 * 60 * 1000); }); @@ -1915,34 +1919,38 @@ describe('xy_expression', () => { }, }, }; - const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined)); + const result = await calculateMinInterval(xyProps); expect(result).toEqual(5); }); it('should return undefined if data table is empty', async () => { xyProps.data.tables.first.rows = []; - const result = await calculateMinInterval( - xyProps, - jest.fn().mockResolvedValue({ interval: '5m' }) - ); + xyProps.data.tables.first.columns[2].meta.source = 'esaggs'; + xyProps.data.tables.first.columns[2].meta.sourceParams = { + type: 'date_histogram', + params: { + used_interval: '5m', + }, + }; + const result = await calculateMinInterval(xyProps); expect(result).toEqual(undefined); }); it('should return undefined if interval can not be checked', async () => { - const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined)); + const result = await calculateMinInterval(xyProps); expect(result).toEqual(undefined); }); it('should return undefined if date column is not found', async () => { xyProps.data.tables.first.columns.splice(2, 1); - const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined)); + const result = await calculateMinInterval(xyProps); expect(result).toEqual(undefined); }); it('should return undefined if x axis is not a date', async () => { xyProps.args.layers[0].xScaleType = 'ordinal'; xyProps.data.tables.first.columns.splice(2, 1); - const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined)); + const result = await calculateMinInterval(xyProps); expect(result).toEqual(undefined); }); }); diff --git a/x-pack/plugins/lens/public/xy_visualization/expression.tsx b/x-pack/plugins/lens/public/xy_visualization/expression.tsx index 0bf5c139e24033..4dda44ad46d659 100644 --- a/x-pack/plugins/lens/public/xy_visualization/expression.tsx +++ b/x-pack/plugins/lens/public/xy_visualization/expression.tsx @@ -45,11 +45,7 @@ import { import { XYArgs, SeriesType, visualizationTypes, LayerArgs } from './types'; import { VisualizationContainer } from '../visualization_container'; import { isHorizontalChart, getSeriesColor } from './state_helpers'; -import { - DataPublicPluginStart, - ExpressionValueSearchContext, - search, -} from '../../../../../src/plugins/data/public'; +import { ExpressionValueSearchContext, search } from '../../../../../src/plugins/data/public'; import { ChartsPluginSetup, PaletteRegistry, @@ -192,10 +188,7 @@ export const xyChart: ExpressionFunctionDefinition< }, }; -export async function calculateMinInterval( - { args: { layers }, data }: XYChartProps, - getIntervalByColumn: DataPublicPluginStart['search']['aggs']['getDateMetaByDatatableColumn'] -) { +export async function calculateMinInterval({ args: { layers }, data }: XYChartProps) { const filteredLayers = getFilteredLayers(layers, data); if (filteredLayers.length === 0) return; const isTimeViz = data.dateRange && filteredLayers.every((l) => l.xScaleType === 'time'); @@ -212,9 +205,9 @@ export async function calculateMinInterval( return undefined; } } - const dateMetaData = await getIntervalByColumn(xColumn); - if (!dateMetaData) return; - const intervalDuration = search.aggs.parseInterval(dateMetaData.interval); + const dateInterval = search.aggs.getDateHistogramMetaDataByDatatableColumn(xColumn)?.interval; + if (!dateInterval) return; + const intervalDuration = search.aggs.parseInterval(dateInterval); if (!intervalDuration) return; return intervalDuration.as('milliseconds'); } @@ -223,7 +216,6 @@ export const getXyChartRenderer = (dependencies: { formatFactory: Promise; chartsThemeService: ChartsPluginSetup['theme']; paletteService: PaletteRegistry; - getIntervalByColumn: DataPublicPluginStart['search']['aggs']['getDateMetaByDatatableColumn']; timeZone: string; }): ExpressionRenderDefinition => ({ name: 'lens_xy_chart_renderer', @@ -254,7 +246,7 @@ export const getXyChartRenderer = (dependencies: { chartsThemeService={dependencies.chartsThemeService} paletteService={dependencies.paletteService} timeZone={dependencies.timeZone} - minInterval={await calculateMinInterval(config, dependencies.getIntervalByColumn)} + minInterval={await calculateMinInterval(config)} onClickValue={onClickValue} onSelectRange={onSelectRange} renderMode={handlers.getRenderMode()} diff --git a/x-pack/plugins/lens/public/xy_visualization/index.ts b/x-pack/plugins/lens/public/xy_visualization/index.ts index 1ca0bbb3f2da91..8650dedca0e2c6 100644 --- a/x-pack/plugins/lens/public/xy_visualization/index.ts +++ b/x-pack/plugins/lens/public/xy_visualization/index.ts @@ -63,7 +63,6 @@ export class XyVisualization { chartsThemeService: charts.theme, paletteService: palettes, timeZone: getTimeZone(core.uiSettings), - getIntervalByColumn: data.search.aggs.getDateMetaByDatatableColumn, }) ); return getXyVisualization({ paletteService: palettes, data });