Skip to content

Commit

Permalink
[Reporting] Migrate server-side usage collector (elastic#67233)
Browse files Browse the repository at this point in the history
* [Reporting] Migrate server/usage

* fix import

* polish

* prefer inferring return type

Co-authored-by: Elastic Machine <[email protected]>
  • Loading branch information
tsullivan and elasticmachine committed May 27, 2020
1 parent 79278c7 commit 68dc5dd
Show file tree
Hide file tree
Showing 8 changed files with 77 additions and 56 deletions.
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/reporting/server/legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { Legacy } from 'kibana';
import { take } from 'rxjs/operators';
import { PluginInitializerContext } from 'src/core/server';
import { ReportingPluginSpecOptions } from '../';
import { LicensingPluginSetup } from '../../../../plugins/licensing/server';
import { PluginsSetup } from '../../../../plugins/reporting/server';
import { SecurityPluginSetup } from '../../../../plugins/security/server';
import { buildConfig } from './config';
Expand Down Expand Up @@ -43,6 +44,7 @@ export const legacyInit = async (
);
await pluginInstance.setup(coreSetup, {
elasticsearch: coreSetup.elasticsearch,
licensing: server.newPlatform.setup.plugins.licensing as LicensingPluginSetup,
security: server.newPlatform.setup.plugins.security as SecurityPluginSetup,
usageCollection: server.newPlatform.setup.plugins.usageCollection,
__LEGACY,
Expand Down
2 changes: 2 additions & 0 deletions x-pack/legacy/plugins/reporting/server/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import * as Rx from 'rxjs';
// eslint-disable-next-line @kbn/eslint/no-restricted-paths
import { DataPluginStart } from 'src/plugins/data/server/plugin';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { LicensingPluginSetup } from '../../../../plugins/licensing/server';
import { ReportingPluginSpecOptions } from '../';
import { CancellationToken } from '../../../../plugins/reporting/common';
import { JobStatus } from '../../../../plugins/reporting/common/types';
Expand Down Expand Up @@ -160,6 +161,7 @@ export type ScreenshotsObservableFn = ({

export interface ReportingSetupDeps {
elasticsearch: ElasticsearchServiceSetup;
licensing: LicensingPluginSetup;
security: SecurityPluginSetup;
usageCollection?: UsageCollectionSetup;
__LEGACY: LegacySetup;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main';
import { ExportTypesRegistry } from '../lib/export_types_registry';
import { FeaturesAvailability } from './';

/*
* Gets a handle to the Reporting export types registry and returns a few
Expand All @@ -21,10 +21,10 @@ export function getExportTypesHandler(exportTypesRegistry: ExportTypesRegistry)
* @param {Object} xpackInfo: xpack_main plugin info object
* @return {Object} availability of each export type
*/
getAvailability(xpackInfo: XPackMainPlugin['info']) {
getAvailability(featuresAvailability: FeaturesAvailability): { [exportType: string]: boolean } {
const exportTypesAvailability: { [exportType: string]: boolean } = {};
const xpackInfoAvailable = xpackInfo && xpackInfo.isAvailable();
const licenseType: string | undefined = xpackInfo.license.getType();
const xpackInfoAvailable = featuresAvailability && featuresAvailability.isAvailable();
const licenseType = featuresAvailability.license.getType();
if (!licenseType) {
throw new Error('No license type returned from XPackMainPlugin#info!');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
import { get } from 'lodash';
import { CallCluster } from 'src/legacy/core_plugins/elasticsearch';
import { ReportingConfig } from '../';
import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main';
import { ExportTypesRegistry } from '../lib/export_types_registry';
import { GetLicense } from './';
import { decorateRangeStats } from './decorate_range_stats';
import { getExportTypesHandler } from './get_export_type_handler';
import {
AggregationResultBuckets,
AppCounts,
Expand All @@ -21,10 +23,6 @@ import {
SearchResponse,
StatusByAppBucket,
} from './types';
import { decorateRangeStats } from './decorate_range_stats';
import { getExportTypesHandler } from './get_export_type_handler';

type XPackInfo = XPackMainPlugin['info'];

const JOB_TYPES_KEY = 'jobTypes';
const JOB_TYPES_FIELD = 'jobtype';
Expand Down Expand Up @@ -123,10 +121,10 @@ async function handleResponse(response: SearchResponse): Promise<Partial<RangeSt

export async function getReportingUsage(
config: ReportingConfig,
xpackMainInfo: XPackInfo,
getLicense: GetLicense,
callCluster: CallCluster,
exportTypesRegistry: ExportTypesRegistry
) {
): Promise<ReportingUsageType> {
const reportingIndex = config.get('index');

const params = {
Expand Down Expand Up @@ -170,6 +168,7 @@ export async function getReportingUsage(
},
};

const featureAvailability = await getLicense();
return callCluster('search', params)
.then((response: SearchResponse) => handleResponse(response))
.then(
Expand All @@ -180,7 +179,7 @@ export async function getReportingUsage(

const exportTypesHandler = getExportTypesHandler(exportTypesRegistry);
const availability = exportTypesHandler.getAvailability(
xpackMainInfo
featureAvailability
) as FeatureAvailabilityMap;

const { last7Days, ...all } = usage;
Expand Down
9 changes: 9 additions & 0 deletions x-pack/legacy/plugins/reporting/server/usage/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,13 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { LicenseType } from '../../../../../plugins/licensing/server';

export interface FeaturesAvailability {
isAvailable: () => boolean;
license: {
getType: () => LicenseType | undefined;
};
}
export type GetLicense = () => Promise<FeaturesAvailability>;
export { registerReportingUsageCollector } from './reporting_usage_collector';
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,19 @@
* you may not use this file except in compliance with the Elastic License.
*/

import * as Rx from 'rxjs';
import sinon from 'sinon';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { ReportingConfig } from '../';
import { createMockReportingCore } from '../../test_helpers';
import { getExportTypesRegistry } from '../lib/export_types_registry';
import { ReportingUsageType, SearchResponse } from './types';
import { ReportingSetupDeps } from '../types';
import { FeaturesAvailability } from './';
import {
getReportingUsageCollector,
registerReportingUsageCollector,
} from './reporting_usage_collector';
import { ReportingUsageType, SearchResponse } from './types';

const exportTypesRegistry = getExportTypesRegistry();

Expand All @@ -32,30 +36,22 @@ function getMockUsageCollection() {
};
}

const getLicenseMock = (licenseType = 'platinum') => () => {
return Promise.resolve({
isAvailable: () => true,
license: { getType: () => licenseType },
} as FeaturesAvailability);
};

function getPluginsMock(
{ license, usageCollection = getMockUsageCollection() } = { license: 'platinum' }
) {
const mockXpackMain = {
info: {
isAvailable: sinon.stub().returns(true),
feature: () => ({
getLicenseCheckResults: sinon.stub(),
}),
license: {
isOneOf: sinon.stub().returns(false),
getType: sinon.stub().returns(license),
},
toJSON: () => ({ b: 1 }),
},
};
return {
return ({
licensing: { license$: Rx.of(getLicenseMock(license)) },
usageCollection,
__LEGACY: {
plugins: {
xpack_main: mockXpackMain,
},
},
} as any;
elasticsearch: {},
security: {},
} as unknown) as ReportingSetupDeps & { usageCollection: UsageCollectionSetup };
}

const getMockReportingConfig = () => ({
Expand All @@ -78,7 +74,7 @@ describe('license checks', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock('basic'),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand Down Expand Up @@ -108,7 +104,7 @@ describe('license checks', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock('none'),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand Down Expand Up @@ -138,7 +134,7 @@ describe('license checks', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock('platinum'),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand Down Expand Up @@ -168,7 +164,7 @@ describe('license checks', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock('basic'),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand All @@ -194,7 +190,7 @@ describe('data modeling', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock(),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand Down Expand Up @@ -247,7 +243,7 @@ describe('data modeling', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock(),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand Down Expand Up @@ -300,7 +296,7 @@ describe('data modeling', () => {
const { fetch } = getReportingUsageCollector(
mockConfig,
plugins.usageCollection,
plugins.__LEGACY.plugins.xpack_main.info,
getLicenseMock(),
exportTypesRegistry,
function isReady() {
return Promise.resolve(true);
Expand Down Expand Up @@ -461,7 +457,7 @@ describe('Ready for collection observable', () => {
const makeCollectorSpy = sinon.spy();
usageCollection.makeUsageCollector = makeCollectorSpy;

const plugins = getPluginsMock({ usageCollection } as any);
const plugins = getPluginsMock({ usageCollection, license: 'platinum' });
registerReportingUsageCollector(mockReporting, plugins);

const [args] = makeCollectorSpy.firstCall.args;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@
* you may not use this file except in compliance with the Elastic License.
*/

import { first, map } from 'rxjs/operators';
import { CallCluster } from 'src/legacy/core_plugins/elasticsearch';
import { UsageCollectionSetup } from 'src/plugins/usage_collection/server';
import { XPackMainPlugin } from '../../../xpack_main/server/xpack_main';
import { ReportingCore } from '../';
import { KIBANA_REPORTING_TYPE } from '../../common/constants';
import { ReportingConfig, ReportingCore } from '../../server';
import { ReportingSetupDeps } from '../../server/types';
import { ReportingConfig } from '../../server';
import { ExportTypesRegistry } from '../lib/export_types_registry';
import { RangeStats } from './types';
import { ReportingSetupDeps } from '../types';
import { GetLicense } from './';
import { getReportingUsage } from './get_reporting_usage';

type XPackInfo = XPackMainPlugin['info'];
import { RangeStats } from './types';

// places the reporting data as kibana stats
const METATYPE = 'kibana_stats';
Expand All @@ -25,14 +25,14 @@ const METATYPE = 'kibana_stats';
export function getReportingUsageCollector(
config: ReportingConfig,
usageCollection: UsageCollectionSetup,
xpackMainInfo: XPackInfo,
getLicense: GetLicense,
exportTypesRegistry: ExportTypesRegistry,
isReady: () => Promise<boolean>
) {
return usageCollection.makeUsageCollector({
type: KIBANA_REPORTING_TYPE,
fetch: (callCluster: CallCluster) =>
getReportingUsage(config, xpackMainInfo, callCluster, exportTypesRegistry),
getReportingUsage(config, getLicense, callCluster, exportTypesRegistry),
isReady,

/*
Expand All @@ -57,23 +57,35 @@ export function getReportingUsageCollector(

export function registerReportingUsageCollector(
reporting: ReportingCore,
plugins: ReportingSetupDeps
{ licensing, usageCollection }: ReportingSetupDeps
) {
if (!plugins.usageCollection) {
if (!usageCollection) {
return;
}
const xpackMainInfo = plugins.__LEGACY.plugins.xpack_main.info;

const config = reporting.getConfig();
const exportTypesRegistry = reporting.getExportTypesRegistry();
const getLicense = async () => {
return await licensing.license$
.pipe(
map(({ isAvailable, type }) => ({
isAvailable: () => isAvailable,
license: {
getType: () => type,
},
})),
first()
)
.toPromise();
};
const collectionIsReady = reporting.pluginHasStarted.bind(reporting);
const config = reporting.getConfig();

const collector = getReportingUsageCollector(
config,
plugins.usageCollection,
xpackMainInfo,
usageCollection,
getLicense,
exportTypesRegistry,
collectionIsReady
);
plugins.usageCollection.registerCollector(collector);
usageCollection.registerCollector(collector);
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const createMockSetupDeps = (setupMock?: any): ReportingSetupDeps => {
return {
elasticsearch: setupMock.elasticsearch,
security: setupMock.security,
licensing: {} as any,
usageCollection: {} as any,
__LEGACY: { plugins: { xpack_main: { status: new EventEmitter() } } } as any,
};
Expand Down

0 comments on commit 68dc5dd

Please sign in to comment.