diff --git a/x-pack/legacy/plugins/apm/common/projections/errors.ts b/x-pack/legacy/plugins/apm/common/projections/errors.ts index c3094f5cbb0b6..adbd2eb1d6d27 100644 --- a/x-pack/legacy/plugins/apm/common/projections/errors.ts +++ b/x-pack/legacy/plugins/apm/common/projections/errors.ts @@ -19,10 +19,10 @@ export function getErrorGroupsProjection({ setup: Setup; serviceName: string; }) { - const { start, end, uiFiltersES, config } = setup; + const { start, end, uiFiltersES, indices } = setup; return { - index: config.get('apm_oss.errorIndices'), + index: indices['apm_oss.errorIndices'], body: { query: { bool: { diff --git a/x-pack/legacy/plugins/apm/common/projections/metrics.ts b/x-pack/legacy/plugins/apm/common/projections/metrics.ts index 5c9eeb54744d7..25d1484624e15 100644 --- a/x-pack/legacy/plugins/apm/common/projections/metrics.ts +++ b/x-pack/legacy/plugins/apm/common/projections/metrics.ts @@ -34,7 +34,7 @@ export function getMetricsProjection({ serviceName: string; serviceNodeName?: string; }) { - const { start, end, uiFiltersES, config } = setup; + const { start, end, uiFiltersES, indices } = setup; const filter = [ { term: { [SERVICE_NAME]: serviceName } }, @@ -45,7 +45,7 @@ export function getMetricsProjection({ ]; return { - index: config.get('apm_oss.metricsIndices'), + index: indices['apm_oss.metricsIndices'], body: { query: { bool: { diff --git a/x-pack/legacy/plugins/apm/common/projections/services.ts b/x-pack/legacy/plugins/apm/common/projections/services.ts index ab72211f92aa7..e889899e11634 100644 --- a/x-pack/legacy/plugins/apm/common/projections/services.ts +++ b/x-pack/legacy/plugins/apm/common/projections/services.ts @@ -9,13 +9,13 @@ import { SERVICE_NAME, PROCESSOR_EVENT } from '../elasticsearch_fieldnames'; import { rangeFilter } from '../../server/lib/helpers/range_filter'; export function getServicesProjection({ setup }: { setup: Setup }) { - const { start, end, uiFiltersES, config } = setup; + const { start, end, uiFiltersES, indices } = setup; return { index: [ - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.metricsIndices'], + indices['apm_oss.errorIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/common/projections/transactions.ts b/x-pack/legacy/plugins/apm/common/projections/transactions.ts index 63abb0572df87..fb249340c867c 100644 --- a/x-pack/legacy/plugins/apm/common/projections/transactions.ts +++ b/x-pack/legacy/plugins/apm/common/projections/transactions.ts @@ -24,7 +24,7 @@ export function getTransactionsProjection({ transactionName?: string; transactionType?: string; }) { - const { start, end, uiFiltersES, config } = setup; + const { start, end, uiFiltersES, indices } = setup; const transactionNameFilter = transactionName ? [{ term: { [TRANSACTION_NAME]: transactionName } }] @@ -48,7 +48,7 @@ export function getTransactionsProjection({ }; return { - index: config.get('apm_oss.transactionIndices'), + index: indices['apm_oss.transactionIndices'], body: { query: { bool diff --git a/x-pack/legacy/plugins/apm/index.ts b/x-pack/legacy/plugins/apm/index.ts index 4d3d2b210bbae..556bce9d37bb5 100644 --- a/x-pack/legacy/plugins/apm/index.ts +++ b/x-pack/legacy/plugins/apm/index.ts @@ -43,8 +43,7 @@ export const apm: LegacyPluginInitializer = kibana => { apmUiEnabled: config.get('xpack.apm.ui.enabled'), // TODO: rename to apm_oss.indexPatternTitle in 7.0 (breaking change) apmIndexPatternTitle: config.get('apm_oss.indexPattern'), - apmServiceMapEnabled: config.get('xpack.apm.serviceMapEnabled'), - apmTransactionIndices: config.get('apm_oss.transactionIndices') + apmServiceMapEnabled: config.get('xpack.apm.serviceMapEnabled') }; }, hacks: ['plugins/apm/hacks/toggle_app_link_in_nav'], diff --git a/x-pack/legacy/plugins/apm/mappings.json b/x-pack/legacy/plugins/apm/mappings.json index 26075d406c993..0b31798242fad 100644 --- a/x-pack/legacy/plugins/apm/mappings.json +++ b/x-pack/legacy/plugins/apm/mappings.json @@ -41,5 +41,30 @@ } } } + }, + "apm-indices": { + "properties": { + "apm_oss.sourcemapIndices": { + "type": "keyword" + }, + "apm_oss.errorIndices": { + "type": "keyword" + }, + "apm_oss.onboardingIndices": { + "type": "keyword" + }, + "apm_oss.spanIndices": { + "type": "keyword" + }, + "apm_oss.transactionIndices": { + "type": "keyword" + }, + "apm_oss.metricsIndices": { + "type": "keyword" + }, + "apm_oss.apmAgentConfigurationIndex": { + "type": "keyword" + } + } } } diff --git a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx index 6c95095592fe4..4769fe6400ac1 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/index.tsx @@ -15,7 +15,9 @@ import { TransactionDetails } from '../../TransactionDetails'; import { Home } from '../../Home'; import { BreadcrumbRoute } from '../ProvideBreadcrumbs'; import { RouteName } from './route_names'; +import { Settings } from '../../Settings'; import { AgentConfigurations } from '../../Settings/AgentConfigurations'; +import { ApmIndices } from '../../Settings/ApmIndices'; import { toQuery } from '../../../shared/Links/url_helpers'; import { ServiceNodeMetrics } from '../../ServiceNodeMetrics'; import { resolveUrlParams } from '../../../../context/UrlParamsContext/resolveUrlParams'; @@ -69,12 +71,41 @@ export const routes: BreadcrumbRoute[] = [ { exact: true, path: '/settings', - component: AgentConfigurations, + render: renderAsRedirectTo('/settings/agent-configuration'), breadcrumb: i18n.translate('xpack.apm.breadcrumb.listSettingsTitle', { defaultMessage: 'Settings' }), name: RouteName.SETTINGS }, + { + exact: true, + path: '/settings/apm-indices', + component: () => ( + + + + ), + breadcrumb: i18n.translate('xpack.apm.breadcrumb.settings.indicesTitle', { + defaultMessage: 'Indices' + }), + name: RouteName.INDICES + }, + { + exact: true, + path: '/settings/agent-configuration', + component: () => ( + + + + ), + breadcrumb: i18n.translate( + 'xpack.apm.breadcrumb.settings.agentConfigurationTitle', + { + defaultMessage: 'Agent Configuration' + } + ), + name: RouteName.AGENT_CONFIGURATION + }, { exact: true, path: '/services/:serviceName', diff --git a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx index 3af5b217ca738..ab02e38ee9c9d 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Main/route_config/route_names.tsx @@ -19,5 +19,7 @@ export enum RouteName { TRANSACTION_TYPE = 'transaction_type', TRANSACTION_NAME = 'transaction_name', SETTINGS = 'settings', + AGENT_CONFIGURATION = 'agent_configuration', + INDICES = 'indices', SERVICE_NODES = 'nodes' } diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx index e2630efbcf500..9e95cfd0fad7f 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/index.tsx @@ -10,7 +10,6 @@ import { EuiTitle, EuiFlexGroup, EuiFlexItem, - EuiButtonEmpty, EuiPanel, EuiSpacer, EuiButton @@ -18,7 +17,6 @@ import { import { isEmpty } from 'lodash'; import { useFetcher } from '../../../../hooks/useFetcher'; import { AgentConfigurationListAPIResponse } from '../../../../../server/lib/settings/agent_configuration/list_configurations'; -import { HomeLink } from '../../../shared/Links/apm/HomeLink'; import { AgentConfigurationList } from './AgentConfigurationList'; import { useTrackPageview } from '../../../../../../infra/public'; import { AddEditFlyout } from './AddEditFlyout'; @@ -62,30 +60,6 @@ export function AgentConfigurations() { /> )} - - - -

- {i18n.translate('xpack.apm.settings.agentConf.pageTitle', { - defaultMessage: 'Settings' - })} -

-
-
- - - - {i18n.translate( - 'xpack.apm.settings.agentConf.returnToOverviewLinkLabel', - { defaultMessage: 'Return to overview' } - )} - - - -
- - - diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx new file mode 100644 index 0000000000000..8fab7da377eb2 --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/ApmIndices/index.tsx @@ -0,0 +1,259 @@ +/* + * 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 React, { useState, useEffect } from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiTitle, + EuiFlexGroup, + EuiFlexItem, + EuiPanel, + EuiSpacer, + EuiText, + EuiForm, + EuiFormRow, + EuiFieldText, + EuiButton, + EuiButtonEmpty +} from '@elastic/eui'; +import { useFetcher } from '../../../../hooks/useFetcher'; +import { useCallApmApi } from '../../../../hooks/useCallApmApi'; +import { APMClient } from '../../../../services/rest/createCallApmApi'; +import { StringMap } from '../../../../../typings/common'; +import { useKibanaCore } from '../../../../../../observability/public'; + +const APM_INDEX_LABELS = [ + { + configurationName: 'apm_oss.sourcemapIndices', + label: i18n.translate( + 'xpack.apm.settings.apmIndices.sourcemapIndicesLabel', + { defaultMessage: 'Sourcemap Indices' } + ) + }, + { + configurationName: 'apm_oss.errorIndices', + label: i18n.translate('xpack.apm.settings.apmIndices.errorIndicesLabel', { + defaultMessage: 'Error Indices' + }) + }, + { + configurationName: 'apm_oss.onboardingIndices', + label: i18n.translate( + 'xpack.apm.settings.apmIndices.onboardingIndicesLabel', + { defaultMessage: 'Onboarding Indices' } + ) + }, + { + configurationName: 'apm_oss.spanIndices', + label: i18n.translate('xpack.apm.settings.apmIndices.spanIndicesLabel', { + defaultMessage: 'Span Indices' + }) + }, + { + configurationName: 'apm_oss.transactionIndices', + label: i18n.translate( + 'xpack.apm.settings.apmIndices.transactionIndicesLabel', + { defaultMessage: 'Transaction Indices' } + ) + }, + { + configurationName: 'apm_oss.metricsIndices', + label: i18n.translate('xpack.apm.settings.apmIndices.metricsIndicesLabel', { + defaultMessage: 'Metrics Indices' + }) + }, + { + configurationName: 'apm_oss.apmAgentConfigurationIndex', + label: i18n.translate( + 'xpack.apm.settings.apmIndices.apmAgentConfigurationIndexLabel', + { defaultMessage: 'Agent Configuration Index' } + ) + } +]; + +async function saveApmIndices({ + callApmApi, + apmIndices +}: { + callApmApi: APMClient; + apmIndices: StringMap; +}) { + await callApmApi({ + method: 'POST', + pathname: '/api/apm/settings/apm-indices/save', + params: { + body: apmIndices + } + }); +} + +export function ApmIndices() { + const { + notifications: { toasts } + } = useKibanaCore(); + + const [apmIndices, setApmIndices] = useState>({}); + const [isSaving, setIsSaving] = useState(false); + + const callApmApiFromHook = useCallApmApi(); + + const { data = [], status, refetch } = useFetcher( + callApmApi => + callApmApi({ pathname: `/api/apm/settings/apm-index-settings` }), + [] + ); + + useEffect(() => { + setApmIndices( + data.reduce( + (acc, { configurationName, savedValue }) => ({ + ...acc, + [configurationName]: savedValue + }), + {} + ) + ); + }, [data]); + + const handleApplyChangesEvent = async ( + event: + | React.FormEvent + | React.MouseEvent + ) => { + event.preventDefault(); + setIsSaving(true); + try { + await saveApmIndices({ + callApmApi: callApmApiFromHook, + apmIndices + }); + toasts.addSuccess({ + title: i18n.translate( + 'xpack.apm.settings.apmIndices.applyChanges.succeeded.title', + { defaultMessage: 'Indices applied' } + ), + text: i18n.translate( + 'xpack.apm.settings.apmIndices.applyChanges.succeeded.text', + { + defaultMessage: + 'The indices changes were successfully applied. These changes are reflected immediately in the APM UI' + } + ) + }); + } catch (error) { + toasts.addDanger({ + title: i18n.translate( + 'xpack.apm.settings.apmIndices.applyChanges.failed.title', + { defaultMessage: 'Indices could not be applied.' } + ), + text: i18n.translate( + 'xpack.apm.settings.apmIndices.applyChanges.failed.text', + { + defaultMessage: + 'Something went wrong when applying indices. Error: {errorMessage}', + values: { errorMessage: error.message } + } + ) + }); + } + setIsSaving(false); + }; + + const handleChangeIndexConfigurationEvent = async ( + event: React.ChangeEvent + ) => { + const { name, value } = event.target; + setApmIndices({ + ...apmIndices, + [name]: value + }); + }; + + return ( + + + + +

+ {i18n.translate('xpack.apm.settings.apmIndices.title', { + defaultMessage: 'Indices' + })} +

+
+ + +

+ {i18n.translate('xpack.apm.settings.apmIndices.description', { + defaultMessage: `The APM UI uses index patterns to query your APM indices. If you've customized the index names that APM Server writes events to, you may need to update these patterns for the APM UI to work. Settings here take precedence over those set in kibana.yml.` + })} +

+ + {APM_INDEX_LABELS.map(({ configurationName, label }) => { + const matchedConfiguration = data.find( + ({ configurationName: configName }) => + configName === configurationName + ); + const defaultValue = matchedConfiguration + ? matchedConfiguration.defaultValue + : ''; + const savedUiIndexValue = apmIndices[configurationName] || ''; + return ( + + + + ); + })} + + + + + {i18n.translate( + 'xpack.apm.settings.apmIndices.cancelButton', + { defaultMessage: 'Cancel' } + )} + + + + + {i18n.translate( + 'xpack.apm.settings.apmIndices.applyButton', + { defaultMessage: 'Apply changes' } + )} + + + + +
+
+
+ + +
+ ); +} diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/index.tsx new file mode 100644 index 0000000000000..f3be5abe4d48b --- /dev/null +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/index.tsx @@ -0,0 +1,66 @@ +/* + * 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 React from 'react'; +import { i18n } from '@kbn/i18n'; +import { + EuiButtonEmpty, + EuiPage, + EuiSideNav, + EuiPageSideBar, + EuiPageBody +} from '@elastic/eui'; +import { HomeLink } from '../../shared/Links/apm/HomeLink'; +import { useLocation } from '../../../hooks/useLocation'; +import { getAPMHref } from '../../shared/Links/apm/APMLink'; + +export const Settings: React.FC = props => { + const { search, pathname } = useLocation(); + return ( + <> + + + {i18n.translate('xpack.apm.settings.returnToOverviewLinkLabel', { + defaultMessage: 'Return to overview' + })} + + + + + + + {props.children} + + + ); +}; diff --git a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts index 9150c63127317..28b14fa722bbd 100644 --- a/x-pack/legacy/plugins/apm/public/services/rest/ml.ts +++ b/x-pack/legacy/plugins/apm/public/services/rest/ml.ts @@ -4,7 +4,6 @@ * you may not use this file except in compliance with the Elastic License. */ -import { npStart } from 'ui/new_platform'; import { HttpServiceBase } from 'kibana/public'; import { PROCESSOR_EVENT, @@ -14,6 +13,7 @@ import { import { getMlJobId, getMlPrefix } from '../../../common/ml_job_constants'; import { callApi } from './callApi'; import { ESFilter } from '../../../typings/elasticsearch'; +import { createCallApmApi, APMClient } from './createCallApmApi'; interface MlResponseItem { id: string; @@ -32,7 +32,14 @@ interface StartedMLJobApiResponse { jobs: MlResponseItem[]; } -const { core } = npStart; +async function getTransactionIndices(http: HttpServiceBase) { + const callApmApi: APMClient = createCallApmApi(http); + const indices = await callApmApi({ + method: 'GET', + pathname: `/api/apm/settings/apm-indices` + }); + return indices['apm_oss.transactionIndices']; +} export async function startMLJob({ serviceName, @@ -43,9 +50,7 @@ export async function startMLJob({ transactionType: string; http: HttpServiceBase; }) { - const indexPatternName = core.injectedMetadata.getInjectedVar( - 'apmTransactionIndices' - ); + const transactionIndices = await getTransactionIndices(http); const groups = ['apm', serviceName.toLowerCase()]; const filter: ESFilter[] = [ { term: { [SERVICE_NAME]: serviceName } }, @@ -59,7 +64,7 @@ export async function startMLJob({ body: JSON.stringify({ prefix: getMlPrefix(serviceName, transactionType), groups, - indexPatternName, + indexPatternName: transactionIndices, startDatafeed: true, query: { bool: { diff --git a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx index 2e3c8940680fe..a18882120fe75 100644 --- a/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx +++ b/x-pack/legacy/plugins/apm/public/utils/testHelpers.tsx @@ -102,6 +102,15 @@ interface MockSetup { has: any; }; uiFiltersES: ESFilter[]; + indices: { + 'apm_oss.sourcemapIndices': string; + 'apm_oss.errorIndices': string; + 'apm_oss.onboardingIndices': string; + 'apm_oss.spanIndices': string; + 'apm_oss.transactionIndices': string; + 'apm_oss.metricsIndices': string; + 'apm_oss.apmAgentConfigurationIndex': string; + }; } export async function inspectSearchParams( @@ -127,7 +136,16 @@ export async function inspectSearchParams( { term: { 'service.environment': 'prod' } } - ] + ], + indices: { + 'apm_oss.sourcemapIndices': 'myIndex', + 'apm_oss.errorIndices': 'myIndex', + 'apm_oss.onboardingIndices': 'myIndex', + 'apm_oss.spanIndices': 'myIndex', + 'apm_oss.transactionIndices': 'myIndex', + 'apm_oss.metricsIndices': 'myIndex', + 'apm_oss.apmAgentConfigurationIndex': 'myIndex' + } }; try { await fn(mockSetup); diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap index 8d89e22fa9864..d336d71424750 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap +++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/__snapshots__/get_buckets.test.ts.snap @@ -50,7 +50,7 @@ Array [ }, "size": 0, }, - "index": "myIndex", + "index": "apm-*", }, ], ] diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts index 0b8cd8ae8703f..b7081c43465bf 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/__tests__/get_buckets.test.ts @@ -39,7 +39,16 @@ describe('timeseriesFetcher', () => { { term: { 'service.environment': 'prod' } } - ] + ], + indices: { + 'apm_oss.sourcemapIndices': 'apm-*', + 'apm_oss.errorIndices': 'apm-*', + 'apm_oss.onboardingIndices': 'apm-*', + 'apm_oss.spanIndices': 'apm-*', + 'apm_oss.transactionIndices': 'apm-*', + 'apm_oss.metricsIndices': 'apm-*', + 'apm_oss.apmAgentConfigurationIndex': '.apm-agent-configuration' + } } }); }); diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts index 6059f2b0051a7..afb8237178a20 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/distribution/get_buckets.ts @@ -25,7 +25,7 @@ export async function getBuckets({ bucketSize: number; setup: Setup; }) { - const { start, end, uiFiltersES, client, config } = setup; + const { start, end, uiFiltersES, client, indices } = setup; const filter: ESFilter[] = [ { term: { [PROCESSOR_EVENT]: 'error' } }, { term: { [SERVICE_NAME]: serviceName } }, @@ -38,7 +38,7 @@ export async function getBuckets({ } const params = { - index: config.get('apm_oss.errorIndices'), + index: indices['apm_oss.errorIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts index dee5deb4064e4..caadbfef32698 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/get_error_group.ts @@ -29,10 +29,10 @@ export async function getErrorGroup({ groupId: string; setup: Setup; }) { - const { start, end, uiFiltersES, client, config } = setup; + const { start, end, uiFiltersES, client, indices } = setup; const params = { - index: config.get('apm_oss.errorIndices'), + index: indices['apm_oss.errorIndices'], body: { size: 1, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts b/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts index aaac56d16c599..9a6aed02e2a84 100644 --- a/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts +++ b/x-pack/legacy/plugins/apm/server/lib/errors/get_trace_errors_per_transaction.ts @@ -24,10 +24,10 @@ export async function getTraceErrorsPerTransaction( traceId: string, setup: Setup ): Promise { - const { start, end, client, config } = setup; + const { start, end, client, indices } = setup; const params = { - index: config.get('apm_oss.errorIndices'), + index: indices['apm_oss.errorIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts index 9b2c97fab7aa3..84c52b895f20d 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/es_client.ts @@ -12,9 +12,10 @@ import { IndicesCreateParams } from 'elasticsearch'; import { Legacy } from 'kibana'; -import { cloneDeep, has, isString, set } from 'lodash'; +import { cloneDeep, has, isString, set, pick } from 'lodash'; import { OBSERVER_VERSION_MAJOR } from '../../../common/elasticsearch_fieldnames'; -import { StringMap } from '../../../typings/common'; +import { StringMap, Omit } from '../../../typings/common'; +import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; import { ESSearchResponse, ESSearchRequest @@ -23,17 +24,6 @@ import { // `type` was deprecated in 7.0 export type APMIndexDocumentParams = Omit, 'type'>; -function getApmIndices(config: Legacy.KibanaConfig) { - return [ - config.get('apm_oss.errorIndices'), - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.onboardingIndices'), - config.get('apm_oss.sourcemapIndices'), - config.get('apm_oss.spanIndices'), - config.get('apm_oss.transactionIndices') - ]; -} - export function isApmIndex( apmIndices: string[], indexParam: SearchParams['index'] @@ -76,10 +66,23 @@ async function getParamsForSearchRequest( params: SearchParams, apmOptions?: APMOptions ) { - const config = req.server.config(); const uiSettings = req.getUiSettingsService(); - const apmIndices = getApmIndices(config); - const includeFrozen = await uiSettings.get('search:includeFrozen'); + const [indices, includeFrozen] = await Promise.all([ + getApmIndices(req.server), + uiSettings.get('search:includeFrozen') + ]); + + // Get indices for legacy data filter (only those which apply) + const apmIndices: string[] = Object.values( + pick(indices, [ + 'apm_oss.sourcemapIndices', + 'apm_oss.errorIndices', + 'apm_oss.onboardingIndices', + 'apm_oss.spanIndices', + 'apm_oss.transactionIndices', + 'apm_oss.metricsIndices' + ]) + ); return { ...addFilterForLegacyData(apmIndices, params, apmOptions), // filter out pre-7.0 data ignore_throttled: !includeFrozen // whether to query frozen indices or not diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts index 3070d7b00b684..81dd8b34c8847 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/saved_objects_client.ts @@ -6,10 +6,10 @@ import { Server } from 'hapi'; -export function getSavedObjectsClient(server: Server) { +export function getSavedObjectsClient(server: Server, clusterName = 'admin') { const { SavedObjectsClient, getSavedObjectsRepository } = server.savedObjects; const { callWithInternalUser } = server.plugins.elasticsearch.getCluster( - 'admin' + clusterName ); const internalRepository = getSavedObjectsRepository(callWithInternalUser); return new SavedObjectsClient(internalRepository); diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts index e8cf56fcd0802..57de438be7f2a 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.test.ts @@ -3,11 +3,22 @@ * or more contributor license agreements. Licensed under the Elastic License; * you may not use this file except in compliance with the Elastic License. */ - import { Legacy } from 'kibana'; import { setupRequest } from './setup_request'; import { uiSettingsServiceMock } from 'src/core/server/mocks'; +jest.mock('../settings/apm_indices/get_apm_indices', () => ({ + getApmIndices: async () => ({ + 'apm_oss.sourcemapIndices': 'apm-*', + 'apm_oss.errorIndices': 'apm-*', + 'apm_oss.onboardingIndices': 'apm-*', + 'apm_oss.spanIndices': 'apm-*', + 'apm_oss.transactionIndices': 'apm-*', + 'apm_oss.metricsIndices': 'apm-*', + 'apm_oss.apmAgentConfigurationIndex': 'apm-*' + }) +})); + function getMockRequest() { const callWithRequestSpy = jest.fn(); const mockRequest = ({ diff --git a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts index 4054537e04b40..3ec519d5e71b5 100644 --- a/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts +++ b/x-pack/legacy/plugins/apm/server/lib/helpers/setup_request.ts @@ -10,6 +10,7 @@ import moment from 'moment'; import { getESClient } from './es_client'; import { getUiFiltersES } from './convert_ui_filters/get_ui_filters_es'; import { PromiseReturnType } from '../../../typings/common'; +import { getApmIndices } from '../settings/apm_indices/get_apm_indices'; function decodeUiFilters(server: Server, uiFiltersEncoded?: string) { if (!uiFiltersEncoded) { @@ -31,12 +32,17 @@ export async function setupRequest(req: Legacy.Request) { const query = (req.query as unknown) as APMRequestQuery; const { server } = req; const config = server.config(); + const [uiFiltersES, indices] = await Promise.all([ + decodeUiFilters(server, query.uiFilters), + getApmIndices(server) + ]); return { start: moment.utc(query.start).valueOf(), end: moment.utc(query.end).valueOf(), - uiFiltersES: await decodeUiFilters(server, query.uiFilters), + uiFiltersES, client: getESClient(req), - config + config, + indices }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap b/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap index 71217ccc36f7b..acd5dc119b737 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap +++ b/x-pack/legacy/plugins/apm/server/lib/services/__snapshots__/queries.test.ts.snap @@ -56,9 +56,7 @@ Object { }, "size": 0, }, - "index": Array [ - "myIndex", - ], + "index": "myIndex", "terminateAfter": 1, } `; @@ -228,8 +226,6 @@ Object { }, "size": 0, }, - "index": Array [ - "myIndex", - ], + "index": "myIndex", } `; diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts index b39e35a305b19..bbb18eae7eb09 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_service_agent_name.ts @@ -13,14 +13,14 @@ import { rangeFilter } from '../helpers/range_filter'; import { Setup } from '../helpers/setup_request'; export async function getServiceAgentName(serviceName: string, setup: Setup) { - const { start, end, client, config } = setup; + const { start, end, client, indices } = setup; const params = { terminateAfter: 1, index: [ - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices'), - config.get('apm_oss.metricsIndices') + indices['apm_oss.errorIndices'], + indices['apm_oss.transactionIndices'], + indices['apm_oss.metricsIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts index 9d651247d5cee..00ffa7484bb48 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_service_transaction_types.ts @@ -16,10 +16,10 @@ export async function getServiceTransactionTypes( serviceName: string, setup: Setup ) { - const { start, end, client, config } = setup; + const { start, end, client, indices } = setup; const params = { - index: [config.get('apm_oss.transactionIndices')], + index: indices['apm_oss.transactionIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts index f9a7671abd994..6c28d19a14711 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_agent_status.ts @@ -9,15 +9,15 @@ import { Setup } from '../../helpers/setup_request'; // Note: this logic is duplicated in tutorials/apm/envs/on_prem export async function getAgentStatus(setup: Setup) { - const { client, config } = setup; + const { client, indices } = setup; const params = { terminateAfter: 1, index: [ - config.get('apm_oss.errorIndices'), - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.sourcemapIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.errorIndices'], + indices['apm_oss.metricsIndices'], + indices['apm_oss.sourcemapIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts index 1379d79326add..5497eaa13d34b 100644 --- a/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts +++ b/x-pack/legacy/plugins/apm/server/lib/services/get_services/get_legacy_data_status.ts @@ -12,11 +12,11 @@ import { Setup } from '../../helpers/setup_request'; // returns true if 6.x data is found export async function getLegacyDataStatus(setup: Setup) { - const { client, config } = setup; + const { client, indices } = setup; const params = { terminateAfter: 1, - index: [config.get('apm_oss.transactionIndices')], + index: indices['apm_oss.transactionIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts index 4226c073b1de0..861732ee03923 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_agent_config_index.ts @@ -6,15 +6,15 @@ import { InternalCoreSetup } from 'src/core/server'; import { CallCluster } from '../../../../../../../../src/legacy/core_plugins/elasticsearch'; +import { getApmIndices } from '../apm_indices/get_apm_indices'; export async function createApmAgentConfigurationIndex( core: InternalCoreSetup ) { try { const { server } = core.http; - const index = server - .config() - .get('apm_oss.apmAgentConfigurationIndex'); + const indices = await getApmIndices(server); + const index = indices['apm_oss.apmAgentConfigurationIndex']; const { callWithInternalUser } = server.plugins.elasticsearch.getCluster( 'admin' ); diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts index 9f0d8e2f1c718..25a4f5141498f 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/create_or_update_configuration.ts @@ -21,11 +21,11 @@ export async function createOrUpdateConfiguration({ >; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; const params: APMIndexDocumentParams = { refresh: true, - index: config.get('apm_oss.apmAgentConfigurationIndex'), + index: indices['apm_oss.apmAgentConfigurationIndex'], body: { agent_name: configuration.agent_name, service: { diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts index 82b192125a5cf..896363c054ba7 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/delete_configuration.ts @@ -13,11 +13,11 @@ export async function deleteConfiguration({ configurationId: string; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; const params = { refresh: 'wait_for', - index: config.get('apm_oss.apmAgentConfigurationIndex'), + index: indices['apm_oss.apmAgentConfigurationIndex'], id: configurationId }; diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts index 7742bc938816f..21663b813f01f 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_agent_name_by_service.ts @@ -19,14 +19,14 @@ export async function getAgentNameByService({ serviceName: string; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; const params = { terminateAfter: 1, index: [ - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.metricsIndices'], + indices['apm_oss.errorIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts index aad31feef000b..8215e2b9fd668 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_all_environments.ts @@ -20,7 +20,7 @@ export async function getAllEnvironments({ serviceName: string | undefined; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; // omit filter for service.name if "All" option is selected const serviceNameFilter = serviceName @@ -29,9 +29,9 @@ export async function getAllEnvironments({ const params = { index: [ - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.metricsIndices'], + indices['apm_oss.errorIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts index 6b557f21f3457..d5aa389cea335 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_environments/get_existing_environments_for_service.ts @@ -19,14 +19,14 @@ export async function getExistingEnvironmentsForService({ serviceName: string | undefined; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; const bool = serviceName ? { filter: [{ term: { [SERVICE_NAME]: serviceName } }] } : { must_not: [{ exists: { field: SERVICE_NAME } }] }; const params = { - index: config.get('apm_oss.apmAgentConfigurationIndex'), + index: indices['apm_oss.apmAgentConfigurationIndex'], body: { size: 0, query: { bool }, diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts index dfc1041c96488..51a4564f53576 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/get_service_names.ts @@ -17,13 +17,13 @@ export type AgentConfigurationServicesAPIResponse = PromiseReturnType< typeof getServiceNames >; export async function getServiceNames({ setup }: { setup: Setup }) { - const { client, config } = setup; + const { client, indices } = setup; const params = { index: [ - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.metricsIndices'], + indices['apm_oss.errorIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts index 9edceb86dda8d..283f30b51441d 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/list_configurations.ts @@ -12,10 +12,10 @@ export type AgentConfigurationListAPIResponse = PromiseReturnType< typeof listConfigurations >; export async function listConfigurations({ setup }: { setup: Setup }) { - const { client, config } = setup; + const { client, indices } = setup; const params = { - index: config.get('apm_oss.apmAgentConfigurationIndex') + index: indices['apm_oss.apmAgentConfigurationIndex'] }; const resp = await client.search(params); diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts index 867045142cea0..e5349edb67f30 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/mark_applied_by_agent.ts @@ -16,10 +16,10 @@ export async function markAppliedByAgent({ body: AgentConfiguration; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; const params = { - index: config.get('apm_oss.apmAgentConfigurationIndex'), + index: indices['apm_oss.apmAgentConfigurationIndex'], id, // by specifying the `id` elasticsearch will do an "upsert" body: { ...body, diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts index e8db37891e7ae..400bd0207771a 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.test.ts @@ -15,7 +15,18 @@ describe('search configurations', () => { environment: 'production', setup: ({ config: { get: () => '' }, - client: { search: async () => searchMocks } + client: { search: async () => searchMocks }, + indices: { + apm_oss: { + sourcemapIndices: 'myIndex', + errorIndices: 'myIndex', + onboardingIndices: 'myIndex', + spanIndices: 'myIndex', + transactionIndices: 'myIndex', + metricsIndices: 'myIndex', + apmAgentConfigurationIndex: 'myIndex' + } + } } as unknown) as Setup }); @@ -29,7 +40,18 @@ describe('search configurations', () => { environment: 'production', setup: ({ config: { get: () => '' }, - client: { search: async () => searchMocks } + client: { search: async () => searchMocks }, + indices: { + apm_oss: { + sourcemapIndices: 'myIndex', + errorIndices: 'myIndex', + onboardingIndices: 'myIndex', + spanIndices: 'myIndex', + transactionIndices: 'myIndex', + metricsIndices: 'myIndex', + apmAgentConfigurationIndex: 'myIndex' + } + } } as unknown) as Setup }); diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts index 6b0dc370dd878..35d76d745cf4f 100644 --- a/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts +++ b/x-pack/legacy/plugins/apm/server/lib/settings/agent_configuration/search.ts @@ -20,7 +20,7 @@ export async function searchConfigurations({ environment?: string; setup: Setup; }) { - const { client, config } = setup; + const { client, indices } = setup; // sorting order // 1. exact match: service.name AND service.environment (eg. opbeans-node / production) @@ -33,7 +33,7 @@ export async function searchConfigurations({ : []; const params = { - index: config.get('apm_oss.apmAgentConfigurationIndex'), + index: indices['apm_oss.apmAgentConfigurationIndex'], body: { query: { bool: { diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts new file mode 100644 index 0000000000000..cd237a5264099 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/get_apm_indices.ts @@ -0,0 +1,101 @@ +/* + * 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 { Server } from 'hapi'; +import { merge } from 'lodash'; +import { KibanaConfig } from 'src/legacy/server/kbn_server'; +import { getSavedObjectsClient } from '../../helpers/saved_objects_client'; +import { Setup } from '../../helpers/setup_request'; +import { PromiseReturnType } from '../../../../typings/common'; + +export interface ApmIndicesConfig { + 'apm_oss.sourcemapIndices': string; + 'apm_oss.errorIndices': string; + 'apm_oss.onboardingIndices': string; + 'apm_oss.spanIndices': string; + 'apm_oss.transactionIndices': string; + 'apm_oss.metricsIndices': string; + 'apm_oss.apmAgentConfigurationIndex': string; +} + +export type ApmIndicesName = keyof ApmIndicesConfig; + +export const APM_INDICES_SAVED_OBJECT_TYPE = 'apm-indices'; +export const APM_INDICES_SAVED_OBJECT_ID = 'apm-indices'; + +async function getApmIndicesSavedObject(server: Server) { + const savedObjectsClient = getSavedObjectsClient(server, 'data'); + const apmIndices = await savedObjectsClient.get>( + APM_INDICES_SAVED_OBJECT_TYPE, + APM_INDICES_SAVED_OBJECT_ID + ); + return apmIndices.attributes; +} + +function getApmIndicesConfig(config: KibanaConfig): ApmIndicesConfig { + return { + 'apm_oss.sourcemapIndices': config.get('apm_oss.sourcemapIndices'), + 'apm_oss.errorIndices': config.get('apm_oss.errorIndices'), + 'apm_oss.onboardingIndices': config.get( + 'apm_oss.onboardingIndices' + ), + 'apm_oss.spanIndices': config.get('apm_oss.spanIndices'), + 'apm_oss.transactionIndices': config.get( + 'apm_oss.transactionIndices' + ), + 'apm_oss.metricsIndices': config.get('apm_oss.metricsIndices'), + 'apm_oss.apmAgentConfigurationIndex': config.get( + 'apm_oss.apmAgentConfigurationIndex' + ) + }; +} + +export async function getApmIndices(server: Server) { + try { + const apmIndicesSavedObject = await getApmIndicesSavedObject(server); + const apmIndicesConfig = getApmIndicesConfig(server.config()); + return merge({}, apmIndicesConfig, apmIndicesSavedObject); + } catch (error) { + return getApmIndicesConfig(server.config()); + } +} + +const APM_UI_INDICES: ApmIndicesName[] = [ + 'apm_oss.sourcemapIndices', + 'apm_oss.errorIndices', + 'apm_oss.onboardingIndices', + 'apm_oss.spanIndices', + 'apm_oss.transactionIndices', + 'apm_oss.metricsIndices', + 'apm_oss.apmAgentConfigurationIndex' +]; + +export async function getApmIndexSettings({ + setup, + server +}: { + setup: Setup; + server: Server; +}) { + const { config } = setup; + let apmIndicesSavedObject: PromiseReturnType; + try { + apmIndicesSavedObject = await getApmIndicesSavedObject(server); + } catch (error) { + if (error.output && error.output.statusCode === 404) { + apmIndicesSavedObject = {}; + } else { + throw error; + } + } + const apmIndicesConfig = getApmIndicesConfig(config); + + return APM_UI_INDICES.map(configurationName => ({ + configurationName, + defaultValue: apmIndicesConfig[configurationName], // value defined in kibana[.dev].yml + savedValue: apmIndicesSavedObject[configurationName] // value saved via Saved Objects service + })); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts new file mode 100644 index 0000000000000..8de47c5c44144 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/lib/settings/apm_indices/save_apm_indices.ts @@ -0,0 +1,28 @@ +/* + * 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 { Server } from 'hapi'; +import { getSavedObjectsClient } from '../../helpers/saved_objects_client'; +import { + ApmIndicesConfig, + APM_INDICES_SAVED_OBJECT_TYPE, + APM_INDICES_SAVED_OBJECT_ID +} from './get_apm_indices'; + +export async function saveApmIndices( + server: Server, + apmIndicesSavedObject: Partial +) { + const savedObjectsClient = getSavedObjectsClient(server, 'data'); + return await savedObjectsClient.create( + APM_INDICES_SAVED_OBJECT_TYPE, + apmIndicesSavedObject, + { + id: APM_INDICES_SAVED_OBJECT_ID, + overwrite: true + } + ); +} diff --git a/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts b/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts index 71b65982db9f0..0df5cc016431d 100644 --- a/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts +++ b/x-pack/legacy/plugins/apm/server/lib/traces/get_trace_items.ts @@ -17,13 +17,13 @@ import { rangeFilter } from '../helpers/range_filter'; import { Setup } from '../helpers/setup_request'; export async function getTraceItems(traceId: string, setup: Setup) { - const { start, end, client, config } = setup; + const { start, end, client, config, indices } = setup; const maxTraceItems = config.get('xpack.apm.ui.maxTraceItems'); const params = { index: [ - config.get('apm_oss.spanIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.spanIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: maxTraceItems, diff --git a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts index fc7b1b4127892..99553690359cf 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transaction_groups/fetcher.test.ts @@ -16,15 +16,22 @@ function getSetup() { config: { get: jest.fn((key: string) => { switch (key) { - case 'apm_oss.transactionIndices': - return 'myIndex'; case 'xpack.apm.ui.transactionGroupBucketSize': return 100; } }), has: () => true }, - uiFiltersES: [{ term: { 'service.environment': 'test' } }] + uiFiltersES: [{ term: { 'service.environment': 'test' } }], + indices: { + 'apm_oss.sourcemapIndices': 'myIndex', + 'apm_oss.errorIndices': 'myIndex', + 'apm_oss.onboardingIndices': 'myIndex', + 'apm_oss.spanIndices': 'myIndex', + 'apm_oss.transactionIndices': 'myIndex', + 'apm_oss.metricsIndices': 'myIndex', + 'apm_oss.apmAgentConfigurationIndex': 'myIndex' + } }; } diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts index e2989498181ca..e092942a25ba6 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/avg_duration_by_country/index.ts @@ -21,9 +21,9 @@ export async function getTransactionAvgDurationByCountry({ setup: Setup; serviceName: string; }) { - const { uiFiltersES, client, config, start, end } = setup; + const { uiFiltersES, client, start, end, indices } = setup; const params = { - index: config.get('apm_oss.transactionIndices'), + index: indices['apm_oss.transactionIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts index e707ce3eafe18..67816d67a29a2 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.test.ts @@ -9,6 +9,16 @@ import * as constants from './constants'; import noDataResponse from './mock-responses/noData.json'; import dataResponse from './mock-responses/data.json'; +const mockIndices = { + 'apm_oss.sourcemapIndices': 'myIndex', + 'apm_oss.errorIndices': 'myIndex', + 'apm_oss.onboardingIndices': 'myIndex', + 'apm_oss.spanIndices': 'myIndex', + 'apm_oss.transactionIndices': 'myIndex', + 'apm_oss.metricsIndices': 'myIndex', + 'apm_oss.apmAgentConfigurationIndex': 'myIndex' +}; + describe('getTransactionBreakdown', () => { it('returns an empty array if no data is available', async () => { const clientSpy = jest.fn().mockReturnValueOnce(noDataResponse); @@ -24,7 +34,8 @@ describe('getTransactionBreakdown', () => { get: () => 'myIndex' as any, has: () => true }, - uiFiltersES: [] + uiFiltersES: [], + indices: mockIndices } }); @@ -47,7 +58,8 @@ describe('getTransactionBreakdown', () => { get: () => 'myIndex' as any, has: () => true }, - uiFiltersES: [] + uiFiltersES: [], + indices: mockIndices } }); @@ -87,7 +99,8 @@ describe('getTransactionBreakdown', () => { get: () => 'myIndex' as any, has: () => true }, - uiFiltersES: [] + uiFiltersES: [], + indices: mockIndices } }); @@ -126,7 +139,8 @@ describe('getTransactionBreakdown', () => { get: () => 'myIndex' as any, has: () => true }, - uiFiltersES: [] + uiFiltersES: [], + indices: mockIndices } }); @@ -149,7 +163,8 @@ describe('getTransactionBreakdown', () => { get: () => 'myIndex' as any, has: () => true }, - uiFiltersES: [] + uiFiltersES: [], + indices: mockIndices } }); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts index ecf963fec3fe9..a21c4f38ac30c 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/breakdown/index.ts @@ -32,7 +32,7 @@ export async function getTransactionBreakdown({ transactionName?: string; transactionType: string; }) { - const { uiFiltersES, client, config, start, end } = setup; + const { uiFiltersES, client, start, end, indices } = setup; const subAggs = { sum_all_self_times: { @@ -88,7 +88,7 @@ export async function getTransactionBreakdown({ } const params = { - index: config.get('apm_oss.metricsIndices'), + index: indices['apm_oss.metricsIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts index 07f1d96618198..cddc66e52cf70 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_anomaly_data/index.test.ts @@ -30,7 +30,16 @@ describe('getAnomalySeries', () => { get: () => 'myIndex' as any, has: () => true }, - uiFiltersES: [] + uiFiltersES: [], + indices: { + 'apm_oss.sourcemapIndices': 'myIndex', + 'apm_oss.errorIndices': 'myIndex', + 'apm_oss.onboardingIndices': 'myIndex', + 'apm_oss.spanIndices': 'myIndex', + 'apm_oss.transactionIndices': 'myIndex', + 'apm_oss.metricsIndices': 'myIndex', + 'apm_oss.apmAgentConfigurationIndex': 'myIndex' + } } }); }); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts index dc568d653a5ee..5056a100de3ce 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.test.ts @@ -29,7 +29,16 @@ describe('timeseriesFetcher', () => { { term: { 'service.environment': 'test' } } - ] + ], + indices: { + 'apm_oss.sourcemapIndices': 'myIndex', + 'apm_oss.errorIndices': 'myIndex', + 'apm_oss.onboardingIndices': 'myIndex', + 'apm_oss.spanIndices': 'myIndex', + 'apm_oss.transactionIndices': 'myIndex', + 'apm_oss.metricsIndices': 'myIndex', + 'apm_oss.apmAgentConfigurationIndex': 'myIndex' + } } }); }); diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts index 97368b7d92efc..0d9cccb3b56d3 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/charts/get_timeseries_data/fetcher.ts @@ -30,7 +30,7 @@ export function timeseriesFetcher({ transactionName: string | undefined; setup: Setup; }) { - const { start, end, uiFiltersES, client, config } = setup; + const { start, end, uiFiltersES, client, indices } = setup; const { intervalString } = getBucketSize(start, end, 'auto'); const filter: ESFilter[] = [ @@ -50,7 +50,7 @@ export function timeseriesFetcher({ } const params = { - index: config.get('apm_oss.transactionIndices'), + index: indices['apm_oss.transactionIndices'], body: { size: 0, query: { bool: { filter } }, diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts index 42b35402aab9d..90d9a925a1f36 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_buckets/fetcher.ts @@ -28,10 +28,10 @@ export async function bucketFetcher( bucketSize: number, setup: Setup ) { - const { start, end, uiFiltersES, client, config } = setup; + const { start, end, uiFiltersES, client, indices } = setup; const params = { - index: config.get('apm_oss.transactionIndices'), + index: indices['apm_oss.transactionIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts index f49cf2b8c8541..a54fa9c10de13 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/distribution/get_distribution_max.ts @@ -19,10 +19,10 @@ export async function getDistributionMax( transactionType: string, setup: Setup ) { - const { start, end, uiFiltersES, client, config } = setup; + const { start, end, uiFiltersES, client, indices } = setup; const params = { - index: config.get('apm_oss.transactionIndices'), + index: indices['apm_oss.transactionIndices'], body: { size: 0, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts b/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts index cdaddc3af3e95..20152ecf06480 100644 --- a/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts +++ b/x-pack/legacy/plugins/apm/server/lib/transactions/get_transaction/index.ts @@ -19,10 +19,10 @@ export async function getTransaction( traceId: string, setup: Setup ) { - const { start, end, uiFiltersES, client, config } = setup; + const { start, end, uiFiltersES, client, indices } = setup; const params = { - index: config.get('apm_oss.transactionIndices'), + index: indices['apm_oss.transactionIndices'], body: { size: 1, query: { diff --git a/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts b/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts index 80795ce468c88..ade491be32fc7 100644 --- a/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts +++ b/x-pack/legacy/plugins/apm/server/lib/ui_filters/get_environments.ts @@ -16,7 +16,7 @@ import { ENVIRONMENT_NOT_DEFINED } from '../../../common/environment_filter_valu import { ESFilter } from '../../../typings/elasticsearch'; export async function getEnvironments(setup: Setup, serviceName?: string) { - const { start, end, client, config } = setup; + const { start, end, client, indices } = setup; const filter: ESFilter[] = [ { terms: { [PROCESSOR_EVENT]: ['transaction', 'error', 'metric'] } }, @@ -31,9 +31,9 @@ export async function getEnvironments(setup: Setup, serviceName?: string) { const params = { index: [ - config.get('apm_oss.metricsIndices'), - config.get('apm_oss.errorIndices'), - config.get('apm_oss.transactionIndices') + indices['apm_oss.metricsIndices'], + indices['apm_oss.errorIndices'], + indices['apm_oss.transactionIndices'] ], body: { size: 0, diff --git a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts index 682ebf27207c4..516f1994c2fb7 100644 --- a/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts +++ b/x-pack/legacy/plugins/apm/server/routes/create_apm_api.ts @@ -25,7 +25,12 @@ import { listAgentConfigurationServicesRoute, updateAgentConfigurationRoute, agentConfigurationAgentNameRoute -} from './settings'; +} from './settings/agent_configuration'; +import { + apmIndexSettingsRoute, + apmIndicesRoute, + saveApmIndicesRoute +} from './settings/apm_indices'; import { metricsChartsRoute } from './metrics'; import { serviceNodesRoute } from './service_nodes'; import { tracesRoute, tracesByIdRoute } from './traces'; @@ -75,6 +80,11 @@ const createApmApi = () => { .add(listAgentConfigurationServicesRoute) .add(updateAgentConfigurationRoute) + // APM indices + .add(apmIndexSettingsRoute) + .add(apmIndicesRoute) + .add(saveApmIndicesRoute) + // Metrics .add(metricsChartsRoute) .add(serviceNodesRoute) diff --git a/x-pack/legacy/plugins/apm/server/routes/settings.ts b/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts similarity index 80% rename from x-pack/legacy/plugins/apm/server/routes/settings.ts rename to x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts index 65ef5df78f3e1..d25ad949d6dde 100644 --- a/x-pack/legacy/plugins/apm/server/routes/settings.ts +++ b/x-pack/legacy/plugins/apm/server/routes/settings/agent_configuration.ts @@ -5,18 +5,18 @@ */ import * as t from 'io-ts'; -import { setupRequest } from '../lib/helpers/setup_request'; -import { getServiceNames } from '../lib/settings/agent_configuration/get_service_names'; -import { createOrUpdateConfiguration } from '../lib/settings/agent_configuration/create_or_update_configuration'; -import { searchConfigurations } from '../lib/settings/agent_configuration/search'; -import { listConfigurations } from '../lib/settings/agent_configuration/list_configurations'; -import { getEnvironments } from '../lib/settings/agent_configuration/get_environments'; -import { deleteConfiguration } from '../lib/settings/agent_configuration/delete_configuration'; -import { createRoute } from './create_route'; -import { transactionSampleRateRt } from '../../common/runtime_types/transaction_sample_rate_rt'; -import { transactionMaxSpansRt } from '../../common/runtime_types/transaction_max_spans_rt'; -import { getAgentNameByService } from '../lib/settings/agent_configuration/get_agent_name_by_service'; -import { markAppliedByAgent } from '../lib/settings/agent_configuration/mark_applied_by_agent'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { getServiceNames } from '../../lib/settings/agent_configuration/get_service_names'; +import { createOrUpdateConfiguration } from '../../lib/settings/agent_configuration/create_or_update_configuration'; +import { searchConfigurations } from '../../lib/settings/agent_configuration/search'; +import { listConfigurations } from '../../lib/settings/agent_configuration/list_configurations'; +import { getEnvironments } from '../../lib/settings/agent_configuration/get_environments'; +import { deleteConfiguration } from '../../lib/settings/agent_configuration/delete_configuration'; +import { createRoute } from '../create_route'; +import { transactionSampleRateRt } from '../../../common/runtime_types/transaction_sample_rate_rt'; +import { transactionMaxSpansRt } from '../../../common/runtime_types/transaction_max_spans_rt'; +import { getAgentNameByService } from '../../lib/settings/agent_configuration/get_agent_name_by_service'; +import { markAppliedByAgent } from '../../lib/settings/agent_configuration/mark_applied_by_agent'; // get list of configurations export const agentConfigurationRoute = createRoute(core => ({ diff --git a/x-pack/legacy/plugins/apm/server/routes/settings/apm_indices.ts b/x-pack/legacy/plugins/apm/server/routes/settings/apm_indices.ts new file mode 100644 index 0000000000000..3c82a35ec7903 --- /dev/null +++ b/x-pack/legacy/plugins/apm/server/routes/settings/apm_indices.ts @@ -0,0 +1,56 @@ +/* + * 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 * as t from 'io-ts'; +import { setupRequest } from '../../lib/helpers/setup_request'; +import { createRoute } from '../create_route'; +import { + getApmIndices, + getApmIndexSettings +} from '../../lib/settings/apm_indices/get_apm_indices'; +import { saveApmIndices } from '../../lib/settings/apm_indices/save_apm_indices'; + +// get list of apm indices and values +export const apmIndexSettingsRoute = createRoute(core => ({ + method: 'GET', + path: '/api/apm/settings/apm-index-settings', + handler: async req => { + const { server } = core.http; + const setup = await setupRequest(req); + return await getApmIndexSettings({ setup, server }); + } +})); + +// get apm indices configuration object +export const apmIndicesRoute = createRoute(core => ({ + method: 'GET', + path: '/api/apm/settings/apm-indices', + handler: async req => { + const { server } = core.http; + return await getApmIndices(server); + } +})); + +// save ui indices +export const saveApmIndicesRoute = createRoute(core => ({ + method: 'POST', + path: '/api/apm/settings/apm-indices/save', + params: { + body: t.partial({ + 'apm_oss.sourcemapIndices': t.string, + 'apm_oss.errorIndices': t.string, + 'apm_oss.onboardingIndices': t.string, + 'apm_oss.spanIndices': t.string, + 'apm_oss.transactionIndices': t.string, + 'apm_oss.metricsIndices': t.string, + 'apm_oss.apmAgentConfigurationIndex': t.string + }) + }, + handler: async (req, { body }) => { + const { server } = core.http; + return await saveApmIndices(server, body); + } +})); diff --git a/x-pack/plugins/translations/translations/ja-JP.json b/x-pack/plugins/translations/translations/ja-JP.json index 55f3fdf1087e4..78c128daafff5 100644 --- a/x-pack/plugins/translations/translations/ja-JP.json +++ b/x-pack/plugins/translations/translations/ja-JP.json @@ -3455,8 +3455,6 @@ "xpack.apm.settings.agentConf.configTable.serviceNameColumnLabel": "サービス名", "xpack.apm.settings.agentConf.configurationsPanelTitle": "構成", "xpack.apm.settings.agentConf.createConfigButtonLabel": "構成の作成", - "xpack.apm.settings.agentConf.pageTitle": "設定", - "xpack.apm.settings.agentConf.returnToOverviewLinkLabel": "概要に戻る", "xpack.apm.transactionDetails.traceNotFound": "選択されたトレースが見つかりません", "xpack.apm.transactionDetails.traceSampleTitle": "トレースのサンプル", "xpack.apm.transactionsTable.notFoundLabel": "トランザクションが見つかりませんでした。", diff --git a/x-pack/plugins/translations/translations/zh-CN.json b/x-pack/plugins/translations/translations/zh-CN.json index f822e90ec3973..dc72e6cf4becd 100644 --- a/x-pack/plugins/translations/translations/zh-CN.json +++ b/x-pack/plugins/translations/translations/zh-CN.json @@ -3456,8 +3456,6 @@ "xpack.apm.settings.agentConf.configTable.serviceNameColumnLabel": "服务名称", "xpack.apm.settings.agentConf.configurationsPanelTitle": "配置", "xpack.apm.settings.agentConf.createConfigButtonLabel": "创建配置", - "xpack.apm.settings.agentConf.pageTitle": "设置", - "xpack.apm.settings.agentConf.returnToOverviewLinkLabel": "返回至概览", "xpack.apm.transactionDetails.traceNotFound": "找不到所选跟踪", "xpack.apm.transactionDetails.traceSampleTitle": "跟踪样例", "xpack.apm.transactionsTable.notFoundLabel": "未找到任何事务。",