diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/ServiceSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/ServiceSection.tsx index eee2c5ecec5c1fa..5e4c52558e5232c 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/ServiceSection.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/ServiceSection.tsx @@ -10,7 +10,6 @@ import { i18n } from '@kbn/i18n'; import { SelectWithPlaceholder } from '../../../../shared/SelectWithPlaceholder'; import { useFetcher } from '../../../../../hooks/useFetcher'; import { ENVIRONMENT_NOT_DEFINED } from '../../../../../../common/environment_filter_values'; -import { Config } from '../index'; import { callApmApi } from '../../../../../services/rest/callApmApi'; const t = (id: string, defaultMessage: string) => i18n.translate(`xpack.apm.settings.agentConf.flyOut.serviceSection.${id}`, { @@ -20,33 +19,41 @@ const t = (id: string, defaultMessage: string) => const SELECT_PLACEHOLDER_LABEL = `- ${t('selectPlaceholder', 'Select')} -`; interface Props { - selectedConfig: Config | null; - environment?: string; - setEnvironment: (env: string) => void; + isReadOnly: boolean; serviceName?: string; setServiceName: (env: string) => void; + environment?: string; + setEnvironment: (env: string) => void; +} + +function getEnvironmentNameLabel(name: string | undefined) { + return name === ENVIRONMENT_NOT_DEFINED + ? t('serviceEnvironmentNotSetOptionLabel', 'Not set') + : name; } export function ServiceSection({ - selectedConfig, - environment, - setEnvironment, + isReadOnly, serviceName, - setServiceName + setServiceName, + environment, + setEnvironment }: Props) { const { data: serviceNames = [], status: serviceNamesStatus } = useFetcher( () => { - return callApmApi({ - pathname: '/api/apm/settings/agent-configuration/services', - forceCache: true - }); + if (!isReadOnly) { + return callApmApi({ + pathname: '/api/apm/settings/agent-configuration/services', + forceCache: true + }); + } }, - [], + [isReadOnly], { preservePreviousData: false } ); const { data: environments = [], status: environmentStatus } = useFetcher( () => { - if (serviceName) { + if (!isReadOnly && serviceName) { return callApmApi({ pathname: '/api/apm/settings/agent-configuration/services/{serviceName}/environments', @@ -54,16 +61,13 @@ export function ServiceSection({ }); } }, - [serviceName], + [isReadOnly, serviceName], { preservePreviousData: false } ); const environmentOptions = environments.map(({ name, alreadyExists }) => ({ disabled: alreadyExists, - text: - name === ENVIRONMENT_NOT_DEFINED - ? t('serviceEnvironmentNotSetOptionLabel', 'Not set') - : name, + text: getEnvironmentNameLabel(name), value: name })); @@ -77,47 +81,57 @@ export function ServiceSection({ - ({ text }))} - value={serviceName} - disabled={Boolean(selectedConfig) || serviceNamesStatus === 'loading'} - onChange={e => { - e.preventDefault(); - setServiceName(e.target.value); - setEnvironment(''); - }} - /> + {isReadOnly ? ( + {serviceName} + ) : ( + ({ text }))} + value={serviceName} + disabled={serviceNamesStatus === 'loading'} + onChange={e => { + e.preventDefault(); + setServiceName(e.target.value); + setEnvironment(''); + }} + /> + )} - { - e.preventDefault(); - setEnvironment(e.target.value); - }} - /> + {isReadOnly ? ( + {getEnvironmentNameLabel(environment)} + ) : ( + { + e.preventDefault(); + setEnvironment(e.target.value); + }} + /> + )} ); diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/SettingsSection.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/SettingsSection.tsx index 25d96d3fadfc25b..4b5ddd164a6489c 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/SettingsSection.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/SettingsSection.tsx @@ -15,33 +15,46 @@ import { import { i18n } from '@kbn/i18n'; import { isEmpty } from 'lodash'; import { SelectWithPlaceholder } from '../../../../shared/SelectWithPlaceholder'; -import { isRumAgentName } from '../../../../../../common/agent_name'; const t = (id: string, defaultMessage: string) => i18n.translate(`xpack.apm.settings.agentConf.flyOut.settingsSection.${id}`, { defaultMessage }); -interface ConfigOption { - value: string; - set: (value: string) => void; - isValid?: boolean; -} - interface Props { - sampleRate: ConfigOption; - captureBody: ConfigOption; - transactionMaxSpans: ConfigOption; - agentName: string | undefined; + isRumService: boolean; + + // sampleRate + sampleRate: string; + setSampleRate: (value: string) => void; + isSampleRateValid?: boolean; + + // captureBody + captureBody: string; + setCaptureBody: (value: string) => void; + + // transactionMaxSpans + transactionMaxSpans: string; + setTransactionMaxSpans: (value: string) => void; + isTransactionMaxSpansValid?: boolean; } export function SettingsSection({ + isRumService, + + // sampleRate sampleRate, + setSampleRate, + isSampleRateValid, + + // captureBody captureBody, + setCaptureBody, + + // transactionMaxSpans transactionMaxSpans, - agentName + setTransactionMaxSpans, + isTransactionMaxSpansValid }: Props) { - const isRumService = isRumAgentName(agentName); - return ( <> @@ -63,17 +76,17 @@ export function SettingsSection({ 'sampleRateConfigurationInputErrorText', 'Sample rate must be between 0.000 and 1' )} - isInvalid={!isEmpty(sampleRate.value) && !sampleRate.isValid} + isInvalid={!isEmpty(sampleRate) && !isSampleRateValid} > { e.preventDefault(); - sampleRate.set(e.target.value); + setSampleRate(e.target.value); }} /> @@ -108,10 +121,10 @@ export function SettingsSection({ text: t('captureBodyConfigOptionAll', 'All') } ]} - value={captureBody.value} + value={captureBody} onChange={e => { e.preventDefault(); - captureBody.set(e.target.value); + setCaptureBody(e.target.value); }} /> @@ -132,7 +145,7 @@ export function SettingsSection({ 'Must be between 0 and 32000' )} isInvalid={ - !isEmpty(transactionMaxSpans.value) && !transactionMaxSpans.isValid + !isEmpty(transactionMaxSpans) && !isTransactionMaxSpansValid } > { e.preventDefault(); - transactionMaxSpans.set(e.target.value); + setTransactionMaxSpans(e.target.value); }} /> diff --git a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/index.tsx b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/index.tsx index 4141325fbf359bc..10b590bd5f940d1 100644 --- a/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/index.tsx +++ b/x-pack/legacy/plugins/apm/public/components/app/Settings/AgentConfigurations/AddEditFlyout/index.tsx @@ -34,12 +34,25 @@ import { ServiceSection } from './ServiceSection'; import { DeleteSection } from './DeleteSection'; import { transactionMaxSpansRt } from '../../../../../../common/runtime_types/transaction_max_spans_rt'; import { useFetcher } from '../../../../../hooks/useFetcher'; +import { isRumAgentName } from '../../../../../../common/agent_name'; const t = (id: string, defaultMessage: string, values?: Record) => i18n.translate(`xpack.apm.settings.agentConf.${id}`, { defaultMessage, values }); +interface Settings { + transaction_sample_rate: number; + capture_body?: string; + transaction_max_spans?: number; +} + +const defaultSettings = { + TRANSACTION_SAMPLE_RATE: '1.0', + CAPTURE_BODY: 'off', + TRANSACTION_MAX_SPANS: '500' +}; + interface Props { onClose: () => void; onSaved: () => void; @@ -80,32 +93,34 @@ export function AddEditFlyout({ ); // config settings - const initialSampleRate = idx( - selectedConfig, - _ => _.settings.transaction_sample_rate - ); const [sampleRate, setSampleRate] = useState( - initialSampleRate != null ? String(initialSampleRate) : '' + ( + idx(selectedConfig, _ => _.settings.transaction_sample_rate) || + defaultSettings.TRANSACTION_SAMPLE_RATE + ).toString() ); const [captureBody, setCaptureBody] = useState( - idx(selectedConfig, _ => _.settings.capture_body) || '' + idx(selectedConfig, _ => _.settings.capture_body) || + defaultSettings.CAPTURE_BODY ); const [transactionMaxSpans, setTransactionMaxSpans] = useState( ( - idx(selectedConfig, _ => _.settings.transaction_max_spans) || '' + idx(selectedConfig, _ => _.settings.transaction_max_spans) || + defaultSettings.TRANSACTION_MAX_SPANS ).toString() ); + const isRumService = isRumAgentName(agentName); const isSampleRateValid = isRight(transactionSampleRateRt.decode(sampleRate)); const isTransactionMaxSpansValid = isRight( transactionMaxSpansRt.decode(transactionMaxSpans) ); const isFormValid = + !!agentName && !!serviceName && !!environment && isSampleRateValid && - !!captureBody && - isTransactionMaxSpansValid; + (isRumService || (!!captureBody && isTransactionMaxSpansValid)); const handleSubmitEvent = async ( event: @@ -115,8 +130,8 @@ export function AddEditFlyout({ event.preventDefault(); setIsSaving(true); - if (sampleRate === '' || captureBody === '' || transactionMaxSpans === '') { - throw new Error('Missing arguments'); + if (!agentName) { + throw new Error('Missing agent_name'); } await saveConfig({ @@ -125,7 +140,8 @@ export function AddEditFlyout({ sampleRate, captureBody, transactionMaxSpans, - configurationId: selectedConfig ? selectedConfig.id : undefined + configurationId: selectedConfig ? selectedConfig.id : undefined, + agentName }); setIsSaving(false); onSaved(); @@ -163,7 +179,8 @@ export function AddEditFlyout({ }} > {selectedConfig ? ( @@ -234,29 +251,37 @@ async function saveConfig({ sampleRate, captureBody, transactionMaxSpans, - configurationId + configurationId, + agentName }: { serviceName: string; - environment: string | undefined; + environment: string; sampleRate: string; captureBody: string; transactionMaxSpans: string; configurationId?: string; + agentName: string; }) { trackEvent({ app: 'apm', name: 'save_agent_configuration' }); try { + const settings: Settings = { + transaction_sample_rate: Number(sampleRate) + }; + + if (!isRumAgentName(agentName)) { + settings.capture_body = captureBody; + settings.transaction_max_spans = Number(transactionMaxSpans); + } + const configuration = { + agent_name: agentName, service: { name: serviceName, environment: environment === ENVIRONMENT_NOT_DEFINED ? undefined : environment }, - settings: { - transaction_sample_rate: Number(sampleRate), - capture_body: captureBody, - transaction_max_spans: Number(transactionMaxSpans) - } + settings }; if (configurationId) { 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 ddd800dc22bf315..71217ccc36f7b6c 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 @@ -110,7 +110,7 @@ Object { "myIndex", "myIndex", ], - "terminate_after": 1, + "terminateAfter": 1, } `; diff --git a/x-pack/legacy/plugins/apm/server/routes/settings.ts b/x-pack/legacy/plugins/apm/server/routes/settings.ts index 6ba3ffd707c6a5a..b76a36d08f8bddb 100644 --- a/x-pack/legacy/plugins/apm/server/routes/settings.ts +++ b/x-pack/legacy/plugins/apm/server/routes/settings.ts @@ -59,15 +59,16 @@ export const listAgentConfigurationServicesRoute = createRoute(() => ({ })); const agentPayloadRt = t.type({ + agent_name: t.string, service: t.intersection([ t.type({ name: t.string }), - t.partial({ environments: t.array(t.string) }) + t.partial({ environment: t.string }) ]), - settings: t.type({ - transaction_sample_rate: transactionSampleRateRt, - capture_body: t.string, - transaction_max_spans: transactionMaxSpansRt - }) + settings: t.intersection([ + t.partial({ transaction_sample_rate: transactionSampleRateRt }), + t.partial({ capture_body: t.string }), + t.partial({ transaction_max_spans: transactionMaxSpansRt }) + ]) }); // get environments for service @@ -108,10 +109,7 @@ export const createAgentConfigurationRoute = createRoute(() => ({ }, handler: async (req, { body }) => { const setup = await setupRequest(req); - const serviceName = body.service.name; - const agentName = await getAgentNameByService({ serviceName, setup }); - const configuration = { ...body, agent_name: agentName }; - return await createOrUpdateConfiguration({ configuration, setup }); + return await createOrUpdateConfiguration({ configuration: body, setup }); } }));