From 774f7bd070db3be9be69681b4cac77e9319de7a9 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 20 Sep 2024 22:27:49 +1000 Subject: [PATCH] [8.x] [Synthetics] Add labels field !! (#193250) (#193536) # Backport This will backport the following commits from `main` to `8.x`: - [[Synthetics] Add labels field !! (#193250)](https://github.com/elastic/kibana/pull/193250) ### Questions ? Please refer to the [Backport tool documentation](https://github.com/sqren/backport) Co-authored-by: Shahzad --- .../common/constants/monitor_defaults.ts | 1 + .../common/constants/monitor_management.ts | 1 + .../monitor_management/monitor_types.ts | 1 + .../monitor_types_project.ts | 1 + .../components/monitor_details_panel.tsx | 19 +++++++ .../monitor_add_edit/form/field_config.tsx | 49 +++++++++++++++++++ .../monitor_add_edit/form/form_config.tsx | 3 ++ .../components/monitor_add_edit/types.ts | 1 + .../add_monitor/add_monitor_api.test.ts | 4 ++ .../migrations/monitors/8.8.0.test.ts | 1 + .../private_formatters/common_formatters.ts | 1 + .../processors_formatter.ts | 5 +- .../formatters/public_formatters/common.ts | 1 + .../public_formatters/format_configs.ts | 3 ++ .../apis/synthetics/add_monitor_project.ts | 4 ++ .../synthetics/fixtures/http_monitor.json | 3 +- .../apis/synthetics/get_monitor.ts | 1 + 17 files changed, 97 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_defaults.ts b/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_defaults.ts index ccc8ab409420e..dcb1a6e72b246 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_defaults.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_defaults.ts @@ -152,6 +152,7 @@ export const DEFAULT_COMMON_FIELDS: CommonFields = { [ConfigKey.CONFIG_HASH]: '', [ConfigKey.MONITOR_QUERY_ID]: '', [ConfigKey.PARAMS]: '', + [ConfigKey.LABELS]: {}, [ConfigKey.MAX_ATTEMPTS]: 2, revision: 1, }; diff --git a/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_management.ts b/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_management.ts index a91e0132ff376..3f0b6c51a3945 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_management.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/constants/monitor_management.ts @@ -27,6 +27,7 @@ export enum ConfigKey { JOURNEY_ID = 'journey_id', MAX_REDIRECTS = 'max_redirects', METADATA = '__ui', + LABELS = 'labels', MODE = 'mode', MONITOR_TYPE = 'type', NAME = 'name', diff --git a/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types.ts b/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types.ts index c0383eaea8b39..426b66597c7d8 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types.ts @@ -86,6 +86,7 @@ export const CommonFieldsCodec = t.intersection([ [ConfigKey.CUSTOM_HEARTBEAT_ID]: t.string, [ConfigKey.ALERT_CONFIG]: AlertConfigsCodec, [ConfigKey.PARAMS]: t.string, + [ConfigKey.LABELS]: t.record(t.string, t.string), retest_on_failure: t.boolean, }), ]); diff --git a/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts b/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts index 0658d0964fe66..8e25ec1a714e4 100644 --- a/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts +++ b/x-pack/plugins/observability_solution/synthetics/common/runtime_types/monitor_management/monitor_types_project.ts @@ -62,6 +62,7 @@ export const ProjectMonitorCodec = t.intersection([ hash: t.string, namespace: t.string, retestOnFailure: t.boolean, + labels: t.record(t.string, t.string), }), ]); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx index 8d08ac966d4b4..d0db68035b147 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/common/components/monitor_details_panel.tsx @@ -18,6 +18,7 @@ import { import { i18n } from '@kbn/i18n'; import { useDispatch } from 'react-redux'; import { TagsList } from '@kbn/observability-shared-plugin/public'; +import { isEmpty } from 'lodash'; import { PanelWithTitle } from './panel_with_title'; import { MonitorEnabled } from '../../monitors_page/management/monitor_list_table/monitor_enabled'; import { getMonitorAction } from '../../../state'; @@ -57,6 +58,7 @@ export const MonitorDetailsPanel = ({ } const url = latestPing?.url?.full ?? (monitor as unknown as MonitorFields)[ConfigKey.URLS]; + const labels = monitor[ConfigKey.LABELS]; return ( + + {!isEmpty(labels) ? ( + <> + {LABELS_LABEL} + + {Object.entries(labels ?? {}).map(([key, value]) => ( +
+ {key}: {value} +
+ ))} +
+ + ) : null}
); @@ -225,6 +240,10 @@ const TAGS_LABEL = i18n.translate('xpack.synthetics.management.monitorList.tags' defaultMessage: 'Tags', }); +const LABELS_LABEL = i18n.translate('xpack.synthetics.management.monitorList.labels', { + defaultMessage: 'Labels', +}); + const ENABLED_LABEL = i18n.translate('xpack.synthetics.detailsPanel.monitorDetails.enabled', { defaultMessage: 'Enabled (all locations)', }); diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx index a55a93853344b..d480a2ae1e258 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/field_config.tsx @@ -1092,6 +1092,55 @@ export const FIELD = (readOnly?: boolean): FieldMap => ({ }, }), }, + [ConfigKey.LABELS]: { + fieldKey: ConfigKey.LABELS, + label: i18n.translate('xpack.synthetics.monitorConfig.meta.label', { + defaultMessage: 'Label fields', + }), + controlled: true, + component: KeyValuePairsField, + helpText: i18n.translate('xpack.synthetics.monitorConfig.meta.helpText', { + defaultMessage: + 'List of key-value pairs that will be sent with each monitor event. Useful for adding custom metadata to your monitor.', + }), + props: ({ field, setValue, trigger }): KeyValuePairsFieldProps => ({ + readOnly, + keyLabel: i18n.translate('xpack.synthetics.monitorConfig.field.key.label', { + defaultMessage: 'Field', + }), + valueLabel: i18n.translate('xpack.synthetics.monitorConfig.field.value.label', { + defaultMessage: 'Value', + }), + addPairControlLabel: i18n.translate('xpack.synthetics.monitorConfig.metaField.label', { + defaultMessage: 'Add label field', + }), + onChange: async (pairs) => { + const value: Record = {}; + pairs.forEach((pair) => { + const [fieldKey, fieldValue] = pair; + value[fieldKey] = String(fieldValue); + }); + if (!isEqual(value, field?.value)) { + setValue(ConfigKey.LABELS, value); + await trigger(ConfigKey.LABELS); + } + }, + defaultPairs: Object.entries(field?.value || {}), + }), + validation: () => ({ + validate: { + validBodyJSON: (value: Record) => { + if (Object.entries(value).some((check) => !check[0] || !check[1])) { + return i18n.translate('xpack.synthetics.monitorConfig.metaFields.error', { + defaultMessage: + 'This meta fields is not valid. Make sure that both the field and value are defined.', + }); + } + return true; + }, + }, + }), + }, isTLSEnabled: { fieldKey: 'isTLSEnabled', component: Switch, diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx index ea7653130759d..7e29504aca41f 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/form/form_config.tsx @@ -19,6 +19,7 @@ const DEFAULT_DATA_OPTIONS = (readOnly: boolean) => ({ }), components: [ FIELD(readOnly)[ConfigKey.TAGS], + FIELD(readOnly)[ConfigKey.LABELS], FIELD(readOnly)[ConfigKey.APM_SERVICE_NAME], FIELD(readOnly)[ConfigKey.NAMESPACE], ], @@ -247,6 +248,7 @@ export const FORM_CONFIG = (readOnly: boolean): FieldConfig => ({ ...DEFAULT_DATA_OPTIONS(readOnly), components: [ FIELD(readOnly)[ConfigKey.TAGS], + FIELD(readOnly)[ConfigKey.LABELS], FIELD(readOnly)[ConfigKey.APM_SERVICE_NAME], FIELD(readOnly)[ConfigKey.SCREENSHOTS], FIELD(readOnly)[ConfigKey.NAMESPACE], @@ -272,6 +274,7 @@ export const FORM_CONFIG = (readOnly: boolean): FieldConfig => ({ ...DEFAULT_DATA_OPTIONS(readOnly), components: [ FIELD(readOnly)[ConfigKey.TAGS], + FIELD(readOnly)[ConfigKey.LABELS], FIELD(readOnly)[ConfigKey.APM_SERVICE_NAME], FIELD(readOnly)[ConfigKey.SCREENSHOTS], FIELD(readOnly)[ConfigKey.NAMESPACE], diff --git a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/types.ts b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/types.ts index 7ba092014ec88..eac26125a56dd 100644 --- a/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/types.ts +++ b/x-pack/plugins/observability_solution/synthetics/public/apps/synthetics/components/monitor_add_edit/types.ts @@ -165,4 +165,5 @@ export interface FieldMap { [ConfigKey.MODE]: FieldMeta; [ConfigKey.IPV4]: FieldMeta; [ConfigKey.MAX_ATTEMPTS]: FieldMeta; + [ConfigKey.LABELS]: FieldMeta; } diff --git a/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/add_monitor/add_monitor_api.test.ts b/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/add_monitor/add_monitor_api.test.ts index ac5047f2e4ba3..47429f7f037ef 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/add_monitor/add_monitor_api.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/routes/monitor_cruds/add_monitor/add_monitor_api.test.ts @@ -107,6 +107,7 @@ describe('AddNewMonitorsPublicAPI', () => { type: 'tcp', 'url.port': null, urls: '', + labels: {}, }); }); it('should normalize icmp', async () => { @@ -143,6 +144,7 @@ describe('AddNewMonitorsPublicAPI', () => { timeout: '16', type: 'icmp', wait: '1', + labels: {}, }); }); it('should normalize http', async () => { @@ -201,6 +203,7 @@ describe('AddNewMonitorsPublicAPI', () => { 'url.port': null, urls: '', username: '', + labels: {}, }); }); it('should normalize browser', async () => { @@ -255,6 +258,7 @@ describe('AddNewMonitorsPublicAPI', () => { type: 'browser', 'url.port': null, urls: '', + labels: {}, }); }); }); diff --git a/x-pack/plugins/observability_solution/synthetics/server/saved_objects/migrations/monitors/8.8.0.test.ts b/x-pack/plugins/observability_solution/synthetics/server/saved_objects/migrations/monitors/8.8.0.test.ts index 546f1c0bdf008..762b3658ed80f 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/saved_objects/migrations/monitors/8.8.0.test.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/saved_objects/migrations/monitors/8.8.0.test.ts @@ -163,6 +163,7 @@ describe('Monitor migrations v8.7.0 -> v8.8.0', () => { type: 'browser', 'url.port': null, urls: 'https://elastic.co', + labels: {}, }, coreMigrationVersion: '8.8.0', created_at: '2023-03-31T20:31:24.177Z', diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/common_formatters.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/common_formatters.ts index 7f34ba0de0bc2..0451b70b6e878 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/common_formatters.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/common_formatters.ts @@ -29,6 +29,7 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.REVISION]: null, [ConfigKey.MONITOR_SOURCE_TYPE]: null, [ConfigKey.FORM_MONITOR_TYPE]: null, + [ConfigKey.LABELS]: null, [ConfigKey.JOURNEY_ID]: stringToJsonFormatter, [ConfigKey.PROJECT_ID]: stringToJsonFormatter, [ConfigKey.CUSTOM_HEARTBEAT_ID]: stringToJsonFormatter, diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/processors_formatter.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/processors_formatter.ts index 3a3aabb4e92d4..cb9ffea41e6a2 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/processors_formatter.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/private_formatters/processors_formatter.ts @@ -5,8 +5,9 @@ * 2.0. */ +import { isEmpty } from 'lodash'; import { ProcessorFields } from './format_synthetics_policy'; -import { HeartbeatFields, MonitorFields } from '../../../../common/runtime_types'; +import { ConfigKey, HeartbeatFields, MonitorFields } from '../../../../common/runtime_types'; interface FieldProcessor { add_fields: { @@ -16,6 +17,7 @@ interface FieldProcessor { } export const processorsFormatter = (config: MonitorFields & ProcessorFields) => { + const labels = config[ConfigKey.LABELS] ?? {}; const processors: FieldProcessor[] = [ { add_fields: { @@ -30,6 +32,7 @@ export const processorsFormatter = (config: MonitorFields & ProcessorFields) => meta: { space_id: config.space_id, }, + ...(isEmpty(labels) ? {} : { labels }), }, target: '', }, diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/common.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/common.ts index c84367a27f0a2..b88475c792e0b 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/common.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/common.ts @@ -55,4 +55,5 @@ export const commonFormatters: CommonFormatMap = { [ConfigKey.SCHEDULE]: (fields) => `@every ${fields[ConfigKey.SCHEDULE]?.number}${fields[ConfigKey.SCHEDULE]?.unit}`, [ConfigKey.TAGS]: arrayFormatter, + [ConfigKey.LABELS]: null, }; diff --git a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/format_configs.ts b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/format_configs.ts index e59a0b625337b..d9c0821154990 100644 --- a/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/format_configs.ts +++ b/x-pack/plugins/observability_solution/synthetics/server/synthetics_service/formatters/public_formatters/format_configs.ts @@ -29,6 +29,7 @@ const UI_KEYS_TO_SKIP = [ ConfigKey.TEXT_ASSERTION, ConfigKey.CONFIG_HASH, ConfigKey.ALERT_CONFIG, + ConfigKey.LABELS, 'secrets', ]; @@ -97,6 +98,7 @@ export const formatHeartbeatRequest = ( const heartbeatIdT = heartbeatId ?? monitor[ConfigKey.MONITOR_QUERY_ID]; const paramsString = params ?? (monitor as BrowserFields)[ConfigKey.PARAMS]; + const { labels } = monitor; return { ...monitor, @@ -110,6 +112,7 @@ export const formatHeartbeatRequest = ( meta: { space_id: spaceId, }, + ...(isEmpty(labels) ? {} : { labels }), }, fields_under_root: true, params: monitor.type === 'browser' ? paramsString : '', diff --git a/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts b/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts index 9498231c2ca73..074f318e77fcf 100644 --- a/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts +++ b/x-pack/test/api_integration/apis/synthetics/add_monitor_project.ts @@ -241,6 +241,7 @@ export default function ({ getService }: FtrProviderContext) { id: `${journeyId}-${project}-default`, hash: 'ekrjelkjrelkjre', max_attempts: 2, + labels: {}, }); } } finally { @@ -425,6 +426,7 @@ export default function ({ getService }: FtrProviderContext) { ipv6: true, ipv4: true, max_attempts: 2, + labels: {}, }); } } finally { @@ -542,6 +544,7 @@ export default function ({ getService }: FtrProviderContext) { ipv4: true, params: '', max_attempts: 2, + labels: {}, }); } } finally { @@ -656,6 +659,7 @@ export default function ({ getService }: FtrProviderContext) { ipv6: true, params: '', max_attempts: 2, + labels: {}, }); } } finally { diff --git a/x-pack/test/api_integration/apis/synthetics/fixtures/http_monitor.json b/x-pack/test/api_integration/apis/synthetics/fixtures/http_monitor.json index 20178f5bbb71b..47d0637a7cd91 100644 --- a/x-pack/test/api_integration/apis/synthetics/fixtures/http_monitor.json +++ b/x-pack/test/api_integration/apis/synthetics/fixtures/http_monitor.json @@ -78,5 +78,6 @@ "mode": "any", "ipv4": true, "ipv6": true, - "params": "" + "params": "", + "labels": {} } diff --git a/x-pack/test/api_integration/apis/synthetics/get_monitor.ts b/x-pack/test/api_integration/apis/synthetics/get_monitor.ts index fc75de4107440..114f7666e7965 100644 --- a/x-pack/test/api_integration/apis/synthetics/get_monitor.ts +++ b/x-pack/test/api_integration/apis/synthetics/get_monitor.ts @@ -203,6 +203,7 @@ export default function ({ getService }: FtrProviderContext) { revision: 1, locations: [LOCAL_LOCATION], name: 'Test HTTP Monitor 044', + labels: {}, }); });