Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Lens] Pass used histogram interval to chart #91370

Merged
merged 10 commits into from
Feb 19, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ search: {
boundLabel: string;
intervalLabel: string;
})[];
getNumberHistogramIntervalByDatatableColumn: (column: import("../../expressions").DatatableColumn) => number | "auto" | undefined;
};
getRequestInspectorStats: typeof getRequestInspectorStats;
getResponseInspectorStats: typeof getResponseInspectorStats;
Expand Down
23 changes: 23 additions & 0 deletions src/plugins/data/common/search/aggs/buckets/histogram.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { AggTypesDependencies } from '../agg_types';
import { BUCKET_TYPES } from './bucket_agg_types';
import { IBucketHistogramAggConfig, getHistogramBucketAgg, AutoBounds } from './histogram';
import { BucketAggType } from './bucket_agg_type';
import { SerializableState } from 'src/plugins/expressions/common';
import { isSerializedAutoInterval } from '../utils/get_number_histogram_interval';

describe('Histogram Agg', () => {
let aggTypesDependencies: AggTypesDependencies;
Expand Down Expand Up @@ -230,6 +232,27 @@ describe('Histogram Agg', () => {
expect(params.interval).toBeNaN();
});

test('will serialize the auto interval along with the actually chosen interval and deserialize correctly', () => {
const aggConfigs = getAggConfigs({
interval: 'auto',
field: {
name: 'field',
},
});
(aggConfigs.aggs[0] as IBucketHistogramAggConfig).setAutoBounds({ min: 0, max: 1000 });
const serializedAgg = aggConfigs.aggs[0].serialize();
const serializedIntervalParam = (serializedAgg.params as SerializableState).interval;
expect(isSerializedAutoInterval(serializedIntervalParam as string | number)).toBe(true);
const freshHistogramAggConfig = getAggConfigs({
interval: 100,
field: {
name: 'field',
},
}).aggs[0];
freshHistogramAggConfig.setParams(serializedAgg.params);
expect(freshHistogramAggConfig.getParam('interval')).toEqual('auto');
});

describe('interval scaling', () => {
const getInterval = (
maxBars: number,
Expand Down
27 changes: 27 additions & 0 deletions src/plugins/data/common/search/aggs/buckets/histogram.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ import { aggHistogramFnName } from './histogram_fn';
import { ExtendedBounds } from './lib/extended_bounds';
import { isAutoInterval, autoInterval } from './_interval_options';
import { calculateHistogramInterval } from './lib/histogram_calculate_interval';
import {
buildSerializedAutoInterval,
isSerializedAutoInterval,
} from '../utils/get_number_histogram_interval';

export interface AutoBounds {
min: number;
Expand Down Expand Up @@ -152,6 +156,29 @@ export const getHistogramBucketAgg = ({
esTypes: aggConfig.params.field?.spec?.esTypes || [],
});
},
serialize(val, aggConfig) {
// store actually used auto interval in serialized agg config to be able to read it from the result data table meta information
const autoBounds = aggConfig?.getAutoBounds();
if (val === autoInterval && aggConfig && autoBounds) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic is duplicated with the write and serialize functions. I can't think of a better way, but maybe you can?

const usedInterval = calculateHistogramInterval({
values: autoBounds,
interval: aggConfig.params.interval,
maxBucketsUiSettings: getConfig(UI_SETTINGS.HISTOGRAM_MAX_BARS),
maxBucketsUserInput: aggConfig.params.maxBars,
intervalBase: aggConfig.params.intervalBase,
esTypes: aggConfig.params.field?.spec?.esTypes || [],
});
return buildSerializedAutoInterval(usedInterval);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could create a new property on this aggConfig calculatedInterval and make its serialize method:

      serialize: (val, aggConfig) => {
          const autoBounds = aggConfig?.getAutoBounds();
          if (aggConfig && autoBounds && aggConfig.params.interval === autoInterval ) {
            const usedInterval = calculateHistogramInterval({
              values: autoBounds,
              interval: aggConfig.params.interval,
              maxBucketsUiSettings: getConfig(UI_SETTINGS.HISTOGRAM_MAX_BARS),
              maxBucketsUserInput: aggConfig.params.maxBars,
              intervalBase: aggConfig.params.intervalBase,
              esTypes: aggConfig.params.field?.spec?.esTypes || [],
            });
            return usedInterval;
         }
         return aggConfig.params.interval;
       }

we don't need any deserialize method for it, write should be _.noop

} else {
return val;
}
},
deserialize(val) {
if (isSerializedAutoInterval(val)) {
return autoInterval;
}
return val;
},
},
{
name: 'maxBars',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
/*
* 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 { getNumberHistogramIntervalByDatatableColumn } from '.';
import { BUCKET_TYPES } from '../buckets';

describe('getNumberHistogramIntervalByDatatableColumn', () => {
it('returns nothing on column from other data source', () => {
expect(
getNumberHistogramIntervalByDatatableColumn({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'essql',
},
})
).toEqual(undefined);
});

it('returns nothing on non histogram column', () => {
expect(
getNumberHistogramIntervalByDatatableColumn({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.TERMS,
},
},
})
).toEqual(undefined);
});

it('returns interval on resolved auto interval', () => {
expect(
getNumberHistogramIntervalByDatatableColumn({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.HISTOGRAM,
params: {
interval: 'auto$$$20',
},
},
},
})
).toEqual(20);
});

it('returns interval on fixed interval', () => {
expect(
getNumberHistogramIntervalByDatatableColumn({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.HISTOGRAM,
params: {
interval: 7,
},
},
},
})
).toEqual(7);
});

it('returns undefined if information is not available', () => {
expect(
getNumberHistogramIntervalByDatatableColumn({
id: 'test',
name: 'test',
meta: {
type: 'date',
source: 'esaggs',
sourceParams: {
type: BUCKET_TYPES.HISTOGRAM,
params: {},
},
},
})
).toEqual(undefined);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/*
* 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 type { AggParamsHistogram } from '../buckets';
import { BUCKET_TYPES } from '../buckets/bucket_agg_types';

const SEPARATOR = '$$$';

function parseSerializedInterval(interval: string | number) {
if (typeof interval === 'number') {
return interval;
}
if (interval === 'auto') {
return 'auto';
}
return Number(interval.split(SEPARATOR)[1]);
}

export function buildSerializedAutoInterval(usedInterval: number) {
return `auto${SEPARATOR}${usedInterval}`;
}

export function isSerializedAutoInterval(interval: string | number) {
return typeof interval === 'string' && interval.startsWith('auto');
}

/**
* Helper function returning the used interval for data table column created by the histogramm agg type.
* "auto" will get expanded to the actually used interval.
* If the column is not a column created by a histogram aggregation of the esaggs data source,
* this function will return undefined.
*/
export const getNumberHistogramIntervalByDatatableColumn = (column: DatatableColumn) => {
if (column.meta.source !== 'esaggs') return;
if (column.meta.sourceParams?.type !== BUCKET_TYPES.HISTOGRAM) return;
const params = (column.meta.sourceParams.params as unknown) as AggParamsHistogram;

if (!params.interval) {
return undefined;
}
return parseSerializedInterval(params.interval);
};
1 change: 1 addition & 0 deletions src/plugins/data/common/search/aggs/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
*/

export * from './calculate_auto_time_expression';
export { getNumberHistogramIntervalByDatatableColumn } from './get_number_histogram_interval';
export * from './date_interval_utils';
export * from './get_format_with_aggs';
export * from './ipv4_address';
Expand Down
2 changes: 2 additions & 0 deletions src/plugins/data/public/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ import {
parseInterval,
toAbsoluteDates,
boundsDescendingRaw,
getNumberHistogramIntervalByDatatableColumn,
// expressions utils
getRequestInspectorStats,
getResponseInspectorStats,
Expand Down Expand Up @@ -416,6 +417,7 @@ export const search = {
termsAggFilter,
toAbsoluteDates,
boundsDescendingRaw,
getNumberHistogramIntervalByDatatableColumn,
},
getRequestInspectorStats,
getResponseInspectorStats,
Expand Down
31 changes: 16 additions & 15 deletions src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2232,6 +2232,7 @@ export const search: {
boundLabel: string;
intervalLabel: string;
})[];
getNumberHistogramIntervalByDatatableColumn: (column: import("../../expressions").DatatableColumn) => number | "auto" | undefined;
};
getRequestInspectorStats: typeof getRequestInspectorStats;
getResponseInspectorStats: typeof getResponseInspectorStats;
Expand Down Expand Up @@ -2607,21 +2608,21 @@ export const UI_SETTINGS: {
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "validateIndexPattern" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "flattenHitWrapper" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:234:27 - (ae-forgotten-export) The symbol "formatHitProvider" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:397:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:399:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:409:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:416:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:420:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:424:1 - (ae-forgotten-export) The symbol "toAbsoluteDates" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "getRequestInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "getResponseInspectorStats" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "tabifyAggResponse" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:398:20 - (ae-forgotten-export) The symbol "tabifyGetColumns" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:400:1 - (ae-forgotten-export) The symbol "CidrMask" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:401:1 - (ae-forgotten-export) The symbol "dateHistogramInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:410:1 - (ae-forgotten-export) The symbol "InvalidEsCalendarIntervalError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:411:1 - (ae-forgotten-export) The symbol "InvalidEsIntervalFormatError" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:412:1 - (ae-forgotten-export) The symbol "Ipv4Address" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:413:1 - (ae-forgotten-export) The symbol "isDateHistogramBucketAggConfig" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:417:1 - (ae-forgotten-export) The symbol "isValidEsInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:418:1 - (ae-forgotten-export) The symbol "isValidInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:421:1 - (ae-forgotten-export) The symbol "parseInterval" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:422:1 - (ae-forgotten-export) The symbol "propFilter" needs to be exported by the entry point index.d.ts
// src/plugins/data/public/index.ts:425: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:42:5 - (ae-forgotten-export) The symbol "UrlGeneratorStateMapping" needs to be exported by the entry point index.d.ts

Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading