Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@

import React from 'react';
import ReactDOM from 'react-dom';
import { I18nContext } from 'ui/i18n';
import { CoreStart } from '../../../../../../../src/core/public';
import { StartDeps } from '../../plugin';
import {
Expand All @@ -30,6 +29,8 @@ const embeddablesRegistry: {
} = {};

const renderEmbeddableFactory = (core: CoreStart, plugins: StartDeps) => {
const I18nContext = core.i18n.Context;

return (embeddableObject: IEmbeddable, domNode: HTMLElement) => {
return (
<div
Expand Down
4 changes: 2 additions & 2 deletions x-pack/legacy/plugins/canvas/i18n/functions/dict/timelion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,12 @@
*/

import { i18n } from '@kbn/i18n';
import { timelion } from '../../../public/functions/timelion';
import { timelionFunctionFactory } from '../../../public/functions/timelion';
import { FunctionHelp } from '../function_help';
import { FunctionFactory } from '../../../types';
import { ELASTICSEARCH, DATEMATH, MOMENTJS_TIMEZONE_URL } from '../../constants';

export const help: FunctionHelp<FunctionFactory<typeof timelion>> = {
export const help: FunctionHelp<FunctionFactory<ReturnType<typeof timelionFunctionFactory>>> = {
help: i18n.translate('xpack.canvas.functions.timelionHelpText', {
defaultMessage: 'Use Timelion to extract one or more timeseries from many sources.',
}),
Expand Down
5 changes: 5 additions & 0 deletions x-pack/legacy/plugins/canvas/public/application.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import { VALUE_CLICK_TRIGGER, ActionByType } from '../../../../../src/plugins/ui
/* eslint-disable */
import { ACTION_VALUE_CLICK } from '../../../../../src/plugins/data/public/actions/value_click_action';
/* eslint-enable */
import { init as initStatsReporter } from './lib/ui_metric';

import { CapabilitiesStrings } from '../i18n';
const { ReadOnlyBadge: strings } = CapabilitiesStrings;
Expand Down Expand Up @@ -121,6 +122,10 @@ export const initializeCanvas = async (
startPlugins.uiActions.attachAction(VALUE_CLICK_TRIGGER, emptyAction);
}

if (setupPlugins.usageCollection) {
initStatsReporter(setupPlugins.usageCollection.reportUiStats);
}

return canvasStore;
};

Expand Down
15 changes: 11 additions & 4 deletions x-pack/legacy/plugins/canvas/public/functions/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,23 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { ExpressionsSetup } from 'src/plugins/expressions/public';
import { asset } from './asset';
import { filtersFunctionFactory } from './filters';
import { timelion } from './timelion';
import { timelionFunctionFactory } from './timelion';
import { toFunctionFactory } from './to';
import { CanvasSetupDeps, CoreSetup } from '../plugin';

export interface InitializeArguments {
typesRegistry: ExpressionsSetup['__LEGACY']['types'];
prependBasePath: CoreSetup['http']['basePath']['prepend'];
typesRegistry: CanvasSetupDeps['expressions']['__LEGACY']['types'];
timefilter: CanvasSetupDeps['data']['query']['timefilter']['timefilter'];
}

export function initFunctions(initialize: InitializeArguments) {
return [asset, filtersFunctionFactory(initialize), timelion, toFunctionFactory(initialize)];
return [
asset,
filtersFunctionFactory(initialize),
timelionFunctionFactory(initialize),
toFunctionFactory(initialize),
];
}
173 changes: 90 additions & 83 deletions x-pack/legacy/plugins/canvas/public/functions/timelion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@

import { flatten } from 'lodash';
import moment from 'moment-timezone';
import chrome from 'ui/chrome';
import { npStart } from 'ui/new_platform';
import { TimeRange } from 'src/plugins/data/common';
import { ExpressionFunctionDefinition, DatatableRow } from 'src/plugins/expressions/public';
import { fetch } from '../../common/lib/fetch';
// @ts-ignore untyped local
import { buildBoolArray } from '../../server/lib/build_bool_array';
import { Datatable, Filter } from '../../types';
import { getFunctionHelp } from '../../i18n';
import { InitializeArguments } from './';

interface Arguments {
query: string;
Expand All @@ -30,110 +29,118 @@ interface Arguments {
* @param timeRange time range to parse
* @param timeZone time zone to do the parsing in
*/
function parseDateMath(timeRange: TimeRange, timeZone: string) {
function parseDateMath(
timeRange: TimeRange,
timeZone: string,
timefilter: InitializeArguments['timefilter']
) {
// the datemath plugin always parses dates by using the current default moment time zone.
// to use the configured time zone, we are switching just for the bounds calculation.
const defaultTimezone = moment().zoneName();
moment.tz.setDefault(timeZone);

const parsedRange = npStart.plugins.data.query.timefilter.timefilter.calculateBounds(timeRange);
const parsedRange = timefilter.calculateBounds(timeRange);

// reset default moment timezone
moment.tz.setDefault(defaultTimezone);

return parsedRange;
}

export function timelion(): ExpressionFunctionDefinition<
type TimelionFunction = ExpressionFunctionDefinition<
'timelion',
Filter,
Arguments,
Promise<Datatable>
> {
const { help, args: argHelp } = getFunctionHelp().timelion;
>;

return {
name: 'timelion',
type: 'datatable',
inputTypes: ['filter'],
help,
args: {
query: {
types: ['string'],
aliases: ['_', 'q'],
help: argHelp.query,
default: '".es(*)"',
},
interval: {
types: ['string'],
help: argHelp.interval,
default: 'auto',
},
from: {
types: ['string'],
help: argHelp.from,
default: 'now-1y',
},
to: {
types: ['string'],
help: argHelp.to,
default: 'now',
},
timezone: {
types: ['string'],
help: argHelp.timezone,
default: 'UTC',
export function timelionFunctionFactory(initialize: InitializeArguments): () => TimelionFunction {
return () => {
const { help, args: argHelp } = getFunctionHelp().timelion;

return {
name: 'timelion',
type: 'datatable',
inputTypes: ['filter'],
help,
args: {
query: {
types: ['string'],
aliases: ['_', 'q'],
help: argHelp.query,
default: '".es(*)"',
},
interval: {
types: ['string'],
help: argHelp.interval,
default: 'auto',
},
from: {
types: ['string'],
help: argHelp.from,
default: 'now-1y',
},
to: {
types: ['string'],
help: argHelp.to,
default: 'now',
},
timezone: {
types: ['string'],
help: argHelp.timezone,
default: 'UTC',
},
},
},
fn: (input, args): Promise<Datatable> => {
// Timelion requires a time range. Use the time range from the timefilter element in the
// workpad, if it exists. Otherwise fall back on the function args.
const timeFilter = input.and.find(and => and.type === 'time');
const range = timeFilter
? { min: timeFilter.from, max: timeFilter.to }
: parseDateMath({ from: args.from, to: args.to }, args.timezone);
fn: (input, args): Promise<Datatable> => {
// Timelion requires a time range. Use the time range from the timefilter element in the
// workpad, if it exists. Otherwise fall back on the function args.
const timeFilter = input.and.find(and => and.type === 'time');
const range = timeFilter
? { min: timeFilter.from, max: timeFilter.to }
: parseDateMath({ from: args.from, to: args.to }, args.timezone, initialize.timefilter);

const body = {
extended: {
es: {
filter: {
bool: {
must: buildBoolArray(input.and),
const body = {
extended: {
es: {
filter: {
bool: {
must: buildBoolArray(input.and),
},
},
},
},
},
sheet: [args.query],
time: {
from: range.min,
to: range.max,
interval: args.interval,
timezone: args.timezone,
},
};
sheet: [args.query],
time: {
from: range.min,
to: range.max,
interval: args.interval,
timezone: args.timezone,
},
};

return fetch(chrome.addBasePath(`/api/timelion/run`), {
method: 'POST',
responseType: 'json',
data: body,
}).then(resp => {
const seriesList = resp.data.sheet[0].list;
const rows = flatten(
seriesList.map((series: { data: any[]; label: string }) =>
series.data.map(row => ({ '@timestamp': row[0], value: row[1], label: series.label }))
)
) as DatatableRow[];
return fetch(initialize.prependBasePath(`/api/timelion/run`), {
method: 'POST',
responseType: 'json',
data: body,
}).then(resp => {
const seriesList = resp.data.sheet[0].list;
const rows = flatten(
seriesList.map((series: { data: any[]; label: string }) =>
series.data.map(row => ({ '@timestamp': row[0], value: row[1], label: series.label }))
)
) as DatatableRow[];

return {
type: 'datatable',
columns: [
{ name: '@timestamp', type: 'date' },
{ name: 'value', type: 'number' },
{ name: 'label', type: 'string' },
],
rows,
};
});
},
return {
type: 'datatable',
columns: [
{ name: '@timestamp', type: 'date' },
{ name: 'value', type: 'number' },
{ name: 'label', type: 'string' },
],
rows,
};
});
},
};
};
}
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/canvas/public/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ const shimCoreStart = {
};

const shimSetupPlugins: CanvasSetupDeps = {
data: npSetup.plugins.data,
expressions: npSetup.plugins.expressions,
home: npSetup.plugins.home,
usageCollection: npSetup.plugins.usageCollection,
};
const shimStartPlugins: CanvasStartDeps = {
...npStart.plugins,
Expand Down
21 changes: 16 additions & 5 deletions x-pack/legacy/plugins/canvas/public/lib/ui_metric.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,21 @@
* you may not use this file except in compliance with the Elastic License.
*/

import {
createUiStatsReporter,
METRIC_TYPE,
} from '../../../../../../src/legacy/core_plugins/ui_metric/public';
import { UiStatsMetricType, METRIC_TYPE } from '@kbn/analytics';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/public';

export const trackCanvasUiMetric = createUiStatsReporter('canvas');
export { METRIC_TYPE };

export let reportUiStats: UsageCollectionSetup['reportUiStats'] | undefined;

export function init(_reportUiStats: UsageCollectionSetup['reportUiStats']): void {
reportUiStats = _reportUiStats;
}

export function trackCanvasUiMetric(metricType: UiStatsMetricType, name: string | string[]) {
if (!reportUiStats) {
return;
}

reportUiStats('canvas', metricType, name);
}
15 changes: 13 additions & 2 deletions x-pack/legacy/plugins/canvas/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ import { HomePublicPluginSetup } from '../../../../../src/plugins/home/public';
import { initLoadingIndicator } from './lib/loading_indicator';
import { featureCatalogueEntry } from './feature_catalogue_entry';
import { ExpressionsSetup, ExpressionsStart } from '../../../../../src/plugins/expressions/public';
import { DataPublicPluginSetup } from '../../../../../src/plugins/data/public';
import { UiActionsStart } from '../../../../../src/plugins/ui_actions/public';
import { EmbeddableStart } from '../../../../../src/plugins/embeddable/public';
import { UsageCollectionSetup } from '../../../../../src/plugins/usage_collection/public';
import { Start as InspectorStart } from '../../../../../src/plugins/inspector/public';
// @ts-ignore untyped local
import { argTypeSpecs } from './expression_types/arg_types';
Expand All @@ -20,22 +22,25 @@ import { legacyRegistries } from './legacy_plugin_support';
import { getPluginApi, CanvasApi } from './plugin_api';
import { initFunctions } from './functions';
import { CanvasSrcPlugin } from '../canvas_plugin_src/plugin';
export { CoreStart };
export { CoreStart, CoreSetup };

/**
* These are the private interfaces for the services your plugin depends on.
* @internal
*/
// This interface will be built out as we require other plugins for setup
export interface CanvasSetupDeps {
data: DataPublicPluginSetup;
expressions: ExpressionsSetup;
home: HomePublicPluginSetup;
usageCollection?: UsageCollectionSetup;
}

export interface CanvasStartDeps {
embeddable: EmbeddableStart;
expressions: ExpressionsStart;
inspector: InspectorStart;

uiActions: UiActionsStart;
__LEGACY: {
absoluteToParsedUrl: (url: string, basePath: string) => any;
Expand Down Expand Up @@ -94,7 +99,13 @@ export class CanvasPlugin
canvasApi.addTypes(legacyRegistries.types.getOriginalFns());

// Register core canvas stuff
canvasApi.addFunctions(initFunctions({ typesRegistry: plugins.expressions.__LEGACY.types }));
canvasApi.addFunctions(
initFunctions({
timefilter: plugins.data.query.timefilter.timefilter,
prependBasePath: core.http.basePath.prepend,
typesRegistry: plugins.expressions.__LEGACY.types,
})
);
canvasApi.addArgumentUIs(argTypeSpecs);
canvasApi.addTransitions(transitions);

Expand Down