[APM] Move service metric config to kibana advanced settings (#141147)

* [APM] Move service metric config  to kibana advanced settings

* Add apmEnableServiceMetrics usage collector
This commit is contained in:
Katerina Patticha 2022-09-21 11:12:52 +02:00 committed by GitHub
parent 724ee2d740
commit 806dfabb0a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 53 additions and 138 deletions

View file

@ -77,9 +77,6 @@ Maximum number of child items displayed when viewing trace details. Defaults to
`xpack.observability.annotations.index` {ess-icon}::
Index name where Observability annotations are stored. Defaults to `observability-annotations`.
`xpack.apm.searchAggregatedServiceMetrics` {ess-icon}::
Enables Service metrics. Defaults to `false`. When set to `true`, additional configuration in APM Server is required.
`xpack.apm.searchAggregatedTransactions` {ess-icon}::
Enables Transaction histogram metrics. Defaults to `auto` so the UI will use metric indices over transaction indices for transactions if aggregated transactions are found. When set to `always`, additional configuration in APM Server is required. When set to `never` and aggregated transactions are not used.
+

View file

@ -438,6 +438,10 @@ export const stackManagementSchema: MakeSchemaFrom<UsageStats> = {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'observability:apmEnableServiceMetrics': {
type: 'boolean',
_meta: { description: 'Non-default value of setting.' },
},
'banners:placement': {
type: 'keyword',
_meta: { description: 'Non-default value of setting.' },

View file

@ -42,6 +42,7 @@ export interface UsageStats {
'observability:maxSuggestions': number;
'observability:enableComparisonByDefault': boolean;
'observability:enableServiceGroups': boolean;
'observability:apmEnableServiceMetrics': boolean;
'observability:enableInfrastructureHostsView': boolean;
'visualize:enableLabs': boolean;
'visualization:heatmap:maxBuckets': number;

View file

@ -8702,6 +8702,12 @@
"description": "Non-default value of setting."
}
},
"observability:apmEnableServiceMetrics": {
"type": "boolean",
"_meta": {
"description": "Non-default value of setting."
}
},
"banners:placement": {
"type": "keyword",
"_meta": {
@ -10323,4 +10329,4 @@
}
}
}
}
}

View file

