[APM] Add license check for significant terms (#88209)
* only shows significant terms under platinum license * addressing PR comments * addressing PR comments Co-authored-by: Kibana Machine <42973632+kibanamachine@users.noreply.github.com>
This commit is contained in:
parent
a0da8bda04
commit
6beef61f93
217
x-pack/plugins/apm/common/license_check.test.ts
Normal file
217
x-pack/plugins/apm/common/license_check.test.ts
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { License } from '../../licensing/common/license';
|
||||
import { isActiveGoldLicense, isActivePlatinumLicense } from './license_check';
|
||||
|
||||
describe('License check', () => {
|
||||
describe('isActivePlatinumLicense', () => {
|
||||
describe('with an expired license', () => {
|
||||
it('returns false', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'platinum',
|
||||
type: 'platinum',
|
||||
status: 'expired',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActivePlatinumLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a basic license', () => {
|
||||
it('returns false', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'basic',
|
||||
type: 'basic',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActivePlatinumLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a gold license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'gold',
|
||||
type: 'gold',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActivePlatinumLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a platinum license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'platinum',
|
||||
type: 'platinum',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActivePlatinumLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an enterprise license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'enterprise',
|
||||
type: 'enterprise',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActivePlatinumLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a trial license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'trial',
|
||||
type: 'trial',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActivePlatinumLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
describe('isActiveGoldLicense', () => {
|
||||
describe('with an expired license', () => {
|
||||
it('returns false', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'gold',
|
||||
type: 'gold',
|
||||
status: 'expired',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActiveGoldLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a basic license', () => {
|
||||
it('returns false', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'basic',
|
||||
type: 'basic',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActiveGoldLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a gold license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'gold',
|
||||
type: 'gold',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActiveGoldLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a platinum license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'platinum',
|
||||
type: 'platinum',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActiveGoldLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an enterprise license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'enterprise',
|
||||
type: 'enterprise',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActiveGoldLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a trial license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'trial',
|
||||
type: 'trial',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(isActiveGoldLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
18
x-pack/plugins/apm/common/license_check.ts
Normal file
18
x-pack/plugins/apm/common/license_check.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
import { ILicense, LicenseType } from '../../licensing/common/types';
|
||||
|
||||
function isActiveLicense(licenseType: LicenseType, license?: ILicense) {
|
||||
return license && license.isActive && license.hasAtLeast(licenseType);
|
||||
}
|
||||
|
||||
export function isActivePlatinumLicense(license?: ILicense) {
|
||||
return isActiveLicense('platinum', license);
|
||||
}
|
||||
|
||||
export function isActiveGoldLicense(license?: ILicense) {
|
||||
return isActiveLicense('gold', license);
|
||||
}
|
|
@ -1,97 +0,0 @@
|
|||
/*
|
||||
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
|
||||
* or more contributor license agreements. Licensed under the Elastic License;
|
||||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import { License } from '../../licensing/common/license';
|
||||
import * as serviceMap from './service_map';
|
||||
|
||||
describe('service map helpers', () => {
|
||||
describe('isActivePlatinumLicense', () => {
|
||||
describe('with an expired license', () => {
|
||||
it('returns false', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'platinum',
|
||||
type: 'platinum',
|
||||
status: 'expired',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(serviceMap.isActivePlatinumLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a basic license', () => {
|
||||
it('returns false', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'basic',
|
||||
type: 'basic',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(serviceMap.isActivePlatinumLicense(license)).toEqual(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a platinum license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'platinum',
|
||||
type: 'platinum',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(serviceMap.isActivePlatinumLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with an enterprise license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'enterprise',
|
||||
type: 'enterprise',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(serviceMap.isActivePlatinumLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('with a trial license', () => {
|
||||
it('returns true', () => {
|
||||
const license = new License({
|
||||
license: {
|
||||
uid: 'test uid',
|
||||
expiryDateInMillis: 0,
|
||||
mode: 'trial',
|
||||
type: 'trial',
|
||||
status: 'active',
|
||||
},
|
||||
signature: 'test signature',
|
||||
});
|
||||
|
||||
expect(serviceMap.isActivePlatinumLicense(license)).toEqual(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
|
@ -6,7 +6,6 @@
|
|||
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import cytoscape from 'cytoscape';
|
||||
import { ILicense } from '../../licensing/common/types';
|
||||
import {
|
||||
AGENT_NAME,
|
||||
SERVICE_ENVIRONMENT,
|
||||
|
@ -61,10 +60,6 @@ export interface ServiceNodeStats {
|
|||
avgErrorRate: number | null;
|
||||
}
|
||||
|
||||
export function isActivePlatinumLicense(license: ILicense) {
|
||||
return license.isActive && license.hasAtLeast('platinum');
|
||||
}
|
||||
|
||||
export const invalidLicenseMessage = i18n.translate(
|
||||
'xpack.apm.serviceMap.invalidLicenseMessage',
|
||||
{
|
||||
|
|
|
@ -4,5 +4,5 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
export const enableCorrelations = 'apm:enableCorrelations';
|
||||
export const enableSignificantTerms = 'apm:enableSignificantTerms';
|
||||
export const enableServiceOverview = 'apm:enableServiceOverview';
|
||||
|
|
|
@ -19,19 +19,25 @@ import {
|
|||
} from '@elastic/eui';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { EuiSpacer } from '@elastic/eui';
|
||||
import { enableCorrelations } from '../../../../common/ui_settings_keys';
|
||||
import { isActivePlatinumLicense } from '../../../../common/license_check';
|
||||
import { enableSignificantTerms } from '../../../../common/ui_settings_keys';
|
||||
import { useApmPluginContext } from '../../../context/apm_plugin/use_apm_plugin_context';
|
||||
import { LatencyCorrelations } from './LatencyCorrelations';
|
||||
import { ErrorCorrelations } from './ErrorCorrelations';
|
||||
import { useUrlParams } from '../../../context/url_params_context/use_url_params';
|
||||
import { createHref } from '../../shared/Links/url_helpers';
|
||||
import { useLicenseContext } from '../../../context/license/use_license_context';
|
||||
|
||||
export function Correlations() {
|
||||
const { uiSettings } = useApmPluginContext().core;
|
||||
const { urlParams } = useUrlParams();
|
||||
const license = useLicenseContext();
|
||||
const history = useHistory();
|
||||
const [isFlyoutVisible, setIsFlyoutVisible] = useState(false);
|
||||
if (!uiSettings.get(enableCorrelations)) {
|
||||
if (
|
||||
!uiSettings.get(enableSignificantTerms) ||
|
||||
!isActivePlatinumLicense(license)
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -7,10 +7,10 @@
|
|||
import { EuiFlexGroup, EuiFlexItem, EuiLoadingSpinner } from '@elastic/eui';
|
||||
import React, { PropsWithChildren, ReactNode } from 'react';
|
||||
import styled from 'styled-components';
|
||||
import { isActivePlatinumLicense } from '../../../../common/license_check';
|
||||
import { useTrackPageview } from '../../../../../observability/public';
|
||||
import {
|
||||
invalidLicenseMessage,
|
||||
isActivePlatinumLicense,
|
||||
SERVICE_MAP_TIMEOUT_ERROR,
|
||||
} from '../../../../common/service_map';
|
||||
import { FETCH_STATUS, useFetcher } from '../../../hooks/use_fetcher';
|
||||
|
|
|
@ -6,11 +6,11 @@
|
|||
|
||||
import { Logger } from 'kibana/server';
|
||||
import moment from 'moment';
|
||||
import { isActivePlatinumLicense } from '../../../common/license_check';
|
||||
import { APMConfig } from '../..';
|
||||
import { KibanaRequest } from '../../../../../../src/core/server';
|
||||
import { UI_SETTINGS } from '../../../../../../src/plugins/data/common';
|
||||
import { ESFilter } from '../../../../../typings/elasticsearch';
|
||||
import { isActivePlatinumLicense } from '../../../common/service_map';
|
||||
import { UIFilters } from '../../../typings/ui_filters';
|
||||
import { APMRequestHandlerContext } from '../../routes/typings';
|
||||
import {
|
||||
|
|
|
@ -4,12 +4,23 @@
|
|||
* you may not use this file except in compliance with the Elastic License.
|
||||
*/
|
||||
|
||||
import Boom from '@hapi/boom';
|
||||
import { i18n } from '@kbn/i18n';
|
||||
import * as t from 'io-ts';
|
||||
import { rangeRt } from './default_api_types';
|
||||
import { getCorrelationsForSlowTransactions } from '../lib/correlations/get_correlations_for_slow_transactions';
|
||||
import { isActivePlatinumLicense } from '../../common/license_check';
|
||||
import { getCorrelationsForFailedTransactions } from '../lib/correlations/get_correlations_for_failed_transactions';
|
||||
import { createRoute } from './create_route';
|
||||
import { getCorrelationsForSlowTransactions } from '../lib/correlations/get_correlations_for_slow_transactions';
|
||||
import { setupRequest } from '../lib/helpers/setup_request';
|
||||
import { createRoute } from './create_route';
|
||||
import { rangeRt } from './default_api_types';
|
||||
|
||||
const INVALID_LICENSE = i18n.translate(
|
||||
'xpack.apm.significanTerms.license.text',
|
||||
{
|
||||
defaultMessage:
|
||||
'To use the correlations API, you must be subscribed to an Elastic Platinum license.',
|
||||
}
|
||||
);
|
||||
|
||||
export const correlationsForSlowTransactionsRoute = createRoute({
|
||||
endpoint: 'GET /api/apm/correlations/slow_transactions',
|
||||
|
@ -30,6 +41,9 @@ export const correlationsForSlowTransactionsRoute = createRoute({
|
|||
}),
|
||||
options: { tags: ['access:apm'] },
|
||||
handler: async ({ context, request }) => {
|
||||
if (!isActivePlatinumLicense(context.licensing.license)) {
|
||||
throw Boom.forbidden(INVALID_LICENSE);
|
||||
}
|
||||
const setup = await setupRequest(context, request);
|
||||
const {
|
||||
serviceName,
|
||||
|
@ -68,6 +82,9 @@ export const correlationsForFailedTransactionsRoute = createRoute({
|
|||
}),
|
||||
options: { tags: ['access:apm'] },
|
||||
handler: async ({ context, request }) => {
|
||||
if (!isActivePlatinumLicense(context.licensing.license)) {
|
||||
throw Boom.forbidden(INVALID_LICENSE);
|
||||
}
|
||||
const setup = await setupRequest(context, request);
|
||||
const {
|
||||
serviceName,
|
||||
|
|
|
@ -6,10 +6,7 @@
|
|||
|
||||
import Boom from '@hapi/boom';
|
||||
import * as t from 'io-ts';
|
||||
import {
|
||||
invalidLicenseMessage,
|
||||
isActivePlatinumLicense,
|
||||
} from '../../common/service_map';
|
||||
import { invalidLicenseMessage } from '../../common/service_map';
|
||||
import { setupRequest } from '../lib/helpers/setup_request';
|
||||
import { getServiceMap } from '../lib/service_map/get_service_map';
|
||||
import { getServiceMapServiceNodeInfo } from '../lib/service_map/get_service_map_service_node_info';
|
||||
|
@ -17,6 +14,7 @@ import { createRoute } from './create_route';
|
|||
import { rangeRt, uiFiltersRt } from './default_api_types';
|
||||
import { notifyFeatureUsage } from '../feature';
|
||||
import { getSearchAggregatedTransactions } from '../lib/helpers/aggregated_transactions';
|
||||
import { isActivePlatinumLicense } from '../../common/license_check';
|
||||
|
||||
export const serviceMapRoute = createRoute({
|
||||
endpoint: 'GET /api/apm/service-map',
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
import * as t from 'io-ts';
|
||||
import Boom from '@hapi/boom';
|
||||
import { isActivePlatinumLicense } from '../../../common/service_map';
|
||||
import { isActivePlatinumLicense } from '../../../common/license_check';
|
||||
import { ML_ERRORS } from '../../../common/anomaly_detection';
|
||||
import { createRoute } from '../create_route';
|
||||
import { getAnomalyDetectionJobs } from '../../lib/anomaly_detection/get_anomaly_detection_jobs';
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
import Boom from '@hapi/boom';
|
||||
import * as t from 'io-ts';
|
||||
import { pick } from 'lodash';
|
||||
import { isActiveGoldLicense } from '../../../common/license_check';
|
||||
import { INVALID_LICENSE } from '../../../common/custom_link';
|
||||
import { ILicense } from '../../../../licensing/common/types';
|
||||
import { FILTER_OPTIONS } from '../../../common/custom_link/custom_link_filter_options';
|
||||
import { notifyFeatureUsage } from '../../feature';
|
||||
import { setupRequest } from '../../lib/helpers/setup_request';
|
||||
|
@ -22,10 +22,6 @@ import { getTransaction } from '../../lib/settings/custom_link/get_transaction';
|
|||
import { listCustomLinks } from '../../lib/settings/custom_link/list_custom_links';
|
||||
import { createRoute } from '../create_route';
|
||||
|
||||
function isActiveGoldLicense(license: ILicense) {
|
||||
return license.isActive && license.hasAtLeast('gold');
|
||||
}
|
||||
|
||||
export const customLinkTransactionRoute = createRoute({
|
||||
endpoint: 'GET /api/apm/settings/custom_links/transaction',
|
||||
options: { tags: ['access:apm'] },
|
||||
|
|
|
@ -8,7 +8,7 @@ import { schema } from '@kbn/config-schema';
|
|||
import { i18n } from '@kbn/i18n';
|
||||
import { UiSettingsParams } from '../../../../src/core/types';
|
||||
import {
|
||||
enableCorrelations,
|
||||
enableSignificantTerms,
|
||||
enableServiceOverview,
|
||||
} from '../common/ui_settings_keys';
|
||||
|
||||
|
@ -16,10 +16,10 @@ import {
|
|||
* uiSettings definitions for APM.
|
||||
*/
|
||||
export const uiSettings: Record<string, UiSettingsParams<boolean>> = {
|
||||
[enableCorrelations]: {
|
||||
[enableSignificantTerms]: {
|
||||
category: ['observability'],
|
||||
name: i18n.translate('xpack.apm.enableCorrelationsExperimentName', {
|
||||
defaultMessage: 'APM Significant terms',
|
||||
defaultMessage: 'APM Significant terms (Platinum required)',
|
||||
}),
|
||||
value: false,
|
||||
description: i18n.translate(
|
||||
|
|
|
@ -68,9 +68,5 @@ export default function apmApiIntegrationTests({ loadTestFile }: FtrProviderCont
|
|||
describe('Metrics', function () {
|
||||
loadTestFile(require.resolve('./metrics_charts/metrics_charts'));
|
||||
});
|
||||
|
||||
describe('Correlations', function () {
|
||||
loadTestFile(require.resolve('./correlations/slow_transactions'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -42,5 +42,9 @@ export default function observabilityApiIntegrationTests({ loadTestFile }: FtrPr
|
|||
loadTestFile(require.resolve('./csm/has_rum_data.ts'));
|
||||
loadTestFile(require.resolve('./csm/page_load_dist.ts'));
|
||||
});
|
||||
|
||||
describe('Correlations', function () {
|
||||
loadTestFile(require.resolve('./correlations/slow_transactions'));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue