Added Telemetry and fixed Template Upload error (#25991)

* phase 2 provisioning

* change url open method

* changed icon

* change sastoken method

* update STS version

* telemetry changes

* upload template fix

* paasing targettype instead of filepath

* update sts and linux file

* string change

* check if armtemplateresult is undefined

* check arm template undefined

---------

Co-authored-by: ROSHAN SAHU <roshansahu@microsoft.com>
This commit is contained in:
Roshan lal Sahu 2024-10-28 07:56:35 +05:30 коммит произвёл GitHub
Родитель 46f4a97ea3
Коммит 660f87d9d9
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
7 изменённых файлов: 62 добавлений и 34 удалений

Просмотреть файл

@ -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",
"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"],

Просмотреть файл

@ -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.");
@ -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");

Просмотреть файл

@ -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';
@ -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);
@ -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,
{}, {}
);
}
});
@ -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);
}
}
@ -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) {
@ -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;
}

Просмотреть файл

@ -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';
@ -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> {
@ -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();
@ -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,
{}, {}
);
}
}

Просмотреть файл

@ -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

Просмотреть файл

@ -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) {

Просмотреть файл

@ -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 {