[SQL-Migration] Login migrations telemetry (#22038)

This PR enhances telemetry for login migrations (and in the following ways:

Add details for starting migration (number of logins migrating, type of logins)
Log Migration result (number of errors per step, duration of each step, type of logins, if system error occurred)
Add sql-migration extension to our telemetry
Adds details when trying to connect to target
Tracks clicking "done" from the wizard
Fixes bucketizing for navigating telemetry in the login migration wizard
Sample usage of kusto query for new telemetry:
RawEventsADS
| where EventName contains 'sql-migration'
| extend view = tostring(Properties['view'])
| extend action = tostring(Properties['action'])
| extend buttonPressed = tostring(Properties['buttonpressed'])
| extend pageTitle = tostring(Properties['pagetitle'])
| extend adsVersion = tostring(Properties['common.adsversion'])
| extend targetType = tostring(Properties['targettype'])
| extend tenantId = tostring(Properties['tenantid'])
| extend subscriptionId = tostring(Properties['subscriptionid'])
| where view contains "login"
//| where adsVersion contains "1.42.0-insider"
| where ClientTimestamp >= ago(18h)
| project EventName, ClientTimestamp, SessionId, view, pageTitle, action, buttonPressed, targetType
, tenantId, subscriptionId
, adsVersion, OSVersion, Properties
This commit is contained in:
AkshayMata
2023-03-01 10:55:01 -08:00
committed by GitHub
parent d6358b3e29
commit bf05ea69ef
9 changed files with 223 additions and 95 deletions

View File

@@ -15,6 +15,7 @@ type ExceptionMap = { [login: string]: any }
export enum LoginType {
Windows_Login = 'windows_login',
SQL_Login = 'sql_login',
Mixed_Mode = 'mixed_mode',
}
export enum LoginMigrationStep {
@@ -64,6 +65,8 @@ export class LoginMigrationModel {
public loginMigrationsResult!: contracts.StartLoginMigrationResult;
public loginMigrationsError: any;
public loginsForMigration!: LoginTableInfo[];
public errorCountMap: Map<string, any> = new Map<string, any>();
public durationPerStep: Map<string, string> = new Map<string, string>();
private _currentStepIdx: number = 0;
private _logins: Map<string, Login>;
private _loginMigrationSteps: LoginMigrationStep[] = [];
@@ -82,6 +85,32 @@ export class LoginMigrationModel {
return this._currentStepIdx === this._loginMigrationSteps.length;
}
public get selectedWindowsLogins(): boolean {
return this.loginsForMigration.some(logins => logins.loginType.toLocaleLowerCase() === LoginType.Windows_Login);
}
public get selectedAllWindowsLogins(): boolean {
return this.loginsForMigration.every(logins => logins.loginType.toLocaleLowerCase() === LoginType.Windows_Login);
}
public get selectedAllSQLLogins(): boolean {
return this.loginsForMigration.every(logins => logins.loginType.toLocaleLowerCase() === LoginType.SQL_Login);
}
public get loginsAuthType(): LoginType {
if (this.selectedAllWindowsLogins) {
return LoginType.Windows_Login;
} else if (this.selectedAllSQLLogins) {
return LoginType.SQL_Login;
}
return LoginType.Mixed_Mode;
}
public get hasSystemError(): boolean {
return this.loginMigrationsError ? true : false;
}
public async MigrateLogins(stateMachine: MigrationStateModel): Promise<boolean> {
this.addNewLogins(stateMachine._loginMigrationModel.loginsForMigration.map(row => row.loginName));
return await this.runLoginMigrationStep(LoginMigrationStep.MigrateLogins, stateMachine);
@@ -102,7 +131,7 @@ export class LoginMigrationModel {
}
public GetLoginMigrationResults(loginName: string): MultiStepResult[] {
public GetDisplayResults(loginName: string): MultiStepResult[] {
let loginResults: MultiStepResult[] = [];
let login = this.getLogin(loginName);
@@ -129,6 +158,15 @@ export class LoginMigrationModel {
return loginResults;
}
private setErrorCountMapPerStep(step: LoginMigrationStep, result: contracts.StartLoginMigrationResult) {
const errorCount = result.exceptionMap ? Object.keys(result.exceptionMap).length : 0;
this.errorCountMap.set(LoginMigrationStep[step], errorCount);
}
private setDurationPerStep(step: LoginMigrationStep, result: contracts.StartLoginMigrationResult) {
this.durationPerStep.set(LoginMigrationStep[step], result.elapsedTime);
}
private setLoginMigrationSteps(steps: LoginMigrationStep[] = []) {
this._loginMigrationSteps = [];
@@ -159,6 +197,10 @@ export class LoginMigrationModel {
this.markLoginStatus(loginName, loginStatus);
}
}
this.updateLoginMigrationResults(newResult);
this.setErrorCountMapPerStep(step, newResult);
this.setDurationPerStep(step, newResult);
}
private updateLoginMigrationResults(newResult: contracts.StartLoginMigrationResult): void {
@@ -194,7 +236,6 @@ export class LoginMigrationModel {
stateMachine._aadDomainName
))!;
this.updateLoginMigrationResults(response);
this.addLoginMigrationResults(LoginMigrationStep.MigrateLogins, response);
return true;
@@ -215,9 +256,8 @@ export class LoginMigrationModel {
stateMachine._aadDomainName
))!;
this.updateLoginMigrationResults(response);
this.addLoginMigrationResults(LoginMigrationStep.EstablishUserMapping, response);
return false;
return true;
} catch (error) {
logError(TelemetryViews.LoginMigrationWizard, 'EstablishingUserMappingFailed', error);
@@ -236,16 +276,14 @@ export class LoginMigrationModel {
stateMachine._aadDomainName
))!;
this.updateLoginMigrationResults(response);
this.addLoginMigrationResults(LoginMigrationStep.MigrateServerRolesAndSetPermissions, response);
return false;
return true;
} catch (error) {
logError(TelemetryViews.LoginMigrationWizard, 'MigratingServerRolesAndSettingPermissionsFailed', error);
this.reportException(LoginMigrationStep.MigrateServerRolesAndSetPermissions, error);
this.loginMigrationsError = error;
return true;
return false;
}
}