Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Telemetry and fixed Template Upload error #25991

Merged
merged 13 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions extensions/sql-migration/config.json
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.migration-{#fileName#}",
"useDefaultLinuxRuntime": true,
"version": "5.0.20241014.2",
"version": "5.0.20241024.1",
sahuroshan marked this conversation as resolved.
Show resolved Hide resolved
"downloadFileNames": {
"Windows_86": "win-x86-net8.0.zip",
"Windows": "win-x64-net8.0.zip",
"OSX": "osx-x64-net8.0.tar.gz",
"Linux": "rhel-x64-net8.0.tar.gz"
"Linux": "linux-x64-net8.0.tar.gz"
},
"installDirectory": "./migrationService/{#platform#}/{#version#}",
"executableFiles": ["MicrosoftSqlToolsMigration", "MicrosoftSqlToolsMigration.exe"],
Expand Down
2 changes: 2 additions & 0 deletions extensions/sql-migration/src/constants/strings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,7 @@ export const IMPORT_PERFORMANCE_DATA_DIALOG_OPEN_FOLDER = localize('sql.migratio
export const UPLOAD_TEMPLATE_TO_AZURE = localize('sql.migration.target.provisioning.upload.to.azure', "Deploy to Azure");
export const SAVE_TO_DEVICE = localize('sql.migration.target.provisioning.generate.template', "Save to device");
export const COPY_TO_CLIPBOARD = localize('sql.migration.target.provisioning.copy.to.clipboard', "Copy to clipboard");
export const ARM_TEMPLATE_GENERATE_FAILED = localize('sql.migration.target.provisioning.arm.template.generation.failed', "Failed to generate ARM template");

export const CLOSE_DIALOG = localize('sql.migration.target.provisioning.close', "Close");
export const TARGET_PROVISIONING_DESCRIPTION = localize('sql.migration.target.provisioning.description', "Below is the ARM script for the recommended target SKU. You can use the following two methods to deploy target SKU to Azure.\n 1.Click on the \"Deploy to Azure\" command to deploy the target resource. This option requires an Azure blob container account.\n 2.Click on \"Save to device\" to save the ARM script and then manually deploy the target resource.");
Expand Down Expand Up @@ -1747,6 +1748,7 @@ export const STORAGE_ACCOUNT_RESOURCE_GROUP_INFO = localize('sql.migration.stora
export const SELECT_A_STORAGE_ACCOUNT = localize('sql.migration.select.storage.select.a.storage.account', "Select a Storage Account");
export const STORAGE_ACCOUNT_SUBSCRIPTION_INFO = localize('sql.migration.storage.account.subscription', "Subscription name for your Storage Account");
export const SAVE_TEMPLATE_SUCCESS = localize('sql.migration.target.provisioning.save.template.success', "Template saved successfully");
export const COPY_TEMPLATE_SUCCESS = localize('sql.migration.target.provisioning.copy.template.success', "Template copied successfully");
export const SAVE_TEMPLATE_FAIL = localize('sql.migration.target.provisioning.save.template.fail', "Failed to save ARM Template");
export const UPLOAD_TEMPLATE_SUCCESS = localize('sql.migration.target.provisioning.upload.template.success', "Azure Portal Custom Deployment page with parameters pre-filled with the default values from the template has been opened in browser. \n \"Note:There can be multiple windows if you are provisioning more than 50 Azure SQL DBs.\"");
export const UPLOAD_TEMPLATE_FAIL = localize('sql.migration.target.provisioning.upload.template.fail', "Failed to upload ARM Template");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import { MigrationStateModel } from '../../models/stateMachine';
import * as constants from '../../constants/strings';
import * as styles from '../../constants/styles';
import * as utils from '../../api/utils';
import { logError, TelemetryViews } from '../../telemetry';
import { logError, TelemetryViews, sendButtonClickEvent, TelemetryAction, sendSqlMigrationActionEvent } from '../../telemetry';
import { IconPathHelper } from '../../constants/iconPathHelper';
import { SelectStorageAccountDialog } from './SelectStorageAccountDialog';

Expand Down Expand Up @@ -108,6 +108,12 @@ export class GenerateProvisioningScriptDialog {
fs.writeFileSync(destinationFilePath!, this._armTemplateText!);
}
void vscode.window.showInformationMessage(constants.SAVE_TEMPLATE_SUCCESS);
// emit Telemetry for the success.
sendSqlMigrationActionEvent(
TelemetryViews.ProvisioningScriptWizard,
TelemetryAction.SaveArmTemplateSuccess,
{}, {}
);
}
catch (e) {
logError(TelemetryViews.ProvisioningScriptWizard, 'ArmTemplateSavetoLocalError', e);
Expand Down Expand Up @@ -150,8 +156,15 @@ export class GenerateProvisioningScriptDialog {
}).component();

copyToClipboardButton.onDidClick(async () => {
if (this.model._armTemplateResult.templates) {
if (this.model._armTemplateResult?.templates?.[0]) {
void vscode.env.clipboard.writeText(this.model._armTemplateResult.templates[0]);
void vscode.window.showInformationMessage(constants.COPY_TEMPLATE_SUCCESS);
// emit Telemetry for the success.
sendSqlMigrationActionEvent(
TelemetryViews.ProvisioningScriptWizard,
TelemetryAction.CopyArmTemplateSuccess,
{}, {}
);
}
});

Expand Down Expand Up @@ -187,11 +200,15 @@ export class GenerateProvisioningScriptDialog {
}

private async displayArmTemplate(): Promise<void> {
this._armTemplateTextBox.value = this.model._armTemplateResult.templates ?
this.model._armTemplateResult.templates[0] :
this.model._armTemplateResult.generateTemplateError?.message;
if (this.model._armTemplateResult?.templates?.[0]) {
this._armTemplateTextBox.value = this.model._armTemplateResult.templates[0];
}
else {
this._armTemplateTextBox.value = constants.ARM_TEMPLATE_GENERATE_FAILED;
await vscode.window.showErrorMessage(constants.ARM_TEMPLATE_GENERATE_FAILED);
}

if (this.model._armTemplateResult.templates?.length! > 1 && this._targetType === utils.MigrationTargetType.SQLDB) {
if (this.model._armTemplateResult?.templates?.length! > 1 && this._targetType === utils.MigrationTargetType.SQLDB) {
await vscode.window.showInformationMessage(constants.DISPLAY_ARM_TEMPLATE_LIMIT);
}
}
Expand All @@ -213,8 +230,10 @@ export class GenerateProvisioningScriptDialog {
azdata.window.openDialog(this.dialog);
await Promise.all(dialogSetupPromises);

const skuRecommendationReportFilePath = this.getSkuRecommendationReportFilePath(this._targetType);
await this.model.getArmTemplate(skuRecommendationReportFilePath);
// emit Telemetry for opening of Wizard.
sendButtonClickEvent(this.model, TelemetryViews.ProvisioningScriptWizard, TelemetryAction.OpenTargetProvisioningWizard, "", constants.UPLOAD_TEMPLATE_TO_AZURE);

await this.model.getArmTemplate(this._targetType);
const error = this.model._armTemplateResult.generateTemplateError;

if (error) {
Expand All @@ -228,17 +247,6 @@ export class GenerateProvisioningScriptDialog {
}
}

private getSkuRecommendationReportFilePath(targetType: string): string {
let fileName;
this.model._skuRecommendationReportFilePaths.forEach(function (filePath) {
if (filePath.includes(targetType)) {
fileName = filePath.substring(0, filePath.lastIndexOf(".")) + ".json";
}
});

return fileName!;
}

protected async execute() {
this._isOpen = false;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ import * as styles from '../../constants/styles';
import * as constants from '../../constants/strings';
import * as utils from '../../api/utils';
import { StorageAccount } from '../../api/azure';
import { logError, TelemetryViews } from '../../telemetry';
import { logError, TelemetryViews, sendButtonClickEvent, TelemetryAction, sendSqlMigrationActionEvent } from '../../telemetry';
import { MigrationStateModel } from '../../models/stateMachine';
import { StorageSharedKeyCredential, BlockBlobClient, BlobSASPermissions, generateBlobSASQueryParameters } from '@azure/storage-blob';
import { StorageSharedKeyCredential, BlockBlobClient, AccountSASServices, AccountSASResourceTypes, AccountSASPermissions, generateAccountSASQueryParameters } from '@azure/storage-blob';
import { getStorageAccountAccessKeys } from '../../api/azure';
import { MigrationTargetType } from '../../api/utils';

Expand Down Expand Up @@ -96,6 +96,9 @@ export class SelectStorageAccountDialog {
await this.uploadTemplate();
}));
azdata.window.openDialog(this._dialog);

// emit Telemetry for opening of Dialog.
sendButtonClickEvent(this.migrationStateModel, TelemetryViews.ProvisioningScriptWizard, TelemetryAction.OpenDeployArmTemplateDialog, "", constants.UPLOAD_TEMPLATE_TO_AZURE);
}

protected async registerContent(view: azdata.ModelView): Promise<void> {
Expand Down Expand Up @@ -591,12 +594,15 @@ export class SelectStorageAccountDialog {
const templates = this.migrationStateModel._armTemplateResult.templates!;
const sharedKeyCredential = new StorageSharedKeyCredential(this._storageAccount.name, storageKeys.keyName1);

const sasToken = generateBlobSASQueryParameters(
{
containerName,
permissions: BlobSASPermissions.parse("racwd"),
expiresOn: new Date(new Date().valueOf() + 86400),
},
const sasOptions = {
services: AccountSASServices.parse("b").toString(), // blobs
resourceTypes: AccountSASResourceTypes.parse("sco").toString(), // service, container, object
permissions: AccountSASPermissions.parse("rwdlacu"), // permissions
expiresOn: new Date(new Date().valueOf() + (1440 * 60 * 1000)), // 24 hrs
};

const sasToken = generateAccountSASQueryParameters(
sasOptions,
sharedKeyCredential
).toString();

Expand Down Expand Up @@ -645,6 +651,13 @@ export class SelectStorageAccountDialog {

void vscode.window.showInformationMessage(constants.UPLOAD_TEMPLATE_SUCCESS);

// emit Telemetry for the success.
sendSqlMigrationActionEvent(
TelemetryViews.UploadArmTemplateDialog,
TelemetryAction.OpenCustomDeploymentPortalSuccess,
{}, {}
);

}

}
4 changes: 2 additions & 2 deletions extensions/sql-migration/src/models/stateMachine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -496,9 +496,9 @@ export class MigrationStateModel implements Model, vscode.Disposable {
return this._assessmentResults;
}

public async getArmTemplate(skuRecommendationReportFilePath: string): Promise<ArmTemplate> {
public async getArmTemplate(targetType: string): Promise<ArmTemplate> {
try {
const response = (await this.migrationService.getArmTemplate(skuRecommendationReportFilePath))!
const response = (await this.migrationService.getArmTemplate(targetType))!
if (response) {
this._armTemplateResult = {
templates: response
Expand Down
4 changes: 2 additions & 2 deletions extensions/sql-migration/src/service/features.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ export class SqlMigrationService extends MigrationExtensionService implements co
return undefined;
}

async getArmTemplate(skuRecommendationReportFilePath: string): Promise<string[] | undefined> {
async getArmTemplate(targetType: string): Promise<string[] | undefined> {
try {
const response = this._client.sendRequest(contracts.GetSqlMigrationGenerateArmTemplateRequest.type, skuRecommendationReportFilePath);
const response = this._client.sendRequest(contracts.GetSqlMigrationGenerateArmTemplateRequest.type, targetType);
return response;
}
catch (e) {
Expand Down
7 changes: 6 additions & 1 deletion extensions/sql-migration/src/telemetry.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,12 @@ export enum TelemetryAction {
TdeConfigurationAlreadyMigrated = 'TdeConfigurationAlreadyMigrated',
TdeConfigurationCancelled = 'TdeConfigurationCancelled',
ImportAssessmentSuccess = 'ImportAssessmentSuccess',
ImportAssessmentFailed = 'ImportAssessmentFailed'
ImportAssessmentFailed = 'ImportAssessmentFailed',
SaveArmTemplateSuccess = 'SaveArmTemplateSuccess',
CopyArmTemplateSuccess = 'CopyArmTemplateSuccess',
OpenCustomDeploymentPortalSuccess = 'OpenCustomDeploymentPortalSuccess',
OpenTargetProvisioningWizard = 'OpenTargetProvisioningWizard',
OpenDeployArmTemplateDialog = 'OpenDeployArmTemplateDialog'
}

export function logError(telemetryView: TelemetryViews, err: string, error: any): void {
Expand Down