diff --git a/extensions/sql-migration/src/dashboard/sqlServerDashboard.ts b/extensions/sql-migration/src/dashboard/sqlServerDashboard.ts index aea2db2bae..0f884e7946 100644 --- a/extensions/sql-migration/src/dashboard/sqlServerDashboard.ts +++ b/extensions/sql-migration/src/dashboard/sqlServerDashboard.ts @@ -6,6 +6,7 @@ import * as azdata from 'azdata'; import * as vscode from 'vscode'; import { MigrationContext, MigrationLocalStorage } from '../models/migrationLocalStorage'; +import { logError, TelemetryViews } from '../telemtery'; import * as loc from '../constants/strings'; import { IconPath, IconPathHelper } from '../constants/iconPathHelper'; import { MigrationStatusDialog } from '../dialog/migrationStatus/migrationStatusDialog'; @@ -298,7 +299,8 @@ export class DashboardWidget { } } catch (error) { - console.log(error); + logError(TelemetryViews.SqlServerDashboard, 'RefreshgMigrationFailed', error); + } finally { this.isRefreshing = false; this._migrationStatusCardLoadingContainer.loading = false; diff --git a/extensions/sql-migration/src/dialog/createSqlMigrationService/createSqlMigrationServiceDialog.ts b/extensions/sql-migration/src/dialog/createSqlMigrationService/createSqlMigrationServiceDialog.ts index f1195c240e..782593c653 100644 --- a/extensions/sql-migration/src/dialog/createSqlMigrationService/createSqlMigrationServiceDialog.ts +++ b/extensions/sql-migration/src/dialog/createSqlMigrationService/createSqlMigrationServiceDialog.ts @@ -7,6 +7,7 @@ import * as azdata from 'azdata'; import * as vscode from 'vscode'; import { createSqlMigrationService, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlMigrationService } from '../../api/azure'; import { MigrationStateModel, NetworkContainerType } from '../../models/stateMachine'; +import { logError, TelemetryViews } from '../../telemtery'; import * as constants from '../../constants/strings'; import * as os from 'os'; import { azureResource } from 'azureResource'; @@ -497,7 +498,7 @@ export class CreateSqlMigrationServiceDialog { description: e.message, level: azdata.window.MessageLevel.Error }; - console.log(e); + logError(TelemetryViews.CreateDataMigrationServiceDialog, 'FetchSqlMigrationServiceFailed', e); } await new Promise(r => setTimeout(r, 5000)); } diff --git a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts index 4ca18d6191..cbf86da746 100644 --- a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts +++ b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialog.ts @@ -12,6 +12,7 @@ import * as loc from '../../constants/strings'; import { convertByteSizeToReadableUnit, convertIsoTimeToLocalTime, getSqlServerName, getMigrationStatusImage, SupportedAutoRefreshIntervals, clearDialogMessage, displayDialogErrorMessage } from '../../api/utils'; import { EOL } from 'os'; import { ConfirmCutoverDialog } from './confirmCutoverDialog'; +import { logError, TelemetryViews } from '../../telemtery'; import { RetryMigrationDialog } from '../retryMigration/retryMigrationDialog'; import * as styles from '../../constants/styles'; import { canRetryMigration } from '../../constants/helper'; @@ -233,7 +234,7 @@ export class MigrationCutoverDialog { await this.refreshStatus(); }); } catch (e) { - console.log(e); + logError(TelemetryViews.MigrationCutoverDialog, 'IntializingFailed', e); } }); this._dialogObject.content = [tab]; diff --git a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts index 9aeb414f00..09cfcce295 100644 --- a/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts +++ b/extensions/sql-migration/src/dialog/migrationCutover/migrationCutoverDialogModel.ts @@ -5,7 +5,7 @@ import { getMigrationStatus, DatabaseMigration, startMigrationCutover, stopMigration, getMigrationAsyncOperationDetails, AzureAsyncOperationResource, BackupFileInfo, getResourceGroupFromId } from '../../api/azure'; import { BackupFileInfoStatus, MigrationContext } from '../../models/migrationLocalStorage'; -import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../../telemtery'; +import { logError, sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../../telemtery'; import * as constants from '../../constants/strings'; import { EOL } from 'os'; import { getMigrationTargetType, getMigrationMode } from '../../constants/helper'; @@ -71,7 +71,7 @@ export class MigrationCutoverDialogModel { } } catch (error) { this.CutoverError = error; - console.log(error); + logError(TelemetryViews.MigrationCutoverDialog, 'StartCutoverError', error); } return undefined!; } @@ -111,7 +111,7 @@ export class MigrationCutoverDialogModel { } } catch (error) { this.CancelMigrationError = error; - console.log(error); + logError(TelemetryViews.MigrationCutoverDialog, 'CancelMigrationError', error); } return undefined!; } diff --git a/extensions/sql-migration/src/models/migrationLocalStorage.ts b/extensions/sql-migration/src/models/migrationLocalStorage.ts index 9e0f5ee456..69aece0025 100644 --- a/extensions/sql-migration/src/models/migrationLocalStorage.ts +++ b/extensions/sql-migration/src/models/migrationLocalStorage.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; import { azureResource } from 'azureResource'; +import { logError, sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../telemtery'; import { DatabaseMigration, SqlMigrationService, SqlManagedInstance, getMigrationStatus, AzureAsyncOperationResource, getMigrationAsyncOperationDetails, SqlVMServer, getSubscriptions } from '../api/azure'; import * as azdata from 'azdata'; @@ -19,7 +20,7 @@ export class MigrationLocalStorage { const undefinedSessionId = '{undefined}'; const result: MigrationContext[] = []; const validMigrations: MigrationContext[] = []; - + const startTime = new Date().toString(); // fetch saved migrations const migrationMementos: MigrationContext[] = this.context.globalState.get(this.mementoToken) || []; for (let i = 0; i < migrationMementos.length; i++) { @@ -53,7 +54,7 @@ export class MigrationLocalStorage { case 'NullMigrationId': continue; default: - console.log(e); + logError(TelemetryViews.MigrationLocalStorage, 'MigrationBySourceConnectionError', e); } } } @@ -62,6 +63,20 @@ export class MigrationLocalStorage { validMigrations.push(migration); } + await this.context.globalState.update(this.mementoToken, validMigrations); + + sendSqlMigrationActionEvent( + TelemetryViews.MigrationLocalStorage, + TelemetryAction.Done, + { + 'startTime': startTime, + 'endTime': new Date().toString() + }, + { + 'migrationCount': migrationMementos.length + } + ); + // only save updated migration context if (refreshStatus) { const migrations: MigrationContext[] = this.context.globalState.get(this.mementoToken) || []; @@ -79,7 +94,6 @@ export class MigrationLocalStorage { await this.context.globalState.update(this.mementoToken, migrations); } } - return result; } @@ -121,7 +135,7 @@ export class MigrationLocalStorage { }); await this.context.globalState.update(this.mementoToken, migrationMementos); } catch (e) { - console.log(e); + logError(TelemetryViews.MigrationLocalStorage, 'CantSaveMigration', e); } } diff --git a/extensions/sql-migration/src/telemtery.ts b/extensions/sql-migration/src/telemtery.ts index 7e86ca58bd..f4aa5afcce 100644 --- a/extensions/sql-migration/src/telemtery.ts +++ b/extensions/sql-migration/src/telemtery.ts @@ -14,13 +14,18 @@ export enum TelemetryViews { SqlServerDashboard = 'SqlServerDashboard', CreateDataMigrationServiceDialog = 'CreateDataMigrationServiceDialog', AssessmentsDialog = 'AssessmentsDialog', + DatabaseBackupPage = 'DatabaseBackupPage', + IntegrationRuntimePage = 'IntegrationRuntimePage', MigrationCutoverDialog = 'MigrationCutoverDialog', MigrationStatusDialog = 'MigrationStatusDialog', MigrationWizardAccountSelectionPage = 'MigrationWizardAccountSelectionPage', MigrationWizardTargetSelectionPage = 'MigrationWizardTargetSelectionPage', + MigrationWizardIntegrationRuntimePage = 'MigrationWizardIntegrationRuntimePage', MigrationWizardSummaryPage = 'MigrationWizardSummaryPage', + MigrationWizardController = 'MigrationWizardController', StartMigrationService = 'StartMigrationSerivce', - SqlMigrationWizard = 'SqlMigrationWizard' + SqlMigrationWizard = 'SqlMigrationWizard', + MigrationLocalStorage = 'MigrationLocalStorage' } export enum TelemetryAction { @@ -41,6 +46,11 @@ export enum TelemetryAction { Cancel = 'cancel', } +export function logError(telemetryView: TelemetryViews, err: string, error: any): void { + console.log(error); + TelemetryReporter.sendErrorEvent(telemetryView, err); +} + export function sendSqlMigrationActionEvent(telemetryView: TelemetryViews, telemetryAction: TelemetryAction, additionalProps: TelemetryEventProperties, additionalMeasurements: TelemetryEventMeasures): void { TelemetryReporter.createActionEvent(telemetryView, telemetryAction) .withAdditionalProperties(additionalProps) diff --git a/extensions/sql-migration/src/wizard/databaseBackupPage.ts b/extensions/sql-migration/src/wizard/databaseBackupPage.ts index 1d43be1209..f78723ae5b 100644 --- a/extensions/sql-migration/src/wizard/databaseBackupPage.ts +++ b/extensions/sql-migration/src/wizard/databaseBackupPage.ts @@ -13,6 +13,7 @@ import * as constants from '../constants/strings'; import { IconPathHelper } from '../constants/iconPathHelper'; import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController'; import { findDropDownItemIndex, selectDropDownIndex } from '../api/utils'; +import { logError, TelemetryViews } from '../telemtery'; import { azureResource } from 'azureResource'; import * as styles from '../constants/styles'; @@ -1233,7 +1234,7 @@ export class DatabaseBackupPage extends MigrationWizardPage { selectDropDownIndex(this._networkShareStorageAccountResourceGroupDropdown, 0); } } catch (error) { - console.log(error); + logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingNetworkStorageResourceGroup', error); } finally { this._networkShareStorageAccountResourceGroupDropdown.loading = false; await this.loadNetworkShareStorageDropdown(); @@ -1246,7 +1247,7 @@ export class DatabaseBackupPage extends MigrationWizardPage { this._networkShareContainerStorageAccountDropdown.values = await this.migrationStateModel.getStorageAccountValues(this.migrationStateModel._databaseBackup.subscription, this.migrationStateModel._databaseBackup.networkShares[0].resourceGroup); selectDropDownIndex(this._networkShareContainerStorageAccountDropdown, 0); } catch (error) { - console.log(error); + logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingNetworkShareStorageDropdown', error); } finally { this._networkShareContainerStorageAccountDropdown.loading = false; } @@ -1269,7 +1270,7 @@ export class DatabaseBackupPage extends MigrationWizardPage { } }); } catch (error) { - console.log(error); + logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobResourceGroup', error); } finally { this._blobContainerResourceGroupDropdowns.forEach(v => v.loading = false); } @@ -1289,7 +1290,7 @@ export class DatabaseBackupPage extends MigrationWizardPage { selectDropDownIndex(this._blobContainerStorageAccountDropdowns[index], 0); } } catch (error) { - console.log(error); + logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobStorageDropdown', error); } finally { this._blobContainerStorageAccountDropdowns[index].loading = false; } @@ -1310,7 +1311,7 @@ export class DatabaseBackupPage extends MigrationWizardPage { selectDropDownIndex(this._blobContainerDropdowns[index], 0); } } catch (error) { - console.log(error); + logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobContainers', error); } finally { this._blobContainerDropdowns[index].loading = false; } @@ -1331,7 +1332,7 @@ export class DatabaseBackupPage extends MigrationWizardPage { selectDropDownIndex(this._blobContainerLastBackupFileDropdowns[index], 0); } } catch (error) { - console.log(error); + logError(TelemetryViews.DatabaseBackupPage, 'ErrorLoadingBlobLastBackupFiles', error); } finally { this._blobContainerLastBackupFileDropdowns[index].loading = false; } diff --git a/extensions/sql-migration/src/wizard/integrationRuntimePage.ts b/extensions/sql-migration/src/wizard/integrationRuntimePage.ts index c1bea0f269..b921c76804 100644 --- a/extensions/sql-migration/src/wizard/integrationRuntimePage.ts +++ b/extensions/sql-migration/src/wizard/integrationRuntimePage.ts @@ -13,6 +13,7 @@ import * as constants from '../constants/strings'; import { WIZARD_INPUT_COMPONENT_WIDTH } from './wizardController'; import { getFullResourceGroupFromId, getLocationDisplayName, getSqlMigrationService, getSqlMigrationServiceAuthKeys, getSqlMigrationServiceMonitoringData, SqlManagedInstance, SqlVMServer } from '../api/azure'; import { IconPathHelper } from '../constants/iconPathHelper'; +import { logError, TelemetryViews } from '../telemtery'; import { findDropDownItemIndex, selectDropDownIndex } from '../api/utils'; import * as styles from '../constants/styles'; @@ -428,7 +429,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage { try { await this.loadStatus(); } catch (error) { - console.log(error); + logError(TelemetryViews.MigrationWizardIntegrationRuntimePage, 'ErrorLoadingMigrationServiceStatus', error); } finally { this._statusLoadingComponent.loading = false; } @@ -507,7 +508,7 @@ export class IntergrationRuntimePage extends MigrationWizardPage { await this._authKeyTable.setDataValues(data); } } catch (e) { - console.log(e); + logError(TelemetryViews.IntegrationRuntimePage, 'ErrorLoadingStatus', e); } } } diff --git a/extensions/sql-migration/src/wizard/wizardController.ts b/extensions/sql-migration/src/wizard/wizardController.ts index 86ac0655a2..807514db12 100644 --- a/extensions/sql-migration/src/wizard/wizardController.ts +++ b/extensions/sql-migration/src/wizard/wizardController.ts @@ -15,7 +15,7 @@ import { IntergrationRuntimePage } from './integrationRuntimePage'; import { SummaryPage } from './summaryPage'; import { MigrationModePage } from './migrationModePage'; import { DatabaseSelectorPage } from './databaseSelectorPage'; -import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../telemtery'; +import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews, logError } from '../telemtery'; import * as styles from '../constants/styles'; export const WIZARD_INPUT_COMPONENT_WIDTH = '600px'; @@ -80,7 +80,7 @@ export class WizardController { this._model.extensionContext.subscriptions.push(this._wizardObject.onPageChanged(async (pageChangeInfo: azdata.window.WizardPageChangeInfo) => { const newPage = pageChangeInfo.newPage; const lastPage = pageChangeInfo.lastPage; - this.sendPageButtonClickEvent(pageChangeInfo).catch(e => console.log(e)); + this.sendPageButtonClickEvent(pageChangeInfo).catch(e => logError(TelemetryViews.MigrationWizardController, 'ErrorSendingPageButtonClick', e)); await pages[lastPage]?.onPageLeave(pageChangeInfo); await pages[newPage]?.onPageEnter(pageChangeInfo); }));