Skip to content

Commit

Permalink
[Lens] Make lens_time_scale function to pick timezone from the context (
Browse files Browse the repository at this point in the history
#108366)

Part of: #97134

Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
  • Loading branch information
alexwizp and kibanamachine committed Aug 17, 2021
1 parent 41162c3 commit 87ac80e
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,9 @@ search: {
intervalLabel: string;
})[];
getNumberHistogramIntervalByDatatableColumn: (column: import("../../expressions").DatatableColumn) => number | undefined;
getDateHistogramMetaDataByDatatableColumn: (column: import("../../expressions").DatatableColumn) => {
getDateHistogramMetaDataByDatatableColumn: (column: import("../../expressions").DatatableColumn, defaults?: Partial<{
timeZone: string;
}>) => {
interval: string | undefined;
timeZone: string | undefined;
timeRange: import("../common").TimeRange | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,12 @@ import { BUCKET_TYPES } from '../buckets/bucket_agg_types';
* 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) => {
export const getDateHistogramMetaDataByDatatableColumn = (
column: DatatableColumn,
defaults: Partial<{
timeZone: string;
}> = {}
) => {
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;
Expand All @@ -29,7 +34,7 @@ export const getDateHistogramMetaDataByDatatableColumn = (column: DatatableColum

return {
interval,
timeZone: params.used_time_zone,
timeZone: params.used_time_zone || defaults.timeZone,
timeRange: column.meta.sourceParams.appliedTimeRange as TimeRange | undefined,
};
};
4 changes: 3 additions & 1 deletion src/plugins/data/public/public.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -2036,7 +2036,9 @@ export const search: {
intervalLabel: string;
})[];
getNumberHistogramIntervalByDatatableColumn: (column: import("../../expressions").DatatableColumn) => number | undefined;
getDateHistogramMetaDataByDatatableColumn: (column: import("../../expressions").DatatableColumn) => {
getDateHistogramMetaDataByDatatableColumn: (column: import("../../expressions").DatatableColumn, defaults?: Partial<{
timeZone: string;
}>) => {
interval: string | undefined;
timeZone: string | undefined;
timeRange: import("../common").TimeRange | undefined;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ jest.mock('../../../../../../src/plugins/data/common/query/timefilter/get_time',
};
});

import { timeScale, TimeScaleArgs } from './time_scale';
import { getTimeScale, TimeScaleArgs } from './time_scale';

describe('time_scale', () => {
let timeScaleWrapped: (input: Datatable, args: TimeScaleArgs) => Promise<Datatable>;
const timeScale = getTimeScale(() => 'UTC');

const emptyTable: Datatable = {
type: 'datatable',
Expand Down
20 changes: 14 additions & 6 deletions x-pack/plugins/lens/common/expressions/time_scale/time_scale.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ import {
parseInterval,
calculateBounds,
} from '../../../../../../src/plugins/data/common';
import { buildResultColumns } from '../../../../../../src/plugins/expressions/common';
import {
buildResultColumns,
ExecutionContext,
} from '../../../../../../src/plugins/expressions/common';
import type { TimeScaleUnit } from './types';

export interface TimeScaleArgs {
Expand All @@ -34,12 +37,14 @@ const unitInMs: Record<TimeScaleUnit, number> = {
d: 1000 * 60 * 60 * 24,
};

export const timeScale: ExpressionFunctionDefinition<
export const getTimeScale = (
getTimezone: (context: ExecutionContext) => string | Promise<string>
): ExpressionFunctionDefinition<
'lens_time_scale',
Datatable,
TimeScaleArgs,
Promise<Datatable>
> = {
> => ({
name: 'lens_time_scale',
type: 'datatable',
help: '',
Expand Down Expand Up @@ -73,7 +78,8 @@ export const timeScale: ExpressionFunctionDefinition<
inputTypes: ['datatable'],
async fn(
input,
{ dateColumnId, inputColumnId, outputColumnId, outputColumnName, targetUnit }: TimeScaleArgs
{ dateColumnId, inputColumnId, outputColumnId, outputColumnName, targetUnit }: TimeScaleArgs,
context
) {
const dateColumnDefinition = input.columns.find((column) => column.id === dateColumnId);

Expand Down Expand Up @@ -101,7 +107,9 @@ export const timeScale: ExpressionFunctionDefinition<
}

const targetUnitInMs = unitInMs[targetUnit];
const timeInfo = getDateHistogramMetaDataByDatatableColumn(dateColumnDefinition);
const timeInfo = getDateHistogramMetaDataByDatatableColumn(dateColumnDefinition, {
timeZone: await getTimezone(context),
});
const intervalDuration = timeInfo?.interval && parseInterval(timeInfo.interval);

if (!timeInfo || !intervalDuration) {
Expand Down Expand Up @@ -148,4 +156,4 @@ export const timeScale: ExpressionFunctionDefinition<

return result;
},
};
});
5 changes: 3 additions & 2 deletions x-pack/plugins/lens/public/indexpattern_datasource/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
FieldFormatsStart,
FieldFormatsSetup,
} from '../../../../../src/plugins/field_formats/public';
import { getTimeZone } from '../utils';

export interface IndexPatternDatasourceSetupPlugins {
expressions: ExpressionsSetup;
Expand Down Expand Up @@ -54,7 +55,7 @@ export class IndexPatternDatasource {
renameColumns,
formatColumn,
counterRate,
timeScale,
getTimeScale,
getSuffixFormatter,
} = await import('../async_services');
return core
Expand All @@ -65,7 +66,7 @@ export class IndexPatternDatasource {
// todo: this code should be executed on setup phase.
fieldFormatsSetup.register([suffixFormatter]);
}
expressions.registerFunction(timeScale);
expressions.registerFunction(getTimeScale(() => getTimeZone(core.uiSettings)));
expressions.registerFunction(counterRate);
expressions.registerFunction(renameColumns);
expressions.registerFunction(formatColumn);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ export {
} from '../../common/expressions';
export { FormatColumnArgs, supportedFormats, formatColumn } from '../../common/expressions';
export { getSuffixFormatter, unitSuffixesLong } from '../../common/suffix_formatter';
export { timeScale, TimeScaleArgs } from '../../common/expressions';
export { getTimeScale, TimeScaleArgs } from '../../common/expressions';
export { renameColumns } from '../../common/expressions';

export function getIndexPatternDatasource({
Expand Down
33 changes: 7 additions & 26 deletions x-pack/plugins/lens/server/expressions/expressions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,10 @@
* 2.0.
*/

import type { CoreSetup, CoreStart, KibanaRequest } from 'kibana/server';
import type { CoreSetup } from 'kibana/server';
import {
pie,
xyChart,
timeScale,
counterRate,
metricChart,
yAxisConfig,
Expand All @@ -21,40 +20,21 @@ import {
datatableColumn,
tickLabelsConfig,
axisTitlesVisibilityConfig,
getTimeScale,
getDatatable,
} from '../../common/expressions';
import type { PluginStartContract } from '../plugin';
import type {
ExecutionContext,
ExpressionsServerSetup,
} from '../../../../../src/plugins/expressions/server';
import { getFormatFactory, getTimeZoneFactory } from './utils';

const getUiSettings = (coreStart: CoreStart, kibanaRequest: KibanaRequest) =>
coreStart.uiSettings.asScopedToClient(coreStart.savedObjects.getScopedClient(kibanaRequest));
import type { PluginStartContract } from '../plugin';
import type { ExpressionsServerSetup } from '../../../../../src/plugins/expressions/server';

export const setupExpressions = (
core: CoreSetup<PluginStartContract>,
expressions: ExpressionsServerSetup
) => {
const getFormatFactory = async (context: ExecutionContext) => {
const [coreStart, { fieldFormats: fieldFormatsStart }] = await core.getStartServices();
const kibanaRequest = context.getKibanaRequest?.();

if (!kibanaRequest) {
throw new Error('"lens_datatable" expression function requires a KibanaRequest to execute');
}

const fieldFormats = await fieldFormatsStart.fieldFormatServiceFactory(
getUiSettings(coreStart, kibanaRequest)
);

return fieldFormats.deserialize;
};

[
pie,
xyChart,
timeScale,
counterRate,
metricChart,
yAxisConfig,
Expand All @@ -66,6 +46,7 @@ export const setupExpressions = (
datatableColumn,
tickLabelsConfig,
axisTitlesVisibilityConfig,
getDatatable(getFormatFactory),
getDatatable(getFormatFactory(core)),
getTimeScale(getTimeZoneFactory(core)),
].forEach((expressionFn) => expressions.registerFunction(expressionFn));
};
47 changes: 47 additions & 0 deletions x-pack/plugins/lens/server/expressions/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
/*
* 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; you may not use this file except in compliance with the Elastic License
* 2.0.
*/

import { CoreSetup, CoreStart } from 'kibana/server';
import { ExecutionContext } from '../../../../../src/plugins/expressions';
import { PluginStartContract } from '../plugin';

const getUiSettings = (coreStart: CoreStart, context: ExecutionContext) => {
const kibanaRequest = context.getKibanaRequest?.();

if (!kibanaRequest) {
throw new Error('expression function cannot be executed without a KibanaRequest');
}

return coreStart.uiSettings.asScopedToClient(
coreStart.savedObjects.getScopedClient(kibanaRequest)
);
};

/** @internal **/
export const getFormatFactory = (core: CoreSetup<PluginStartContract>) => async (
context: ExecutionContext
) => {
const [coreStart, { fieldFormats: fieldFormatsStart }] = await core.getStartServices();

const fieldFormats = await fieldFormatsStart.fieldFormatServiceFactory(
getUiSettings(coreStart, context)
);

return fieldFormats.deserialize;
};

/** @internal **/
export const getTimeZoneFactory = (core: CoreSetup<PluginStartContract>) => async (
context: ExecutionContext
) => {
const [coreStart] = await core.getStartServices();
const uiSettings = await getUiSettings(coreStart, context);
const timezone = await uiSettings.get('dateFormat:tz');

/** if `Browser`, hardcode it to 'UTC' so the export has data that makes sense **/
return timezone === 'Browser' ? 'UTC' : timezone;
};

0 comments on commit 87ac80e

Please sign in to comment.