Simplify date histogram meta and apply interval scaling to all levels (#95206)

This commit is contained in:
Joe Reuter 2021-03-31 11:31:48 +02:00 committed by GitHub
parent ede6b4fd64
commit a9d0b6f478
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
32 changed files with 249 additions and 341 deletions

View file

@ -7,9 +7,9 @@
<b>Signature:</b>
```typescript
fieldIsTimeField(): boolean | "" | undefined;
fieldIsTimeField(): boolean;
```
<b>Returns:</b>
`boolean | "" | undefined`
`boolean`

View file

@ -23,6 +23,7 @@ export declare class AggConfigs
| [aggs](./kibana-plugin-plugins-data-public.aggconfigs.aggs.md) | | <code>IAggConfig[]</code> | |
| [createAggConfig](./kibana-plugin-plugins-data-public.aggconfigs.createaggconfig.md) | | <code>&lt;T extends AggConfig = AggConfig&gt;(params: CreateAggConfigParams, { addToAggConfigs }?: {</code><br/><code> addToAggConfigs?: boolean &#124; undefined;</code><br/><code> }) =&gt; T</code> | |
| [indexPattern](./kibana-plugin-plugins-data-public.aggconfigs.indexpattern.md) | | <code>IndexPattern</code> | |
| [timeFields](./kibana-plugin-plugins-data-public.aggconfigs.timefields.md) | | <code>string[]</code> | |
| [timeRange](./kibana-plugin-plugins-data-public.aggconfigs.timerange.md) | | <code>TimeRange</code> | |
## Methods
@ -43,6 +44,7 @@ export declare class AggConfigs
| [getResponseAggs()](./kibana-plugin-plugins-data-public.aggconfigs.getresponseaggs.md) | | Gets the AggConfigs (and possibly ResponseAggConfigs) that represent the values that will be produced when all aggs are run.<!-- -->With multi-value metric aggs it is possible for a single agg request to result in multiple agg values, which is why the length of a vis' responseValuesAggs may be different than the vis' aggs {<!-- -->array\[AggConfig\]<!-- -->} |
| [jsonDataEquals(aggConfigs)](./kibana-plugin-plugins-data-public.aggconfigs.jsondataequals.md) | | Data-by-data comparison of this Aggregation Ignores the non-array indexes |
| [onSearchRequestStart(searchSource, options)](./kibana-plugin-plugins-data-public.aggconfigs.onsearchrequeststart.md) | | |
| [setTimeFields(timeFields)](./kibana-plugin-plugins-data-public.aggconfigs.settimefields.md) | | |
| [setTimeRange(timeRange)](./kibana-plugin-plugins-data-public.aggconfigs.settimerange.md) | | |
| [toDsl(hierarchical)](./kibana-plugin-plugins-data-public.aggconfigs.todsl.md) | | |

View file

@ -0,0 +1,22 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) &gt; [setTimeFields](./kibana-plugin-plugins-data-public.aggconfigs.settimefields.md)
## AggConfigs.setTimeFields() method
<b>Signature:</b>
```typescript
setTimeFields(timeFields: string[] | undefined): void;
```
## Parameters
| Parameter | Type | Description |
| --- | --- | --- |
| timeFields | <code>string[] &#124; undefined</code> | |
<b>Returns:</b>
`void`

View file

@ -0,0 +1,11 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->
[Home](./index.md) &gt; [kibana-plugin-plugins-data-public](./kibana-plugin-plugins-data-public.md) &gt; [AggConfigs](./kibana-plugin-plugins-data-public.aggconfigs.md) &gt; [timeFields](./kibana-plugin-plugins-data-public.aggconfigs.timefields.md)
## AggConfigs.timeFields property
<b>Signature:</b>
```typescript
timeFields?: string[];
```

View file

@ -14,7 +14,7 @@ search: {
intervalOptions: ({
display: string;
val: string;
enabled(agg: import("../common").IBucketAggConfig): boolean | "" | undefined;
enabled(agg: import("../common").IBucketAggConfig): boolean;
} | {
display: string;
val: string;
@ -47,6 +47,11 @@ search: {
intervalLabel: string;
})[];
getNumberHistogramIntervalByDatatableColumn: (column: import("../../expressions").DatatableColumn) => number | undefined;
getDateHistogramMetaDataByDatatableColumn: (column: import("../../expressions").DatatableColumn) => {
interval: string | undefined;
timeZone: string | undefined;
timeRange: import("../common").TimeRange | undefined;
} | undefined;
};
getRequestInspectorStats: typeof getRequestInspectorStats;
getResponseInspectorStats: typeof getResponseInspectorStats;

View file

@ -14,7 +14,7 @@ search: {
intervalOptions: ({
display: string;
val: string;
enabled(agg: import("../common").IBucketAggConfig): boolean | "" | undefined;
enabled(agg: import("../common").IBucketAggConfig): boolean;
} | {
display: string;
val: string;

View file

@ -439,10 +439,14 @@ export class AggConfig {
}
fieldIsTimeField() {
const indexPattern = this.getIndexPattern();
if (!indexPattern) return false;
const timeFieldName = indexPattern.timeFieldName;
return timeFieldName && this.fieldName() === timeFieldName;
const defaultTimeField = this.getIndexPattern()?.getTimeField?.()?.name;
const defaultTimeFields = defaultTimeField ? [defaultTimeField] : [];
const allTimeFields =
this.aggConfigs.timeFields && this.aggConfigs.timeFields.length > 0
? this.aggConfigs.timeFields
: defaultTimeFields;
const currentFieldName = this.fieldName();
return allTimeFields.includes(currentFieldName);
}
public get type() {

View file

@ -64,6 +64,7 @@ export type IAggConfigs = AggConfigs;
export class AggConfigs {
public indexPattern: IndexPattern;
public timeRange?: TimeRange;
public timeFields?: string[];
private readonly typesRegistry: AggTypesRegistryStart;
aggs: IAggConfig[];
@ -83,6 +84,10 @@ export class AggConfigs {
configStates.forEach((params: any) => this.createAggConfig(params));
}
setTimeFields(timeFields: string[] | undefined) {
this.timeFields = timeFields;
}
setTimeRange(timeRange: TimeRange) {
this.timeRange = timeRange;

View file

@ -194,9 +194,8 @@ describe('Aggs service', () => {
describe('start()', () => {
test('exposes proper contract', () => {
const start = service.start(startDeps);
expect(Object.keys(start).length).toBe(5);
expect(Object.keys(start).length).toBe(4);
expect(start).toHaveProperty('calculateAutoTimeExpression');
expect(start).toHaveProperty('getDateMetaByDatatableColumn');
expect(start).toHaveProperty('createAggConfigs');
expect(start).toHaveProperty('types');
expect(start).toHaveProperty('datatableUtilities');

View file

@ -17,7 +17,6 @@ import {
getCalculateAutoTimeExpression,
} from './';
import { AggsCommonSetup, AggsCommonStart } from './types';
import { getDateMetaByDatatableColumn } from './utils/time_column_meta';
import { getDatatableColumnUtilities } from './utils/datatable_column_meta';
/** @internal */
@ -89,12 +88,6 @@ export class AggsCommonService {
return {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn: getDateMetaByDatatableColumn({
calculateAutoTimeExpression,
getIndexPattern,
getConfig,
isDefaultTimezone,
}),
datatableUtilities: getDatatableColumnUtilities({
getIndexPattern,
createAggConfigs,

View file

@ -64,7 +64,9 @@ export interface AggParamsDateHistogram extends BaseAggParams {
useNormalizedEsInterval?: boolean;
scaleMetricValues?: boolean;
interval?: string;
used_interval?: string;
time_zone?: string;
used_time_zone?: string;
drop_partials?: boolean;
format?: string;
min_doc_count?: number;
@ -220,6 +222,21 @@ export const getDateHistogramBucketAgg = ({
}
},
},
{
name: 'used_interval',
default: autoInterval,
shouldShow() {
return false;
},
write: () => {},
serialize(val, agg) {
if (!agg) return undefined;
const { useNormalizedEsInterval } = agg.params;
const interval = agg.buckets.getInterval(useNormalizedEsInterval);
return interval.expression;
},
toExpressionAst: () => undefined,
},
{
name: 'time_zone',
default: undefined,
@ -232,6 +249,18 @@ export const getDateHistogramBucketAgg = ({
output.params.time_zone = tz;
},
},
{
name: 'used_timezone',
shouldShow() {
return false;
},
write: () => {},
serialize(val, agg) {
if (!agg) return undefined;
return inferTimeZone(agg.params, agg.getIndexPattern(), isDefaultTimezone, getConfig);
},
toExpressionAst: () => undefined,
},
{
name: 'drop_partials',
default: false,

View file

@ -9,7 +9,6 @@
import { Assign } from '@kbn/utility-types';
import { DatatableColumn } from 'src/plugins/expressions';
import { IndexPattern } from '../../index_patterns/index_patterns/index_pattern';
import { TimeRange } from '../../query';
import {
aggAvg,
aggBucketAvg,
@ -106,19 +105,6 @@ export interface AggsCommonSetup {
/** @internal */
export interface AggsCommonStart {
calculateAutoTimeExpression: ReturnType<typeof getCalculateAutoTimeExpression>;
/**
* Helper function returning meta data about use date intervals for a data table column.
* If the column is not a column created by a date histogram aggregation of the esaggs data source,
* this function will return undefined.
*
* Otherwise, it will return the following attributes in an object:
* * `timeZone` time zone used to create the buckets (important e.g. for DST),
* * `timeRange` total time range of the fetch data (to infer partial buckets at the beginning and end of the data)
* * `interval` Interval used on elasticsearch (`auto` resolved to the actual interval)
*/
getDateMetaByDatatableColumn: (
column: DatatableColumn
) => Promise<undefined | { timeZone: string; timeRange?: TimeRange; interval: string }>;
datatableUtilities: {
getIndexPattern: (column: DatatableColumn) => Promise<IndexPattern | undefined>;
getAggConfig: (column: DatatableColumn) => Promise<AggConfig | undefined>;

View file

@ -0,0 +1,35 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DatatableColumn } from 'src/plugins/expressions/common';
import { TimeRange } from '../../../types';
import type { AggParamsDateHistogram } from '../buckets';
import { BUCKET_TYPES } from '../buckets/bucket_agg_types';
/**
* Helper function returning the used interval, used time zone and applied time filters for data table column created by the date_histogramm agg type.
* "auto" will get expanded to the actually used interval.
* If the column is not a column created by a date_histogram aggregation of the esaggs data source,
* this function will return undefined.
*/
export const getDateHistogramMetaDataByDatatableColumn = (column: DatatableColumn) => {
if (column.meta.source !== 'esaggs') return;
if (column.meta.sourceParams?.type !== BUCKET_TYPES.DATE_HISTOGRAM) return;
const params = (column.meta.sourceParams.params as unknown) as AggParamsDateHistogram;
let interval: string | undefined;
if (params.used_interval && params.used_interval !== 'auto') {
interval = params.used_interval;
}
return {
interval,
timeZone: params.used_time_zone,
timeRange: column.meta.sourceParams.appliedTimeRange as TimeRange | undefined,
};
};

View file

@ -8,6 +8,7 @@
export * from './calculate_auto_time_expression';
export { getNumberHistogramIntervalByDatatableColumn } from './get_number_histogram_interval';
export { getDateHistogramMetaDataByDatatableColumn } from './get_date_histogram_meta';
export * from './date_interval_utils';
export * from './get_format_with_aggs';
export * from './ipv4_address';

View file

@ -1,147 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { BUCKET_TYPES } from '../buckets';
import { DateMetaByColumnDeps, getDateMetaByDatatableColumn } from './time_column_meta';
describe('getDateMetaByDatatableColumn', () => {
let params: DateMetaByColumnDeps;
beforeEach(() => {
params = {
calculateAutoTimeExpression: jest.fn().mockReturnValue('5m'),
getIndexPattern: jest.fn().mockResolvedValue({}),
isDefaultTimezone: jest.fn().mockReturnValue(true),
getConfig: jest.fn(),
};
});
it('returns nothing on column from other data source', async () => {
expect(
await getDateMetaByDatatableColumn(params)({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'essql',
},
})
).toEqual(undefined);
});
it('returns nothing on non date histogram column', async () => {
expect(
await getDateMetaByDatatableColumn(params)({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.TERMS,
},
},
})
).toEqual(undefined);
});
it('returns time range, time zone and interval', async () => {
expect(
await getDateMetaByDatatableColumn(params)({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.DATE_HISTOGRAM,
params: {
time_zone: 'UTC',
interval: '1h',
},
appliedTimeRange: {
from: 'now-5d',
to: 'now',
},
},
},
})
).toEqual({
timeZone: 'UTC',
timeRange: {
from: 'now-5d',
to: 'now',
},
interval: '1h',
});
});
it('throws if unable to resolve interval', async () => {
await expect(
getDateMetaByDatatableColumn(params)({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.DATE_HISTOGRAM,
params: {
time_zone: 'UTC',
interval: 'auto',
},
},
},
})
).rejects.toBeDefined();
await expect(
getDateMetaByDatatableColumn(params)({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.DATE_HISTOGRAM,
params: {
time_zone: 'UTC',
},
},
},
})
).rejects.toBeDefined();
});
it('returns resolved auto interval', async () => {
expect(
await getDateMetaByDatatableColumn(params)({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.DATE_HISTOGRAM,
params: {
time_zone: 'UTC',
interval: 'auto',
},
appliedTimeRange: {
from: '2020-10-05T00:00:00.000Z',
to: '2020-10-10T00:00:00.000Z',
},
},
},
})
).toEqual(
expect.objectContaining({
interval: '5m',
})
);
});
});

View file

@ -1,57 +0,0 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License
* 2.0 and the Server Side Public License, v 1; you may not use this file except
* in compliance with, at your election, the Elastic License 2.0 or the Server
* Side Public License, v 1.
*/
import { DatatableColumn } from 'src/plugins/expressions/common';
import { IndexPattern } from '../../../index_patterns';
import { TimeRange } from '../../../types';
import { AggParamsDateHistogram, BUCKET_TYPES } from '../buckets';
import { inferTimeZone } from './infer_time_zone';
export interface DateMetaByColumnDeps {
calculateAutoTimeExpression: (range: TimeRange) => string | undefined;
getIndexPattern: (id: string) => Promise<IndexPattern>;
isDefaultTimezone: () => boolean;
getConfig: <T = any>(key: string) => T;
}
export const getDateMetaByDatatableColumn = ({
calculateAutoTimeExpression,
getIndexPattern,
isDefaultTimezone,
getConfig,
}: DateMetaByColumnDeps) => async (
column: DatatableColumn
): Promise<undefined | { timeZone: string; timeRange?: TimeRange; interval: string }> => {
if (column.meta.source !== 'esaggs') return;
if (column.meta.sourceParams?.type !== BUCKET_TYPES.DATE_HISTOGRAM) return;
const params = column.meta.sourceParams.params as AggParamsDateHistogram;
const appliedTimeRange = column.meta.sourceParams.appliedTimeRange as TimeRange | undefined;
const tz = inferTimeZone(
params,
await getIndexPattern(column.meta.sourceParams.indexPatternId as string),
isDefaultTimezone,
getConfig
);
const interval =
params.interval === 'auto' && appliedTimeRange
? calculateAutoTimeExpression(appliedTimeRange)
: params.interval;
if (!interval || interval === 'auto') {
throw new Error('time interval could not be determined');
}
return {
timeZone: tz,
timeRange: appliedTimeRange,
interval,
};
};

View file

@ -33,6 +33,7 @@ describe('esaggs expression function - public', () => {
setTimeRange: jest.fn(),
toDsl: jest.fn().mockReturnValue({ aggs: {} }),
onSearchRequestStart: jest.fn(),
setTimeFields: jest.fn(),
} as unknown) as jest.Mocked<IAggConfigs>,
filters: undefined,
indexPattern: ({ id: 'logstash-*' } as unknown) as jest.Mocked<IndexPattern>,

View file

@ -73,6 +73,7 @@ export const handleRequest = async ({
const requestSearchSource = timeFilterSearchSource.createChild({ callParentStartHandlers: true });
aggs.setTimeRange(timeRange as TimeRange);
aggs.setTimeFields(timeFields);
// For now we need to mirror the history of the passed search source, since
// the request inspector wouldn't work otherwise.

View file

@ -313,6 +313,7 @@ import {
toAbsoluteDates,
boundsDescendingRaw,
getNumberHistogramIntervalByDatatableColumn,
getDateHistogramMetaDataByDatatableColumn,
// expressions utils
getRequestInspectorStats,
getResponseInspectorStats,
@ -423,6 +424,7 @@ export const search = {
toAbsoluteDates,
boundsDescendingRaw,
getNumberHistogramIntervalByDatatableColumn,
getDateHistogramMetaDataByDatatableColumn,
},
getRequestInspectorStats,
getResponseInspectorStats,

View file

@ -132,7 +132,7 @@ export class AggConfig {
enabled: boolean;
static ensureIds(list: any[]): any[];
// (undocumented)
fieldIsTimeField(): boolean | "" | undefined;
fieldIsTimeField(): boolean;
// (undocumented)
fieldName(): any;
// (undocumented)
@ -260,8 +260,12 @@ export class AggConfigs {
// (undocumented)
onSearchRequestStart(searchSource: ISearchSource_2, options?: ISearchOptions_2): Promise<[unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown, unknown]>;
// (undocumented)
setTimeFields(timeFields: string[] | undefined): void;
// (undocumented)
setTimeRange(timeRange: TimeRange): void;
// (undocumented)
timeFields?: string[];
// (undocumented)
timeRange?: TimeRange;
// (undocumented)
toDsl(hierarchical?: boolean): Record<string, any>;
@ -2240,7 +2244,7 @@ export const search: {
intervalOptions: ({
display: string;
val: string;
enabled(agg: import("../common").IBucketAggConfig): boolean | "" | undefined;
enabled(agg: import("../common").IBucketAggConfig): boolean;
} | {
display: string;
val: string;
@ -2273,6 +2277,11 @@ export const search: {
intervalLabel: string;
})[];
getNumberHistogramIntervalByDatatableColumn: (column: import("../../expressions").DatatableColumn) => number | undefined;
getDateHistogramMetaDataByDatatableColumn: (column: import("../../expressions").DatatableColumn) => {
interval: string | undefined;
timeZone: string | undefined;
timeRange: import("../common").TimeRange | undefined;
} | undefined;
};
getRequestInspectorStats: typeof getRequestInspectorStats;
getResponseInspectorStats: typeof getResponseInspectorStats;
@ -2642,7 +2651,7 @@ export const UI_SETTINGS: {
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:65:5 - (ae-forgotten-export) The symbol "FormatFieldFn" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:138:7 - (ae-forgotten-export) The symbol "FieldAttrSet" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/index_patterns/index_patterns/index_pattern.ts:169:7 - (ae-forgotten-export) The symbol "RuntimeField" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/search/aggs/types.ts:141:51 - (ae-forgotten-export) The symbol "AggTypesRegistryStart" needs to be exported by the entry point index.d.ts
// src/plugins/data/common/search/aggs/types.ts:127:51 - (ae-forgotten-export) The symbol "AggTypesRegistryStart" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/field_formats/field_formats_service.ts:56:3 - (ae-forgotten-export) The symbol "FormatFactory" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "FILTERS" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:56:23 - (ae-forgotten-export) The symbol "getDisplayValueFromFilter" needs to be exported by the entry point index.d.ts
@ -2676,21 +2685,21 @@ export const UI_SETTINGS: {
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:238:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:403:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:405:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:415:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:426:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:430:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:404:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:406:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:407:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:419:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:423:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:427:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:428:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:431:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/query/state_sync/connect_to_query_state.ts:34:5 - (ae-forgotten-export) The symbol "FilterStateStore" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/search/session/session_service.ts:56:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts

View file

@ -79,9 +79,8 @@ describe('AggsService - public', () => {
describe('start()', () => {
test('exposes proper contract', () => {
const start = service.start(startDeps);
expect(Object.keys(start).length).toBe(5);
expect(Object.keys(start).length).toBe(4);
expect(start).toHaveProperty('calculateAutoTimeExpression');
expect(start).toHaveProperty('getDateMetaByDatatableColumn');
expect(start).toHaveProperty('createAggConfigs');
expect(start).toHaveProperty('types');
expect(start).toHaveProperty('datatableUtilities');

View file

@ -91,16 +91,13 @@ export class AggsService {
public start({ fieldFormats, uiSettings, indexPatterns }: AggsStartDependencies): AggsStart {
const isDefaultTimezone = () => uiSettings.isDefault('dateFormat:tz');
const {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn,
datatableUtilities,
types,
} = this.aggsCommonService.start({
getConfig: this.getConfig!,
getIndexPattern: indexPatterns.get,
isDefaultTimezone,
});
const { calculateAutoTimeExpression, datatableUtilities, types } = this.aggsCommonService.start(
{
getConfig: this.getConfig!,
getIndexPattern: indexPatterns.get,
isDefaultTimezone,
}
);
const aggTypesDependencies: AggTypesDependencies = {
calculateBounds: this.calculateBounds,
@ -140,7 +137,6 @@ export class AggsService {
return {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn,
datatableUtilities,
createAggConfigs: (indexPattern, configStates = []) => {
return new AggConfigs(indexPattern, configStates, { typesRegistry });

View file

@ -56,7 +56,6 @@ export const searchAggsSetupMock = (): AggsSetup => ({
export const searchAggsStartMock = (): AggsStart => ({
calculateAutoTimeExpression: getCalculateAutoTimeExpression(getConfig),
getDateMetaByDatatableColumn: jest.fn(),
datatableUtilities: {
isFilterable: jest.fn(),
getAggConfig: jest.fn(),

View file

@ -74,7 +74,6 @@ export class AggsService {
const {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn,
datatableUtilities,
types,
} = this.aggsCommonService.start({
@ -119,7 +118,6 @@ export class AggsService {
return {
calculateAutoTimeExpression,
getDateMetaByDatatableColumn,
datatableUtilities,
createAggConfigs: (indexPattern, configStates = []) => {
return new AggConfigs(indexPattern, configStates, { typesRegistry });

View file

@ -58,7 +58,6 @@ export const searchAggsSetupMock = (): AggsSetup => ({
const commonStartMock = (): AggsCommonStart => ({
calculateAutoTimeExpression: getCalculateAutoTimeExpression(getConfig),
getDateMetaByDatatableColumn: jest.fn(),
datatableUtilities: {
getIndexPattern: jest.fn(),
getAggConfig: jest.fn(),

View file

@ -1297,7 +1297,7 @@ export const search: {
intervalOptions: ({
display: string;
val: string;
enabled(agg: import("../common").IBucketAggConfig): boolean | "" | undefined;
enabled(agg: import("../common").IBucketAggConfig): boolean;
} | {
display: string;
val: string;

View file

@ -24,45 +24,46 @@ describe('applyAggsToSearchSource', () => {
const aggsConfig = applyAggsToSearchSource(true, searchSource, 'auto', indexPattern, dataMock);
expect(aggsConfig!.aggs).toMatchInlineSnapshot(`
Array [
Object {
"enabled": true,
"id": "1",
"params": Object {},
"schema": "metric",
"type": "count",
},
Object {
"enabled": true,
"id": "2",
"params": Object {
"drop_partials": false,
"extended_bounds": Object {},
"field": "timestamp",
"interval": "auto",
"min_doc_count": 1,
"scaleMetricValues": false,
"useNormalizedEsInterval": true,
Array [
Object {
"enabled": true,
"id": "1",
"params": Object {},
"schema": "metric",
"type": "count",
},
"schema": "segment",
"type": "date_histogram",
},
]
`);
Object {
"enabled": true,
"id": "2",
"params": Object {
"drop_partials": false,
"extended_bounds": Object {},
"field": "timestamp",
"interval": "auto",
"min_doc_count": 1,
"scaleMetricValues": false,
"useNormalizedEsInterval": true,
"used_interval": "0ms",
},
"schema": "segment",
"type": "date_histogram",
},
]
`);
expect(setField).toHaveBeenCalledWith('aggs', expect.any(Function));
const dslFn = setField.mock.calls[0][1];
expect(dslFn()).toMatchInlineSnapshot(`
Object {
"2": Object {
"date_histogram": Object {
"field": "timestamp",
"min_doc_count": 1,
"time_zone": "America/New_York",
},
},
}
`);
Object {
"2": Object {
"date_histogram": Object {
"field": "timestamp",
"min_doc_count": 1,
"time_zone": "America/New_York",
},
},
}
`);
});
test('enabled = false', () => {

View file

@ -7,7 +7,7 @@
import moment from 'moment';
import { Datatable } from 'src/plugins/expressions/public';
import { DataPublicPluginStart } from 'src/plugins/data/public';
import { DataPublicPluginStart, TimeRange } from 'src/plugins/data/public';
import { dataPluginMock } from '../../../../../src/plugins/data/public/mocks';
import { functionWrapper } from 'src/plugins/expressions/common/expression_functions/specs/tests/utils';
import { getTimeScaleFunction, TimeScaleArgs } from './time_scale';
@ -44,9 +44,25 @@ describe('time_scale', () => {
targetUnit: 'h',
};
function setDateHistogramMeta(options: {
timeZone: string;
timeRange: TimeRange;
interval: string;
}) {
emptyTable.columns[0].meta.source = 'esaggs';
emptyTable.columns[0].meta.sourceParams = {
type: 'date_histogram',
params: {
used_interval: options.interval,
used_time_zone: options.timeZone,
},
appliedTimeRange: options.timeRange,
};
}
beforeEach(() => {
dataMock = dataPluginMock.createStartContract();
(dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({
setDateHistogramMeta({
timeZone: 'UTC',
timeRange: {
from: '2020-10-05T00:00:00.000Z',
@ -156,7 +172,7 @@ describe('time_scale', () => {
});
it('should be able to scale up as well', async () => {
(dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({
setDateHistogramMeta({
timeZone: 'UTC',
timeRange: {
from: '2020-10-05T12:00:00.000Z',
@ -196,7 +212,7 @@ describe('time_scale', () => {
});
it('can scale starting from unit multiple target intervals', async () => {
(dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({
setDateHistogramMeta({
timeZone: 'UTC',
timeRange: {
from: '2020-10-05T13:00:00.000Z',
@ -238,7 +254,7 @@ describe('time_scale', () => {
});
it('take start and end of timerange into account', async () => {
(dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({
setDateHistogramMeta({
timeZone: 'UTC',
timeRange: {
from: '2020-10-05T12:00:00.000Z',
@ -283,7 +299,7 @@ describe('time_scale', () => {
});
it('should respect DST switches', async () => {
(dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({
setDateHistogramMeta({
timeZone: 'Europe/Berlin',
timeRange: {
from: '2020-10-23T00:00:00.000+02:00',
@ -323,7 +339,7 @@ describe('time_scale', () => {
});
it('take leap years into account', async () => {
(dataMock.search.aggs.getDateMetaByDatatableColumn as jest.Mock).mockReturnValue({
setDateHistogramMeta({
timeZone: 'UTC',
timeRange: {
from: '2010-01-01T00:00:00.000Z',

View file

@ -97,8 +97,8 @@ export function getTimeScaleFunction(data: DataPublicPluginStart) {
}
const targetUnitInMs = unitInMs[targetUnit];
const timeInfo = await data.search.aggs.getDateMetaByDatatableColumn(dateColumnDefinition);
const intervalDuration = timeInfo && search.aggs.parseInterval(timeInfo.interval);
const timeInfo = search.aggs.getDateHistogramMetaDataByDatatableColumn(dateColumnDefinition);
const intervalDuration = timeInfo?.interval && search.aggs.parseInterval(timeInfo.interval);
if (!timeInfo || !intervalDuration) {
throw new Error(

View file

@ -1894,10 +1894,14 @@ describe('xy_expression', () => {
xyProps.args.layers[0].xScaleType = 'time';
});
it('should use first valid layer and determine interval', async () => {
const result = await calculateMinInterval(
xyProps,
jest.fn().mockResolvedValue({ interval: '5m' })
);
xyProps.data.tables.first.columns[2].meta.source = 'esaggs';
xyProps.data.tables.first.columns[2].meta.sourceParams = {
type: 'date_histogram',
params: {
used_interval: '5m',
},
};
const result = await calculateMinInterval(xyProps);
expect(result).toEqual(5 * 60 * 1000);
});
@ -1915,34 +1919,38 @@ describe('xy_expression', () => {
},
},
};
const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined));
const result = await calculateMinInterval(xyProps);
expect(result).toEqual(5);
});
it('should return undefined if data table is empty', async () => {
xyProps.data.tables.first.rows = [];
const result = await calculateMinInterval(
xyProps,
jest.fn().mockResolvedValue({ interval: '5m' })
);
xyProps.data.tables.first.columns[2].meta.source = 'esaggs';
xyProps.data.tables.first.columns[2].meta.sourceParams = {
type: 'date_histogram',
params: {
used_interval: '5m',
},
};
const result = await calculateMinInterval(xyProps);
expect(result).toEqual(undefined);
});
it('should return undefined if interval can not be checked', async () => {
const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined));
const result = await calculateMinInterval(xyProps);
expect(result).toEqual(undefined);
});
it('should return undefined if date column is not found', async () => {
xyProps.data.tables.first.columns.splice(2, 1);
const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined));
const result = await calculateMinInterval(xyProps);
expect(result).toEqual(undefined);
});
it('should return undefined if x axis is not a date', async () => {
xyProps.args.layers[0].xScaleType = 'ordinal';
xyProps.data.tables.first.columns.splice(2, 1);
const result = await calculateMinInterval(xyProps, jest.fn().mockResolvedValue(undefined));
const result = await calculateMinInterval(xyProps);
expect(result).toEqual(undefined);
});
});

View file

@ -46,11 +46,7 @@ import {
import { XYArgs, SeriesType, visualizationTypes, LayerArgs } from './types';
import { VisualizationContainer } from '../visualization_container';
import { isHorizontalChart, getSeriesColor } from './state_helpers';
import {
DataPublicPluginStart,
ExpressionValueSearchContext,
search,
} from '../../../../../src/plugins/data/public';
import { ExpressionValueSearchContext, search } from '../../../../../src/plugins/data/public';
import {
ChartsPluginSetup,
PaletteRegistry,
@ -200,10 +196,7 @@ export const xyChart: ExpressionFunctionDefinition<
},
};
export async function calculateMinInterval(
{ args: { layers }, data }: XYChartProps,
getIntervalByColumn: DataPublicPluginStart['search']['aggs']['getDateMetaByDatatableColumn']
) {
export async function calculateMinInterval({ args: { layers }, data }: XYChartProps) {
const filteredLayers = getFilteredLayers(layers, data);
if (filteredLayers.length === 0) return;
const isTimeViz = data.dateRange && filteredLayers.every((l) => l.xScaleType === 'time');
@ -220,9 +213,9 @@ export async function calculateMinInterval(
return undefined;
}
}
const dateMetaData = await getIntervalByColumn(xColumn);
if (!dateMetaData) return;
const intervalDuration = search.aggs.parseInterval(dateMetaData.interval);
const dateInterval = search.aggs.getDateHistogramMetaDataByDatatableColumn(xColumn)?.interval;
if (!dateInterval) return;
const intervalDuration = search.aggs.parseInterval(dateInterval);
if (!intervalDuration) return;
return intervalDuration.as('milliseconds');
}
@ -231,7 +224,6 @@ export const getXyChartRenderer = (dependencies: {
formatFactory: Promise<FormatFactory>;
chartsThemeService: ChartsPluginSetup['theme'];
paletteService: PaletteRegistry;
getIntervalByColumn: DataPublicPluginStart['search']['aggs']['getDateMetaByDatatableColumn'];
timeZone: string;
}): ExpressionRenderDefinition<XYChartProps> => ({
name: 'lens_xy_chart_renderer',
@ -262,7 +254,7 @@ export const getXyChartRenderer = (dependencies: {
chartsThemeService={dependencies.chartsThemeService}
paletteService={dependencies.paletteService}
timeZone={dependencies.timeZone}
minInterval={await calculateMinInterval(config, dependencies.getIntervalByColumn)}
minInterval={await calculateMinInterval(config)}
onClickValue={onClickValue}
onSelectRange={onSelectRange}
renderMode={handlers.getRenderMode()}

View file

@ -63,7 +63,6 @@ export class XyVisualization {
chartsThemeService: charts.theme,
paletteService: palettes,
timeZone: getTimeZone(core.uiSettings),
getIntervalByColumn: data.search.aggs.getDateMetaByDatatableColumn,
})
);
return getXyVisualization({ paletteService: palettes, data });