[SQL-Migration] Improve log migrations telemetry (#22927)

- Bucketized errors to track top errors
- Created separate login migration specific error to improve monitoring

---------

Co-authored-by: Akshay Mata <akma@microsoft.com>
This commit is contained in:
AkshayMata
2023-05-03 10:35:44 -07:00
committed by GitHub
parent 2c07c09d0d
commit a8a88ccbeb
6 changed files with 73 additions and 10 deletions

View File

@@ -1,7 +1,7 @@
{
"downloadUrl": "https://github.com/Microsoft/sqltoolsservice/releases/download/{#version#}/microsoft.sqltools.migration-{#fileName#}",
"useDefaultLinuxRuntime": true,
"version": "4.7.0.3",
"version": "4.7.0.13",
"downloadFileNames": {
"Windows_86": "win-x86-net7.0.zip",
"Windows": "win-x64-net7.0.zip",

View File

@@ -26,6 +26,12 @@ export enum LoginMigrationStep {
MigrationCompleted = 3,
}
export const CollectingSourceLoginsFailed = 'Collecting source logins failed';
export const CollectingTargetLoginsFailed = 'Collecting target logins failed';
export const ConnectingToTargetFailed = 'Connecting to target failed';
export const InternalServerError = 'Login Migrations Internal Server Error';
export function GetLoginMigrationStepString(step: LoginMigrationStep): string {
switch (step) {
case LoginMigrationStep.NotStarted:
@@ -159,8 +165,21 @@ export class LoginMigrationModel {
}
private setErrorCountMapPerStep(step: LoginMigrationStep, result: contracts.StartLoginMigrationResult) {
const errorCount = result.exceptionMap ? Object.keys(result.exceptionMap).length : 0;
this.errorCountMap.set(LoginMigrationStep[step], errorCount);
const errorBuckets: Map<string, number> = new Map<string, number>();
if (!result.exceptionMap) {
return;
}
for (const exceptions of Object.values(result.exceptionMap)) {
for (const exception of exceptions) {
// Get the value for the key, or the default value of t0 if he key is not in the map
const errorCount = errorBuckets.get(exception.ErrorCodeString) ?? 0;
errorBuckets.set(exception.ErrorCodeString, errorCount + 1)
}
}
this.errorCountMap.set(LoginMigrationStep[step], errorBuckets);
}
private setDurationPerStep(step: LoginMigrationStep, result: contracts.StartLoginMigrationResult) {

View File

@@ -77,6 +77,7 @@ export enum TelemetryAction {
OpenLoginMigrationWizard = 'OpenLoginMigrationWizard',
LoginMigrationStarted = 'LoginMigrationStarted',
LoginMigrationCompleted = 'LoginMigrationCompleted',
LoginMigrationError = 'LoginMigrationError',
TdeMigrationSuccess = 'TdeMigrationSuccess',
TdeMigrationFailures = 'TdeMigrationFailures',
TdeMigrationClientException = 'TdeMigrationClientException',

View File

@@ -14,6 +14,7 @@ import { IconPathHelper } from '../constants/iconPathHelper';
import { LoginMigrationStatusCodes } from '../constants/helper';
import { MultiStepStatusDialog } from '../dialog/generic/multiStepStatusDialog';
import { getTelemetryProps, logError, sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../telemetry';
import { InternalServerError } from '../models/loginMigrationModel';
export class LoginMigrationStatusPage extends MigrationWizardPage {
private _view!: azdata.ModelView;
@@ -93,7 +94,17 @@ export class LoginMigrationStatusPage extends MigrationWizardPage {
};
this._progressLoader.loading = false;
logError(TelemetryViews.LoginMigrationWizard, 'LoginMigrationFailed', 'Login Migrations Internal Server Error');
logError(TelemetryViews.LoginMigrationWizard, 'LoginMigrationFailed', InternalServerError);
sendSqlMigrationActionEvent(
TelemetryViews.LoginMigrationStatusPage,
TelemetryAction.LoginMigrationError,
{
...getTelemetryProps(this.migrationStateModel),
'errorMessage': InternalServerError,
},
{}
);
}
this._logMigrationResult();
@@ -450,9 +461,10 @@ export class LoginMigrationStatusPage extends MigrationWizardPage {
'numberLoginsFailingPerStep': JSON.stringify(Array.from(this.migrationStateModel._loginMigrationModel.errorCountMap)),
'durationPerStepTimestamp': JSON.stringify(Array.from(this.migrationStateModel._loginMigrationModel.durationPerStep)),
'hasSystemError': JSON.stringify(this.migrationStateModel._loginMigrationModel.hasSystemError),
// AKMA TODO: add error code string count map
},
{}
{
'numberLogins': this.migrationStateModel._loginMigrationModel.loginsForMigration.length,
}
);
}
}

View File

@@ -18,6 +18,7 @@ import { AzureSqlDatabaseServer, getVMInstanceView, SqlVMServer } from '../api/a
import { collectSourceLogins, collectTargetLogins, getSourceConnectionId, getSourceConnectionProfile, isSourceConnectionSysAdmin, LoginTableInfo } from '../api/sqlUtils';
import { NetworkInterfaceModel } from '../api/dataModels/azure/networkInterfaceModel';
import { getTelemetryProps, logError, sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../telemetry';
import { ConnectingToTargetFailed, } from '../models/loginMigrationModel';
export class LoginMigrationTargetSelectionPage extends MigrationWizardPage {
private _view!: azdata.ModelView;
@@ -636,7 +637,16 @@ export class LoginMigrationTargetSelectionPage extends MigrationWizardPage {
loginsOnTarget,
constants.AZURE_SQL_TARGET_CONNECTION_ERROR_TITLE);
logError(TelemetryViews.LoginMigrationTargetSelectionPage, 'ConnectingToTargetFailed', error);
logError(TelemetryViews.LoginMigrationTargetSelectionPage, ConnectingToTargetFailed, error);
sendSqlMigrationActionEvent(
TelemetryViews.LoginMigrationTargetSelectionPage,
TelemetryAction.LoginMigrationError,
{
...getTelemetryProps(this.migrationStateModel),
'errorMessage': ConnectingToTargetFailed,
},
{}
);
connectionSuccessful = false;
}
finally {

View File

@@ -13,7 +13,8 @@ import * as styles from '../constants/styles';
import { collectSourceLogins, collectTargetLogins, getSourceConnectionId, LoginTableInfo } from '../api/sqlUtils';
import { IconPathHelper } from '../constants/iconPathHelper';
import * as utils from '../api/utils';
import { logError, TelemetryViews } from '../telemetry';
import { getTelemetryProps, logError, sendSqlMigrationActionEvent, TelemetryAction, TelemetryViews } from '../telemetry';
import { CollectingSourceLoginsFailed, CollectingTargetLoginsFailed } from '../models/loginMigrationModel';
export class LoginSelectorPage extends MigrationWizardPage {
@@ -367,7 +368,17 @@ export class LoginSelectorPage extends MigrationWizardPage {
description: constants.LOGIN_MIGRATIONS_GET_LOGINS_ERROR(error.message),
};
logError(TelemetryViews.LoginMigrationWizard, 'CollectingSourceLoginsFailed', error);
logError(TelemetryViews.LoginMigrationWizard, CollectingSourceLoginsFailed, error);
sendSqlMigrationActionEvent(
TelemetryViews.LoginMigrationSelectorPage,
TelemetryAction.LoginMigrationError,
{
...getTelemetryProps(this.migrationStateModel),
'errorMessage': CollectingSourceLoginsFailed,
},
{}
);
}
}
@@ -400,7 +411,17 @@ export class LoginSelectorPage extends MigrationWizardPage {
description: constants.LOGIN_MIGRATIONS_GET_LOGINS_ERROR(error.message),
};
logError(TelemetryViews.LoginMigrationWizard, 'CollectingTargetLoginsFailed', error);
logError(TelemetryViews.LoginMigrationWizard, CollectingTargetLoginsFailed, error);
sendSqlMigrationActionEvent(
TelemetryViews.LoginMigrationSelectorPage,
TelemetryAction.LoginMigrationError,
{
...getTelemetryProps(this.migrationStateModel),
'errorMessage': CollectingTargetLoginsFailed,
},
{}
);
}
}