From 840bbb718919630bf74ddbda05af914f7b0db81e Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Fri, 17 Apr 2020 18:07:41 +0200 Subject: [PATCH 01/26] Bind non primary time fields to timepicker --- .../data/public/query/timefilter/get_time.ts | 52 ++++++++++++++----- .../data/public/search/expressions/esaggs.ts | 47 ++++++++++++++--- .../data/public/search/tabify/buckets.ts | 12 ++--- .../data/public/search/tabify/tabify.ts | 18 +------ .../data/public/search/tabify/types.ts | 10 +++- .../indexpattern_datasource/to_expression.ts | 8 +++ 6 files changed, 105 insertions(+), 42 deletions(-) diff --git a/src/plugins/data/public/query/timefilter/get_time.ts b/src/plugins/data/public/query/timefilter/get_time.ts index fa15406189041..9e88e936be79d 100644 --- a/src/plugins/data/public/query/timefilter/get_time.ts +++ b/src/plugins/data/public/query/timefilter/get_time.ts @@ -32,6 +32,44 @@ export function calculateBounds(timeRange: TimeRange, options: CalculateBoundsOp }; } +function createTimeRangeFilter( + indexPattern: IIndexPattern, + timeRange: TimeRange, + field: IFieldType, + forceNow?: Date +) { + const bounds = calculateBounds(timeRange, { forceNow }); + if (!bounds) { + return; + } + return buildRangeFilter( + field, + { + ...(bounds.min && { gte: bounds.min.toISOString() }), + ...(bounds.max && { lte: bounds.max.toISOString() }), + format: 'strict_date_optional_time', + }, + indexPattern + ); +} + +export function getTimeForField( + indexPattern: IIndexPattern | undefined, + timeRange: TimeRange, + fieldName: string +) { + if (!indexPattern) { + return; + } + + const field = indexPattern.fields.find(f => f.name === fieldName); + if (!field) { + return; + } + + return createTimeRangeFilter(indexPattern, timeRange, field); +} + export function getTime( indexPattern: IIndexPattern | undefined, timeRange: TimeRange, @@ -50,17 +88,5 @@ export function getTime( return; } - const bounds = calculateBounds(timeRange, { forceNow }); - if (!bounds) { - return; - } - return buildRangeFilter( - timefield, - { - ...(bounds.min && { gte: bounds.min.toISOString() }), - ...(bounds.max && { lte: bounds.max.toISOString() }), - format: 'strict_date_optional_time', - }, - indexPattern - ); + return createTimeRangeFilter(indexPattern, timeRange, timefield, forceNow); } diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 2341f4fe447db..41e98a98c7117 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -32,16 +32,26 @@ import { Adapters } from '../../../../../plugins/inspector/public'; import { IAggConfigs } from '../aggs'; import { ISearchSource, SearchSource } from '../search_source'; import { tabifyAggResponse } from '../tabify'; -import { Filter, Query, serializeFieldFormat, TimeRange } from '../../../common'; -import { FilterManager, getTime } from '../../query'; +import { + Filter, + Query, + serializeFieldFormat, + TimeRange, + IIndexPattern, + RangeFilter, +} from '../../../common'; +import { FilterManager } from '../../query'; import { getSearchService, getQueryService, getIndexPatterns } from '../../services'; import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { getRequestInspectorStats, getResponseInspectorStats, serializeAggConfig } from './utils'; +import { calculateBounds, getTimeForField } from '../../query/timefilter/get_time'; export interface RequestHandlerParams { searchSource: ISearchSource; aggs: IAggConfigs; timeRange?: TimeRange; + timeFields?: string[]; + indexPattern?: IIndexPattern; query?: Query; filters?: Filter[]; forceFetch: boolean; @@ -65,12 +75,15 @@ interface Arguments { partialRows: boolean; includeFormatHints: boolean; aggConfigs: string; + timeField: string[]; } const handleCourierRequest = async ({ searchSource, aggs, timeRange, + timeFields, + indexPattern, query, filters, forceFetch, @@ -111,9 +124,22 @@ const handleCourierRequest = async ({ return aggs.onSearchRequestStart(paramSearchSource, options); }); - if (timeRange) { + // If timeFields have been specified, use the specified ones, otherwise use primary time field of index + // pattern if it's available. + const allTimeFields = + timeFields && timeFields.length > 0 + ? timeFields + : [ + indexPattern?.fields.find(field => field.name === indexPattern.timeFieldName)?.name, + ].filter((fieldName): fieldName is string => Boolean(fieldName)); + + // If a timeRange has been specified and we had at least one timeField available, create range + // filters for that those time fields + if (timeRange && allTimeFields.length > 0) { timeFilterSearchSource.setField('filter', () => { - return getTime(searchSource.getField('index'), timeRange); + return allTimeFields + .map(fieldName => getTimeForField(indexPattern, timeRange, fieldName)) + .filter((rangeFilter): rangeFilter is RangeFilter => Boolean(rangeFilter)); }); } @@ -181,11 +207,13 @@ const handleCourierRequest = async ({ (searchSource as any).finalResponse = resp; - const parsedTimeRange = timeRange ? getTime(aggs.indexPattern, timeRange) : null; + const parsedTimeRange = timeRange ? calculateBounds(timeRange) : null; const tabifyParams = { metricsAtAllLevels, partialRows, - timeRange: parsedTimeRange ? parsedTimeRange.range : undefined, + timeRange: parsedTimeRange + ? { from: parsedTimeRange.min, to: parsedTimeRange.max, timeFields: allTimeFields } + : undefined, }; const tabifyCacheHash = calculateObjectHash({ tabifyAggs: aggs, ...tabifyParams }); @@ -242,6 +270,11 @@ export const esaggs = (): ExpressionFunctionDefinition { - if (moment(bucket.key).isBefore(timeRange.gte)) { + if (moment(bucket.key).isBefore(timeRange.from)) { return false; } - if (moment(bucket.key + interval).isAfter(timeRange.lte)) { + if (moment(bucket.key + interval).isAfter(timeRange.to)) { return false; } return true; diff --git a/src/plugins/data/public/search/tabify/tabify.ts b/src/plugins/data/public/search/tabify/tabify.ts index e93e989034252..9cb55f94537c5 100644 --- a/src/plugins/data/public/search/tabify/tabify.ts +++ b/src/plugins/data/public/search/tabify/tabify.ts @@ -20,7 +20,7 @@ import { get } from 'lodash'; import { TabbedAggResponseWriter } from './response_writer'; import { TabifyBuckets } from './buckets'; -import { TabbedResponseWriterOptions, TabbedRangeFilterParams } from './types'; +import { TabbedResponseWriterOptions } from './types'; import { AggResponseBucket } from './types'; import { AggGroupNames, IAggConfigs } from '../aggs'; @@ -54,7 +54,7 @@ export function tabifyAggResponse( switch (agg.type.type) { case AggGroupNames.Buckets: const aggBucket = get(bucket, agg.id); - const tabifyBuckets = new TabifyBuckets(aggBucket, agg.params, timeRange); + const tabifyBuckets = new TabifyBuckets(aggBucket, agg.params, respOpts?.timeRange); if (tabifyBuckets.length) { tabifyBuckets.forEach((subBucket, tabifyBucketKey) => { @@ -153,20 +153,6 @@ export function tabifyAggResponse( doc_count: esResponse.hits.total, }; - let timeRange: TabbedRangeFilterParams | undefined; - - // Extract the time range object if provided - if (respOpts && respOpts.timeRange) { - const [timeRangeKey] = Object.keys(respOpts.timeRange); - - if (timeRangeKey) { - timeRange = { - name: timeRangeKey, - ...respOpts.timeRange[timeRangeKey], - }; - } - } - collectBucket(aggConfigs, write, topLevelBucket, '', 1); return write.response(); diff --git a/src/plugins/data/public/search/tabify/types.ts b/src/plugins/data/public/search/tabify/types.ts index 1e051880d3f19..72e91eb58c8a9 100644 --- a/src/plugins/data/public/search/tabify/types.ts +++ b/src/plugins/data/public/search/tabify/types.ts @@ -17,6 +17,7 @@ * under the License. */ +import { Moment } from 'moment'; import { RangeFilterParams } from '../../../common'; import { IAggConfig } from '../aggs'; @@ -25,11 +26,18 @@ export interface TabbedRangeFilterParams extends RangeFilterParams { name: string; } +/** @internal */ +export interface TimeRangeInformation { + from?: Moment; + to?: Moment; + timeFields: string[]; +} + /** @internal **/ export interface TabbedResponseWriterOptions { metricsAtAllLevels: boolean; partialRows: boolean; - timeRange?: { [key: string]: RangeFilterParams }; + timeRange?: TimeRangeInformation; } /** @internal */ diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index 3ab51b5fa3f2b..0f28e35dfd85b 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -10,6 +10,7 @@ import { IndexPatternColumn } from './indexpattern'; import { operationDefinitionMap } from './operations'; import { IndexPattern, IndexPatternPrivateState } from './types'; import { OriginalColumn } from './rename_columns'; +import { dateHistogramOperation } from './operations/definitions'; function getExpressionForLayer( indexPattern: IndexPattern, @@ -68,6 +69,12 @@ function getExpressionForLayer( return base; }); + const allDateHistogramFields = Object.values(columns) + .map(column => + column.operationType === dateHistogramOperation.type ? column.sourceField : null + ) + .filter(field => Boolean(field)); + return { type: 'expression', chain: [ @@ -79,6 +86,7 @@ function getExpressionForLayer( metricsAtAllLevels: [false], partialRows: [false], includeFormatHints: [true], + timeField: allDateHistogramFields, aggConfigs: [ { type: 'expression', From f04a572da2dc0aeff462f3c121cd7631ed7a82a5 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Fri, 17 Apr 2020 18:24:59 +0200 Subject: [PATCH 02/26] Fix typescript argument types --- src/plugins/data/public/search/expressions/esaggs.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 41e98a98c7117..d5b36eb84da72 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -75,7 +75,7 @@ interface Arguments { partialRows: boolean; includeFormatHints: boolean; aggConfigs: string; - timeField: string[]; + timeField?: string[]; } const handleCourierRequest = async ({ From f4073fc6b2a385c846c332a34543d3dff15a9e4c Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 20 Apr 2020 15:50:26 +0200 Subject: [PATCH 03/26] Allow auto interval on all fields --- src/plugins/data/public/search/aggs/buckets/date_histogram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts index 57f3aa85ad944..3ecdc17cb57f3 100644 --- a/src/plugins/data/public/search/aggs/buckets/date_histogram.ts +++ b/src/plugins/data/public/search/aggs/buckets/date_histogram.ts @@ -45,7 +45,7 @@ const updateTimeBuckets = ( customBuckets?: IBucketDateHistogramAggConfig['buckets'] ) => { const bounds = - agg.params.timeRange && agg.fieldIsTimeField() + agg.params.timeRange && (agg.fieldIsTimeField() || agg.params.interval === 'auto') ? timefilter.calculateBounds(agg.params.timeRange) : undefined; const buckets = customBuckets || agg.buckets; From c78f3f1e13ed98976c1748ab74f0b4758df42c81 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 20 Apr 2020 15:50:53 +0200 Subject: [PATCH 04/26] Remove lens_auto_date function --- .../indexpattern_datasource/auto_date.test.ts | 83 ------------------- .../indexpattern_datasource/auto_date.ts | 79 ------------------ .../public/indexpattern_datasource/index.ts | 4 +- .../indexpattern_datasource/to_expression.ts | 17 +--- 4 files changed, 3 insertions(+), 180 deletions(-) delete mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts delete mode 100644 x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts deleted file mode 100644 index 5f35ef650a08c..0000000000000 --- a/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.test.ts +++ /dev/null @@ -1,83 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; -import { getAutoDate } from './auto_date'; - -describe('auto_date', () => { - let autoDate: ReturnType; - - beforeEach(() => { - autoDate = getAutoDate({ data: dataPluginMock.createSetupContract() }); - }); - - it('should do nothing if no time range is provided', () => { - const result = autoDate.fn( - { - type: 'kibana_context', - }, - { - aggConfigs: 'canttouchthis', - }, - // eslint-disable-next-line - {} as any - ); - - expect(result).toEqual('canttouchthis'); - }); - - it('should not change anything if there are no auto date histograms', () => { - const aggConfigs = JSON.stringify([ - { type: 'date_histogram', params: { interval: '35h' } }, - { type: 'count' }, - ]); - const result = autoDate.fn( - { - timeRange: { - from: 'now-10d', - to: 'now', - }, - type: 'kibana_context', - }, - { - aggConfigs, - }, - // eslint-disable-next-line - {} as any - ); - - expect(result).toEqual(aggConfigs); - }); - - it('should change auto date histograms', () => { - const aggConfigs = JSON.stringify([ - { type: 'date_histogram', params: { interval: 'auto' } }, - { type: 'count' }, - ]); - const result = autoDate.fn( - { - timeRange: { - from: 'now-10d', - to: 'now', - }, - type: 'kibana_context', - }, - { - aggConfigs, - }, - // eslint-disable-next-line - {} as any - ); - - const interval = JSON.parse(result).find( - (agg: { type: string }) => agg.type === 'date_histogram' - ).params.interval; - - expect(interval).toBeTruthy(); - expect(typeof interval).toEqual('string'); - expect(interval).not.toEqual('auto'); - }); -}); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts b/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts deleted file mode 100644 index 97a46f4a3e176..0000000000000 --- a/x-pack/plugins/lens/public/indexpattern_datasource/auto_date.ts +++ /dev/null @@ -1,79 +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; - * you may not use this file except in compliance with the Elastic License. - */ - -import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public'; -import { - ExpressionFunctionDefinition, - KibanaContext, -} from '../../../../../src/plugins/expressions/public'; - -interface LensAutoDateProps { - aggConfigs: string; -} - -export function getAutoDate(deps: { - data: DataPublicPluginSetup; -}): ExpressionFunctionDefinition< - 'lens_auto_date', - KibanaContext | null, - LensAutoDateProps, - string -> { - function autoIntervalFromContext(ctx?: KibanaContext | null) { - if (!ctx || !ctx.timeRange) { - return; - } - - return deps.data.search.aggs.calculateAutoTimeExpression(ctx.timeRange); - } - - /** - * Convert all 'auto' date histograms into a concrete value (e.g. 2h). - * This allows us to support 'auto' on all date fields, and opens the - * door to future customizations (e.g. adjusting the level of detail, etc). - */ - return { - name: 'lens_auto_date', - aliases: [], - help: '', - inputTypes: ['kibana_context', 'null'], - args: { - aggConfigs: { - types: ['string'], - default: '""', - help: '', - }, - }, - fn(input, args) { - const interval = autoIntervalFromContext(input); - - if (!interval) { - return args.aggConfigs; - } - - const configs = JSON.parse(args.aggConfigs) as Array<{ - type: string; - params: { interval: string }; - }>; - - const updatedConfigs = configs.map(c => { - if (c.type !== 'date_histogram' || !c.params || c.params.interval !== 'auto') { - return c; - } - - return { - ...c, - params: { - ...c.params, - interval, - }, - }; - }); - - return JSON.stringify(updatedConfigs); - }, - }; -} diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/index.ts b/x-pack/plugins/lens/public/indexpattern_datasource/index.ts index fe14f472341af..73fd144b9c7f8 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/index.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/index.ts @@ -8,7 +8,6 @@ import { CoreSetup } from 'kibana/public'; import { Storage } from '../../../../../src/plugins/kibana_utils/public'; import { getIndexPatternDatasource } from './indexpattern'; import { renameColumns } from './rename_columns'; -import { getAutoDate } from './auto_date'; import { ExpressionsSetup } from '../../../../../src/plugins/expressions/public'; import { DataPublicPluginSetup, @@ -31,10 +30,9 @@ export class IndexPatternDatasource { setup( core: CoreSetup, - { data: dataSetup, expressions, editorFrame }: IndexPatternDatasourceSetupPlugins + { expressions, editorFrame }: IndexPatternDatasourceSetupPlugins ) { expressions.registerFunction(renameColumns); - expressions.registerFunction(getAutoDate({ data: dataSetup })); editorFrame.registerDatasource( core.getStartServices().then(([coreStart, { data }]) => diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index 0f28e35dfd85b..50e2682a446aa 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -73,7 +73,7 @@ function getExpressionForLayer( .map(column => column.operationType === dateHistogramOperation.type ? column.sourceField : null ) - .filter(field => Boolean(field)); + .filter((field): field is string => Boolean(field)); return { type: 'expression', @@ -87,20 +87,7 @@ function getExpressionForLayer( partialRows: [false], includeFormatHints: [true], timeField: allDateHistogramFields, - aggConfigs: [ - { - type: 'expression', - chain: [ - { - type: 'function', - function: 'lens_auto_date', - arguments: { - aggConfigs: [JSON.stringify(aggs)], - }, - }, - ], - }, - ], + aggConfigs: [JSON.stringify(aggs)], }, }, { From fbde5fbc5fcf43356ae4096362dbeb1b254cc9cc Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Mon, 20 Apr 2020 17:28:37 +0200 Subject: [PATCH 05/26] Fix existing jest tests and add test todos --- .../data/public/search/tabify/buckets.test.ts | 29 +++++++++++-------- .../indexpattern.test.ts | 18 +++--------- 2 files changed, 21 insertions(+), 26 deletions(-) diff --git a/src/plugins/data/public/search/tabify/buckets.test.ts b/src/plugins/data/public/search/tabify/buckets.test.ts index 98048cb25db2f..c077b429370dc 100644 --- a/src/plugins/data/public/search/tabify/buckets.test.ts +++ b/src/plugins/data/public/search/tabify/buckets.test.ts @@ -19,6 +19,7 @@ import { TabifyBuckets } from './buckets'; import { AggGroupNames } from '../aggs'; +import moment from 'moment'; describe('Buckets wrapper', () => { const check = (aggResp: any, count: number, keys: string[]) => { @@ -187,9 +188,9 @@ describe('Buckets wrapper', () => { }, }; const timeRange = { - gte: 150, - lte: 350, - name: 'date', + from: moment(150), + to: moment(350), + timeFields: ['date'], }; const buckets = new TabifyBuckets(aggResp, aggParams, timeRange); @@ -204,9 +205,9 @@ describe('Buckets wrapper', () => { }, }; const timeRange = { - gte: 150, - lte: 350, - name: 'date', + from: moment(150), + to: moment(350), + timeFields: ['date'], }; const buckets = new TabifyBuckets(aggResp, aggParams, timeRange); @@ -221,9 +222,9 @@ describe('Buckets wrapper', () => { }, }; const timeRange = { - gte: 100, - lte: 400, - name: 'date', + from: moment(100), + to: moment(400), + timeFields: ['date'], }; const buckets = new TabifyBuckets(aggResp, aggParams, timeRange); @@ -238,13 +239,17 @@ describe('Buckets wrapper', () => { }, }; const timeRange = { - gte: 150, - lte: 350, - name: 'date', + from: moment(150), + to: moment(350), + timeFields: ['date'], }; const buckets = new TabifyBuckets(aggResp, aggParams, timeRange); expect(buckets).toHaveLength(4); }); + + test.todo('does drop bucket when multiple time fields specified'); + + test.todo('does drop all buckets with matchin time fields'); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index e4f3677d0fe88..c559cf055ab82 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -262,20 +262,7 @@ describe('IndexPattern Data Source', () => { Object { "arguments": Object { "aggConfigs": Array [ - Object { - "chain": Array [ - Object { - "arguments": Object { - "aggConfigs": Array [ - "[{\\"id\\":\\"col1\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}},{\\"id\\":\\"col2\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"timestamp\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"1d\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}}]", - ], - }, - "function": "lens_auto_date", - "type": "function", - }, - ], - "type": "expression", - }, + "[{\\"id\\":\\"col1\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}},{\\"id\\":\\"col2\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"timestamp\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"1d\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}}]", ], "includeFormatHints": Array [ true, @@ -289,6 +276,9 @@ describe('IndexPattern Data Source', () => { "partialRows": Array [ false, ], + "timeField": Array [ + "timestamp", + ], }, "function": "esaggs", "type": "function", From c8baa9ad8e87f3e7f1d9aa44296416371acd2f17 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 21 Apr 2020 10:16:37 +0200 Subject: [PATCH 06/26] Remove lens_auto_date from esarchives --- .../es_archives/lens/basic/data.json.gz | Bin 4183 -> 4170 bytes .../es_archives/lens/reporting/data.json.gz | Bin 4542 -> 4671 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/x-pack/test/functional/es_archives/lens/basic/data.json.gz b/x-pack/test/functional/es_archives/lens/basic/data.json.gz index 4ed7c29f7391e4b01ea2737a318cb533d72bf63a..5293eeb9110021181830c68bd462bb0fc1a94e72 100644 GIT binary patch literal 4170 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 UI)*hi?LO%IAK6p-zo@DJ0Pju$MgRZ+ delta 4172 zcmV-S5VP;fAlD#&ABzYGj0AdK00U%UbYU)Pb8l_{?Hy~6+cxrheud7sPluJEmmdo-1kdh5rB_Ks{^czet`A4WzICu(aI-ZWT5wF-?6ulD|zywAf#H7(DUV2?t z7u^Mj%LHPW+(3$bnq=@|U*$vWC1{)GSd6aL2rJ~jbPW|gL4^VQ+eqw$FmOZYzlI>q zk_sLICZu711U76YuQ;t5b14X(BmF|CEUT838Kh|UV)x?3_x@aB3{kfrO<@u_VZ6dA zz-#p%=P;}St4iAd!O*7^7=8M_U=v=9oWzi;H^;v$FW32+T$c6r4q1zkwpb<;3iJ)=H>Ds7lJn2o=&>9>#bbko`>+I5q2);Kg3Z=V-O%okrzT|6Zam=wupKuftzp$e9N5>r#=tz5c&{7d$@mpx7<7eh!c8sTjmVX4+- zj*(1MVi)-(IuFkAk%>Z2cL%nKi&QF7GM$*EoUlt;>3DKRidK=pR0UU7XIm;|{t~3Lk)i2-b5%D~ zL%-5A$1)vlHrDLve;+nm%FA#XZeP@rHKa}rsZ&Gh zlq}13NS*o%s5zugJpeI>)TtqVbxK-N4yjW^>Xe++98#wqhK{md6&_Nj9)N;UT_zk- zryhZdL+aF{k@R_3=R@k$kUAwdE#)?ahSaJ1(@?s7d`O)dQl}n*N<-?@kUBM_PCYy} zL+aFXN}ZyVDt`e>%t{(P8v+1MO^>pj!c6ai9+ zcq8{q;1aFRG5!c{p#R?e6ME@edXpiS(vJ-LpFX~SH_oS6fzZySvc;~Gt<_0(v(;8L zT{Vm=-F8gFG4-*b5w@1?>$DQcSo=*haUrzMx6+%ktu}oMgy;ZbmeFezj_`FcVv9Zm z(JEseHNC5rc`zbhccdbJKw(PnIyj%MFZf-9L zi9EKMIl87%KKVpxvK#^qbOVV-_ww(+BkK&u30LYtoNPdvSJ7Lw!eyFWg&4bBwO}4I^ z(?Zs1gD@t0Y@=JHeBbeHUQEe-U9Owm<7M1Rwn3b`2@iWnf!eT#aFPyt$gqbDd&nd0 zAxsB2@#jCcD}2sw!TKLmT<T|x;8#DjAZPlK8foiy}Hif~|gqk~QbpH$~A*

%~lb0)L|zMxuCbqP2kmta9~uc-ZdZ< z^0Qqh0K+DKB850Lq1CC~lo4J*RFJoB$F)j@wkGun)e&r)M5D>BPKFmpD^Vp%wbrXAT8-~Z<)xsQh?&{#)d43hWPsw0bg#&+Z_H$bZ(AK6k8{ zV_4(aRDWO&g=E1wvuWU2L>^Tyu&i8lxwdJlfj_s5nHHG9)6Zca1zu$yyxk_0d-*Pr zLs&$A|5G?Dj~>?Dri#L3_i{lDxrJb(F6ahH{;>5$zg*BiUy3JINB`d~Mhf3s2#inH zq?C+7u~}|lvVuz%^u$UC?qKr9r;WU+4(1?mRiMu&sucjJ0&QxkfosmKX)yJy2{8eb zMWiTs=gaR9Q&UJ`1R)Ui0zum4)(w7{z6`^EpQ#ClFPZ9Aw)B2F2!Dyc79}Y1!p!Hg z_all@d`SgZA;5oN0z!sjsDmtxmsCQ;ss()s(t_Dc1qBSx*X+4AS4~?dQ?Ua}bxl`O z=f-S0gDx=4U{(^ZFs~M+fwkZ!Rsn7UZp+r(&?>8P8?LD3_SS+~T#LfyDjMf6w^%TL zyN3KxI77%fAwC7+e3)$_LQVfI*cOZ@g{r3Zolia}ArQC{@#iLPfh5AY!Nupyjj;u{ z%*$SH!7bWk8zl~u5^>fn-oo5dzUn3t2=_It@xG3&k=N~nxj2)NyB!tzy@XSyENNi?whtOi-xW?h}aOQ{DZq#ohm+eLl?AY?@oSYHWLD8L#)Ugh+cTPW8>PIgFT& z>agwlD6K9tDqnE#sf*J>Zr-SmU^MNkinY`jvVAW7hwJLiS#-s>y?oiX8i=fa?OqRb znbl=erWq*A`YP&%UeOY?D^U>Lt(nGP#v$!u0AqY!vNtQ;{<&p#tR7BrD?=X4QBTB zS+#B5d+NnvHf_yW1K)&G1I&OL>KPN8AP@v9Fal47&d)|hglf0ZQDTjH$?m$rXi}X4R5gJ zu}7vsXz1~+Y1|i&%|+> zfr&piO;`26G*B&Q%~fCtzhQ6)y`#C7U(YVqoHtGW9BV|NO#pwYDBvWaCyYL zfLD!rS3$HyzDvK0N57d{b5ZAikm&{bJTS=SY}sV1@U4joCX+z*?O8CNYlflO_6Z!K zGO=6}H5RYvdtx4hRl*Boiw+rv@2HRxH3F`|lh5ze5JKOT z?R;-W0KbWR4~6t);I2SU)z!Yr zqK)Y-tGK~#b}{uZ!@CrJOe=5oPTsa))5YVeP>D*VRRlVAEy+`ntx9lInEk0f0JJGp16x0=3_XzJ6 zpSFnDb*-#<9)2``=v$zDIP_b#J0}EOc0Lda7FzXLrbl4psP+gD*ShqP(1Q#uA@$J~ zJt6g2dtEY9d|JcVl~Im`w$GVfKUfT&82F|(M=#Q_o|Q0oTXd=mZ&l0L@f4 zg6_ds=DI(&TH+q~iQQP&!XKx&_FA8Pr&5lvzqLe1>Z>v7r?=K*<5WWfY;Sb;^4QsN z4aVsB1=+(V$>p#er?tiBpaFmE{I=5gzUJ*g(^fpC?d4V+1Xew-6+G=D-RcLp_x3WX zN4dRh@l%}2RuStw-Yr`kJLWAL9y#vin6+Zjar7%&^5Vdub@fig-uI61?|+bWQ4KA0 z9sK_O$1^_k&5)WOVK}dd4s>IX_#Z$7L!LGFCi*oA&%foeAHlZY W^`(wsjZM1;b^Z@zBFy>UssI3%^Y;w^ diff --git a/x-pack/test/functional/es_archives/lens/reporting/data.json.gz b/x-pack/test/functional/es_archives/lens/reporting/data.json.gz index 3c06824f606462a44aabd3a24b000cc4a6975cd8..74e4a6ab71733b5d6d976b3d2b6aca02dcae6f1b 100644 GIT binary patch literal 4671 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 Date: Tue, 21 Apr 2020 11:05:09 +0200 Subject: [PATCH 07/26] Add TimeBuckets jest tests --- .../data/public/search/tabify/buckets.test.ts | 38 ++++++++++++++++++- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/plugins/data/public/search/tabify/buckets.test.ts b/src/plugins/data/public/search/tabify/buckets.test.ts index c077b429370dc..81d9f3d5ca3fd 100644 --- a/src/plugins/data/public/search/tabify/buckets.test.ts +++ b/src/plugins/data/public/search/tabify/buckets.test.ts @@ -21,6 +21,10 @@ import { TabifyBuckets } from './buckets'; import { AggGroupNames } from '../aggs'; import moment from 'moment'; +interface Bucket { + key: number | string; +} + describe('Buckets wrapper', () => { const check = (aggResp: any, count: number, keys: string[]) => { test('reads the length', () => { @@ -248,8 +252,38 @@ describe('Buckets wrapper', () => { expect(buckets).toHaveLength(4); }); - test.todo('does drop bucket when multiple time fields specified'); + test('does drop bucket when multiple time fields specified', () => { + const aggParams = { + drop_partials: true, + field: { + name: 'date', + }, + }; + const timeRange = { + from: moment(100), + to: moment(350), + timeFields: ['date', 'other_datefield'], + }; + const buckets = new TabifyBuckets(aggResp, aggParams, timeRange); + + expect(buckets.buckets.map((b: Bucket) => b.key)).toEqual([100, 200]); + }); - test.todo('does drop all buckets with matchin time fields'); + test('does not drop bucket when no timeFields have been specified', () => { + const aggParams = { + drop_partials: true, + field: { + name: 'date', + }, + }; + const timeRange = { + from: moment(100), + to: moment(350), + timeFields: [], + }; + const buckets = new TabifyBuckets(aggResp, aggParams, timeRange); + + expect(buckets.buckets.map((b: Bucket) => b.key)).toEqual([0, 100, 200, 300]); + }); }); }); From 2dcbb7693d51961b292be62a8843caf6ed82b6fc Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 21 Apr 2020 12:04:50 +0200 Subject: [PATCH 08/26] Fix typo in esarchiver --- .../es_archives/lens/reporting/data.json.gz | Bin 4671 -> 4667 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/x-pack/test/functional/es_archives/lens/reporting/data.json.gz b/x-pack/test/functional/es_archives/lens/reporting/data.json.gz index 74e4a6ab71733b5d6d976b3d2b6aca02dcae6f1b..eca4514f14caeeb24153e37477828c80964e0ef9 100644 GIT binary patch delta 467 zcmV;^0WAK%B)cRAABzYGFT}A1H4uL(lWWa&O;slj1+EG;9yC_jW`_o#w!;J?Rr#=1|>)7^TbY50H zm`>}m>YxWP#*GOd%g@7byt*odRXjj2J<2K`!Wb8{YzIB=8LgiEU37xY!vufCcfD9S z+DFxoEcQ|JX5S!2@4wkMXx|T4XWz4}vd7NPcAu)L)T;W_R*k1nYEKBA|EDUohT&t4 z*?<5$+=SB|2-vI{`qZ~n?3$*dIx;D>Hsg2A6 zsU73R;z`iA4FfrB57^vWVsL*{sp|mWXFEXku|@q;Ooi_hFCNMZW4yROUOW`TX1sVP zx4gi3@zANYZ7n`UAsvOBEIGD})z)=2Cl`MU@jD3qNvq2s631|*42Ic|!}U>y*%0>W z3s(-|qYD~!gC6()Ih572OoNtq4D;@0A#<2_G{>tSST-Q`};!xnKP~-7qmF;_I0BSo- zMq(A)hI@iP2;DBv@CF@v*3P}^IdnP~by&QUUOjxp>;+pRtbH zhwrT(Os92kbz5I-eQ%)Kpr5Y9%Ud8VT=nJxq}|}j0VvDE;@g~{9yv( zyWX)JO{MBb7E`Ht$!`#&_h0fGwC{&&w(r?i*<s}ed=2(c1_b!9hpMMHsg2A~M>i z%+5bSsU1Vd;z`iA4FfrB57>X)abj>(sp|mWXFEXku|@q;Ooi_hIv&akW9Ya)bUYNp zX6Se*x4gj6@zANYZ7n`UAsvOBEIGCe+tzh8Cl`MU@jD3qNvq2s6357;42Ic|!}U>y z*%0>Wi(C%jqYD~!gC6()IjYsOOoNtqjQH+mA#=ocG{>tSSpTDe From 290611df62cd526ea3c1d16a53660b25fab2495f Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 21 Apr 2020 17:20:23 +0200 Subject: [PATCH 09/26] Address review feedback --- src/plugins/data/common/index_patterns/types.ts | 1 + .../data/public/query/timefilter/get_time.ts | 2 +- src/plugins/data/public/query/timefilter/index.ts | 2 +- .../data/public/search/expressions/esaggs.ts | 15 +++++++-------- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index 698edbf9cd6a8..c153f7b7d418f 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -26,6 +26,7 @@ export interface IIndexPattern { id?: string; type?: string; timeFieldName?: string; + getTimeField(): IFieldType | undefined; fieldFormatMap?: Record< string, { diff --git a/src/plugins/data/public/query/timefilter/get_time.ts b/src/plugins/data/public/query/timefilter/get_time.ts index 9e88e936be79d..3802efd18fef2 100644 --- a/src/plugins/data/public/query/timefilter/get_time.ts +++ b/src/plugins/data/public/query/timefilter/get_time.ts @@ -53,7 +53,7 @@ function createTimeRangeFilter( ); } -export function getTimeForField( +export function getTimeFilter( indexPattern: IIndexPattern | undefined, timeRange: TimeRange, fieldName: string diff --git a/src/plugins/data/public/query/timefilter/index.ts b/src/plugins/data/public/query/timefilter/index.ts index a6260e782c12f..4609dde599d5a 100644 --- a/src/plugins/data/public/query/timefilter/index.ts +++ b/src/plugins/data/public/query/timefilter/index.ts @@ -22,6 +22,6 @@ export { TimefilterService, TimefilterSetup } from './timefilter_service'; export * from './types'; export { Timefilter, TimefilterContract } from './timefilter'; export { TimeHistory, TimeHistoryContract } from './time_history'; -export { getTime } from './get_time'; +export { getTime, calculateBounds, getTimeFilter } from './get_time'; export { changeTimeFilter } from './lib/change_time_filter'; export { extractTimeFilter } from './lib/extract_time_filter'; diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index d5b36eb84da72..a3a450626d553 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -38,13 +38,12 @@ import { serializeFieldFormat, TimeRange, IIndexPattern, - RangeFilter, + isRangeFilter, } from '../../../common'; -import { FilterManager } from '../../query'; +import { FilterManager, calculateBounds, getTimeFilter } from '../../query'; import { getSearchService, getQueryService, getIndexPatterns } from '../../services'; import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { getRequestInspectorStats, getResponseInspectorStats, serializeAggConfig } from './utils'; -import { calculateBounds, getTimeForField } from '../../query/timefilter/get_time'; export interface RequestHandlerParams { searchSource: ISearchSource; @@ -129,17 +128,17 @@ const handleCourierRequest = async ({ const allTimeFields = timeFields && timeFields.length > 0 ? timeFields - : [ - indexPattern?.fields.find(field => field.name === indexPattern.timeFieldName)?.name, - ].filter((fieldName): fieldName is string => Boolean(fieldName)); + : indexPattern?.getTimeField() + ? [indexPattern?.getTimeField()] + : []; // If a timeRange has been specified and we had at least one timeField available, create range // filters for that those time fields if (timeRange && allTimeFields.length > 0) { timeFilterSearchSource.setField('filter', () => { return allTimeFields - .map(fieldName => getTimeForField(indexPattern, timeRange, fieldName)) - .filter((rangeFilter): rangeFilter is RangeFilter => Boolean(rangeFilter)); + .map(fieldName => getTimeFilter(indexPattern, timeRange, fieldName)) + .filter(isRangeFilter); }); } From 5b2f684f67ad9609640e9b349e203be1c1683728 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Tue, 21 Apr 2020 18:40:18 +0200 Subject: [PATCH 10/26] Make code a bit better readable --- src/plugins/data/public/search/expressions/esaggs.ts | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index a3a450626d553..60ede2dc22e44 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -125,12 +125,8 @@ const handleCourierRequest = async ({ // If timeFields have been specified, use the specified ones, otherwise use primary time field of index // pattern if it's available. - const allTimeFields = - timeFields && timeFields.length > 0 - ? timeFields - : indexPattern?.getTimeField() - ? [indexPattern?.getTimeField()] - : []; + const defaultTimeFields = indexPattern?.getTimeField() ? [indexPattern?.getTimeField()] : []; + const allTimeFields = timeFields && timeFields.length > 0 ? timeFields : defaultTimeFields; // If a timeRange has been specified and we had at least one timeField available, create range // filters for that those time fields From e69e1018c95e3434a74752c1ee7f6e6acf63fa42 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 22 Apr 2020 09:20:21 +0200 Subject: [PATCH 11/26] Fix default time field retrieval --- src/plugins/data/public/search/expressions/esaggs.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 60ede2dc22e44..2a1bcb4481237 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -125,7 +125,8 @@ const handleCourierRequest = async ({ // If timeFields have been specified, use the specified ones, otherwise use primary time field of index // pattern if it's available. - const defaultTimeFields = indexPattern?.getTimeField() ? [indexPattern?.getTimeField()] : []; + const defaultTimeField = indexPattern?.getTimeField(); + const defaultTimeFields = defaultTimeField ? [defaultTimeField.name] : []; const allTimeFields = timeFields && timeFields.length > 0 ? timeFields : defaultTimeFields; // If a timeRange has been specified and we had at least one timeField available, create range From 872d76e6b2d60a3b481d95a67cfca1d3be5fd526 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 22 Apr 2020 09:42:25 +0200 Subject: [PATCH 12/26] Fix TS errors --- src/plugins/data/common/index_patterns/types.ts | 2 +- src/plugins/data/public/search/expressions/esaggs.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/data/common/index_patterns/types.ts b/src/plugins/data/common/index_patterns/types.ts index c153f7b7d418f..e21d27a70e02a 100644 --- a/src/plugins/data/common/index_patterns/types.ts +++ b/src/plugins/data/common/index_patterns/types.ts @@ -26,7 +26,7 @@ export interface IIndexPattern { id?: string; type?: string; timeFieldName?: string; - getTimeField(): IFieldType | undefined; + getTimeField?(): IFieldType | undefined; fieldFormatMap?: Record< string, { diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 2a1bcb4481237..e6e493acd1ed7 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -68,7 +68,7 @@ const name = 'esaggs'; type Input = KibanaContext | null; type Output = Promise; -interface Arguments { +export interface Arguments { index: string; metricsAtAllLevels: boolean; partialRows: boolean; @@ -125,7 +125,7 @@ const handleCourierRequest = async ({ // If timeFields have been specified, use the specified ones, otherwise use primary time field of index // pattern if it's available. - const defaultTimeField = indexPattern?.getTimeField(); + const defaultTimeField = indexPattern?.getTimeField?.(); const defaultTimeFields = defaultTimeField ? [defaultTimeField.name] : []; const allTimeFields = timeFields && timeFields.length > 0 ? timeFields : defaultTimeFields; From 47234a3c7c55338d8a3a850dbc65acc58ee468b0 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 22 Apr 2020 11:41:10 +0200 Subject: [PATCH 13/26] Add esaggs interpreter tests --- .../test_suites/run_pipeline/esaggs.ts | 93 +++++++++++++++++++ .../test_suites/run_pipeline/index.ts | 1 + 2 files changed, 94 insertions(+) create mode 100644 test/interpreter_functional/test_suites/run_pipeline/esaggs.ts diff --git a/test/interpreter_functional/test_suites/run_pipeline/esaggs.ts b/test/interpreter_functional/test_suites/run_pipeline/esaggs.ts new file mode 100644 index 0000000000000..cd991aa3b2eac --- /dev/null +++ b/test/interpreter_functional/test_suites/run_pipeline/esaggs.ts @@ -0,0 +1,93 @@ +/* + * 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 expect from '@kbn/expect'; +import { ExpectExpression, expectExpressionProvider } from './helpers'; +import { FtrProviderContext } from '../../../functional/ftr_provider_context'; + +function getCell(esaggsResult: any, column: number, row: number): unknown | undefined { + const columnId = esaggsResult?.columns[column]?.id; + if (!columnId) { + return; + } + return esaggsResult?.rows[row]?.[columnId]; +} + +export default function({ + getService, + updateBaselines, +}: FtrProviderContext & { updateBaselines: boolean }) { + let expectExpression: ExpectExpression; + describe('esaggs pipeline expression tests', () => { + before(() => { + expectExpression = expectExpressionProvider({ getService, updateBaselines }); + }); + + describe('correctly renders tagcloud', () => { + it('filters on index pattern primary date field by default', async () => { + const aggConfigs = [{ id: 1, enabled: true, type: 'count', schema: 'metric', params: {} }]; + const timeRange = { + from: '2006-09-21T00:00:00Z', + to: '2015-09-22T00:00:00Z', + }; + const expression = ` + kibana_context timeRange='${JSON.stringify(timeRange)}' + | esaggs index='logstash-*' aggConfigs='${JSON.stringify(aggConfigs)}' + `; + const result = await expectExpression('esaggs_primary_timefield', expression).getResponse(); + expect(getCell(result, 0, 0)).to.be(9375); + }); + + it('filters on the specified date field', async () => { + const aggConfigs = [{ id: 1, enabled: true, type: 'count', schema: 'metric', params: {} }]; + const timeRange = { + from: '2006-09-21T00:00:00Z', + to: '2015-09-22T00:00:00Z', + }; + const expression = ` + kibana_context timeRange='${JSON.stringify(timeRange)}' + | esaggs index='logstash-*' timeField='relatedContent.article:published_time' aggConfigs='${JSON.stringify( + aggConfigs + )}' + `; + const result = await expectExpression('esaggs_other_timefield', expression).getResponse(); + expect(getCell(result, 0, 0)).to.be(11134); + }); + + it('filters on multiple specified date field', async () => { + const aggConfigs = [{ id: 1, enabled: true, type: 'count', schema: 'metric', params: {} }]; + const timeRange = { + from: '2006-09-21T00:00:00Z', + to: '2015-09-22T00:00:00Z', + }; + const expression = ` + kibana_context timeRange='${JSON.stringify(timeRange)}' + | esaggs index='logstash-*' timeField='relatedContent.article:published_time' timeField='@timestamp' aggConfigs='${JSON.stringify( + aggConfigs + )}' + `; + const result = await expectExpression( + 'esaggs_multiple_timefields', + expression + ).getResponse(); + expect(getCell(result, 0, 0)).to.be(7452); + }); + }); + }); +} diff --git a/test/interpreter_functional/test_suites/run_pipeline/index.ts b/test/interpreter_functional/test_suites/run_pipeline/index.ts index 031a0e3576ccc..9590f9f8c1794 100644 --- a/test/interpreter_functional/test_suites/run_pipeline/index.ts +++ b/test/interpreter_functional/test_suites/run_pipeline/index.ts @@ -46,5 +46,6 @@ export default function({ getService, getPageObjects, loadTestFile }: FtrProvide loadTestFile(require.resolve('./basic')); loadTestFile(require.resolve('./tag_cloud')); loadTestFile(require.resolve('./metric')); + loadTestFile(require.resolve('./esaggs')); }); } From 1da467a5ef6d375403d0acc979c8ab38af3e1774 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 22 Apr 2020 11:51:26 +0200 Subject: [PATCH 14/26] Change public API doc of data plugin --- src/plugins/data/public/public.api.md | 2 ++ src/plugins/data/server/server.api.md | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index 427c4f7864554..5f5c8ba69a3ad 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -753,6 +753,8 @@ export interface IIndexPattern { // (undocumented) fields: IFieldType[]; // (undocumented) + getTimeField?(): IFieldType | undefined; + // (undocumented) id?: string; // (undocumented) timeFieldName?: string; diff --git a/src/plugins/data/server/server.api.md b/src/plugins/data/server/server.api.md index c41023eab6d20..63384fdfc0d2a 100644 --- a/src/plugins/data/server/server.api.md +++ b/src/plugins/data/server/server.api.md @@ -408,6 +408,8 @@ export interface IIndexPattern { // (undocumented) fields: IFieldType[]; // (undocumented) + getTimeField?(): IFieldType | undefined; + // (undocumented) id?: string; // (undocumented) timeFieldName?: string; From 315809710d578e03b26de3052bbfe6fefe2fc395 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Wed, 22 Apr 2020 21:25:33 +0200 Subject: [PATCH 15/26] Add toExpression tests for index pattern datasource --- .../indexpattern.test.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts index c559cf055ab82..039d44a8756bb 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/indexpattern.test.ts @@ -10,6 +10,7 @@ import { DatasourcePublicAPI, Operation, Datasource } from '../types'; import { coreMock } from 'src/core/public/mocks'; import { IndexPatternPersistedState, IndexPatternPrivateState } from './types'; import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks'; +import { Ast } from '@kbn/interpreter/common'; jest.mock('./loader'); jest.mock('../id_generator'); @@ -297,6 +298,89 @@ describe('IndexPattern Data Source', () => { } `); }); + + it('should put all time fields used in date_histograms to the esaggs timeField parameter', async () => { + const queryPersistedState: IndexPatternPersistedState = { + currentIndexPatternId: '1', + layers: { + first: { + indexPatternId: '1', + columnOrder: ['col1', 'col2', 'col3'], + columns: { + col1: { + label: 'Count of records', + dataType: 'number', + isBucketed: false, + sourceField: 'Records', + operationType: 'count', + }, + col2: { + label: 'Date', + dataType: 'date', + isBucketed: true, + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: 'auto', + }, + }, + col3: { + label: 'Date 2', + dataType: 'date', + isBucketed: true, + operationType: 'date_histogram', + sourceField: 'another_datefield', + params: { + interval: 'auto', + }, + }, + }, + }, + }, + }; + + const state = stateFromPersistedState(queryPersistedState); + + const ast = indexPatternDatasource.toExpression(state, 'first') as Ast; + expect(ast.chain[0].arguments.timeField).toEqual(['timestamp', 'another_datefield']); + }); + + it('should not put date fields used outside date_histograms to the esaggs timeField parameter', async () => { + const queryPersistedState: IndexPatternPersistedState = { + currentIndexPatternId: '1', + layers: { + first: { + indexPatternId: '1', + columnOrder: ['col1', 'col2'], + columns: { + col1: { + label: 'Count of records', + dataType: 'date', + isBucketed: false, + sourceField: 'timefield', + operationType: 'cardinality', + }, + col2: { + label: 'Date', + dataType: 'date', + isBucketed: true, + operationType: 'date_histogram', + sourceField: 'timestamp', + params: { + interval: 'auto', + }, + }, + }, + }, + }, + }; + + const state = stateFromPersistedState(queryPersistedState); + + const ast = indexPatternDatasource.toExpression(state, 'first') as Ast; + expect(ast.chain[0].arguments.timeField).toEqual(['timestamp']); + expect(ast.chain[0].arguments.timeField).not.toContain('timefield'); + }); }); describe('#insertLayer', () => { From b6a9fc2d2f7d4c1046acb7ea8b1d37f97ad027e9 Mon Sep 17 00:00:00 2001 From: Tim Roes Date: Fri, 24 Apr 2020 08:56:40 +0200 Subject: [PATCH 16/26] Add migration stub --- x-pack/plugins/lens/server/migrations.ts | 44 ++++++++++++++++++++++-- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/lens/server/migrations.ts b/x-pack/plugins/lens/server/migrations.ts index 3d238723b7438..6f03e7d9deeaf 100644 --- a/x-pack/plugins/lens/server/migrations.ts +++ b/x-pack/plugins/lens/server/migrations.ts @@ -4,8 +4,9 @@ * you may not use this file except in compliance with the Elastic License. */ -import { cloneDeep } from 'lodash'; -import { SavedObjectMigrationFn } from 'src/core/server'; +import { cloneDeep, flow } from 'lodash'; +import { fromExpression, toExpression } from '@kbn/interpreter/common'; +import { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'src/core/server'; interface XYLayerPre77 { layerId: string; @@ -14,6 +15,42 @@ interface XYLayerPre77 { accessors: string[]; } +function removeLensAutoDate(doc: SavedObjectUnsanitizedDoc) { + const expression: string = doc.attributes?.expression; + const ast = fromExpression(expression); + + // TODO: Magic AST manipulation + // esaggs aggConfigs={lens_auto_date aggConfigs='[{}, {}]'} + // -> + // esaggs aggConfigs='[{}, {}]' + + return { + ...doc, + attributes: { + ...doc.attributes, + expression: toExpression(ast), + }, + }; +} + +function addTimeFieldToEsaggs(doc: SavedObjectUnsanitizedDoc) { + const expression: string = doc.attributes?.expression; + const ast = fromExpression(expression); + + // TODO: Magiv AST manipulation + // esaggs aggConfigs='[{id, type: 'date_histogram', params: { field: 'timestamp' }}, ... ]' + // -> + // esaggs timeField='timestamp' timeField='another_date_field' aggConfigs='[the same as before]' + + return { + ...doc, + attributes: { + ...doc.attributes, + expression: toExpression(ast), + }, + }; +} + export const migrations: Record = { '7.7.0': doc => { const newDoc = cloneDeep(doc); @@ -34,4 +71,7 @@ export const migrations: Record = { } return newDoc; }, + // The order of these migrations matter, since the timefield migration relies on the aggConfigs + // sitting directly on the esaggs as an argument and not a nested function (which lens_auto_date was). + '7.8.0': flow(removeLensAutoDate, addTimeFieldToEsaggs), }; From d745736b007b0e0cf7006833fd8ba0eafbd46781 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Mon, 27 Apr 2020 20:15:22 -0400 Subject: [PATCH 17/26] Add full migration --- x-pack/plugins/lens/server/migrations.test.ts | 104 ++++++++++++++++++ x-pack/plugins/lens/server/migrations.ts | 79 +++++++++++-- 2 files changed, 172 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/lens/server/migrations.test.ts b/x-pack/plugins/lens/server/migrations.test.ts index e80308cc9acdb..eff56d5d9a8df 100644 --- a/x-pack/plugins/lens/server/migrations.test.ts +++ b/x-pack/plugins/lens/server/migrations.test.ts @@ -158,4 +158,108 @@ describe('Lens migrations', () => { ]); }); }); + + describe('7.8.0 auto timestamp', () => { + const context = {} as SavedObjectMigrationContext; + + const example = { + type: 'lens', + attributes: { + expression: `kibana + | kibana_context query="{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"}" filters="[]" + | lens_merge_tables layerIds="bd09dc71-a7e2-42d0-83bd-85df8291f03c" + tables={esaggs + index="ff959d40-b880-11e8-a6d9-e546fe2bba5f" + metricsAtAllLevels=false + partialRows=false + includeFormatHints=true + aggConfigs={ + lens_auto_date + aggConfigs="[{\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"products.created_on\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"auto\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}},{\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}}]" + } + | lens_rename_columns idMap="{\\"col-0-1d9cc16c-1460-41de-88f8-471932ecbc97\\":{\\"label\\":\\"products.created_on\\",\\"dataType\\":\\"date\\",\\"operationType\\":\\"date_histogram\\",\\"sourceField\\":\\"products.created_on\\",\\"isBucketed\\":true,\\"scale\\":\\"interval\\",\\"params\\":{\\"interval\\":\\"auto\\"},\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\"},\\"col-1-66115819-8481-4917-a6dc-8ffb10dd02df\\":{\\"label\\":\\"Count of records\\",\\"dataType\\":\\"number\\",\\"operationType\\":\\"count\\",\\"suggestedPriority\\":0,\\"isBucketed\\":false,\\"scale\\":\\"ratio\\",\\"sourceField\\":\\"Records\\",\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\"}}" + } + | lens_xy_chart + xTitle="products.created_on" + yTitle="Count of records" + legend={lens_xy_legendConfig isVisible=true position="right"} + layers={lens_xy_layer + layerId="bd09dc71-a7e2-42d0-83bd-85df8291f03c" + hide=false + xAccessor="1d9cc16c-1460-41de-88f8-471932ecbc97" + yScaleType="linear" + xScaleType="time" + isHistogram=true + seriesType="bar_stacked" + accessors="66115819-8481-4917-a6dc-8ffb10dd02df" + columnToLabel="{\\"66115819-8481-4917-a6dc-8ffb10dd02df\\":\\"Count of records\\"}" + } + `, + state: { + datasourceStates: { + indexpattern: { + currentIndexPatternId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + layers: { + 'bd09dc71-a7e2-42d0-83bd-85df8291f03c': { + indexPatternId: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', + columns: { + '1d9cc16c-1460-41de-88f8-471932ecbc97': { + label: 'products.created_on', + dataType: 'date', + operationType: 'date_histogram', + sourceField: 'products.created_on', + isBucketed: true, + scale: 'interval', + params: { interval: 'auto' }, + }, + '66115819-8481-4917-a6dc-8ffb10dd02df': { + label: 'Count of records', + dataType: 'number', + operationType: 'count', + suggestedPriority: 0, + isBucketed: false, + scale: 'ratio', + sourceField: 'Records', + }, + }, + columnOrder: [ + '1d9cc16c-1460-41de-88f8-471932ecbc97', + '66115819-8481-4917-a6dc-8ffb10dd02df', + ], + }, + }, + }, + }, + datasourceMetaData: { + filterableIndexPatterns: [ + { id: 'ff959d40-b880-11e8-a6d9-e546fe2bba5f', title: 'kibana_sample_data_ecommerce' }, + ], + }, + visualization: { + legend: { isVisible: true, position: 'right' }, + preferredSeriesType: 'bar_stacked', + layers: [ + { + layerId: 'bd09dc71-a7e2-42d0-83bd-85df8291f03c', + accessors: ['66115819-8481-4917-a6dc-8ffb10dd02df'], + position: 'top', + seriesType: 'bar_stacked', + showGridlines: false, + xAccessor: '1d9cc16c-1460-41de-88f8-471932ecbc97', + }, + ], + }, + query: { query: '', language: 'kuery' }, + filters: [], + }, + title: 'Bar chart', + visualizationType: 'lnsXY', + }, + }; + + it('should remove the lens_auto_date expression', () => { + const result = migrations['7.8.0'](example, context); + expect(result.attributes.expression).toContain(`timeFields=\"products.created_on\"`); + }); + }); }); diff --git a/x-pack/plugins/lens/server/migrations.ts b/x-pack/plugins/lens/server/migrations.ts index 6f03e7d9deeaf..b36982bb74ab8 100644 --- a/x-pack/plugins/lens/server/migrations.ts +++ b/x-pack/plugins/lens/server/migrations.ts @@ -5,7 +5,7 @@ */ import { cloneDeep, flow } from 'lodash'; -import { fromExpression, toExpression } from '@kbn/interpreter/common'; +import { fromExpression, toExpression, Ast, ExpressionFunctionAST } from '@kbn/interpreter/common'; import { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'src/core/server'; interface XYLayerPre77 { @@ -19,16 +19,40 @@ function removeLensAutoDate(doc: SavedObjectUnsanitizedDoc) { const expression: string = doc.attributes?.expression; const ast = fromExpression(expression); - // TODO: Magic AST manipulation - // esaggs aggConfigs={lens_auto_date aggConfigs='[{}, {}]'} - // -> - // esaggs aggConfigs='[{}, {}]' + const newChain: ExpressionFunctionAST[] = ast.chain.map(topNode => { + if (topNode.function !== 'lens_merge_tables') { + return topNode; + } + return { + ...topNode, + arguments: { + ...topNode.arguments, + tables: (topNode.arguments.tables as Ast[]).map(middleNode => { + return { + type: 'expression', + chain: middleNode.chain.map(node => { + if (node.function === 'esaggs') { + return { + ...node, + arguments: { + ...node.arguments, + aggConfigs: (node.arguments.aggConfigs[0] as Ast).chain[0].arguments.aggConfigs, + }, + }; + } + return node; + }), + }; + }), + }, + }; + }); return { ...doc, attributes: { ...doc.attributes, - expression: toExpression(ast), + expression: toExpression({ ...ast, chain: newChain }), }, }; } @@ -37,16 +61,49 @@ function addTimeFieldToEsaggs(doc: SavedObjectUnsanitizedDoc) { const expression: string = doc.attributes?.expression; const ast = fromExpression(expression); - // TODO: Magiv AST manipulation - // esaggs aggConfigs='[{id, type: 'date_histogram', params: { field: 'timestamp' }}, ... ]' - // -> - // esaggs timeField='timestamp' timeField='another_date_field' aggConfigs='[the same as before]' + const newChain: ExpressionFunctionAST[] = ast.chain.map(topNode => { + if (topNode.function !== 'lens_merge_tables') { + return topNode; + } + return { + ...topNode, + arguments: { + ...topNode.arguments, + tables: (topNode.arguments.tables as Ast[]).map(middleNode => { + return { + type: 'expression', + chain: middleNode.chain.map(node => { + if (node.function !== 'esaggs') { + return node; + } + const timeFields: string[] = []; + JSON.parse(node.arguments.aggConfigs[0] as string).forEach( + (agg: { type: string; params: { field: string } }) => { + if (agg.type !== 'date_histogram') { + return; + } + timeFields.push(agg.params.field); + } + ); + return { + ...node, + arguments: { + ...node.arguments, + timeFields, + }, + }; + }), + }; + }), + }, + }; + }); return { ...doc, attributes: { ...doc.attributes, - expression: toExpression(ast), + expression: toExpression({ ...ast, chain: newChain }), }, }; } From 20e69adec516cf3c0fbd154b49f99b844919b78b Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Mon, 27 Apr 2020 20:36:00 -0400 Subject: [PATCH 18/26] Fix naming inconsistency in esaggs --- src/plugins/data/public/search/expressions/esaggs.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index d329149cb2b76..288b6fbc50e6b 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -74,7 +74,7 @@ export interface Arguments { partialRows: boolean; includeFormatHints: boolean; aggConfigs: string; - timeField?: string[]; + timeFields?: string[]; } const handleCourierRequest = async ({ @@ -266,7 +266,7 @@ export const esaggs = (): ExpressionFunctionDefinition Date: Tue, 28 Apr 2020 16:31:30 -0400 Subject: [PATCH 19/26] Fix naming issue --- src/plugins/data/public/search/expressions/esaggs.ts | 6 +++--- x-pack/plugins/lens/server/migrations.test.ts | 2 +- x-pack/plugins/lens/server/migrations.ts | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index 288b6fbc50e6b..d329149cb2b76 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -74,7 +74,7 @@ export interface Arguments { partialRows: boolean; includeFormatHints: boolean; aggConfigs: string; - timeFields?: string[]; + timeField?: string[]; } const handleCourierRequest = async ({ @@ -266,7 +266,7 @@ export const esaggs = (): ExpressionFunctionDefinition { it('should remove the lens_auto_date expression', () => { const result = migrations['7.8.0'](example, context); - expect(result.attributes.expression).toContain(`timeFields=\"products.created_on\"`); + expect(result.attributes.expression).toContain(`timeField=\"products.created_on\"`); }); }); }); diff --git a/x-pack/plugins/lens/server/migrations.ts b/x-pack/plugins/lens/server/migrations.ts index b36982bb74ab8..50d8d1afd5148 100644 --- a/x-pack/plugins/lens/server/migrations.ts +++ b/x-pack/plugins/lens/server/migrations.ts @@ -76,20 +76,20 @@ function addTimeFieldToEsaggs(doc: SavedObjectUnsanitizedDoc) { if (node.function !== 'esaggs') { return node; } - const timeFields: string[] = []; + const timeField: string[] = []; JSON.parse(node.arguments.aggConfigs[0] as string).forEach( (agg: { type: string; params: { field: string } }) => { if (agg.type !== 'date_histogram') { return; } - timeFields.push(agg.params.field); + timeField.push(agg.params.field); } ); return { ...node, arguments: { ...node.arguments, - timeFields, + timeField, }, }; }), From 8016d5a78d60664d90f7643a2b31ef9bf023932a Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Tue, 28 Apr 2020 19:04:51 -0400 Subject: [PATCH 20/26] Revert archives to un-migrated version --- .../es_archives/lens/basic/data.json.gz | Bin 4170 -> 4183 bytes .../es_archives/lens/reporting/data.json.gz | Bin 4667 -> 4542 bytes 2 files changed, 0 insertions(+), 0 deletions(-) diff --git a/x-pack/test/functional/es_archives/lens/basic/data.json.gz b/x-pack/test/functional/es_archives/lens/basic/data.json.gz index 5293eeb9110021181830c68bd462bb0fc1a94e72..4ed7c29f7391e4b01ea2737a318cb533d72bf63a 100644 GIT binary patch delta 4172 zcmV-S5VP;fAlD#&ABzYGj0AdK00U%UbYU)Pb8l_{?Hy~6+cxrheud7sPluJEmmdo-1kdh5rB_Ks{^czet`A4WzICu(aI-ZWT5wF-?6ulD|zywAf#H7(DUV2?t z7u^Mj%LHPW+(3$bnq=@|U*$vWC1{)GSd6aL2rJ~jbPW|gL4^VQ+eqw$FmOZYzlI>q zk_sLICZu711U76YuQ;t5b14X(BmF|CEUT838Kh|UV)x?3_x@aB3{kfrO<@u_VZ6dA zz-#p%=P;}St4iAd!O*7^7=8M_U=v=9oWzi;H^;v$FW32+T$c6r4q1zkwpb<;3iJ)=H>Ds7lJn2o=&>9>#bbko`>+I5q2);Kg3Z=V-O%okrzT|6Zam=wupKuftzp$e9N5>r#=tz5c&{7d$@mpx7<7eh!c8sTjmVX4+- zj*(1MVi)-(IuFkAk%>Z2cL%nKi&QF7GM$*EoUlt;>3DKRidK=pR0UU7XIm;|{t~3Lk)i2-b5%D~ zL%-5A$1)vlHrDLve;+nm%FA#XZeP@rHKa}rsZ&Gh zlq}13NS*o%s5zugJpeI>)TtqVbxK-N4yjW^>Xe++98#wqhK{md6&_Nj9)N;UT_zk- zryhZdL+aF{k@R_3=R@k$kUAwdE#)?ahSaJ1(@?s7d`O)dQl}n*N<-?@kUBM_PCYy} zL+aFXN}ZyVDt`e>%t{(P8v+1MO^>pj!c6ai9+ zcq8{q;1aFRG5!c{p#R?e6ME@edXpiS(vJ-LpFX~SH_oS6fzZySvc;~Gt<_0(v(;8L zT{Vm=-F8gFG4-*b5w@1?>$DQcSo=*haUrzMx6+%ktu}oMgy;ZbmeFezj_`FcVv9Zm z(JEseHNC5rc`zbhccdbJKw(PnIyj%MFZf-9L zi9EKMIl87%KKVpxvK#^qbOVV-_ww(+BkK&u30LYtoNPdvSJ7Lw!eyFWg&4bBwO}4I^ z(?Zs1gD@t0Y@=JHeBbeHUQEe-U9Owm<7M1Rwn3b`2@iWnf!eT#aFPyt$gqbDd&nd0 zAxsB2@#jCcD}2sw!TKLmT<T|x;8#DjAZPlK8foiy}Hif~|gqk~QbpH$~A*

%~lb0)L|zMxuCbqP2kmta9~uc-ZdZ< z^0Qqh0K+DKB850Lq1CC~lo4J*RFJoB$F)j@wkGun)e&r)M5D>BPKFmpD^Vp%wbrXAT8-~Z<)xsQh?&{#)d43hWPsw0bg#&+Z_H$bZ(AK6k8{ zV_4(aRDWO&g=E1wvuWU2L>^Tyu&i8lxwdJlfj_s5nHHG9)6Zca1zu$yyxk_0d-*Pr zLs&$A|5G?Dj~>?Dri#L3_i{lDxrJb(F6ahH{;>5$zg*BiUy3JINB`d~Mhf3s2#inH zq?C+7u~}|lvVuz%^u$UC?qKr9r;WU+4(1?mRiMu&sucjJ0&QxkfosmKX)yJy2{8eb zMWiTs=gaR9Q&UJ`1R)Ui0zum4)(w7{z6`^EpQ#ClFPZ9Aw)B2F2!Dyc79}Y1!p!Hg z_all@d`SgZA;5oN0z!sjsDmtxmsCQ;ss()s(t_Dc1qBSx*X+4AS4~?dQ?Ua}bxl`O z=f-S0gDx=4U{(^ZFs~M+fwkZ!Rsn7UZp+r(&?>8P8?LD3_SS+~T#LfyDjMf6w^%TL zyN3KxI77%fAwC7+e3)$_LQVfI*cOZ@g{r3Zolia}ArQC{@#iLPfh5AY!Nupyjj;u{ z%*$SH!7bWk8zl~u5^>fn-oo5dzUn3t2=_It@xG3&k=N~nxj2)NyB!tzy@XSyENNi?whtOi-xW?h}aOQ{DZq#ohm+eLl?AY?@oSYHWLD8L#)Ugh+cTPW8>PIgFT& z>agwlD6K9tDqnE#sf*J>Zr-SmU^MNkinY`jvVAW7hwJLiS#-s>y?oiX8i=fa?OqRb znbl=erWq*A`YP&%UeOY?D^U>Lt(nGP#v$!u0AqY!vNtQ;{<&p#tR7BrD?=X4QBTB zS+#B5d+NnvHf_yW1K)&G1I&OL>KPN8AP@v9Fal47&d)|hglf0ZQDTjH$?m$rXi}X4R5gJ zu}7vsXz1~+Y1|i&%|+> zfr&piO;`26G*B&Q%~fCtzhQ6)y`#C7U(YVqoHtGW9BV|NO#pwYDBvWaCyYL zfLD!rS3$HyzDvK0N57d{b5ZAikm&{bJTS=SY}sV1@U4joCX+z*?O8CNYlflO_6Z!K zGO=6}H5RYvdtx4hRl*Boiw+rv@2HRxH3F`|lh5ze5JKOT z?R;-W0KbWR4~6t);I2SU)z!Yr zqK)Y-tGK~#b}{uZ!@CrJOe=5oPTsa))5YVeP>D*VRRlVAEy+`ntx9lInEk0f0JJGp16x0=3_XzJ6 zpSFnDb*-#<9)2``=v$zDIP_b#J0}EOc0Lda7FzXLrbl4psP+gD*ShqP(1Q#uA@$J~ zJt6g2dtEY9d|JcVl~Im`w$GVfKUfT&82F|(M=#Q_o|Q0oTXd=mZ&l0L@f4 zg6_ds=DI(&TH+q~iQQP&!XKx&_FA8Pr&5lvzqLe1>Z>v7r?=K*<5WWfY;Sb;^4QsN z4aVsB1=+(V$>p#er?tiBpaFmE{I=5gzUJ*g(^fpC?d4V+1Xew-6+G=D-RcLp_x3WX zN4dRh@l%}2RuStw-Yr`kJLWAL9y#vin6+Zjar7%&^5Vdub@fig-uI61?|+bWQ4KA0 z9sK_O$1^_k&5)WOVK}dd4s>IX_#Z$7L!LGFCi*oA&%foeAHlZY W^`(wsjZM1;b^Z@zBFy>UssI3%^Y;w^ literal 4170 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 UI)*hi?LO%IAK6p-zo@DJ0Pju$MgRZ+ diff --git a/x-pack/test/functional/es_archives/lens/reporting/data.json.gz b/x-pack/test/functional/es_archives/lens/reporting/data.json.gz index eca4514f14caeeb24153e37477828c80964e0ef9..3c06824f606462a44aabd3a24b000cc4a6975cd8 100644 GIT binary patch literal 4542 zcmd7U^&=b(z<_ZM)6+41rlz~5nQnHv9d1n5u!)J&v14jDo#%@=)7{f?a>p?}Jw4v{ z{V(3e&~>zz5V&w zVdmQDf^(q6?N)+lEbYVQgEoNQ%A(-Ss0wn^|I2m<#d$X|rC}edDzzAIF3;Ghv3-t| zcCL-yv}5`V-q`r!J2!QTTLm4ndXtAlCES`j{7t)xlB**Aztwq% z0tSvudN<{{SNd~FYJ{@(oWEr3DvUk=3b92!Z+Cbd62Rsn-ll!i8L60h(1>|0oALgD zfJu3pI@NS#^tX>&e{a7po8%$5DYc_YsLNo}7e25skmiP_w`uV#(Iyx+4XGy22o$b@ zR*}@1QYiDaX*XE~6phZngtA|$ieMY6J8{^RkOUD|N+!9?36GiEey_o|PHM9cRXDa3 zLcMDUrRXz@UDi=}64djh_^f2XvY9;zdKKRX&1i+HR8vG8Mf!IVVxR(cfXXC{b=7pQ zkM!HwV)?WkH@KXnOcIfksLfA?4@%(l*nUqDXC_pBd zXiMmcGM>>`EJ?JOpEgga3(L9-x4#2tkuJibS?`h-CWMvOH)hC^0~n!;&}r6#)53_H zOu%mu`7BQXsyW8`NL)<;riOrA;j&3EcDlBC2Hh>q7(U%;Wi))Z9Ve6^(U{#>B;$XU7O znW-kqUKw9l&uiWg71d~^cUD@*X~QP@N7Dn`RCYY2>*R7^g5%q`xOMIGxB2?@OfEj$ue)wJ$|H1@F46l%&xEK?vg6{- z#XEMgk4YJW>LK$O#LBa|=%?1-%nsDM7)1ZkR>j3RVslD7%#84h$$wLH9`-GV9^JE_ z65RZn^7d3GeJs5kR*yOmFANpEe2Vf-JXTkn>hwN!?*^8a{Hr>3D)x-8u6t zp?N@R8tZ-(motibe7Df}xNOWVRru^+&1}H7VwB4(NgX?RT&fX#R|d4N&ucV(4!)Hu zM~VMxKC>gt8uKVu<=IpFF%6Tz{awsA#wjcKsGeOYmgQ1rNH*sYb6%{oR{h?(d>NV6 zAfR>+j!8Eb^JoFb(O>$sKm}X0scr|uNX@Uyb($MX`ApYeXLuv+_$5HCwLZg*`SNBS z;TGz2HPuR$S~eD^AH3ZQ-*m?}dpx@4Qj8v(os*2&E?-ux4zbLIjao_Gh)pm?yMKS= z8R6sZpiB0h<#kLtT>1>DyILP;dDEnHU2(VOQHa2RMDTp#D@Fx)4 zyuih`#jR5?<&*osRY&LafuZeKpkP9J1aNua?DmuE-*1B*-9@X95e#0Dp7^p2Y)ZD| zST+?3r}9jImjp$ss>7wi*-W}mx_IoX3#D--l$(`vw)8~mCrehJK~(yYqqf&q_GJm- zi{m6BAq1L(`f)XXobJ;!ctwktgxVe6JHg#Y9%Col)sNm|>_@JSmi#UttG9pWZLDf& zs>JoSBeEupRBf0ObFep=Ezka;Kat~KcCk`jxDzMn^9|y)g;uqTt>(U%ocHe>ehkhQ zCoCEKnb-HKBem$&P79|Ve7=}1q2wVDR4`?x^*v*U`t<|i+@5N1d);L)G>pJz{hD;u zS77g6??RbvH?)e)_0|i}(QWq$b$5P_X&*tGPO}n2NI48!+e@f1ii>5(6Z}Cg<|e2a z)*KZPMQT{%Hf~FHdSIvyoT3ePLVB~Gl2$?@#OZ~ z(wyVa(^v0HN2t#rX=_bvatJ3i$CE*U(AjY7%?av2>nc8cwI-emL~~MD?}jY$d$Hqe zndAw%iWTk>5A@%L3u9?sd)UW70l3V>(UJQW`g``{i@#-aLAqTx+Bw3X#Nz>7eJOZ1 zKl%zB>d(!59!i8)mSU(ES1i{wHO{8?zgBZCXvNOX%%l*zKYCO7}8663mHMY{e-(ZO-fhFfiwHs&JUweMGd&#(Rs+AC+VSuqGO zbI5($S@t4;leDU43|9S&uF%4VbAl!%mU2J;zO|xf|AiNbaG3r>;v$XAhnErddx82Z z_n?O(0wJUborGsAR}635hCo|9C@(WB*76p@XbI-DBMCDY=Q|YDkLFh%gpk|LxX(KT z!H}s%8Pu;7X>9kp1pM8|*8c#}%wZ>>u)@iZ?;o5LXMf6m7bmKk{tL0mWJ5dWbDr;j z&}+?c@p85DE)!{UtFFq_*0;9i*UWo@_@oXoTEp`OyZ`E)<;h7u+Mtgz)V`Jt2<5lw zuU4|r@`a^*szE9Pj=C4^yG&HESTBIjV9(&#ICLsx@_ex++rQ{jC^?0X42c~RBAjlR`d#d? zS?_UiY0J32r$<&vQTO*zGC8pvTX zB%-;#eqQ7KB6!4Qz%8%Z5;TXjeaG{GG4G`OY*|T~Xa>za$BGGUHZ=^Y+%Ty~ZLY{m z33bs!d(7V7J*K_y=hhN~w2-B5@4Ck2B9wly4K7N2EZR4W91Af;3(G8z62_{k(y_DJ zPx(iJE$D*_R3oX#Syy0f|REzn**v9ciO?-VA{#6zhnhz zL$5Y?cJ4r}{!H;pH+5F+(x)DQs01IQsKL&$q^K%;QSNmBhM{OcMd!I6&B>SvLET=7ylAm3`+hj-Ia~y4Swi%8*k!}M= zk*|=Or#-`Xw6k3bjGr}lzIcwv;AKjYdPD1Rs+NAW@r(=DC(o|}cx$PSK!B8 zg-&yUbwaX2@Q#gRn?7WrJiqF#GNEtR3SCutxY2c!Pd` zvm8f`>ZSdDAeJ0@Are9{g~Hi;$sBO(yEHHt1UYSCUPIpJfRh7ja~*)H}X?acvT6l*eUvIxHuX7##;Rr=G0RDgRsqutSRAu3!07 zum5?NuNQfeGTUYK5VKb5z6LYE&H7;R=eY|~EC%t!;jp_&a^~1KSyspn_)!>qXrsIr zL0|4=Nxii6`>v;1o}7FguY6xM8lWjptY}4kSA%O4T<+Hk3>v7w8TRv-^NHM~^px?- z!@m(M@A1{$egTiS9+n0wtOtI-S6O)57H(eKcD8xEfa_`3LB+G7&chk*;-#(FMruCq zLGwhIKd+Oqui+Lc$^-3rx}Jm z>!?xLoe}Tvm+Osb=XYW6!(fChP_8=Illzv zM+PZfipJ2Z4ab8BzK)yPCRIm|+g}~K>hv-@0ZwkIf>nP!C=+%7@!{Oo3eYJQky|N( zc~`xB{^5bq>48yI^Me<2sd2OCxESpi1!=rnc1ryyyYL+rwm)eP#R`obkb+XX2+xy? z3l0ND94;a8n!lBhGUW%fmKQx6%AbUlen~6>9QyoJeiggG(-7SwDdOhsYY9oa+cz)H z(HounyPi`K3!Ik;&iQn!LrdWh)$lkMl3ht;PoIn2f*vto(;{CHc)MZaTeUgiW-&5s zev7YGPS^!=R_ETZ6x82Qjol0YtE$2uF7{`QWpUd~Xs8cOG=d7)j{;T5FT*8|o~0i% zD&Wm~r;V6WMKGnrO*h~~tLPRvbf^87ce2{1B}Wv-%)pMS^^?I8P_juK*R6Fzof{C4 z!w(0ktcm4;zT*ChsSLfr0TZOTc)Ma`ITK`jtG>ae ze$q`Ly|+dt6@We~X&j!M3M8w6oF44VFVs~C2ODU%KGidHWYIW&zK_ES?dueiC%8e# zTtW8smRjB$T-!o>56?^NmoSsmqG9$xG@uKN+cW#|xasx46{*}#j=_Xj|8z6|_Sx2E z0$U>If7&0(qJfG`Ay8(9JEEPOIMM!W*W)QMvOx#2DLI&pt$o3Vy~UMJ*-OQ+eB;io5T=>A#4J9Mx60DdNz`Ph%|Thk+%lW^)GWJ zpXV371wP8L`@E`6w1NOh3AH;AKdZc`z6!5Zk*#Z_=yQOZ*BnXUF&n(xV8VDzk=1=Pj?Ir_$D>unVW9z zwrMxX&c@woZ9)qhD!~vOkSFr5v7*WKFFpoRk&YtEzWGeVWh+)08#(RF;0OtE=vf z5f=$fX>vg<{R-6SQ0=bcwREv}&4AM1D--^_v*~%7I9$y6sgLMbiX* zeL||r(k`NS)gDb5TBZ^~#L1BhpMb4ehSr-lMFeH^Ip|pgXmT<+RpH~9c~OY5Hbu?CXCSGdLy{F^vXDPd7U3hvkxBS?_Zdwu!q68W28RKI zC)ksN<@@hU3%$!|#Pv3Ln5QO5CI(v4c#7jVAwh%=Scz3GHgQnyz-OS0X}(Xn`%k7P zO|WF-$b`^}wPKH!NLj2Xl4-}S;wN3PQxRg+$b`W?&YB-LsK?jBF&0%f)W}c@fc~i zn^TpiG@1HAl4eD@e8h#Qi?-+EuFYyA7rPfOd})}y1-X7zz--{ za4)1B4#*x#H@O!E>FOnrno^ue>({uiAc$0VxD1%qDgnDM4O5c^UN#txtWf{SLsKdhV#BmH`=95 zw3{(~g;zInfesRqj;Chr=K)Qusd+|q zgZ31<*8g2LTMFlC7OxjYYTKAPHKtCT3elK4HKtCDsZ&o!(wI6mrcRBiQ)BAXY)qXR zQ>RWMX-u6OQ>Pw_&X_tircRwg#h5xZrcPZJsWEkGOr082r^eK&F?DK8oswnSj;T}M z0nIUW>H=VnsZ(R>l(bNesZ(R>l$>aesZ*E1QTD6CW9rle5R~dN;g~x01SpQFQ%?rz z%h1lp)TuFbN^UIWR)xmYsmEg|-8nv{PK~Kkmq2Muof=c8#?-0HQ!}Pcy`>6sU64M(H;1(z!$-8I`cxg5o~ATLstG^H{c5ZduP-S6 zh;AwQ;Qf>0>>aw>}X*a4n)3uqd zPBqAuwQj$URRhMo??h{EgwFZ4dh=!5n?4_e$pEI7@oN;b#>@FcZ2AyI%UoF0{H|J# zX~bS`S%n{j8Ncf=`}Fy$yleOi_1{;*eid$@{M$G(E}O&sM}qc!qqSUxdb#a|l&_O>Z2Mbk7}g!Gn%yE67C!s0NSsSxsY zB1~wC9D;JtHDwYV7q1a!`z(!zSYPH*z6k+9yH#EMSfPD=l|*yPOl2#fg|L z+H8ug-)gbFY7ewNl$WBMiDJZQi1IMJ+OMp>vzXNv>$cyZ#?4brPbCHf$niX&s?-Ip zgMFZR9<-=$=@fdCgYI7_2eO?_de|!BhC1z~pZY}gLRXXh3GEZuHHm{J+kF^b^}XA@Zhk#=*VO8RRH!DR zK}+YTsjjxgOoQ-&Q}M%J|H3!uFgyHETluX;MW>cx1J%A!?U`xJG;6Bc&ZR#dCXW1I zIdi6P3eOQVMgO*>DGs&33&J3~pOyRbbrh_HI+Y%NSGku5A$gy#S&a*!t-7ve8nyvl zx2ZmGaDEgArIce~ z9;~~|6h-jv^_(ek^M;N(=LaPFCH5D8am9cAR=pE-{Qq`7QTV9*`HMA8mUJQ9oT(C` zdz!o@DH|GFDsqtT0i-%6FnmM-f|db%Pj?KsyeM$LsHHLp~us&Vm|6?37kFc?bE8TT_wfvsnluOo&Sd51RDaA083pgqU9isAO6)7;r)?;emV7<%IW4QKOF7}P1Qol1TSaeBhu%@@ zK75sgNcp+2Licqc{?l<#9<`7wDbw$KuYTGG-{A~tJ}S~Fz#_Gu6WSAO8yeFxlSqamzts9LlXg@Z?S&t>@I`g)g3bW=+F z!l>)ijYQiZEo_c{t+s9|%vC<-{=VrSJ>Jm5l~j?#Bu#(o6r+MmMV}+>1pA4YlTfw= z4V{e-l-hCxqEkylHUd~PUB)rK50K_#K&j_z(6b?Qy3B)J|EESch|Wehh@?Q+q6Wki z0ZVfk!n$Vw7rO*_2BkVQk%p-=6k)Cj4aB#t?(Ma#;bl^oDt```&A4R88ArJ@X1Uk> z0BTOxVpR>(-|>h^wwnc0b`qwQ2@^KY;%>Bi@ouhdJ=D-5?p;m{&hUH?_&@5a9RTv#_izwLOjy&wa z6ih<6d04mvs<4b0uNjCF1q;ZZ_NYmUlJ+cp*Y`D3)qzGB*BXpOfE>aEqU%#c3=e9M zbk1^E$J1x2K6;kbQi_6NmY$^%o9GsBbc}$ZnjUamTLrp799Q+Ai&WG(%V8Z)pQXm0 zc5vJ77g|L-_RNW$%>9W;Jtd)=ILUtR36~xS)Z=mgri>9W|Dm5*-Wkxh*~0s(F+>uU z{i;xZ$>ZHod?D<+q)7(}j-hMNhi8+ZKAr?u*G$hPXOo}}BBA$a+%4&`^HGHWYB#De zGn|=eO`+{RiQ9QNL%bNbb7`k=2kvK9`j8XaBbx5&1_dUz*?C}_4)BO-16_9^LLQ`! zfn{<+dzNFFx@7~+CQLnMiVbjWOo3tP$kBWq*_L*K6S{3p_xYo%nEo(_bmJ4;s}4+w zc+cm_G)+qWH+@?g%WcAfW-0&0P4apOlEj-uiDL2SGK|mtty1w+a6~emk$TY^_ z?<>JST<&vAr1EomYjEfszG-lyMJfgwgo9F=!npN+DcsVsZJY5-x+;yPqvNcZ@;0=MT~i;qpfX z>4t2C9+&taKD%ImZxE@^8XW17mt$~b=rf10)H8+{52fV^iz^QF!C}U3+&W61GpNM* z^%rL49o{aT_&f))yiFd(Ux8}w^YbK&8x8tHM{-B5E*d%-#Q&Y^4LxM*mgWKtI~p)d z#{#ZnTEI~?>T1{|8ud;N9Su5uI)-RQOtQF30PaPX8j4V7<5m3iPf0+y3YPZo*27?w z2Yp{REsICc2r#fofrotqSlCc4%`m0HLqnda(8NV~8P^(yfL<#FS zB>eREe>`32NrgbQs-$6cYN?k_8Wyg#6C9oYv92|UR9AB;pqhnvG@1ZpF&uo$^bqnf zfto3kYt3~{RVNMwt_n3CG*;PWhX$aw!vrH%v2C~~IDydZ@(dTyp*!u|`<+9lb5SqF z>szL@Ea~oc=W!oJ8>4;?MVDWvJ^mT%*!E#`URFJrPV2Jjpa(I=jR_yi&%06W}-(;W!dtQq>$w^Zz!rlUGC zDYZ7^cg^G%oDeha4dfcYH8c+xs>_UTi Date: Tue, 28 Apr 2020 21:53:07 -0400 Subject: [PATCH 21/26] Ignore expressions that are already migrated --- x-pack/plugins/lens/server/migrations.test.ts | 28 +++ x-pack/plugins/lens/server/migrations.ts | 183 ++++++++++-------- 2 files changed, 131 insertions(+), 80 deletions(-) diff --git a/x-pack/plugins/lens/server/migrations.test.ts b/x-pack/plugins/lens/server/migrations.test.ts index 079ef5fab9569..184e1af8eb39c 100644 --- a/x-pack/plugins/lens/server/migrations.test.ts +++ b/x-pack/plugins/lens/server/migrations.test.ts @@ -261,5 +261,33 @@ describe('Lens migrations', () => { const result = migrations['7.8.0'](example, context); expect(result.attributes.expression).toContain(`timeField=\"products.created_on\"`); }); + + it('should handle pre-migrated expression', () => { + const input = { + type: 'lens', + attributes: { + ...example.attributes, + expression: `kibana + | kibana_context query="{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"}" filters="[]" + | lens_merge_tables layerIds="bd09dc71-a7e2-42d0-83bd-85df8291f03c" + tables={esaggs + index="ff959d40-b880-11e8-a6d9-e546fe2bba5f" + metricsAtAllLevels=false + partialRows=false + includeFormatHints=true + aggConfigs="[{\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"products.created_on\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"auto\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}},{\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}}]" + timeField=\\"products.created_on\\" + } + | lens_xy_chart + xTitle="products.created_on" + yTitle="Count of records" + legend={lens_xy_legendConfig isVisible=true position="right"} + layers={} + `, + }, + }; + const result = migrations['7.8.0'](input, context); + expect(result).toEqual(input); + }); }); }); diff --git a/x-pack/plugins/lens/server/migrations.ts b/x-pack/plugins/lens/server/migrations.ts index 50d8d1afd5148..8297f7ffe68c8 100644 --- a/x-pack/plugins/lens/server/migrations.ts +++ b/x-pack/plugins/lens/server/migrations.ts @@ -6,7 +6,7 @@ import { cloneDeep, flow } from 'lodash'; import { fromExpression, toExpression, Ast, ExpressionFunctionAST } from '@kbn/interpreter/common'; -import { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from 'src/core/server'; +import { SavedObjectMigrationFn } from 'src/core/server'; interface XYLayerPre77 { layerId: string; @@ -15,98 +15,121 @@ interface XYLayerPre77 { accessors: string[]; } -function removeLensAutoDate(doc: SavedObjectUnsanitizedDoc) { +/** + * Removes the `lens_auto_date` subexpression from a stored expression + * string. For example: aggConfigs={lens_auto_date aggConfigs="JSON string"} + */ +const removeLensAutoDate: SavedObjectMigrationFn = (doc, context) => { const expression: string = doc.attributes?.expression; - const ast = fromExpression(expression); + try { + const ast = fromExpression(expression); + const newChain: ExpressionFunctionAST[] = ast.chain.map(topNode => { + if (topNode.function !== 'lens_merge_tables') { + return topNode; + } + return { + ...topNode, + arguments: { + ...topNode.arguments, + tables: (topNode.arguments.tables as Ast[]).map(middleNode => { + return { + type: 'expression', + chain: middleNode.chain.map(node => { + // Check for sub-expression in aggConfigs + if ( + node.function === 'esaggs' && + typeof node.arguments.aggConfigs[0] !== 'string' + ) { + return { + ...node, + arguments: { + ...node.arguments, + aggConfigs: (node.arguments.aggConfigs[0] as Ast).chain[0].arguments + .aggConfigs, + }, + }; + } + return node; + }), + }; + }), + }, + }; + }); - const newChain: ExpressionFunctionAST[] = ast.chain.map(topNode => { - if (topNode.function !== 'lens_merge_tables') { - return topNode; - } return { - ...topNode, - arguments: { - ...topNode.arguments, - tables: (topNode.arguments.tables as Ast[]).map(middleNode => { - return { - type: 'expression', - chain: middleNode.chain.map(node => { - if (node.function === 'esaggs') { + ...doc, + attributes: { + ...doc.attributes, + expression: toExpression({ ...ast, chain: newChain }), + }, + }; + } catch (e) { + context.log.warning(e.message); + return { ...doc }; + } +}; + +/** + * Adds missing timeField arguments to esaggs in the Lens expression + */ +const addTimeFieldToEsaggs: SavedObjectMigrationFn = (doc, context) => { + const expression: string = doc.attributes?.expression; + + try { + const ast = fromExpression(expression); + const newChain: ExpressionFunctionAST[] = ast.chain.map(topNode => { + if (topNode.function !== 'lens_merge_tables') { + return topNode; + } + return { + ...topNode, + arguments: { + ...topNode.arguments, + tables: (topNode.arguments.tables as Ast[]).map(middleNode => { + return { + type: 'expression', + chain: middleNode.chain.map(node => { + // Skip if there are any timeField arguments already, because that indicates + // the fix is already applied + if (node.function !== 'esaggs' || node.arguments.timeField) { + return node; + } + const timeField: string[] = []; + JSON.parse(node.arguments.aggConfigs[0] as string).forEach( + (agg: { type: string; params: { field: string } }) => { + if (agg.type !== 'date_histogram') { + return; + } + timeField.push(agg.params.field); + } + ); return { ...node, arguments: { ...node.arguments, - aggConfigs: (node.arguments.aggConfigs[0] as Ast).chain[0].arguments.aggConfigs, + timeField, }, }; - } - return node; - }), - }; - }), - }, - }; - }); - - return { - ...doc, - attributes: { - ...doc.attributes, - expression: toExpression({ ...ast, chain: newChain }), - }, - }; -} + }), + }; + }), + }, + }; + }); -function addTimeFieldToEsaggs(doc: SavedObjectUnsanitizedDoc) { - const expression: string = doc.attributes?.expression; - const ast = fromExpression(expression); - - const newChain: ExpressionFunctionAST[] = ast.chain.map(topNode => { - if (topNode.function !== 'lens_merge_tables') { - return topNode; - } return { - ...topNode, - arguments: { - ...topNode.arguments, - tables: (topNode.arguments.tables as Ast[]).map(middleNode => { - return { - type: 'expression', - chain: middleNode.chain.map(node => { - if (node.function !== 'esaggs') { - return node; - } - const timeField: string[] = []; - JSON.parse(node.arguments.aggConfigs[0] as string).forEach( - (agg: { type: string; params: { field: string } }) => { - if (agg.type !== 'date_histogram') { - return; - } - timeField.push(agg.params.field); - } - ); - return { - ...node, - arguments: { - ...node.arguments, - timeField, - }, - }; - }), - }; - }), + ...doc, + attributes: { + ...doc.attributes, + expression: toExpression({ ...ast, chain: newChain }), }, }; - }); - - return { - ...doc, - attributes: { - ...doc.attributes, - expression: toExpression({ ...ast, chain: newChain }), - }, - }; -} + } catch (e) { + context.log.warning(e.message); + return { ...doc }; + } +}; export const migrations: Record = { '7.7.0': doc => { From caad0b7675520283796a29ad46d72f6f766999d5 Mon Sep 17 00:00:00 2001 From: Marta Bondyra Date: Wed, 29 Apr 2020 14:33:16 +0200 Subject: [PATCH 22/26] test: remove extra spaces and timeField=\\"products.created_on\\"} to timeField=\"products.created_on\"} --- x-pack/plugins/lens/server/migrations.test.ts | 20 ++++--------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/x-pack/plugins/lens/server/migrations.test.ts b/x-pack/plugins/lens/server/migrations.test.ts index 184e1af8eb39c..3386ce41c3e11 100644 --- a/x-pack/plugins/lens/server/migrations.test.ts +++ b/x-pack/plugins/lens/server/migrations.test.ts @@ -268,22 +268,10 @@ describe('Lens migrations', () => { attributes: { ...example.attributes, expression: `kibana - | kibana_context query="{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"}" filters="[]" - | lens_merge_tables layerIds="bd09dc71-a7e2-42d0-83bd-85df8291f03c" - tables={esaggs - index="ff959d40-b880-11e8-a6d9-e546fe2bba5f" - metricsAtAllLevels=false - partialRows=false - includeFormatHints=true - aggConfigs="[{\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"products.created_on\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"auto\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}},{\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}}]" - timeField=\\"products.created_on\\" - } - | lens_xy_chart - xTitle="products.created_on" - yTitle="Count of records" - legend={lens_xy_legendConfig isVisible=true position="right"} - layers={} - `, +| kibana_context query="{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"}" filters="[]" +| lens_merge_tables layerIds="bd09dc71-a7e2-42d0-83bd-85df8291f03c" + tables={esaggs index="ff959d40-b880-11e8-a6d9-e546fe2bba5f" metricsAtAllLevels=false partialRows=false includeFormatHints=true aggConfigs="[{\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"products.created_on\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"auto\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}},{\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}}]" timeField=\"products.created_on\"} +| lens_xy_chart xTitle="products.created_on" yTitle="Count of records" legend={lens_xy_legendConfig isVisible=true position="right"} layers={}`, }, }; const result = migrations['7.8.0'](input, context); From 5517aef77a3b8f624ec3e40a1224f3112d73e188 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 29 Apr 2020 14:26:22 -0400 Subject: [PATCH 23/26] Rename all timeField -> timeFields --- src/plugins/data/public/search/expressions/esaggs.ts | 8 ++++---- .../test_suites/run_pipeline/esaggs.ts | 4 ++-- .../indexpattern_datasource/indexpattern.test.ts | 12 ++++++------ .../public/indexpattern_datasource/to_expression.ts | 2 +- x-pack/plugins/lens/server/migrations.test.ts | 4 ++-- x-pack/plugins/lens/server/migrations.ts | 8 ++++---- 6 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index d329149cb2b76..e361a8c9134bc 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -68,13 +68,13 @@ const name = 'esaggs'; type Input = KibanaContext | null; type Output = Promise; -export interface Arguments { +interface Arguments { index: string; metricsAtAllLevels: boolean; partialRows: boolean; includeFormatHints: boolean; aggConfigs: string; - timeField?: string[]; + timeFields?: string[]; } const handleCourierRequest = async ({ @@ -266,7 +266,7 @@ export const esaggs = (): ExpressionFunctionDefinition { "partialRows": Array [ false, ], - "timeField": Array [ + "timeFields": Array [ "timestamp", ], }, @@ -299,7 +299,7 @@ describe('IndexPattern Data Source', () => { `); }); - it('should put all time fields used in date_histograms to the esaggs timeField parameter', async () => { + it('should put all time fields used in date_histograms to the esaggs timeFields parameter', async () => { const queryPersistedState: IndexPatternPersistedState = { currentIndexPatternId: '1', layers: { @@ -342,10 +342,10 @@ describe('IndexPattern Data Source', () => { const state = stateFromPersistedState(queryPersistedState); const ast = indexPatternDatasource.toExpression(state, 'first') as Ast; - expect(ast.chain[0].arguments.timeField).toEqual(['timestamp', 'another_datefield']); + expect(ast.chain[0].arguments.timeFields).toEqual(['timestamp', 'another_datefield']); }); - it('should not put date fields used outside date_histograms to the esaggs timeField parameter', async () => { + it('should not put date fields used outside date_histograms to the esaggs timeFields parameter', async () => { const queryPersistedState: IndexPatternPersistedState = { currentIndexPatternId: '1', layers: { @@ -378,8 +378,8 @@ describe('IndexPattern Data Source', () => { const state = stateFromPersistedState(queryPersistedState); const ast = indexPatternDatasource.toExpression(state, 'first') as Ast; - expect(ast.chain[0].arguments.timeField).toEqual(['timestamp']); - expect(ast.chain[0].arguments.timeField).not.toContain('timefield'); + expect(ast.chain[0].arguments.timeFields).toEqual(['timestamp']); + expect(ast.chain[0].arguments.timeFields).not.toContain('timefield'); }); }); diff --git a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts index 50e2682a446aa..1308fa3b7ca60 100644 --- a/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts +++ b/x-pack/plugins/lens/public/indexpattern_datasource/to_expression.ts @@ -86,7 +86,7 @@ function getExpressionForLayer( metricsAtAllLevels: [false], partialRows: [false], includeFormatHints: [true], - timeField: allDateHistogramFields, + timeFields: allDateHistogramFields, aggConfigs: [JSON.stringify(aggs)], }, }, diff --git a/x-pack/plugins/lens/server/migrations.test.ts b/x-pack/plugins/lens/server/migrations.test.ts index 3386ce41c3e11..4cc330d40efd7 100644 --- a/x-pack/plugins/lens/server/migrations.test.ts +++ b/x-pack/plugins/lens/server/migrations.test.ts @@ -259,7 +259,7 @@ describe('Lens migrations', () => { it('should remove the lens_auto_date expression', () => { const result = migrations['7.8.0'](example, context); - expect(result.attributes.expression).toContain(`timeField=\"products.created_on\"`); + expect(result.attributes.expression).toContain(`timeFields=\"products.created_on\"`); }); it('should handle pre-migrated expression', () => { @@ -270,7 +270,7 @@ describe('Lens migrations', () => { expression: `kibana | kibana_context query="{\\"query\\":\\"\\",\\"language\\":\\"kuery\\"}" filters="[]" | lens_merge_tables layerIds="bd09dc71-a7e2-42d0-83bd-85df8291f03c" - tables={esaggs index="ff959d40-b880-11e8-a6d9-e546fe2bba5f" metricsAtAllLevels=false partialRows=false includeFormatHints=true aggConfigs="[{\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"products.created_on\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"auto\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}},{\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}}]" timeField=\"products.created_on\"} + tables={esaggs index="ff959d40-b880-11e8-a6d9-e546fe2bba5f" metricsAtAllLevels=false partialRows=false includeFormatHints=true aggConfigs="[{\\"id\\":\\"1d9cc16c-1460-41de-88f8-471932ecbc97\\",\\"enabled\\":true,\\"type\\":\\"date_histogram\\",\\"schema\\":\\"segment\\",\\"params\\":{\\"field\\":\\"products.created_on\\",\\"useNormalizedEsInterval\\":true,\\"interval\\":\\"auto\\",\\"drop_partials\\":false,\\"min_doc_count\\":0,\\"extended_bounds\\":{}}},{\\"id\\":\\"66115819-8481-4917-a6dc-8ffb10dd02df\\",\\"enabled\\":true,\\"type\\":\\"count\\",\\"schema\\":\\"metric\\",\\"params\\":{}}]" timeFields=\"products.created_on\"} | lens_xy_chart xTitle="products.created_on" yTitle="Count of records" legend={lens_xy_legendConfig isVisible=true position="right"} layers={}`, }, }; diff --git a/x-pack/plugins/lens/server/migrations.ts b/x-pack/plugins/lens/server/migrations.ts index 8297f7ffe68c8..51fcd3b6198c3 100644 --- a/x-pack/plugins/lens/server/migrations.ts +++ b/x-pack/plugins/lens/server/migrations.ts @@ -92,23 +92,23 @@ const addTimeFieldToEsaggs: SavedObjectMigrationFn = (doc, context) => { chain: middleNode.chain.map(node => { // Skip if there are any timeField arguments already, because that indicates // the fix is already applied - if (node.function !== 'esaggs' || node.arguments.timeField) { + if (node.function !== 'esaggs' || node.arguments.timeFields) { return node; } - const timeField: string[] = []; + const timeFields: string[] = []; JSON.parse(node.arguments.aggConfigs[0] as string).forEach( (agg: { type: string; params: { field: string } }) => { if (agg.type !== 'date_histogram') { return; } - timeField.push(agg.params.field); + timeFields.push(agg.params.field); } ); return { ...node, arguments: { ...node.arguments, - timeField, + timeFields, }, }; }), From 5f7d3e52f1aaaa93e36b1f675677c33dbb6491c0 Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 29 Apr 2020 14:39:19 -0400 Subject: [PATCH 24/26] Combine duplicate functions --- .../data/public/query/timefilter/get_time.ts | 63 +++++++------------ .../data/public/query/timefilter/index.ts | 2 +- .../public/query/timefilter/timefilter.ts | 4 +- .../data/public/search/expressions/esaggs.ts | 4 +- 4 files changed, 29 insertions(+), 44 deletions(-) diff --git a/src/plugins/data/public/query/timefilter/get_time.ts b/src/plugins/data/public/query/timefilter/get_time.ts index 3802efd18fef2..aa5eda13af655 100644 --- a/src/plugins/data/public/query/timefilter/get_time.ts +++ b/src/plugins/data/public/query/timefilter/get_time.ts @@ -19,7 +19,7 @@ import dateMath from '@elastic/datemath'; import { IIndexPattern } from '../..'; -import { TimeRange, IFieldType, buildRangeFilter } from '../../../common'; +import { TimeRange, buildRangeFilter } from '../../../common'; interface CalculateBoundsOptions { forceNow?: Date; @@ -32,61 +32,44 @@ export function calculateBounds(timeRange: TimeRange, options: CalculateBoundsOp }; } -function createTimeRangeFilter( - indexPattern: IIndexPattern, +export function getTime( + indexPattern: IIndexPattern | undefined, timeRange: TimeRange, - field: IFieldType, - forceNow?: Date + options?: { forceNow?: Date; fieldName?: string } ) { - const bounds = calculateBounds(timeRange, { forceNow }); - if (!bounds) { - return; - } - return buildRangeFilter( - field, - { - ...(bounds.min && { gte: bounds.min.toISOString() }), - ...(bounds.max && { lte: bounds.max.toISOString() }), - format: 'strict_date_optional_time', - }, - indexPattern + return createTimeRangeFilter( + indexPattern, + timeRange, + options?.fieldName || indexPattern?.timeFieldName, + options?.forceNow ); } -export function getTimeFilter( +function createTimeRangeFilter( indexPattern: IIndexPattern | undefined, timeRange: TimeRange, - fieldName: string + fieldName?: string, + forceNow?: Date ) { if (!indexPattern) { return; } - - const field = indexPattern.fields.find(f => f.name === fieldName); + const field = indexPattern.fields.find(f => f.name === fieldName || indexPattern.timeFieldName); if (!field) { return; } - return createTimeRangeFilter(indexPattern, timeRange, field); -} - -export function getTime( - indexPattern: IIndexPattern | undefined, - timeRange: TimeRange, - forceNow?: Date -) { - if (!indexPattern) { - // in CI, we sometimes seem to fail here. + const bounds = calculateBounds(timeRange, { forceNow }); + if (!bounds) { return; } - - const timefield: IFieldType | undefined = indexPattern.fields.find( - field => field.name === indexPattern.timeFieldName + return buildRangeFilter( + field, + { + ...(bounds.min && { gte: bounds.min.toISOString() }), + ...(bounds.max && { lte: bounds.max.toISOString() }), + format: 'strict_date_optional_time', + }, + indexPattern ); - - if (!timefield) { - return; - } - - return createTimeRangeFilter(indexPattern, timeRange, timefield, forceNow); } diff --git a/src/plugins/data/public/query/timefilter/index.ts b/src/plugins/data/public/query/timefilter/index.ts index 4609dde599d5a..034af03842ab8 100644 --- a/src/plugins/data/public/query/timefilter/index.ts +++ b/src/plugins/data/public/query/timefilter/index.ts @@ -22,6 +22,6 @@ export { TimefilterService, TimefilterSetup } from './timefilter_service'; export * from './types'; export { Timefilter, TimefilterContract } from './timefilter'; export { TimeHistory, TimeHistoryContract } from './time_history'; -export { getTime, calculateBounds, getTimeFilter } from './get_time'; +export { getTime, calculateBounds } from './get_time'; export { changeTimeFilter } from './lib/change_time_filter'; export { extractTimeFilter } from './lib/extract_time_filter'; diff --git a/src/plugins/data/public/query/timefilter/timefilter.ts b/src/plugins/data/public/query/timefilter/timefilter.ts index 4fbdac47fb3b0..86ef69be572a9 100644 --- a/src/plugins/data/public/query/timefilter/timefilter.ts +++ b/src/plugins/data/public/query/timefilter/timefilter.ts @@ -164,7 +164,9 @@ export class Timefilter { }; public createFilter = (indexPattern: IndexPattern, timeRange?: TimeRange) => { - return getTime(indexPattern, timeRange ? timeRange : this._time, this.getForceNow()); + return getTime(indexPattern, timeRange ? timeRange : this._time, { + forceNow: this.getForceNow(), + }); }; public getBounds(): TimeRangeBounds { diff --git a/src/plugins/data/public/search/expressions/esaggs.ts b/src/plugins/data/public/search/expressions/esaggs.ts index e361a8c9134bc..eec75b0841133 100644 --- a/src/plugins/data/public/search/expressions/esaggs.ts +++ b/src/plugins/data/public/search/expressions/esaggs.ts @@ -40,7 +40,7 @@ import { IIndexPattern, isRangeFilter, } from '../../../common'; -import { FilterManager, calculateBounds, getTimeFilter } from '../../query'; +import { FilterManager, calculateBounds, getTime } from '../../query'; import { getSearchService, getQueryService, getIndexPatterns } from '../../services'; import { buildTabularInspectorData } from './build_tabular_inspector_data'; import { getRequestInspectorStats, getResponseInspectorStats, serializeAggConfig } from './utils'; @@ -134,7 +134,7 @@ const handleCourierRequest = async ({ if (timeRange && allTimeFields.length > 0) { timeFilterSearchSource.setField('filter', () => { return allTimeFields - .map(fieldName => getTimeFilter(indexPattern, timeRange, fieldName)) + .map(fieldName => getTime(indexPattern, timeRange, { fieldName })) .filter(isRangeFilter); }); } From 4b08d1e7eb7af1f54379f425d48b45bc14a3dfcc Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 29 Apr 2020 16:37:46 -0400 Subject: [PATCH 25/26] Fix boolean error and add test for it --- .../public/query/timefilter/get_time.test.ts | 38 +++++++++++++++++++ .../data/public/query/timefilter/get_time.ts | 2 +- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/plugins/data/public/query/timefilter/get_time.test.ts b/src/plugins/data/public/query/timefilter/get_time.test.ts index a8eb3a3fe8102..4dba157a6f554 100644 --- a/src/plugins/data/public/query/timefilter/get_time.test.ts +++ b/src/plugins/data/public/query/timefilter/get_time.test.ts @@ -51,5 +51,43 @@ describe('get_time', () => { }); clock.restore(); }); + + test('build range filter for non-primary field', () => { + const clock = sinon.useFakeTimers(moment.utc([2000, 1, 1, 0, 0, 0, 0]).valueOf()); + + const filter = getTime( + { + id: 'test', + title: 'test', + timeFieldName: 'date', + fields: [ + { + name: 'date', + type: 'date', + esTypes: ['date'], + aggregatable: true, + searchable: true, + filterable: true, + }, + { + name: 'myCustomDate', + type: 'date', + esTypes: ['date'], + aggregatable: true, + searchable: true, + filterable: true, + }, + ], + } as any, + { from: 'now-60y', to: 'now' }, + { fieldName: 'myCustomDate' } + ); + expect(filter!.range.myCustomDate).toEqual({ + gte: '1940-02-01T00:00:00.000Z', + lte: '2000-02-01T00:00:00.000Z', + format: 'strict_date_optional_time', + }); + clock.restore(); + }); }); }); diff --git a/src/plugins/data/public/query/timefilter/get_time.ts b/src/plugins/data/public/query/timefilter/get_time.ts index aa5eda13af655..9cdd25d3213ce 100644 --- a/src/plugins/data/public/query/timefilter/get_time.ts +++ b/src/plugins/data/public/query/timefilter/get_time.ts @@ -54,7 +54,7 @@ function createTimeRangeFilter( if (!indexPattern) { return; } - const field = indexPattern.fields.find(f => f.name === fieldName || indexPattern.timeFieldName); + const field = indexPattern.fields.find(f => f.name === (fieldName || indexPattern.timeFieldName)); if (!field) { return; } From 856281246f56ae35cd206a409c0724ebbd398b9b Mon Sep 17 00:00:00 2001 From: Wylie Conlon Date: Wed, 29 Apr 2020 17:57:53 -0400 Subject: [PATCH 26/26] Commit API changes --- .../kibana-plugin-plugins-data-public.gettime.md | 7 +++++-- ...gins-data-public.iindexpattern.gettimefield.md | 15 +++++++++++++++ ...na-plugin-plugins-data-public.iindexpattern.md | 6 ++++++ .../public/kibana-plugin-plugins-data-public.md | 2 +- src/plugins/data/public/public.api.md | 5 ++++- 5 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.gettimefield.md diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.gettime.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.gettime.md index 04a0d871cab2d..3969a97fa7789 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.gettime.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.gettime.md @@ -7,7 +7,10 @@ Signature: ```typescript -export declare function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, forceNow?: Date): import("../..").RangeFilter | undefined; +export declare function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, options?: { + forceNow?: Date; + fieldName?: string; +}): import("../..").RangeFilter | undefined; ``` ## Parameters @@ -16,7 +19,7 @@ export declare function getTime(indexPattern: IIndexPattern | undefined, timeRan | --- | --- | --- | | indexPattern | IIndexPattern | undefined | | | timeRange | TimeRange | | -| forceNow | Date | | +| options | {
forceNow?: Date;
fieldName?: string;
} | | Returns: diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.gettimefield.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.gettimefield.md new file mode 100644 index 0000000000000..c3998876c9712 --- /dev/null +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.gettimefield.md @@ -0,0 +1,15 @@ + + +[Home](./index.md) > [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) > [IIndexPattern](./kibana-plugin-plugins-data-public.iindexpattern.md) > [getTimeField](./kibana-plugin-plugins-data-public.iindexpattern.gettimefield.md) + +## IIndexPattern.getTimeField() method + +Signature: + +```typescript +getTimeField?(): IFieldType | undefined; +``` +Returns: + +`IFieldType | undefined` + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md index 1bbd6cf67f0ce..1cb89822eb605 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.iindexpattern.md @@ -21,3 +21,9 @@ export interface IIndexPattern | [title](./kibana-plugin-plugins-data-public.iindexpattern.title.md) | string | | | [type](./kibana-plugin-plugins-data-public.iindexpattern.type.md) | string | | +## Methods + +| Method | Description | +| --- | --- | +| [getTimeField()](./kibana-plugin-plugins-data-public.iindexpattern.gettimefield.md) | | + diff --git a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md index 0fd82ffb2240c..e1df493143b73 100644 --- a/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md +++ b/docs/development/plugins/data/public/kibana-plugin-plugins-data-public.md @@ -43,7 +43,7 @@ | [getEsPreference(uiSettings, sessionId)](./kibana-plugin-plugins-data-public.getespreference.md) | | | [getQueryLog(uiSettings, storage, appName, language)](./kibana-plugin-plugins-data-public.getquerylog.md) | | | [getSearchErrorType({ message })](./kibana-plugin-plugins-data-public.getsearcherrortype.md) | | -| [getTime(indexPattern, timeRange, forceNow)](./kibana-plugin-plugins-data-public.gettime.md) | | +| [getTime(indexPattern, timeRange, options)](./kibana-plugin-plugins-data-public.gettime.md) | | | [plugin(initializerContext)](./kibana-plugin-plugins-data-public.plugin.md) | | ## Interfaces diff --git a/src/plugins/data/public/public.api.md b/src/plugins/data/public/public.api.md index e30044c0763de..91dea66f06a94 100644 --- a/src/plugins/data/public/public.api.md +++ b/src/plugins/data/public/public.api.md @@ -699,7 +699,10 @@ export function getSearchErrorType({ message }: Pick): " // Warning: (ae-missing-release-tag) "getTime" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) -export function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, forceNow?: Date): import("../..").RangeFilter | undefined; +export function getTime(indexPattern: IIndexPattern | undefined, timeRange: TimeRange, options?: { + forceNow?: Date; + fieldName?: string; +}): import("../..").RangeFilter | undefined; // Warning: (ae-missing-release-tag) "IAggConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) //