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

[TSVB] use new Search API for rollup search #83275

Merged
merged 14 commits into from
Nov 18, 2020
Merged
1 change: 1 addition & 0 deletions .github/CODEOWNERS
Validating CODEOWNERS rules …
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
/x-pack/plugins/discover_enhanced/ @elastic/kibana-app
/x-pack/plugins/lens/ @elastic/kibana-app
/x-pack/plugins/graph/ @elastic/kibana-app
/x-pack/plugins/vis_type_timeseries_enhanced/ @elastic/kibana-app
/src/plugins/advanced_settings/ @elastic/kibana-app
/src/plugins/charts/ @elastic/kibana-app
/src/plugins/discover/ @elastic/kibana-app
Expand Down
4 changes: 4 additions & 0 deletions docs/developer/plugin-list.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -554,6 +554,10 @@ in their infrastructure.
|NOTE: This plugin contains implementation of URL drilldown. For drilldowns infrastructure code refer to ui_actions_enhanced plugin.


|{kib-repo}blob/{branch}/x-pack/plugins/vis_type_timeseries_enhanced/README.md[visTypeTimeseriesEnhanced]
|The vis_type_timeseries_enhanced plugin is the x-pack counterpart to the OSS vis_type_timeseries plugin.


|{kib-repo}blob/{branch}/x-pack/plugins/watcher/README.md[watcher]
|This plugins adopts some conventions in addition to or in place of conventions in Kibana (at the time of the plugin's creation):

Expand Down
4 changes: 3 additions & 1 deletion src/plugins/vis_type_timeseries/server/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ export {
AbstractSearchStrategy,
ReqFacade,
} from './lib/search_strategies/strategies/abstract_search_strategy';
// @ts-ignore

export { VisPayload } from '../common/types';

export { DefaultSearchCapabilities } from './lib/search_strategies/default_search_capabilities';

export function plugin(initializerContext: PluginInitializerContext) {
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/vis_type_timeseries/server/lib/get_fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ export async function getFields(
// removes the need to refactor many layers of dependencies on "req", and instead just augments the top
// level object passed from here. The layers should be refactored fully at some point, but for now
// this works and we are still using the New Platform services for these vis data portions.
const reqFacade: ReqFacade = {
const reqFacade: ReqFacade<{}> = {
requestContext,
...request,
framework,
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/vis_type_timeseries/server/lib/get_vis_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export function getVisData(
// removes the need to refactor many layers of dependencies on "req", and instead just augments the top
// level object passed from here. The layers should be refactored fully at some point, but for now
// this works and we are still using the New Platform services for these vis data portions.
const reqFacade: ReqFacade = {
const reqFacade: ReqFacade<GetVisDataOptions> = {
requestContext,
...request,
framework,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
* under the License.
*/
import { DefaultSearchCapabilities } from './default_search_capabilities';
import { ReqFacade } from './strategies/abstract_search_strategy';
import { VisPayload } from '../../../common/types';

describe('DefaultSearchCapabilities', () => {
let defaultSearchCapabilities;
let req;
let defaultSearchCapabilities: DefaultSearchCapabilities;
let req: ReqFacade<VisPayload>;

beforeEach(() => {
req = {};
req = {} as ReqFacade<VisPayload>;
defaultSearchCapabilities = new DefaultSearchCapabilities(req);
});

Expand All @@ -45,13 +47,13 @@ describe('DefaultSearchCapabilities', () => {
});

test('should return Search Timezone', () => {
defaultSearchCapabilities.request = {
defaultSearchCapabilities.request = ({
payload: {
timerange: {
timezone: 'UTC',
},
},
};
} as unknown) as ReqFacade<VisPayload>;

expect(defaultSearchCapabilities.searchTimezone).toEqual('UTC');
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,77 +16,80 @@
* specific language governing permissions and limitations
* under the License.
*/
import { Unit } from '@elastic/datemath';
import {
convertIntervalToUnit,
parseInterval,
getSuitableUnit,
} from '../vis_data/helpers/unit_to_seconds';
import { RESTRICTIONS_KEYS } from '../../../common/ui_restrictions';
import { ReqFacade } from './strategies/abstract_search_strategy';
import { VisPayload } from '../../../common/types';

const getTimezoneFromRequest = (request) => {
const getTimezoneFromRequest = (request: ReqFacade<VisPayload>) => {
return request.payload.timerange.timezone;
};

export class DefaultSearchCapabilities {
constructor(request, fieldsCapabilities = {}) {
this.request = request;
this.fieldsCapabilities = fieldsCapabilities;
}
constructor(
public request: ReqFacade<VisPayload>,
public fieldsCapabilities: Record<string, any> = {}
) {}

get defaultTimeInterval() {
public get defaultTimeInterval() {
return null;
}

get whiteListedMetrics() {
public get whiteListedMetrics() {
return this.createUiRestriction();
}

get whiteListedGroupByFields() {
public get whiteListedGroupByFields() {
return this.createUiRestriction();
}

get whiteListedTimerangeModes() {
public get whiteListedTimerangeModes() {
return this.createUiRestriction();
}

get uiRestrictions() {
public get uiRestrictions() {
return {
[RESTRICTIONS_KEYS.WHITE_LISTED_METRICS]: this.whiteListedMetrics,
[RESTRICTIONS_KEYS.WHITE_LISTED_GROUP_BY_FIELDS]: this.whiteListedGroupByFields,
[RESTRICTIONS_KEYS.WHITE_LISTED_TIMERANGE_MODES]: this.whiteListedTimerangeModes,
};
}

get searchTimezone() {
public get searchTimezone() {
return getTimezoneFromRequest(this.request);
}

createUiRestriction(restrictionsObject) {
createUiRestriction(restrictionsObject?: Record<string, any>) {
return {
'*': !restrictionsObject,
...(restrictionsObject || {}),
};
}

parseInterval(interval) {
parseInterval(interval: string) {
return parseInterval(interval);
}

getSuitableUnit(intervalInSeconds) {
getSuitableUnit(intervalInSeconds: string | number) {
return getSuitableUnit(intervalInSeconds);
}

convertIntervalToUnit(intervalString, unit) {
convertIntervalToUnit(intervalString: string, unit: Unit) {
const parsedInterval = this.parseInterval(intervalString);

if (parsedInterval.unit !== unit) {
if (parsedInterval?.unit !== unit) {
return convertIntervalToUnit(intervalString, unit);
}

return parsedInterval;
}

getValidTimeInterval(intervalString) {
getValidTimeInterval(intervalString: string) {
// Default search capabilities doesn't have any restrictions for the interval string
return intervalString;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,10 @@ import { DefaultSearchCapabilities } from './default_search_capabilities';

class MockSearchStrategy extends AbstractSearchStrategy {
checkForViability() {
return {
return Promise.resolve({
isViable: true,
capabilities: {},
};
});
}
}

Expand Down Expand Up @@ -65,7 +65,7 @@ describe('SearchStrategyRegister', () => {
});

test('should add a strategy if it is an instance of AbstractSearchStrategy', () => {
const anotherSearchStrategy = new MockSearchStrategy('es');
const anotherSearchStrategy = new MockSearchStrategy();
const addedStrategies = registry.addStrategy(anotherSearchStrategy);

expect(addedStrategies.length).toEqual(2);
Expand All @@ -75,7 +75,7 @@ describe('SearchStrategyRegister', () => {
test('should return a MockSearchStrategy instance', async () => {
const req = {};
const indexPattern = '*';
const anotherSearchStrategy = new MockSearchStrategy('es');
const anotherSearchStrategy = new MockSearchStrategy();
registry.addStrategy(anotherSearchStrategy);

const { searchStrategy, capabilities } = (await registry.getViableStrategy(req, indexPattern))!;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,8 @@ export interface ReqFacade<T = unknown> extends FakeRequest {
getEsShardTimeout: () => Promise<number>;
}

export class AbstractSearchStrategy {
public indexType?: string;
public additionalParams: any;

constructor(type?: string, additionalParams: any = {}) {
this.indexType = type;
this.additionalParams = additionalParams;
}

async search(req: ReqFacade<VisPayload>, bodies: any[], options = {}) {
export abstract class AbstractSearchStrategy {
async search(req: ReqFacade<VisPayload>, bodies: any[], indexType?: string) {
const requests: any[] = [];
const { sessionId } = req.payload;

Expand All @@ -64,15 +56,13 @@ export class AbstractSearchStrategy {
req.requestContext
.search!.search(
{
indexType,
params: {
...body,
...this.additionalParams,
},
indexType: this.indexType,
},
{
sessionId,
...options,
}
)
.toPromise()
Expand All @@ -81,19 +71,23 @@ export class AbstractSearchStrategy {
return Promise.all(requests);
}

async getFieldsForWildcard(req: ReqFacade, indexPattern: string, capabilities: any) {
checkForViability(
req: ReqFacade<VisPayload>,
indexPattern: string
): Promise<{ isViable: boolean; capabilities: unknown }> {
throw new TypeError('Must override method');
}

async getFieldsForWildcard<TPayload = unknown>(
req: ReqFacade<TPayload>,
indexPattern: string,
capabilities?: unknown
) {
const { indexPatternsService } = req.pre;

return await indexPatternsService!.getFieldsForWildcard({
pattern: indexPattern,
fieldCapsOptions: { allow_no_indices: true },
});
}

checkForViability(
req: ReqFacade,
indexPattern: string
): { isViable: boolean; capabilities: any } {
throw new TypeError('Must override method');
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,15 @@
* under the License.
*/
import { DefaultSearchStrategy } from './default_search_strategy';
import { ReqFacade } from './abstract_search_strategy';
import { VisPayload } from '../../../../common/types';

describe('DefaultSearchStrategy', () => {
let defaultSearchStrategy;
let req;
let defaultSearchStrategy: DefaultSearchStrategy;
let req: ReqFacade<VisPayload>;

beforeEach(() => {
req = {};
req = {} as ReqFacade<VisPayload>;
defaultSearchStrategy = new DefaultSearchStrategy();
});

Expand All @@ -34,8 +36,8 @@ describe('DefaultSearchStrategy', () => {
expect(defaultSearchStrategy.getFieldsForWildcard).toBeDefined();
});

test('should check a strategy for viability', () => {
const value = defaultSearchStrategy.checkForViability(req);
test('should check a strategy for viability', async () => {
const value = await defaultSearchStrategy.checkForViability(req);

expect(value.isViable).toBe(true);
expect(value.capabilities).toEqual({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@
* under the License.
*/

import { AbstractSearchStrategy } from './abstract_search_strategy';
import { AbstractSearchStrategy, ReqFacade } from './abstract_search_strategy';
import { DefaultSearchCapabilities } from '../default_search_capabilities';
import { VisPayload } from '../../../../common/types';

export class DefaultSearchStrategy extends AbstractSearchStrategy {
name = 'default';

checkForViability(req) {
return {
checkForViability(req: ReqFacade<VisPayload>) {
return Promise.resolve({
isViable: true,
capabilities: new DefaultSearchCapabilities(req),
};
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,18 @@ const calculateBucketData = (timeInterval, capabilities) => {
}

// Check decimal
if (parsedInterval.value % 1 !== 0) {
if (parsedInterval && parsedInterval.value % 1 !== 0) {
if (parsedInterval.unit !== 'ms') {
const { value, unit } = convertIntervalToUnit(
const converted = convertIntervalToUnit(
intervalString,
ASCENDING_UNIT_ORDER[ASCENDING_UNIT_ORDER.indexOf(parsedInterval.unit) - 1]
);

intervalString = value + unit;
if (converted) {
intervalString = converted.value + converted.unit;
}

intervalString = undefined;
} else {
intervalString = '1ms';
}
Expand Down
Loading