diff --git a/changelog/unreleased/issue-20086.toml b/changelog/unreleased/issue-20086.toml new file mode 100644 index 000000000000..1035cc2909ad --- /dev/null +++ b/changelog/unreleased/issue-20086.toml @@ -0,0 +1,5 @@ +type="a" +message="Datanode migration telemetry" + +issues=["20086"] +pulls=["20225"] diff --git a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAConfiguration.tsx b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAConfiguration.tsx index d49cb4f2169b..04b4c9efd7a2 100644 --- a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAConfiguration.tsx +++ b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAConfiguration.tsx @@ -21,6 +21,8 @@ import { Tabs, Tab, Alert } from 'components/bootstrap'; import CACreateForm from 'components/datanode/DataNodeConfiguration/CACreateForm'; import CAUpload from 'components/datanode/DataNodeConfiguration/CAUpload'; import DocumentationLink from 'components/support/DocumentationLink'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; const StyledAlert = styled(Alert)` margin-top: 10px; @@ -28,27 +30,44 @@ const StyledAlert = styled(Alert)` `; const TAB_KEYS = ['create', 'upload']; -const CAConfiguration = () => ( - <> -

Configure Certificate Authority

-

- In this step you can either upload or create a new certificate authority.
- The certificate authority will provision and manage certificates for your Data Nodes more easily. -

- - If your existing cluster uses certificates, by default these will get replaced with the Graylog CA - and automatically generated certificates during provisioning of the data nodes in the next step. - If you want to include your own CA, you can upload an existing certificate. - Please see for more information. - - - - - - - - - - -); + +const UploadCA = 'Upload CA'; + +const CAConfiguration = () => { + const sendTelemetry = useSendTelemetry(); + + const handleTabSwitch = (e) => { + sendTelemetry((e?.target?.innerText === UploadCA) + ? TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_UPLOAD_TAB_CLICKED + : TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_CREATE_TAB_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + }; + + return ( + <> +

Configure Certificate Authority

+

+ In this step you can either upload or create a new certificate authority.
+ The certificate authority will provision and manage certificates for your Data Nodes more easily. +

+ + If your existing cluster uses certificates, by default these will get replaced with the Graylog CA + and automatically generated certificates during provisioning of the data nodes in the next step. + If you want to include your own CA, you can upload an existing certificate. + Please see for more information. + + + + + + + + + + + ); +}; + export default CAConfiguration; diff --git a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CACreateForm.tsx b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CACreateForm.tsx index 1bbb6eb6fcb9..d56e24d114fa 100644 --- a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CACreateForm.tsx +++ b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CACreateForm.tsx @@ -25,6 +25,8 @@ import { FormikInput } from 'components/common'; import { Button } from 'components/bootstrap'; import { QUERY_KEY as DATA_NODES_CA_QUERY_KEY } from 'components/datanode/hooks/useDataNodesCA'; import { MIGRATION_STATE_QUERY_KEY } from 'components/datanode/hooks/useMigrationState'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; type FormValues = { organization: string @@ -39,6 +41,7 @@ const createCA = (caData: FormValues) => fetch( const CaCreateForm = () => { const queryClient = useQueryClient(); + const sendTelemetry = useSendTelemetry(); const { mutateAsync: onCreateCA } = useMutation(createCA, { onSuccess: () => { @@ -50,7 +53,15 @@ const CaCreateForm = () => { UserNotification.error(`CA creation failed with error: ${error}`); }, }); - const onSubmit = (formValues: FormValues) => onCreateCA(formValues).catch(() => {}); + + const onSubmit = (formValues: FormValues) => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_CREATE_CA_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + return onCreateCA(formValues).catch(() => {}); + }; return (
diff --git a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAUpload.tsx b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAUpload.tsx index cbec0ed10402..bd2d354f09c6 100644 --- a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAUpload.tsx +++ b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CAUpload.tsx @@ -28,6 +28,8 @@ import { qualifyUrl } from 'util/URLUtils'; import { QUERY_KEY as DATA_NODES_CA_QUERY_KEY } from 'components/datanode/hooks/useDataNodesCA'; import UnsecureConnectionAlert from 'preflight/components/ConfigurationWizard/UnsecureConnectionAlert'; import { MIGRATION_STATE_QUERY_KEY } from 'components/datanode/hooks/useMigrationState'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; type FormValues = { files?: Array, @@ -95,6 +97,7 @@ const Explanation = styled.p` const CAUpload = () => { const queryClient = useQueryClient(); + const sendTelemetry = useSendTelemetry(); const onRejectUpload = useCallback(() => { UserNotification.error('CA upload failed'); }, []); @@ -110,7 +113,14 @@ const CAUpload = () => { }, }); - const onSubmit = useCallback((formValues: FormValues) => onProcessUpload(formValues).catch(() => {}), [onProcessUpload]); + const onSubmit = useCallback((formValues: FormValues) => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_UPLOAD_CA_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + return onProcessUpload(formValues).catch(() => {}); + }, [onProcessUpload, sendTelemetry]); return ( initialValues={{}} onSubmit={onSubmit} validate={validate}> diff --git a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CertificateRenewalPolicyConfig.tsx b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CertificateRenewalPolicyConfig.tsx index 62822d5bd57f..a14af7d41a58 100644 --- a/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CertificateRenewalPolicyConfig.tsx +++ b/graylog2-web-interface/src/components/datanode/DataNodeConfiguration/CertificateRenewalPolicyConfig.tsx @@ -31,8 +31,6 @@ import { ConfigurationType } from 'components/configurations/ConfigurationTypes' import { IfPermitted, TimeUnitInput, Spinner } from 'components/common'; import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; import Select from 'components/common/Select'; -import useLocation from 'routing/useLocation'; -import { getPathnameWithoutId } from 'util/URLUtils'; import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; import { MIGRATION_STATE_QUERY_KEY } from 'components/datanode/hooks/useMigrationState'; @@ -121,7 +119,6 @@ const CertificateRenewalPolicyConfig = ({ className }: Props) => { const { data: currentConfig, isLoading } = useQuery(queryKey, fetchCurrentConfig); const sendTelemetry = useSendTelemetry(); - const { pathname } = useLocation(); const queryClient = useQueryClient(); const { mutateAsync: updateConfig } = useMutation(handleSaveConfig, { @@ -166,10 +163,9 @@ const CertificateRenewalPolicyConfig = ({ className }: Props) => { }; const saveConfig = (values: FormConfig) => { - sendTelemetry(TELEMETRY_EVENT_TYPE.CONFIGURATIONS.CERTIFICATE_RENEWAL_POLICY_UPDATED, { - app_pathname: getPathnameWithoutId(pathname), - app_section: 'certificate-renewal-policy', - app_action_value: 'configuration-save', + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CR_UPDATE_CONFIGURATION_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', }); const newConfig = { @@ -202,6 +198,11 @@ const CertificateRenewalPolicyConfig = ({ className }: Props) => { diff --git a/graylog2-web-interface/src/components/datanode/migrations/ManualMigrationStep.tsx b/graylog2-web-interface/src/components/datanode/migrations/ManualMigrationStep.tsx index 94bba18b9187..c8477507c0cf 100644 --- a/graylog2-web-interface/src/components/datanode/migrations/ManualMigrationStep.tsx +++ b/graylog2-web-interface/src/components/datanode/migrations/ManualMigrationStep.tsx @@ -30,13 +30,26 @@ import { } from 'components/datanode/Constants'; import RemoteReindexingMigration from 'components/datanode/migrations/RemoteReindexingMigration'; import MigrationError from 'components/datanode/migrations/common/MigrationError'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; const ManualMigrationStep = () => { const { currentStep } = useMigrationState(); const { onTriggerNextState } = useTriggerMigrationState(); + const sendTelemetry = useSendTelemetry(); const onMigrationStepChange = async (step: MigrationActions, args?: StepArgs = {}) => onTriggerNextState({ step, args }); + const handleSelectMigrationType = async (step: MigrationActions, args?: StepArgs = {}) => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.MIGRATION_TYPE_SELECTED, { + app_pathname: 'datanode', + app_section: 'migration', + event_details: { migration_type: (step === 'SELECT_ROLLING_UPGRADE_MIGRATION') ? 'IN-PLACE' : 'REMOTE REINDEX' }, + }); + + return onTriggerNextState({ step, args }); + }; + const migrationTypeOptions = [ { label: 'In-Place migration', value: 'SELECT_ROLLING_UPGRADE_MIGRATION' }, { label: 'Remote Re-indexing Migration', value: 'SELECT_REMOTE_REINDEX_MIGRATION' }, @@ -59,7 +72,7 @@ const ManualMigrationStep = () => { inputId="datanode-migration-type-select" options={migrationTypeOptions} matchProp="label" - onChange={onMigrationStepChange} + onChange={handleSelectMigrationType} value={null} /> diff --git a/graylog2-web-interface/src/components/datanode/migrations/common/MigrationStepTriggerButtonToolbar.tsx b/graylog2-web-interface/src/components/datanode/migrations/common/MigrationStepTriggerButtonToolbar.tsx index bce4135d00a8..073e7f2ede95 100644 --- a/graylog2-web-interface/src/components/datanode/migrations/common/MigrationStepTriggerButtonToolbar.tsx +++ b/graylog2-web-interface/src/components/datanode/migrations/common/MigrationStepTriggerButtonToolbar.tsx @@ -17,9 +17,13 @@ import React from 'react'; import styled, { css } from 'styled-components'; -import type { MigrationActions, OnTriggerStepFunction, StepArgs } from 'components/datanode/Types'; +import type { MigrationActions, MigrationStateItem, OnTriggerStepFunction, StepArgs } from 'components/datanode/Types'; import { Button, ButtonToolbar } from 'components/bootstrap'; import { MIGRATION_ACTIONS } from 'components/datanode/Constants'; +import useMigrationState from 'components/datanode/hooks/useMigrationState'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; +import type { TelemetryEventType } from 'logic/telemetry/TelemetryContext'; const StyledButtonToolbar = styled(ButtonToolbar)(({ theme }) => css` margin-top: ${theme.spacings.md}; @@ -45,14 +49,73 @@ type Props = { children?: React.ReactNode, } +const getTelemetryEvent = (state: MigrationStateItem, step: MigrationActions): TelemetryEventType => { + switch (state) { + case 'MIGRATION_WELCOME_PAGE': + if (step === 'SHOW_MIGRATION_SELECTION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.WELCOME_GO_TO_MIGRATION_STEPS_CLICKED; + if (step === 'SHOW_RENEWAL_POLICY_CREATION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.WELCOME_CONFIGURE_CERTIFICATE_RENEWAL_POLICY_CLICKED; + + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.WELCOME_NEXT_CLICKED; + case 'CA_CREATION_PAGE': + if (step === 'SHOW_MIGRATION_SELECTION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_GO_TO_MIGRATION_STEPS_CLICKED; + if (step === 'SHOW_RENEWAL_POLICY_CREATION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_CONFIGURE_CERTIFICATE_RENEWAL_POLICY_CLICKED; + + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CA_NEXT_CLICKED; + case 'RENEWAL_POLICY_CREATION_PAGE': + if (step === 'SHOW_MIGRATION_SELECTION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CR_GO_TO_MIGRATION_STEPS_CLICKED; + + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.CR_NEXT_CLICKED; + case 'ROLLING_UPGRADE_MIGRATION_WELCOME_PAGE': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.INPLACE_RUN_DIRECTORY_COMPATIBILITY_CHECK_CLICKED; + case 'DIRECTORY_COMPATIBILITY_CHECK_PAGE': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.INPLACE_DIRECTORY_COMPATIBILITY_CHECK_NEXT_CLICKED; + case 'JOURNAL_SIZE_DOWNTIME_WARNING': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.INPLACE_JOURNAL_SIZE_DOWNTIME_WARNING_NEXT_CLICKED; + case 'MESSAGE_PROCESSING_STOP': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.INPLACE_STOP_MESSAGE_PROCESSING_NEXT_CLICKED; + case 'RESTART_GRAYLOG': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.INPLACE_RESTART_GRAYLOG_NEXT_CLICKED; + case 'REMOTE_REINDEX_WELCOME_PAGE': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_WELCOME_NEXT_CLICKED; + case 'EXISTING_DATA_MIGRATION_QUESTION_PAGE': + if (step === 'SKIP_EXISTING_DATA_MIGRATION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_MIGRATE_EXISTING_DATA_QUESTION_SKIP_CLICKED; + + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_MIGRATE_EXISTING_DATA_QUESTION_NEXT_CLICKED; + case 'MIGRATE_EXISTING_DATA': + if (step === 'START_REMOTE_REINDEX_MIGRATION') return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_MIGRATE_EXISTING_DATA_START_CLICKED; + + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_MIGRATE_EXISTING_DATA_CHECK_CONNECTION_CLICKED; + case 'ASK_TO_SHUTDOWN_OLD_CLUSTER': + return TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_SHUTDOWN_OLD_CLUSTER_NEXT_CLICKED; + default: + return null; + } +}; + const MigrationStepTriggerButtonToolbar = ({ nextSteps, disabled, onTriggerStep, args, hidden, children }: Props) => { + const sendTelemetry = useSendTelemetry(); + const { currentStep } = useMigrationState(); + if (hidden) { return null; } + const handleButtonClick = (step: MigrationActions) => { + const eventType = getTelemetryEvent(currentStep?.state, step); + + if (eventType) { + sendTelemetry(eventType, { + app_pathname: 'datanode', + app_section: 'migration', + }); + } + + onTriggerStep(step, args); + }; + return ( - {getSortedNextSteps(nextSteps).map((step, index) => )} + {getSortedNextSteps(nextSteps).map((step, index) => )} {children} ); diff --git a/graylog2-web-interface/src/components/datanode/migrations/common/ResetMigrationButton.tsx b/graylog2-web-interface/src/components/datanode/migrations/common/ResetMigrationButton.tsx index 6ebbac4aadab..8305e7d84e57 100644 --- a/graylog2-web-interface/src/components/datanode/migrations/common/ResetMigrationButton.tsx +++ b/graylog2-web-interface/src/components/datanode/migrations/common/ResetMigrationButton.tsx @@ -25,12 +25,15 @@ import { qualifyUrl } from 'util/URLUtils'; import UserNotification from 'util/UserNotification'; import { QUERY_KEY as DATA_NODES_CA_QUERY_KEY } from 'preflight/hooks/useDataNodesCA'; import { MIGRATION_STATE_QUERY_KEY } from 'components/datanode/hooks/useMigrationState'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; const resetMigration = async () => fetch('DELETE', qualifyUrl('/migration/state')); const ResetMigrationButton = () => { const queryClient = useQueryClient(); const [showDialog, setShowDialog] = useState(false); + const sendTelemetry = useSendTelemetry(); const { mutateAsync: onResetMigration } = useMutation(resetMigration, { onSuccess: () => { @@ -43,18 +46,34 @@ const ResetMigrationButton = () => { }, }); + const handleResetClick = () => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.RESET_MIGRATION_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + setShowDialog(true); + }; + + const handleConfirmClick = async () => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.RESET_MIGRATION_CONFIRM_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + await onResetMigration(); + setShowDialog(false); + }; + return ( <> - {showDialog && ( { - await onResetMigration(); - setShowDialog(false); - }} + onConfirm={handleConfirmClick} onCancel={() => setShowDialog(false)}> Are you sure you want to reset the migration? diff --git a/graylog2-web-interface/src/components/datanode/migrations/remoteReindexing/RemoteReindexRunning.tsx b/graylog2-web-interface/src/components/datanode/migrations/remoteReindexing/RemoteReindexRunning.tsx index 7ed91c4f7dcd..d58112e5b9f1 100644 --- a/graylog2-web-interface/src/components/datanode/migrations/remoteReindexing/RemoteReindexRunning.tsx +++ b/graylog2-web-interface/src/components/datanode/migrations/remoteReindexing/RemoteReindexRunning.tsx @@ -22,6 +22,8 @@ import { useQueryParam, StringParam } from 'use-query-params'; import { ConfirmDialog } from 'components/common'; import { Alert, BootstrapModalWrapper, Button, Modal } from 'components/bootstrap'; +import useSendTelemetry from 'logic/telemetry/useSendTelemetry'; +import { TELEMETRY_EVENT_TYPE } from 'logic/telemetry/Constants'; import type { MigrationStepComponentProps } from '../../Types'; import MigrationStepTriggerButtonToolbar from '../common/MigrationStepTriggerButtonToolbar'; @@ -70,6 +72,9 @@ const RemoteReindexRunning = ({ currentStep, onTriggerStep, hideActions }: Migra const [showLogView, setShowLogView] = useState(false); const [showRetryMigrationConfirmDialog, setShowRetryMigrationConfirmDialog] = useState(false); const [showLogsQuery, setShowLogsQuery] = useQueryParam('show_logs', StringParam); + const sendTelemetry = useSendTelemetry(); + + const hasMigrationFailed = migrationStatus?.progress === 100 && migrationStatus?.status === 'ERROR'; useEffect(() => { if (showLogsQuery === 'true' && !showLogView) { @@ -82,7 +87,37 @@ const RemoteReindexRunning = ({ currentStep, onTriggerStep, hideActions }: Migra setShowLogsQuery(undefined); }; - const hasMigrationFailed = migrationStatus?.progress === 100 && migrationStatus?.status === 'ERROR'; + const handleLogViewClick = () => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_RUNNING_LOGVIEW_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + setShowLogView(true); + }; + + const handleRetryClick = () => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_RUNNING_RETRY_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + if (hasMigrationFailed) { + handleTriggerStep(RetryMigrateExistingData); + } else { + setShowRetryMigrationConfirmDialog(true); + } + }; + + const handleRetryConfirmClick = () => { + sendTelemetry(TELEMETRY_EVENT_TYPE.DATANODE_MIGRATION.REMOTEREINDEX_RUNNING_RETRY_CONFIRM_CLICKED, { + app_pathname: 'datanode', + app_section: 'migration', + }); + + handleTriggerStep(RetryMigrateExistingData); + setShowRetryMigrationConfirmDialog(false); + }; return ( <> @@ -104,17 +139,14 @@ const RemoteReindexRunning = ({ currentStep, onTriggerStep, hideActions }: Migra )} {showRetryMigrationConfirmDialog && ( setShowRetryMigrationConfirmDialog(false)} - onConfirm={() => { - handleTriggerStep(RetryMigrateExistingData); - setShowRetryMigrationConfirmDialog(false); - }}> + onConfirm={handleRetryConfirmClick}> Are you sure you want to stop the current running remote reindexing migration and retry migrating existing data? )} diff --git a/graylog2-web-interface/src/logic/telemetry/Constants.ts b/graylog2-web-interface/src/logic/telemetry/Constants.ts index d121e7a37117..1161d6805047 100644 --- a/graylog2-web-interface/src/logic/telemetry/Constants.ts +++ b/graylog2-web-interface/src/logic/telemetry/Constants.ts @@ -348,4 +348,37 @@ export const TELEMETRY_EVENT_TYPE = { SELECT_OPENED: 'Index Set Template Selected Opened', SELECT_CLOSED: 'Index Set Template Selected Cancelled', }, + DATANODE_MIGRATION: { + RESET_MIGRATION_CLICKED: 'Datanode Migration Reset Migration Clicked', + RESET_MIGRATION_CONFIRM_CLICKED: 'Datanode Migration Reset Migration Confirm Clicked', + WELCOME_GO_TO_MIGRATION_STEPS_CLICKED: 'Datanode Migration Welcome Go To Migration Steps Clicked', + WELCOME_CONFIGURE_CERTIFICATE_RENEWAL_POLICY_CLICKED: 'Datanode Migration Welcome Configure Certificate Renewal Policy Clicked', + WELCOME_NEXT_CLICKED: 'Datanode Migration Welcome Next Clicked', + CA_CREATE_TAB_CLICKED: 'Datanode Migration CA Create Tab Clicked', + CA_UPLOAD_TAB_CLICKED: 'Datanode Migration CA Upload Tab Clicked', + CA_CREATE_CA_CLICKED: 'Datanode Migration CA Create CA Clicked', + CA_UPLOAD_CA_CLICKED: 'Datanode Migration CA Upload CA Clicked', + CA_GO_TO_MIGRATION_STEPS_CLICKED: 'Datanode Migration CA Go To Migration Steps Clicked', + CA_CONFIGURE_CERTIFICATE_RENEWAL_POLICY_CLICKED: 'Datanode Migration CA Configure Certificate Renewal Policy Clicked', + CA_NEXT_CLICKED: 'Datanode Migration CA Next Clicked', + CR_EDIT_CONFIGURATION_CLICKED: 'Datanode Migration CR Edit Configuration Clicked', + CR_UPDATE_CONFIGURATION_CLICKED: 'Datanode Migration CR Update Configuration Clicked', + CR_GO_TO_MIGRATION_STEPS_CLICKED: 'Datanode Migration CR Go To Migration Steps Clicked', + CR_NEXT_CLICKED: 'Datanode Migration CR Next Clicked', + MIGRATION_TYPE_SELECTED: 'Datanode Migration Migration Type Selected', + INPLACE_RUN_DIRECTORY_COMPATIBILITY_CHECK_CLICKED: 'Datanode Migration Inplace Run Directory Compatibility Check Clicked', + INPLACE_DIRECTORY_COMPATIBILITY_CHECK_NEXT_CLICKED: 'Datanode Migration Inplace Directory Compatibility Check Next Clicked', + INPLACE_JOURNAL_SIZE_DOWNTIME_WARNING_NEXT_CLICKED: 'Datanode Migration Inplace Journal Size Downtime Warning Next Clicked', + INPLACE_STOP_MESSAGE_PROCESSING_NEXT_CLICKED: 'Datanode Migration Inplace Stop Message Processing Next Clicked', + INPLACE_RESTART_GRAYLOG_NEXT_CLICKED: 'Datanode Migration Inplace Restart Graylog Next Clicked', + REMOTEREINDEX_WELCOME_NEXT_CLICKED: 'Datanode Migration RemoteReindex Welcome Next Clicked', + REMOTEREINDEX_MIGRATE_EXISTING_DATA_QUESTION_NEXT_CLICKED: 'Datanode Migration RemoteReindex Migrate Existing Data Question Next Clicked', + REMOTEREINDEX_MIGRATE_EXISTING_DATA_QUESTION_SKIP_CLICKED: 'Datanode Migration RemoteReindex Migrate Existing Data Question Skip Clicked', + REMOTEREINDEX_MIGRATE_EXISTING_DATA_CHECK_CONNECTION_CLICKED: 'Datanode Migration RemoteReindex Migrate Existing Data Check Connection Clicked', + REMOTEREINDEX_MIGRATE_EXISTING_DATA_START_CLICKED: 'Datanode Migration RemoteReindex Migrate Existing Data Start Clicked', + REMOTEREINDEX_RUNNING_LOGVIEW_CLICKED: 'Datanode Migration RemoteReindex Running Logview Clicked', + REMOTEREINDEX_RUNNING_RETRY_CLICKED: 'Datanode Migration RemoteReindex Running Retry Clicked', + REMOTEREINDEX_RUNNING_RETRY_CONFIRM_CLICKED: 'Datanode Migration RemoteReindex Running Retry Confirm Clicked', + REMOTEREINDEX_SHUTDOWN_OLD_CLUSTER_NEXT_CLICKED: 'Datanode Migration RemoteReindex Shutdown Old Cluster Next Clicked', + }, } as const;