[Watcher] Use fixed_interval instead of interval (#113527)

This commit is contained in:
Sébastien Loix 2021-10-09 14:53:55 +01:00 committed by GitHub
parent cbc4f5235c
commit 961fe752c5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 232 additions and 132 deletions

View file

@ -515,7 +515,6 @@ export const useField = <T, FormType = FormData, I = T>(
if (resetValue) {
hasBeenReset.current = true;
const newValue = deserializeValue(updatedDefaultValue ?? defaultValue);
// updateStateIfMounted('value', newValue);
setValue(newValue);
return newValue;
}

View file

@ -9,6 +9,7 @@ import React from 'react';
import { of } from 'rxjs';
import { ComponentType } from 'enzyme';
import { LocationDescriptorObject } from 'history';
import {
docLinksServiceMock,
uiSettingsServiceMock,
@ -17,6 +18,7 @@ import {
scopedHistoryMock,
} from '../../../../../../src/core/public/mocks';
import { AppContextProvider } from '../../../public/application/app_context';
import { AppDeps } from '../../../public/application/app';
import { LicenseStatus } from '../../../common/types/license_status';
class MockTimeBuckets {
@ -35,7 +37,7 @@ history.createHref.mockImplementation((location: LocationDescriptorObject) => {
return `${location.pathname}${location.search ? '?' + location.search : ''}`;
});
export const mockContextValue = {
export const mockContextValue: AppDeps = {
licenseStatus$: of<LicenseStatus>({ valid: true }),
docLinks: docLinksServiceMock.createStartContract(),
setBreadcrumbs: jest.fn(),

View file

@ -11,7 +11,7 @@ import { setup as watchCreateJsonSetup } from './watch_create_json.helpers';
import { setup as watchCreateThresholdSetup } from './watch_create_threshold.helpers';
import { setup as watchEditSetup } from './watch_edit.helpers';
export { nextTick, getRandomString, findTestSubject, TestBed } from '@kbn/test/jest';
export { getRandomString, findTestSubject, TestBed } from '@kbn/test/jest';
export { wrapBodyResponse, unwrapBodyResponse } from './body_response';
export { setupEnvironment } from './setup_environment';

View file

@ -7,6 +7,7 @@
import axios from 'axios';
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
import { init as initHttpRequests } from './http_requests';
import { setHttpClient, setSavedObjectsClient } from '../../../public/application/lib/api';

View file

@ -93,7 +93,7 @@ export type TestSubjects =
| 'toEmailAddressInput'
| 'triggerIntervalSizeInput'
| 'watchActionAccordion'
| 'watchActionAccordion.mockComboBox'
| 'watchActionAccordion.toEmailAddressInput'
| 'watchActionsPanel'
| 'watchThresholdButton'
| 'watchThresholdInput'

View file

@ -7,7 +7,7 @@
import { act } from 'react-dom/test-utils';
import { registerTestBed, findTestSubject, TestBed, TestBedConfig, nextTick } from '@kbn/test/jest';
import { registerTestBed, findTestSubject, TestBed, TestBedConfig } from '@kbn/test/jest';
import { WatchList } from '../../../public/application/sections/watch_list/components/watch_list';
import { ROUTES, REFRESH_INTERVALS } from '../../../common/constants';
import { withAppContext } from './app_context.mock';
@ -24,7 +24,6 @@ const initTestBed = registerTestBed(withAppContext(WatchList), testBedConfig);
export interface WatchListTestBed extends TestBed<WatchListTestSubjects> {
actions: {
selectWatchAt: (index: number) => void;
clickWatchAt: (index: number) => void;
clickWatchActionAt: (index: number, action: 'delete' | 'edit') => void;
searchWatches: (term: string) => void;
advanceTimeToTableRefresh: () => Promise<void>;
@ -45,18 +44,6 @@ export const setup = async (): Promise<WatchListTestBed> => {
checkBox.simulate('change', { target: { checked: true } });
};
const clickWatchAt = async (index: number) => {
const { rows } = testBed.table.getMetaData('watchesTable');
const watchesLink = findTestSubject(rows[index].reactWrapper, 'watchesLink');
await act(async () => {
const { href } = watchesLink.props();
testBed.router.navigateTo(href!);
await nextTick();
testBed.component.update();
});
};
const clickWatchActionAt = async (index: number, action: 'delete' | 'edit') => {
const { component, table } = testBed;
const { rows } = table.getMetaData('watchesTable');
@ -95,7 +82,6 @@ export const setup = async (): Promise<WatchListTestBed> => {
...testBed,
actions: {
selectWatchAt,
clickWatchAt,
clickWatchActionAt,
searchWatches,
advanceTimeToTableRefresh,

View file

@ -7,7 +7,7 @@
import { act } from 'react-dom/test-utils';
import { registerTestBed, findTestSubject, TestBed, TestBedConfig, delay } from '@kbn/test/jest';
import { registerTestBed, findTestSubject, TestBed, TestBedConfig } from '@kbn/test/jest';
import { WatchStatus } from '../../../public/application/sections/watch_status/components/watch_status';
import { ROUTES } from '../../../common/constants';
import { WATCH_ID } from './jest_constants';
@ -89,9 +89,8 @@ export const setup = async (): Promise<WatchStatusTestBed> => {
await act(async () => {
button.simulate('click');
await delay(100);
component.update();
});
component.update();
};
return {

View file

@ -9,7 +9,7 @@ import { act } from 'react-dom/test-utils';
import { getExecuteDetails } from '../../__fixtures__';
import { defaultWatch } from '../../public/application/models/watch';
import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers';
import { setupEnvironment, pageHelpers, wrapBodyResponse } from './helpers';
import { WatchCreateJsonTestBed } from './helpers/watch_create_json.helpers';
import { WATCH } from './helpers/jest_constants';
@ -19,19 +19,19 @@ describe('<JsonWatchEdit /> create route', () => {
const { server, httpRequestsMockHelpers } = setupEnvironment();
let testBed: WatchCreateJsonTestBed;
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
server.restore();
});
describe('on component mount', () => {
beforeEach(async () => {
testBed = await setup();
await act(async () => {
const { component } = testBed;
await nextTick();
component.update();
});
testBed.component.update();
});
test('should set the correct page title', () => {
@ -92,7 +92,6 @@ describe('<JsonWatchEdit /> create route', () => {
await act(async () => {
actions.clickSubmitButton();
await nextTick();
});
const latestRequest = server.requests[server.requests.length - 1];
@ -141,9 +140,8 @@ describe('<JsonWatchEdit /> create route', () => {
await act(async () => {
actions.clickSubmitButton();
await nextTick();
component.update();
});
component.update();
expect(exists('sectionError')).toBe(true);
expect(find('sectionError').text()).toContain(error.message);
@ -169,7 +167,6 @@ describe('<JsonWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
const latestRequest = server.requests[server.requests.length - 1];
@ -230,9 +227,8 @@ describe('<JsonWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
component.update();
});
component.update();
const latestRequest = server.requests[server.requests.length - 1];

View file

@ -9,15 +9,10 @@ import React from 'react';
import { act } from 'react-dom/test-utils';
import axiosXhrAdapter from 'axios/lib/adapters/xhr';
import axios from 'axios';
import { getExecuteDetails } from '../../__fixtures__';
import { WATCH_TYPES } from '../../common/constants';
import {
setupEnvironment,
pageHelpers,
nextTick,
wrapBodyResponse,
unwrapBodyResponse,
} from './helpers';
import { setupEnvironment, pageHelpers, wrapBodyResponse, unwrapBodyResponse } from './helpers';
import { WatchCreateThresholdTestBed } from './helpers/watch_create_threshold.helpers';
const WATCH_NAME = 'my_test_watch';
@ -76,7 +71,9 @@ jest.mock('@elastic/eui', () => {
// which does not produce a valid component wrapper
EuiComboBox: (props: any) => (
<input
data-test-subj="mockComboBox"
data-test-subj={props['data-test-subj'] || 'mockComboBox'}
data-currentvalue={props.selectedOptions}
value={props.selectedOptions[0]?.value ?? ''}
onChange={(syntheticEvent: any) => {
props.onChange([syntheticEvent['0']]);
}}
@ -91,7 +88,12 @@ describe('<ThresholdWatchEdit /> create route', () => {
const { server, httpRequestsMockHelpers } = setupEnvironment();
let testBed: WatchCreateThresholdTestBed;
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
server.restore();
});
@ -99,7 +101,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
beforeEach(async () => {
testBed = await setup();
const { component } = testBed;
await nextTick();
component.update();
});
@ -159,46 +160,60 @@ describe('<ThresholdWatchEdit /> create route', () => {
test('it should enable the Create button and render additional content with valid fields', async () => {
const { form, find, component, exists } = testBed;
form.setInputValue('nameInput', 'my_test_watch');
find('mockComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
form.setInputValue('watchTimeFieldSelect', '@timestamp');
expect(find('saveWatchButton').props().disabled).toBe(true);
await act(async () => {
await nextTick();
component.update();
form.setInputValue('nameInput', 'my_test_watch');
find('indicesComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
form.setInputValue('watchTimeFieldSelect', '@timestamp');
});
component.update();
expect(find('saveWatchButton').props().disabled).toEqual(false);
expect(find('saveWatchButton').props().disabled).toBe(false);
expect(find('watchConditionTitle').text()).toBe('Match the following condition');
expect(exists('watchVisualizationChart')).toBe(true);
expect(exists('watchActionsPanel')).toBe(true);
});
// Looks like there is an issue with using 'mockComboBox'.
describe.skip('watch conditions', () => {
beforeEach(() => {
const { form, find } = testBed;
describe('watch conditions', () => {
beforeEach(async () => {
const { form, find, component } = testBed;
// Name, index and time fields are required before the watch condition expression renders
form.setInputValue('nameInput', 'my_test_watch');
act(() => {
find('mockComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
await act(async () => {
form.setInputValue('nameInput', 'my_test_watch');
find('indicesComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
form.setInputValue('watchTimeFieldSelect', '@timestamp');
});
form.setInputValue('watchTimeFieldSelect', '@timestamp');
component.update();
});
test('should require a threshold value', () => {
const { form, find } = testBed;
test('should require a threshold value', async () => {
const { form, find, component } = testBed;
// Display the threshold pannel
act(() => {
find('watchThresholdButton').simulate('click');
});
component.update();
await act(async () => {
// Provide invalid value
form.setInputValue('watchThresholdInput', '');
});
// We need to wait for the debounced validation to be triggered and update the DOM
jest.advanceTimersByTime(500);
component.update();
expect(form.getErrorsMessages()).toContain('A value is required.');
await act(async () => {
// Provide valid value
form.setInputValue('watchThresholdInput', '0');
});
expect(form.getErrorsMessages()).toContain('A value is required.');
component.update();
// No need to wait as the validation errors are cleared whenever the field changes
expect(form.getErrorsMessages().length).toEqual(0);
});
});
@ -209,14 +224,12 @@ describe('<ThresholdWatchEdit /> create route', () => {
const { form, find, component } = testBed;
// Set up valid fields needed for actions component to render
form.setInputValue('nameInput', WATCH_NAME);
find('mockComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
form.setInputValue('watchTimeFieldSelect', WATCH_TIME_FIELD);
await act(async () => {
await nextTick();
component.update();
form.setInputValue('nameInput', WATCH_NAME);
find('indicesComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]);
form.setInputValue('watchTimeFieldSelect', WATCH_TIME_FIELD);
});
component.update();
});
test('should simulate a logging action', async () => {
@ -240,7 +253,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -303,7 +315,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -366,7 +377,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -431,15 +441,14 @@ describe('<ThresholdWatchEdit /> create route', () => {
expect(exists('watchActionAccordion')).toBe(true);
// Provide valid fields and verify
find('watchActionAccordion.mockComboBox').simulate('change', [
find('watchActionAccordion.toEmailAddressInput').simulate('change', [
{ label: EMAIL_RECIPIENT, value: EMAIL_RECIPIENT },
]); // Using mocked EuiComboBox
]);
form.setInputValue('emailSubjectInput', EMAIL_SUBJECT);
form.setInputValue('emailBodyInput', EMAIL_BODY);
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -532,7 +541,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -621,7 +629,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -702,7 +709,6 @@ describe('<ThresholdWatchEdit /> create route', () => {
await act(async () => {
actions.clickSimulateButton();
await nextTick();
});
// Verify request
@ -753,20 +759,66 @@ describe('<ThresholdWatchEdit /> create route', () => {
});
});
describe('watch visualize data payload', () => {
test('should send the correct payload', async () => {
const { form, find, component } = testBed;
// Set up required fields
await act(async () => {
form.setInputValue('nameInput', WATCH_NAME);
find('indicesComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]);
form.setInputValue('watchTimeFieldSelect', WATCH_TIME_FIELD);
});
component.update();
const latestReqToGetVisualizeData = server.requests.find(
(req) => req.method === 'POST' && req.url === '/api/watcher/watch/visualize'
);
if (!latestReqToGetVisualizeData) {
throw new Error(`No request found to fetch visualize data.`);
}
const requestBody = unwrapBodyResponse(latestReqToGetVisualizeData.requestBody);
expect(requestBody.watch).toEqual({
id: requestBody.watch.id, // id is dynamic
name: 'my_test_watch',
type: 'threshold',
isNew: true,
isActive: true,
actions: [],
index: ['index1'],
timeField: '@timestamp',
triggerIntervalSize: 1,
triggerIntervalUnit: 'm',
aggType: 'count',
termSize: 5,
termOrder: 'desc',
thresholdComparator: '>',
timeWindowSize: 5,
timeWindowUnit: 'm',
hasTermsAgg: false,
threshold: 1000,
});
expect(requestBody.options.interval).toBeDefined();
});
});
describe('form payload', () => {
test('should send the correct payload', async () => {
const { form, find, component, actions } = testBed;
// Set up required fields
form.setInputValue('nameInput', WATCH_NAME);
find('mockComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]); // Using mocked EuiComboBox
form.setInputValue('watchTimeFieldSelect', WATCH_TIME_FIELD);
await act(async () => {
form.setInputValue('nameInput', WATCH_NAME);
find('indicesComboBox').simulate('change', [{ label: 'index1', value: 'index1' }]);
form.setInputValue('watchTimeFieldSelect', WATCH_TIME_FIELD);
});
component.update();
await act(async () => {
await nextTick();
component.update();
actions.clickSubmitButton();
await nextTick();
});
// Verify request

View file

@ -12,7 +12,7 @@ import { getRandomString } from '@kbn/test/jest';
import { getWatch } from '../../__fixtures__';
import { defaultWatch } from '../../public/application/models/watch';
import { setupEnvironment, pageHelpers, nextTick, wrapBodyResponse } from './helpers';
import { setupEnvironment, pageHelpers, wrapBodyResponse } from './helpers';
import { WatchEditTestBed } from './helpers/watch_edit.helpers';
import { WATCH } from './helpers/jest_constants';
@ -41,7 +41,12 @@ describe('<WatchEdit />', () => {
const { server, httpRequestsMockHelpers } = setupEnvironment();
let testBed: WatchEditTestBed;
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
server.restore();
});
@ -50,11 +55,7 @@ describe('<WatchEdit />', () => {
httpRequestsMockHelpers.setLoadWatchResponse(WATCH);
testBed = await setup();
await act(async () => {
await nextTick();
testBed.component.update();
});
testBed.component.update();
});
describe('on component mount', () => {
@ -87,7 +88,6 @@ describe('<WatchEdit />', () => {
await act(async () => {
actions.clickSubmitButton();
await nextTick();
});
const latestRequest = server.requests[server.requests.length - 1];
@ -141,12 +141,7 @@ describe('<WatchEdit />', () => {
httpRequestsMockHelpers.setLoadWatchResponse({ watch });
testBed = await setup();
await act(async () => {
const { component } = testBed;
await nextTick();
component.update();
});
testBed.component.update();
});
describe('on component mount', () => {
@ -172,7 +167,6 @@ describe('<WatchEdit />', () => {
await act(async () => {
actions.clickSubmitButton();
await nextTick();
});
const latestRequest = server.requests[server.requests.length - 1];

View file

@ -9,7 +9,7 @@ import { act } from 'react-dom/test-utils';
import moment from 'moment';
import { getWatchHistory } from '../../__fixtures__';
import { ROUTES, WATCH_STATES, ACTION_STATES } from '../../common/constants';
import { setupEnvironment, pageHelpers, nextTick } from './helpers';
import { setupEnvironment, pageHelpers } from './helpers';
import { WatchStatusTestBed } from './helpers/watch_status.helpers';
import { WATCH } from './helpers/jest_constants';
@ -43,7 +43,12 @@ describe('<WatchStatus />', () => {
const { server, httpRequestsMockHelpers } = setupEnvironment();
let testBed: WatchStatusTestBed;
beforeAll(() => {
jest.useFakeTimers();
});
afterAll(() => {
jest.useRealTimers();
server.restore();
});
@ -53,11 +58,7 @@ describe('<WatchStatus />', () => {
httpRequestsMockHelpers.setLoadWatchHistoryResponse(watchHistoryItems);
testBed = await setup();
await act(async () => {
await nextTick();
testBed.component.update();
});
testBed.component.update();
});
test('should set the correct page title', () => {
@ -175,9 +176,8 @@ describe('<WatchStatus />', () => {
await act(async () => {
confirmButton!.click();
await nextTick();
component.update();
});
component.update();
const latestRequest = server.requests[server.requests.length - 1];

View file

@ -8,13 +8,11 @@
import { i18n } from '@kbn/i18n';
import { CoreSetup, Plugin, CoreStart, Capabilities } from 'kibana/public';
import { first, map, skip } from 'rxjs/operators';
import { Subject, combineLatest } from 'rxjs';
import { FeatureCatalogueCategory } from '../../../../src/plugins/home/public';
import { LicenseStatus } from '../common/types/license_status';
import { ILicense } from '../../licensing/public';
import { LicenseStatus } from '../common/types/license_status';
import { PLUGIN } from '../common/constants';
import { Dependencies } from './types';

View file

@ -0,0 +1,36 @@
/*
* 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 { getIntervalType } from './get_interval_type';
describe('get interval type', () => {
test('should detect fixed intervals', () => {
['1ms', '1s', '1m', '1h', '1d', '21s', '7d'].forEach((interval) => {
const intervalDetected = getIntervalType(interval);
try {
expect(intervalDetected).toBe('fixed_interval');
} catch (e) {
throw new Error(
`Expected [${interval}] to be a fixed interval but got [${intervalDetected}]`
);
}
});
});
test('should detect calendar intervals', () => {
['1w', '1M', '1q', '1y'].forEach((interval) => {
const intervalDetected = getIntervalType(interval);
try {
expect(intervalDetected).toBe('calendar_interval');
} catch (e) {
throw new Error(
`Expected [${interval}] to be a calendar interval but got [${intervalDetected}]`
);
}
});
});
});

View file

@ -0,0 +1,21 @@
/*
* 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.
*/
/**
* Since 8.x we use the "fixed_interval" or "calendar_interval" parameter instead
* of the less precise "interval". This helper parse the interval and return its type.
* @param interval Interval value (e.g. "1d", "1w"...)
*/
export const getIntervalType = (interval: string): 'fixed_interval' | 'calendar_interval' => {
// We will consider all interval as fixed except if they are
// weekly (w), monthly (M), quarterly (q) or yearly (y)
const intervalMetric = interval.charAt(interval.length - 1);
if (['w', 'M', 'q', 'y'].includes(intervalMetric)) {
return 'calendar_interval';
}
return 'fixed_interval';
};

View file

@ -0,0 +1,8 @@
/*
* 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.
*/
export { getIntervalType } from './get_interval_type';

View file

@ -6,8 +6,10 @@
*/
import { cloneDeep } from 'lodash';
import { buildInput } from '../../../../common/lib/serialization';
import { AGG_TYPES } from '../../../../common/constants';
import { getIntervalType } from '../lib/get_interval_type';
/*
input.search.request.body.query.bool.filter.range
@ -22,17 +24,6 @@ function buildRange({ rangeFrom, rangeTo, timeField }) {
};
}
function buildDateAgg({ field, interval, timeZone }) {
return {
date_histogram: {
field,
interval,
time_zone: timeZone,
min_doc_count: 1,
},
};
}
function buildAggsCount(body, dateAgg) {
return {
dateAgg,
@ -93,7 +84,7 @@ function buildAggs(body, { aggType, termField }, dateAgg) {
}
}
export function buildVisualizeQuery(watch, visualizeOptions) {
export function buildVisualizeQuery(watch, visualizeOptions, kibanaVersion) {
const {
index,
timeWindowSize,
@ -117,11 +108,22 @@ export function buildVisualizeQuery(watch, visualizeOptions) {
termOrder,
});
const body = watchInput.search.request.body;
const dateAgg = buildDateAgg({
field: watch.timeField,
interval: visualizeOptions.interval,
timeZone: visualizeOptions.timezone,
});
const dateAgg = {
date_histogram: {
field: watch.timeField,
time_zone: visualizeOptions.timezone,
min_doc_count: 1,
},
};
if (kibanaVersion.major < 8) {
// In 7.x we use the deprecated "interval" in date_histogram agg
dateAgg.date_histogram.interval = visualizeOptions.interval;
} else {
// From 8.x we use the more precise "fixed_interval" or "calendar_interval"
const intervalType = getIntervalType(visualizeOptions.interval);
dateAgg.date_histogram[intervalType] = visualizeOptions.interval;
}
// override the query range
body.query.bool.filter.range = buildRange({

View file

@ -48,8 +48,8 @@ export class ThresholdWatch extends BaseWatch {
return serializeThresholdWatch(this);
}
getVisualizeQuery(visualizeOptions) {
return buildVisualizeQuery(this, visualizeOptions);
getVisualizeQuery(visualizeOptions, kibanaVersion) {
return buildVisualizeQuery(this, visualizeOptions, kibanaVersion);
}
formatVisualizeData(results) {

View file

@ -6,7 +6,7 @@
*/
import { i18n } from '@kbn/i18n';
import { SemVer } from 'semver';
import { CoreStart, CoreSetup, Logger, Plugin, PluginInitializerContext } from 'kibana/server';
import { PLUGIN, INDEX_NAMES } from '../common/constants';
@ -27,17 +27,19 @@ export class WatcherServerPlugin implements Plugin<void, void, any, any> {
private readonly license: License;
private readonly logger: Logger;
constructor(ctx: PluginInitializerContext) {
constructor(private ctx: PluginInitializerContext) {
this.logger = ctx.logger.get();
this.license = new License();
}
setup({ http, getStartServices }: CoreSetup, { licensing, features }: SetupDependencies) {
setup({ http }: CoreSetup, { features }: SetupDependencies) {
this.license.setup({
pluginName: PLUGIN.getI18nName(i18n),
logger: this.logger,
});
const kibanaVersion = new SemVer(this.ctx.env.packageInfo.version);
const router = http.createRouter();
const routeDependencies: RouteDependencies = {
router,
@ -45,6 +47,7 @@ export class WatcherServerPlugin implements Plugin<void, void, any, any> {
lib: {
handleEsError,
},
kibanaVersion,
};
features.registerElasticsearchFeature({

View file

@ -37,6 +37,7 @@ export function registerVisualizeRoute({
router,
license,
lib: { handleEsError },
kibanaVersion,
}: RouteDependencies) {
router.post(
{
@ -48,7 +49,7 @@ export function registerVisualizeRoute({
license.guardApiRoute(async (ctx, request, response) => {
const watch = Watch.fromDownstreamJson(request.body.watch);
const options = VisualizeOptions.fromDownstreamJson(request.body.options);
const body = watch.getVisualizeQuery(options);
const body = watch.getVisualizeQuery(options, kibanaVersion);
try {
const hits = await fetchVisualizeData(ctx.core.elasticsearch.client, watch.index, body);

View file

@ -5,6 +5,7 @@
* 2.0.
*/
import { SemVer } from 'semver';
import type { IRouter } from 'src/core/server';
import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server';
@ -33,4 +34,5 @@ export interface RouteDependencies {
lib: {
handleEsError: typeof handleEsError;
};
kibanaVersion: SemVer;
}