@ -31,9 +31,6 @@ const configSchema = schema.object({
transactionGroupBucketSize: schema.number({ defaultValue: 1000 }),
maxTraceItems: schema.number({ defaultValue: 1000 }),
}),
searchAggregatedServiceMetrics: schema.boolean({
defaultValue: false,
}),
searchAggregatedTransactions: schema.oneOf(
[
schema.literal(SearchAggregatedTransactionSetting.auto),

View file

@ -11,11 +11,13 @@ import { APMConfig } from '../..';
export async function getServiceInventorySearchSource({
config,
serviceMetricsEnabled,
apmEventClient,
start,
end,
kuery,
}: {
serviceMetricsEnabled: boolean;
config: APMConfig;
apmEventClient: APMEventClient;
start: number;
@ -26,7 +28,6 @@ export async function getServiceInventorySearchSource({
searchAggregatedServiceMetrics: boolean;
}> {
const commonProps = {
config,
apmEventClient,
kuery,
start,
@ -34,8 +35,11 @@ export async function getServiceInventorySearchSource({
};
const [searchAggregatedTransactions, searchAggregatedServiceMetrics] =
await Promise.all([
getSearchAggregatedTransactions(commonProps),
getSearchAggregatedServiceMetrics(commonProps),
getSearchAggregatedTransactions({ ...commonProps, config }),
getSearchAggregatedServiceMetrics({
...commonProps,
serviceMetricsEnabled,
}),
]);
return {

View file

@ -1,124 +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
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import { getSearchAggregatedServiceMetrics } from '.';
import {
SearchParamsMock,
inspectSearchParams,
} from '../../../utils/test_helpers';
import { Setup } from '../setup_request';
const mockResponseWithServiceMetricsHits = {
took: 398,
timed_out: false,
_shards: {
total: 1,
successful: 1,
skipped: 0,
failed: 0,
},
hits: {
total: {
value: 1,
relation: 'gte' as const,
},
hits: [],
},
};
const mockResponseWithServiceMetricsNoHits = {
took: 398,
timed_out: false,
_shards: {
total: 1,
successful: 1,
skipped: 0,
failed: 0,
},
hits: {
total: {
value: 0,
relation: 'gte' as const,
},
hits: [],
},
};
describe('get default configuration for aggregated service metrics', () => {
it('should be false by default', async () => {
const mockSetup = {
apmEventClient: { search: () => Promise.resolve(response) },
config: {},
} as unknown as Setup;
const response = await getSearchAggregatedServiceMetrics({
apmEventClient: mockSetup.apmEventClient,
config: mockSetup.config,
kuery: '',
});
expect(response).toBeFalsy();
});
});
describe('get has aggregated', () => {
it('should be false when xpack.apm.searchAggregatedServiceMetrics=false ', async () => {
const mockSetup = {
apmEventClient: { search: () => Promise.resolve(response) },
config: { 'xpack.apm.searchAggregatedServiceMetrics': false },
} as unknown as Setup;
const response = await getSearchAggregatedServiceMetrics({
apmEventClient: mockSetup.apmEventClient,
config: mockSetup.config,
kuery: '',
});
expect(response).toBeFalsy();
});
describe('with xpack.apm.searchAggregatedServiceMetrics=true', () => {
let mock: SearchParamsMock;
const config = {
searchAggregatedServiceMetrics: true,
};
afterEach(() => {
mock.teardown();
});
it('should be true when service metrics data are found', async () => {
mock = await inspectSearchParams(
(setup) =>
getSearchAggregatedServiceMetrics({
apmEventClient: setup.apmEventClient,
config: setup.config,
kuery: '',
}),
{
config,
mockResponse: () => mockResponseWithServiceMetricsHits,
}
);
expect(mock.response).toBeTruthy();
});
it('should be false when service metrics data are not found', async () => {
mock = await inspectSearchParams(
(setup) =>
getSearchAggregatedServiceMetrics({
apmEventClient: setup.apmEventClient,
config: setup.config,
kuery: '',
}),
{
config,
mockResponse: () => mockResponseWithServiceMetricsNoHits,
}
);
expect(mock.response).toBeFalsy();
});
});
});

View file

@ -8,23 +8,22 @@
import { kqlQuery, rangeQuery } from '@kbn/observability-plugin/server';
import { ProcessorEvent } from '@kbn/observability-plugin/common';
import { METRICSET_NAME } from '../../../../common/elasticsearch_fieldnames';
import { APMConfig } from '../../..';
import { APMEventClient } from '../create_es_client/create_apm_event_client';
export async function getSearchAggregatedServiceMetrics({
config,
serviceMetricsEnabled,
start,
end,
apmEventClient,
kuery,
}: {
config: APMConfig;
serviceMetricsEnabled: boolean;
start?: number;
end?: number;
apmEventClient: APMEventClient;
kuery: string;
}): Promise<boolean> {
if (config.searchAggregatedServiceMetrics) {
if (serviceMetricsEnabled) {
return getHasAggregatedServicesMetrics({
start,
end,

View file

@ -7,6 +7,7 @@
import Boom from '@hapi/boom';
import { isoToEpochRt, jsonRt, toNumberRt } from '@kbn/io-ts-utils';
import { enableServiceMetrics } from '@kbn/observability-plugin/common';
import * as t from 'io-ts';
import { uniq, mergeWith } from 'lodash';
import {
@ -122,6 +123,7 @@ const servicesRoute = createApmServerRoute({
probability,
} = params.query;
const savedObjectsClient = (await context.core).savedObjects.client;
const coreContext = await resources.context.core;
const [setup, serviceGroup, randomSampler] = await Promise.all([
setupRequest(resources),
@ -132,8 +134,13 @@ const servicesRoute = createApmServerRoute({
]);
const { apmEventClient, config } = setup;
const serviceMetricsEnabled =
await coreContext.uiSettings.client.get<boolean>(enableServiceMetrics);
const { searchAggregatedTransactions, searchAggregatedServiceMetrics } =
await getServiceInventorySearchSource({
serviceMetricsEnabled,
config,
apmEventClient,
kuery,
@ -208,6 +215,7 @@ const servicesDetailedStatisticsRoute = createApmServerRoute({
request,
plugins: { security },
} = resources;
const coreContext = await resources.context.core;
const { environment, kuery, offset, start, end, probability } =
params.query;
@ -220,8 +228,13 @@ const servicesDetailedStatisticsRoute = createApmServerRoute({
]);
const { apmEventClient, config } = setup;
const serviceMetricsEnabled =
await coreContext.uiSettings.client.get<boolean>(enableServiceMetrics);
const { searchAggregatedTransactions, searchAggregatedServiceMetrics } =
await getServiceInventorySearchSource({
serviceMetricsEnabled,
config,
apmEventClient,
kuery,

View file

@ -25,6 +25,7 @@ export {
apmOperationsTab,
apmLabsButton,
enableInfrastructureHostsView,
enableServiceMetrics,
enableAwsLambdaMetrics,
} from './ui_settings_keys';

View file

@ -21,3 +21,4 @@ export const apmOperationsTab = 'observability:apmOperationsTab';
export const apmLabsButton = 'observability:apmLabsButton';
export const enableInfrastructureHostsView = 'observability:enableInfrastructureHostsView';
export const enableAwsLambdaMetrics = 'observability:enableAwsLambdaMetrics';
export const enableServiceMetrics = 'observability:apmEnableServiceMetrics';

View file

@ -23,6 +23,7 @@ import {
apmOperationsTab,
apmLabsButton,
enableInfrastructureHostsView,
enableServiceMetrics,
enableAwsLambdaMetrics,
} from '../common/ui_settings_keys';
@ -168,6 +169,21 @@ export const uiSettings: Record<string, UiSettings> = {
requiresPageReload: true,
showInLabs: true,
},
[enableServiceMetrics]: {
category: [observabilityFeatureId],
name: i18n.translate('xpack.observability.apmEnableServiceMetrics', {
defaultMessage: 'Service metrics',
}),
value: false,
description: i18n.translate('xpack.observability.apmEnableServiceMetricsGroupsDescription', {
defaultMessage:
'{technicalPreviewLabel} Enables Service metrics. When is enabled, additional configuration in APM Server is required.',
values: { technicalPreviewLabel: `<em>[${technicalPreviewLabel}]</em>` },
}),
schema: schema.boolean(),
requiresPageReload: true,
showInLabs: true,
},
[apmServiceInventoryOptimizedSorting]: {
category: [observabilityFeatureId],
name: i18n.translate('xpack.observability.apmServiceInventoryOptimizedSorting', {