diff --git a/extensions/sql-migration/src/constants/helper.ts b/extensions/sql-migration/src/constants/helper.ts new file mode 100644 index 0000000000..bad1071738 --- /dev/null +++ b/extensions/sql-migration/src/constants/helper.ts @@ -0,0 +1,27 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the Source EULA. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { MigrationContext } from '../models/migrationLocalStorage'; +import * as loc from './strings'; + +export enum SQLTargetAssetType { + SQLMI = 'microsoft.sql/managedinstances', + SQLVM = 'Microsoft.SqlVirtualMachine/sqlVirtualMachines', +} + +export function getMigrationTargetType(migration: MigrationContext): string { + switch (migration.targetManagedInstance.type) { + case SQLTargetAssetType.SQLMI: + return loc.SQL_MANAGED_INSTANCE; + case SQLTargetAssetType.SQLVM: + return loc.SQL_VIRTUAL_MACHINE; + default: + return ''; + } +} + +export function getMigrationMode(migration: MigrationContext): string { + return migration.migrationContext.properties.autoCutoverConfiguration?.autoCutover?.valueOf() ? loc.OFFLINE : loc.OFFLINE; +} diff --git a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts index 9539cab6ad..d4a0e803ce 100644 --- a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts +++ b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts @@ -3,10 +3,11 @@ * Licensed under the Source EULA. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import { getMigrationStatus, DatabaseMigration, startMigrationCutover, stopMigration, getMigrationAsyncOperationDetails, AzureAsyncOperationResource, BackupFileInfo } from '../../api/azure'; +import { getMigrationStatus, DatabaseMigration, startMigrationCutover, stopMigration, getMigrationAsyncOperationDetails, AzureAsyncOperationResource, BackupFileInfo, getResourceGroupFromId } from '../../api/azure'; import { MigrationContext } from '../../models/migrationLocalStorage'; import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../../telemtery'; import * as constants from '../../constants/strings'; +import { getMigrationTargetType, getMigrationMode } from '../../constants/helper'; export class MigrationCutoverDialogModel { @@ -57,8 +58,8 @@ export class MigrationCutoverDialogModel { TelemetryViews.MigrationCutoverDialog, TelemetryAction.CutoverMigration, { - 'sessionId': this._migration.sessionId!, - 'migrationEndTime': new Date().toString() + ...this.getTelemetryProps(this._migration), + 'migrationEndTime': new Date().toString(), }, {} ); @@ -84,7 +85,8 @@ export class MigrationCutoverDialogModel { TelemetryViews.MigrationCutoverDialog, TelemetryAction.CancelMigration, { - 'sessionId': this._migration.sessionId!, + ...this.getTelemetryProps(this._migration), + 'migrationMode': getMigrationMode(this._migration), 'cutoverStartTime': cutoverStartTime }, {} @@ -131,4 +133,17 @@ export class MigrationCutoverDialogModel { }); return files; } + + private getTelemetryProps(migration: MigrationContext) { + return { + 'sessionId': migration.sessionId!, + 'subscriptionId': migration.subscription.id, + 'resourceGroup': getResourceGroupFromId(migration.targetManagedInstance.id), + 'sqlServerName': migration.sourceConnectionProfile.serverName, + 'sourceDatabaseName': migration.migrationContext.properties.sourceDatabaseName, + 'targetType': getMigrationTargetType(migration), + 'targetDatabaseName': migration.migrationContext.name, + 'targetServerName': migration.targetManagedInstance.name, + }; + } } diff --git a/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts b/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts index 7d293ba133..492af5d2fc 100644 --- a/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts +++ b/extensions/sql-migration/src/dialog/migrationStatus/migrationStatusDialog.ts @@ -14,6 +14,7 @@ import { clearDialogMessage, convertTimeDifferenceToDuration, filterMigrations, import { SqlMigrationServiceDetailsDialog } from '../sqlMigrationService/sqlMigrationServiceDetailsDialog'; import { ConfirmCutoverDialog } from '../migrationCutover/confirmCutoverDialog'; import { MigrationCutoverDialogModel } from '../migrationCutover/migrationCutoverDialogModel'; +import { getMigrationTargetType, getMigrationMode } from '../../constants/helper'; const refreshFrequency: SupportedAutoRefreshIntervals = 180000; @@ -326,8 +327,8 @@ export class MigrationStatusDialog { return [ { value: this._getDatabaserHyperLink(migration) }, { value: this._getMigrationStatus(migration) }, - { value: this._getMigrationMode(migration) }, - { value: this._getMigrationTargetType(migration) }, + { value: getMigrationMode(migration) }, + { value: getMigrationTargetType(migration) }, { value: migration.targetManagedInstance.name }, { value: migration.controller.name }, { @@ -404,21 +405,11 @@ export class MigrationStatusDialog { return '---'; } - private _getMigrationTargetType(migration: MigrationContext): string { - return migration.targetManagedInstance.type === 'microsoft.sql/managedinstances' - ? loc.SQL_MANAGED_INSTANCE - : loc.SQL_VIRTUAL_MACHINE; - } - - private _getMigrationMode(migration: MigrationContext): string { - return migration.migrationContext.properties.autoCutoverConfiguration?.autoCutover?.valueOf() ? loc.OFFLINE : loc.ONLINE; - } - private _getMenuCommands(migration: MigrationContext): string[] { const menuCommands: string[] = []; const migrationStatus = migration?.migrationContext?.properties?.migrationStatus; - if (this._getMigrationMode(migration) === loc.ONLINE && + if (getMigrationMode(migration) === loc.ONLINE && this.canCutoverMigration(migrationStatus)) { menuCommands.push(MenuCommands.Cutover); } diff --git a/extensions/sql-migration/src/models/stateMachine.ts b/extensions/sql-migration/src/models/stateMachine.ts index ad27d32c7b..b9f7441e66 100644 --- a/extensions/sql-migration/src/models/stateMachine.ts +++ b/extensions/sql-migration/src/models/stateMachine.ts @@ -258,6 +258,8 @@ export class MigrationStateModel implements Model, vscode.Disposable { { 'sessionId': this._sessionId, 'tenantId': this._azureAccount.properties.tenants[0].id, + 'subscriptionId': this._targetSubscription?.id, + 'resourceGroup': this._resourceGroup?.name, 'hashedServerName': hashString(this._assessmentApiResponse.assessmentResult.name), 'startTime': startTime.toString(), 'endTime': endTime.toString(), @@ -291,6 +293,8 @@ export class MigrationStateModel implements Model, vscode.Disposable { TelemetryAction.DatabaseAssessment, { 'sessionId': this._sessionId, + 'subscriptionId': this._targetSubscription?.id, + 'resourceGroup': this._resourceGroup?.name, 'hashedDatabaseName': hashString(d.name), 'compatibilityLevel': d.compatibilityLevel }, @@ -327,6 +331,8 @@ export class MigrationStateModel implements Model, vscode.Disposable { TelemetryAction.DatabaseAssessmentWarning, { 'sessionId': this._sessionId, + 'subscriptionId': this._targetSubscription?.id, + 'resourceGroup': this._resourceGroup?.name, 'warnings': JSON.stringify(databaseWarnings) }, {} @@ -345,6 +351,8 @@ export class MigrationStateModel implements Model, vscode.Disposable { TelemetryAction.DatabaseAssessmentError, { 'sessionId': this._sessionId, + 'subscriptionId': this._targetSubscription?.id, + 'resourceGroup': this._resourceGroup?.name, 'errors': JSON.stringify(databaseErrors) }, {} @@ -924,15 +932,18 @@ export class MigrationStateModel implements Model, vscode.Disposable { TelemetryViews.MigrationWizardSummaryPage, TelemetryAction.StartMigration, { + 'sessionId': this._sessionId, + 'tenantId': this._azureAccount.properties.tenants[0].id, + 'subscriptionId': this._targetSubscription?.id, + 'resourceGroup': this._resourceGroup?.name, + 'location': this._targetServerInstance.location, + 'targetType': this._targetType, 'hashedServerName': hashString(this._assessmentApiResponse.assessmentResult.name), 'hashedDatabaseName': hashString(this._migrationDbs[i]), 'migrationMode': isOfflineMigration ? 'offline' : 'online', - 'sessionId': this._sessionId, 'migrationStartTime': new Date().toString(), 'targetDatabaseName': this._targetDatabaseNames[i], 'serverName': this._targetServerInstance.name, - 'tenantId': this._azureAccount.properties.tenants[0].id, - 'location': this._targetServerInstance.location, 'sqlMigrationServiceId': Buffer.from(this._sqlMigrationService?.id!).toString('base64'), 'irRegistered': (this._nodeNames.length > 0).toString() }, diff --git a/extensions/sql-migration/src/telemtery.ts b/extensions/sql-migration/src/telemtery.ts index 1727deff79..7e86ca58bd 100644 --- a/extensions/sql-migration/src/telemtery.ts +++ b/extensions/sql-migration/src/telemtery.ts @@ -34,7 +34,11 @@ export enum TelemetryAction { CutoverMigration = 'CutoverMigration', CancelMigration = 'CancelMigration', MigrationStatus = 'MigrationStatus', - PageButtonClick = 'PageButtonClick' + PageButtonClick = 'PageButtonClick', + Prev = 'prev', + Next = 'next', + Done = 'done', + Cancel = 'cancel', } export function sendSqlMigrationActionEvent(telemetryView: TelemetryViews, telemetryAction: TelemetryAction, additionalProps: TelemetryEventProperties, additionalMeasurements: TelemetryEventMeasures): void { diff --git a/extensions/sql-migration/src/wizard/wizardController.ts b/extensions/sql-migration/src/wizard/wizardController.ts index ddbcd5b0e7..78293b4b17 100644 --- a/extensions/sql-migration/src/wizard/wizardController.ts +++ b/extensions/sql-migration/src/wizard/wizardController.ts @@ -95,8 +95,8 @@ export class WizardController { TelemetryViews.SqlMigrationWizard, TelemetryAction.PageButtonClick, { - 'sessionId': this._model._sessionId, - 'buttonPressed': 'cancel', + ...this.getTelemetryProps(), + 'buttonPressed': TelemetryAction.Cancel, 'pageTitle': this._wizardObject.pages[this._wizardObject.currentPage].title }, {}); }); @@ -106,25 +106,34 @@ export class WizardController { TelemetryViews.SqlMigrationWizard, TelemetryAction.PageButtonClick, { - 'sessionId': this._model._sessionId, - 'buttonPressed': 'done', + ...this.getTelemetryProps(), + 'buttonPressed': TelemetryAction.Done, 'pageTitle': this._wizardObject.pages[this._wizardObject.currentPage].title }, {}); }); } private async sendPageButtonClickEvent(pageChangeInfo: azdata.window.WizardPageChangeInfo) { - const buttonPressed = pageChangeInfo.newPage > pageChangeInfo.lastPage ? 'next' : 'prev'; - const pageTitle = this._wizardObject.pages[pageChangeInfo.lastPage].title; + const buttonPressed = pageChangeInfo.newPage > pageChangeInfo.lastPage ? TelemetryAction.Next : TelemetryAction.Prev; + const pageTitle = this._wizardObject.pages[pageChangeInfo.lastPage]?.title; sendSqlMigrationActionEvent( TelemetryViews.SqlMigrationWizard, TelemetryAction.PageButtonClick, { - 'sessionId': this._model._sessionId, + ...this.getTelemetryProps(), 'buttonPressed': buttonPressed, 'pageTitle': pageTitle }, {}); } + + private getTelemetryProps() { + return { + 'sessionId': this._model._sessionId, + 'subscriptionId': this._model._targetSubscription?.id, + 'resourceGroup': this._model._resourceGroup?.name, + 'targetType': this._model._targetType, + }; + } } export function createInformationRow(view: azdata.ModelView, label: string, value: string): azdata.FlexContainer {