From 385523927354342d7386d66561869d15e3dfa9c6 Mon Sep 17 00:00:00 2001 From: Nathan L Smith Date: Wed, 17 Jun 2020 19:18:15 -0500 Subject: [PATCH] [APM] License feature tracking for service maps (#69455) Use the license feature API to register the service maps feature and track its usage when the API endpoint is accessed. Fixes #64850. --- x-pack/plugins/apm/server/feature.ts | 3 ++ x-pack/plugins/apm/server/plugin.ts | 39 +++++++++++++------ .../server/routes/create_api/index.test.ts | 3 +- .../plugins/apm/server/routes/service_map.ts | 5 +++ x-pack/plugins/apm/server/routes/typings.ts | 5 ++- 5 files changed, 42 insertions(+), 13 deletions(-) diff --git a/x-pack/plugins/apm/server/feature.ts b/x-pack/plugins/apm/server/feature.ts index 60a7be9391eea3..80f722bae08686 100644 --- a/x-pack/plugins/apm/server/feature.ts +++ b/x-pack/plugins/apm/server/feature.ts @@ -70,3 +70,6 @@ export const APM_FEATURE = { }, }, }; + +export const APM_SERVICE_MAPS_FEATURE_NAME = 'APM service maps'; +export const APM_SERVICE_MAPS_LICENSE_TYPE = 'platinum'; diff --git a/x-pack/plugins/apm/server/plugin.ts b/x-pack/plugins/apm/server/plugin.ts index f0a05dfc0df30c..eb781ee0783075 100644 --- a/x-pack/plugins/apm/server/plugin.ts +++ b/x-pack/plugins/apm/server/plugin.ts @@ -14,7 +14,7 @@ import { import { Observable, combineLatest } from 'rxjs'; import { map, take } from 'rxjs/operators'; import { ObservabilityPluginSetup } from '../../observability/server'; -import { SecurityPluginSetup } from '../../security/public'; +import { SecurityPluginSetup } from '../../security/server'; import { UsageCollectionSetup } from '../../../../src/plugins/usage_collection/server'; import { TaskManagerSetupContract } from '../../task_manager/server'; import { AlertingPlugin } from '../../alerts/server'; @@ -28,11 +28,19 @@ import { APMConfig, mergeConfigs, APMXPackConfig } from '.'; import { HomeServerPluginSetup } from '../../../../src/plugins/home/server'; import { CloudSetup } from '../../cloud/server'; import { getInternalSavedObjectsClient } from './lib/helpers/get_internal_saved_objects_client'; -import { LicensingPluginSetup } from '../../licensing/public'; +import { + LicensingPluginSetup, + LicensingPluginStart, +} from '../../licensing/server'; import { registerApmAlerts } from './lib/alerts/register_apm_alerts'; import { createApmTelemetry } from './lib/apm_telemetry'; + import { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; -import { APM_FEATURE } from './feature'; +import { + APM_FEATURE, + APM_SERVICE_MAPS_FEATURE_NAME, + APM_SERVICE_MAPS_LICENSE_TYPE, +} from './feature'; import { apmIndices, apmTelemetry } from './saved_objects'; import { createElasticCloudInstructions } from './tutorial/elastic_cloud'; import { MlPluginSetup } from '../../ml/server'; @@ -120,16 +128,25 @@ export class APMPlugin implements Plugin { elasticCloud: createElasticCloudInstructions(plugins.cloud), }; }); + plugins.features.registerFeature(APM_FEATURE); + plugins.licensing.featureUsage.register( + APM_SERVICE_MAPS_FEATURE_NAME, + APM_SERVICE_MAPS_LICENSE_TYPE + ); - createApmApi().init(core, { - config$: mergedConfig$, - logger: this.logger!, - plugins: { - observability: plugins.observability, - security: plugins.security, - ml: plugins.ml, - }, + core.getStartServices().then(([_coreStart, pluginsStart]) => { + createApmApi().init(core, { + config$: mergedConfig$, + logger: this.logger!, + plugins: { + licensing: (pluginsStart as { licensing: LicensingPluginStart }) + .licensing, + observability: plugins.observability, + security: plugins.security, + ml: plugins.ml, + }, + }); }); return { diff --git a/x-pack/plugins/apm/server/routes/create_api/index.test.ts b/x-pack/plugins/apm/server/routes/create_api/index.test.ts index 3d3e26f680e0d2..f5db936c00d3a7 100644 --- a/x-pack/plugins/apm/server/routes/create_api/index.test.ts +++ b/x-pack/plugins/apm/server/routes/create_api/index.test.ts @@ -9,6 +9,7 @@ import { CoreSetup, Logger } from 'src/core/server'; import { Params } from '../typings'; import { BehaviorSubject } from 'rxjs'; import { APMConfig } from '../..'; +import { LicensingPluginStart } from '../../../../licensing/server'; const getCoreMock = () => { const get = jest.fn(); @@ -40,7 +41,7 @@ const getCoreMock = () => { logger: ({ error: jest.fn(), } as unknown) as Logger, - plugins: {}, + plugins: { licensing: {} as LicensingPluginStart }, }, }; }; diff --git a/x-pack/plugins/apm/server/routes/service_map.ts b/x-pack/plugins/apm/server/routes/service_map.ts index df0403be7b9759..3937c18b3fe5e0 100644 --- a/x-pack/plugins/apm/server/routes/service_map.ts +++ b/x-pack/plugins/apm/server/routes/service_map.ts @@ -15,6 +15,7 @@ import { getServiceMap } from '../lib/service_map/get_service_map'; import { getServiceMapServiceNodeInfo } from '../lib/service_map/get_service_map_service_node_info'; import { createRoute } from './create_route'; import { rangeRt } from './default_api_types'; +import { APM_SERVICE_MAPS_FEATURE_NAME } from '../feature'; export const serviceMapRoute = createRoute(() => ({ path: '/api/apm/service-map', @@ -35,6 +36,10 @@ export const serviceMapRoute = createRoute(() => ({ throw Boom.forbidden(invalidLicenseMessage); } + context.plugins.licensing.featureUsage.notifyUsage( + APM_SERVICE_MAPS_FEATURE_NAME + ); + const setup = await setupRequest(context, request); const { query: { serviceName, environment }, diff --git a/x-pack/plugins/apm/server/routes/typings.ts b/x-pack/plugins/apm/server/routes/typings.ts index bc31cb7a582af2..f30a9d18d7aeab 100644 --- a/x-pack/plugins/apm/server/routes/typings.ts +++ b/x-pack/plugins/apm/server/routes/typings.ts @@ -14,10 +14,11 @@ import { import { PickByValue, Optional } from 'utility-types'; import { Observable } from 'rxjs'; import { Server } from 'hapi'; +import { LicensingPluginStart } from '../../../licensing/server'; import { ObservabilityPluginSetup } from '../../../observability/server'; // eslint-disable-next-line @kbn/eslint/no-restricted-paths import { FetchOptions } from '../../public/services/rest/callApi'; -import { SecurityPluginSetup } from '../../../security/public'; +import { SecurityPluginSetup } from '../../../security/server'; import { MlPluginSetup } from '../../../ml/server'; import { APMConfig } from '..'; @@ -66,6 +67,7 @@ export type APMRequestHandlerContext< config: APMConfig; logger: Logger; plugins: { + licensing: LicensingPluginStart; observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; ml?: MlPluginSetup; @@ -114,6 +116,7 @@ export interface ServerAPI { config$: Observable; logger: Logger; plugins: { + licensing: LicensingPluginStart; observability?: ObservabilityPluginSetup; security?: SecurityPluginSetup; ml?: MlPluginSetup;