mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-01-28 09:35:38 -05:00
[SKU Recommendation] Adding telemetry for errors happening during data collection/ get recommendation and telemetry (#18345)
* Adding telemetry for errors happening during data collection/ telemetry for sku recommendation * log and error happended during get sku recommendation * Resolving comments from PR https://github.com/microsoft/azuredatastudio/pull/18252. 1) Adding click and close events to dispoable collection to avoid leaks. 2) Adding readable constant for number representing minutes. * Changes - 1) updating migration workflow strings, 2) adding more onclick events to disposable collection. * Remove PaaS, IaaS terms from string * Changes - 1) Renamed 'Saved assessment result' to 'saved session'. 2) Removed Title from 'saved session' page. 3) Added stop data collection on migration start.
This commit is contained in:
@@ -19,8 +19,8 @@ export function WIZARD_TITLE(instanceName: string): string {
|
||||
|
||||
// Resume Migration Dialog
|
||||
export const RESUME_TITLE = localize('sql.migration.resume.title', "Run migration workflow again");
|
||||
export const START_MIGRATION = localize('sql.migration.resume.start', "Start with migration assessment again (recommended)");
|
||||
export const CONTINUE_MIGRATION = localize('sql.migration.resume.continue', "Continue last migration attempt...");
|
||||
export const START_MIGRATION = localize('sql.migration.resume.start', "Start a new session");
|
||||
export const CONTINUE_MIGRATION = localize('sql.migration.resume.continue', "Resume previously saved session");
|
||||
|
||||
// Databases for assessment
|
||||
export const DATABASE_FOR_ASSESSMENT_PAGE_TITLE = localize('sql.migration.database.assessment.title', "Databases for assessment");
|
||||
@@ -63,13 +63,13 @@ export const REFRESH_ASSESSMENT_BUTTON_LABEL = localize('sql.migration.refresh.a
|
||||
export const SKU_RECOMMENDATION_CHOOSE_A_TARGET = localize('sql.migration.wizard.sku.choose_a_target', "Choose your Azure SQL target");
|
||||
|
||||
|
||||
export const SKU_RECOMMENDATION_MI_CARD_TEXT = localize('sql.migration.sku.mi.card.title', "Azure SQL Managed Instance (PaaS)");
|
||||
export const SKU_RECOMMENDATION_DB_CARD_TEXT = localize('sql.migration.sku.db.card.title', "Azure SQL Database (PaaS)");
|
||||
export const SKU_RECOMMENDATION_VM_CARD_TEXT = localize('sql.migration.sku.vm.card.title', "SQL Server on Azure Virtual Machine (IaaS)");
|
||||
export const SKU_RECOMMENDATION_MI_CARD_TEXT = localize('sql.migration.sku.mi.card.title', "Azure SQL Managed Instance");
|
||||
export const SKU_RECOMMENDATION_DB_CARD_TEXT = localize('sql.migration.sku.db.card.title', "Azure SQL Database");
|
||||
export const SKU_RECOMMENDATION_VM_CARD_TEXT = localize('sql.migration.sku.vm.card.title', "SQL Server on Azure Virtual Machine");
|
||||
export const SELECT_AZURE_MI = localize('sql.migration.select.azure.mi', "Select your target Azure subscription and your target Azure SQL Managed Instance.");
|
||||
export const SELECT_AZURE_VM = localize('sql.migration.select.azure.vm', "Select your target Azure Subscription and your target SQL Server on Azure Virtual Machine for your target.");
|
||||
export const SKU_RECOMMENDATION_VIEW_ASSESSMENT_MI = localize('sql.migration.sku.recommendation.view.assessment.mi', "To migrate to Azure SQL Managed Instance (PaaS), view assessment results and select one or more databases.");
|
||||
export const SKU_RECOMMENDATION_VIEW_ASSESSMENT_VM = localize('sql.migration.sku.recommendation.view.assessment.vm', "To migrate to SQL Server on Azure Virtual Machine (IaaS), view assessment results and select one or more databases.");
|
||||
export const SKU_RECOMMENDATION_VIEW_ASSESSMENT_MI = localize('sql.migration.sku.recommendation.view.assessment.mi', "To migrate to Azure SQL Managed Instance, view assessment results and select one or more databases.");
|
||||
export const SKU_RECOMMENDATION_VIEW_ASSESSMENT_VM = localize('sql.migration.sku.recommendation.view.assessment.vm', "To migrate to SQL Server on Azure Virtual Machine, view assessment results and select one or more databases.");
|
||||
export const VIEW_SELECT_BUTTON_LABEL = localize('sql.migration.view.select.button.label', "View/Select");
|
||||
export function TOTAL_DATABASES_SELECTED(selectedDbCount: number, totalDbCount: number): string {
|
||||
return localize('total.databases.selected', "{0} of {1} databases selected", selectedDbCount, totalDbCount);
|
||||
@@ -232,6 +232,9 @@ export const EMPTY_TIME = localize('sql.migration.sku.recommendations.empty.time
|
||||
export function LAST_REFRESHED_TIME(d: string = EMPTY_TIME): string {
|
||||
return localize('sql.migration.sku.recommendations.lastRefreshed', "Last refreshed: {0}", d);
|
||||
}
|
||||
export function TIME_IN_MINUTES(val: number): number {
|
||||
return val * 60000;
|
||||
}
|
||||
|
||||
// Azure SQL Target
|
||||
export const AZURE_SQL_TARGET_PAGE_TITLE = localize('sql.migration.wizard.target.title', "Azure SQL target");
|
||||
@@ -721,7 +724,7 @@ export const REFRESH_BUTTON_LABEL = localize('sql.migration.status.refresh.label
|
||||
// Saved Assessment Dialog
|
||||
export const NEXT_LABEL = localize('sql.migration.saved.assessment.next', "Next");
|
||||
export const CANCEL_LABEL = localize('sql.migration.saved.assessment.cancel', "Cancel");
|
||||
export const SAVED_ASSESSMENT_RESULT = localize('sql.migration.saved.assessment.result', "Saved assessment result");
|
||||
export const SAVED_ASSESSMENT_RESULT = localize('sql.migration.saved.assessment.result', "Saved session");
|
||||
|
||||
// Retry Migration
|
||||
export const MIGRATION_CANNOT_RETRY = localize('sql.migration.cannot.retry', 'Migration cannot be retried.');
|
||||
|
||||
@@ -89,14 +89,6 @@ export class SavedAssessmentDialog {
|
||||
public initializePageContent(view: azdata.ModelView): azdata.FlexContainer {
|
||||
const buttonGroup = 'resumeMigration';
|
||||
|
||||
const pageTitle = view.modelBuilder.text().withProps({
|
||||
CSSStyles: {
|
||||
...styles.PAGE_TITLE_CSS,
|
||||
'margin-bottom': '12px'
|
||||
},
|
||||
value: constants.RESUME_TITLE
|
||||
}).component();
|
||||
|
||||
const radioStart = view.modelBuilder.radioButton().withProps({
|
||||
label: constants.START_MIGRATION,
|
||||
name: buttonGroup,
|
||||
@@ -137,7 +129,6 @@ export class SavedAssessmentDialog {
|
||||
'margin': '20px 15px',
|
||||
}
|
||||
}).component();
|
||||
flex.addItem(pageTitle, { flex: '0 0 auto' });
|
||||
flex.addItem(radioStart, { flex: '0 0 auto' });
|
||||
flex.addItem(radioContinue, { flex: '0 0 auto' });
|
||||
|
||||
|
||||
@@ -308,7 +308,7 @@ export class GetAzureRecommendationDialog {
|
||||
|
||||
this.dialog.okButton.label = GetAzureRecommendationDialog.StartButtonText;
|
||||
this._disposables.push(this.dialog.okButton.onClick(async () => await this.execute()));
|
||||
this.dialog.cancelButton.onClick(() => this._isOpen = false);
|
||||
this._disposables.push(this.dialog.cancelButton.onClick(() => this._isOpen = false));
|
||||
|
||||
const dialogSetupPromises: Thenable<void>[] = [];
|
||||
dialogSetupPromises.push(this.initializeDialog(this.dialog));
|
||||
|
||||
@@ -207,7 +207,7 @@ export class SkuEditParametersDialog {
|
||||
this.dialog.okButton.label = SkuEditParametersDialog.UpdateButtonText;
|
||||
this._disposables.push(this.dialog.okButton.onClick(async () => await this.execute()));
|
||||
|
||||
this.dialog.cancelButton.onClick(() => this._isOpen = false);
|
||||
this._disposables.push(this.dialog.cancelButton.onClick(() => this._isOpen = false));
|
||||
|
||||
const dialogSetupPromises: Thenable<void>[] = [];
|
||||
dialogSetupPromises.push(this.initializeDialog(this.dialog));
|
||||
|
||||
@@ -13,7 +13,7 @@ import * as constants from '../constants/strings';
|
||||
import { MigrationLocalStorage } from './migrationLocalStorage';
|
||||
import * as nls from 'vscode-nls';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../telemtery';
|
||||
import { sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews, logError } from '../telemtery';
|
||||
import { hashString, deepClone } from '../api/utils';
|
||||
import { SKURecommendationPage } from '../wizard/skuRecommendationPage';
|
||||
const localize = nls.loadMessageBundle();
|
||||
@@ -218,7 +218,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
|
||||
public refreshPerfDataCollectionFrequency = this._performanceDataQueryIntervalInSeconds * 1000;
|
||||
private _autoRefreshPerfDataCollectionHandle!: NodeJS.Timeout;
|
||||
public refreshGetSkuRecommendationFrequency = 600000; // 10 minutes
|
||||
public refreshGetSkuRecommendationFrequency = constants.TIME_IN_MINUTES(10);
|
||||
private _autoRefreshGetSkuRecommendationHandle!: NodeJS.Timeout;
|
||||
|
||||
public _skuScalingFactor!: number;
|
||||
@@ -370,9 +370,6 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
// clone list of databases currently being assessed and store them, so that if the user ever changes the list we can refresh new recommendations
|
||||
this._skuRecommendationRecommendedDatabaseList = this._databaseAssessment.slice();
|
||||
|
||||
console.log('sqlinstancerequirements: ');
|
||||
console.log(this._skuRecommendationApiResponse.instanceRequirements);
|
||||
|
||||
if (response?.sqlDbRecommendationResults || response?.sqlMiRecommendationResults || response?.sqlVmRecommendationResults) {
|
||||
this._skuRecommendationResults = {
|
||||
recommendations: {
|
||||
@@ -394,7 +391,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
logError(TelemetryViews.SkuRecommendationWizard, 'GetSkuRecommendationFailed', error);
|
||||
|
||||
this._skuRecommendationResults = {
|
||||
recommendations: {
|
||||
@@ -490,7 +487,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
);
|
||||
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
logError(TelemetryViews.SkuRecommendationWizard, 'GetSkuRecommendationTelemetryFailed', e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -537,7 +534,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
);
|
||||
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
logError(TelemetryViews.DataCollectionWizard, 'StartDataCollectionTelemetryFailed', e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -581,7 +578,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
clearInterval(this._autoRefreshGetSkuRecommendationHandle);
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
logError(TelemetryViews.DataCollectionWizard, 'StopDataCollectionFailed', error);
|
||||
}
|
||||
|
||||
// Generate telemetry for stop data collection request
|
||||
@@ -602,7 +599,7 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
);
|
||||
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
logError(TelemetryViews.DataCollectionWizard, 'StopDataCollectionTelemetryFailed', e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -620,15 +617,15 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
}
|
||||
}
|
||||
catch (error) {
|
||||
console.log(error);
|
||||
logError(TelemetryViews.DataCollectionWizard, 'RefreshDataCollectionFailed', error);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async isWaitingForFirstTimeRefresh(): Promise<boolean> {
|
||||
const elapsedTimeInMins = Math.abs(new Date().getTime() - new Date(this._perfDataCollectionStartDate!).getTime()) / 60000;
|
||||
const skuRecAutoRefreshTimeInMins = this.refreshGetSkuRecommendationFrequency / 60000;
|
||||
const elapsedTimeInMins = Math.abs(new Date().getTime() - new Date(this._perfDataCollectionStartDate!).getTime()) / constants.TIME_IN_MINUTES(1);
|
||||
const skuRecAutoRefreshTimeInMins = this.refreshGetSkuRecommendationFrequency / constants.TIME_IN_MINUTES(1);
|
||||
|
||||
return elapsedTimeInMins < skuRecAutoRefreshTimeInMins;
|
||||
}
|
||||
@@ -1392,6 +1389,14 @@ export class MigrationStateModel implements Model, vscode.Disposable {
|
||||
localize('sql.migration.starting.migration.error', "An error occurred while starting the migration: '{0}'", e.message));
|
||||
console.log(e);
|
||||
}
|
||||
finally {
|
||||
// kill existing data collection if user start migration
|
||||
await this.refreshPerfDataCollection();
|
||||
if ((!this.resumeAssessment || this.retryMigration) && this._perfDataCollectionIsCollecting) {
|
||||
void this.stopPerfDataCollection();
|
||||
void vscode.window.showInformationMessage(constants.AZURE_RECOMMENDATION_STOP_POPUP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ export const WIZARD_INPUT_COMPONENT_WIDTH = '600px';
|
||||
export class WizardController {
|
||||
private _wizardObject!: azdata.window.Wizard;
|
||||
private _model!: MigrationStateModel;
|
||||
private _disposables: vscode.Disposable[] = [];
|
||||
constructor(private readonly extensionContext: vscode.ExtensionContext, model: MigrationStateModel) {
|
||||
this._model = model;
|
||||
}
|
||||
@@ -111,16 +112,16 @@ export class WizardController {
|
||||
this._model.extensionContext.subscriptions.push(this._wizardObject.doneButton.onClick(async (e) => {
|
||||
await stateModel.startMigration();
|
||||
}));
|
||||
saveAndCloseButton.onClick(async () => {
|
||||
this._disposables.push(saveAndCloseButton.onClick(async () => {
|
||||
await stateModel.saveInfo(serverName, this._wizardObject.currentPage);
|
||||
await this._wizardObject.close();
|
||||
|
||||
if (stateModel.performanceCollectionInProgress()) {
|
||||
void vscode.window.showInformationMessage(loc.SAVE_AND_CLOSE_POPUP);
|
||||
}
|
||||
});
|
||||
}));
|
||||
|
||||
this._wizardObject.cancelButton.onClick(e => {
|
||||
this._disposables.push(this._wizardObject.cancelButton.onClick(e => {
|
||||
sendSqlMigrationActionEvent(
|
||||
TelemetryViews.SqlMigrationWizard,
|
||||
TelemetryAction.PageButtonClick,
|
||||
@@ -129,11 +130,11 @@ export class WizardController {
|
||||
'buttonPressed': TelemetryAction.Cancel,
|
||||
'pageTitle': this._wizardObject.pages[this._wizardObject.currentPage].title
|
||||
}, {});
|
||||
});
|
||||
}));
|
||||
|
||||
this._wizardObject.doneButton.label = loc.START_MIGRATION_TEXT;
|
||||
|
||||
this._wizardObject.doneButton.onClick(e => {
|
||||
this._disposables.push(this._wizardObject.doneButton.onClick(e => {
|
||||
sendSqlMigrationActionEvent(
|
||||
TelemetryViews.SqlMigrationWizard,
|
||||
TelemetryAction.PageButtonClick,
|
||||
@@ -142,7 +143,7 @@ export class WizardController {
|
||||
'buttonPressed': TelemetryAction.Done,
|
||||
'pageTitle': this._wizardObject.pages[this._wizardObject.currentPage].title
|
||||
}, {});
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
private async sendPageButtonClickEvent(pageChangeInfo: azdata.window.WizardPageChangeInfo) {
|
||||
|
||||
Reference in New Issue
Block a user