mirror of
https://github.com/ckaczor/azuredatastudio.git
synced 2026-02-10 18:22:34 -05:00
Send telemetry with Auth Library when adding/refreshing account (#22506)
This commit is contained in:
@@ -28,6 +28,8 @@ import { DisposableStore } from 'vs/base/common/lifecycle';
|
||||
import { IConfigurationService } from 'vs/platform/configuration/common/configuration';
|
||||
import { filterAccounts } from 'sql/workbench/services/accountManagement/browser/accountDialog';
|
||||
import { ADAL_AUTH_LIBRARY, MSAL_AUTH_LIBRARY, AuthLibrary, AZURE_AUTH_LIBRARY_CONFIG, getAuthLibrary } from 'sql/workbench/services/accountManagement/utils';
|
||||
import { IAdsTelemetryService } from 'sql/platform/telemetry/common/telemetry';
|
||||
import { TelemetryAction, TelemetryError, TelemetryPropertyName, TelemetryView } from 'sql/platform/telemetry/common/telemetryKeys';
|
||||
|
||||
export class AccountManagementService implements IAccountManagementService {
|
||||
// CONSTANTS ///////////////////////////////////////////////////////////
|
||||
@@ -61,7 +63,8 @@ export class AccountManagementService implements IAccountManagementService {
|
||||
@IOpenerService private _openerService: IOpenerService,
|
||||
@ILogService private readonly _logService: ILogService,
|
||||
@INotificationService private readonly _notificationService: INotificationService,
|
||||
@IConfigurationService private _configurationService: IConfigurationService
|
||||
@IConfigurationService private _configurationService: IConfigurationService,
|
||||
@IAdsTelemetryService private _telemetryService: IAdsTelemetryService
|
||||
) {
|
||||
this._mementoContext = new Memento(AccountManagementService.ACCOUNT_MEMENTO, this._storageService);
|
||||
const mementoObj = this._mementoContext.getMemento(StorageScope.GLOBAL, StorageTarget.MACHINE);
|
||||
@@ -147,18 +150,28 @@ export class AccountManagementService implements IAccountManagementService {
|
||||
if (accountResult.canceled === true) {
|
||||
return;
|
||||
} else {
|
||||
this._telemetryService.createErrorEvent(TelemetryView.LinkedAccounts, TelemetryError.AddAzureAccountError, accountResult.errorCode,
|
||||
this.getErrorType(accountResult.errorMessage))
|
||||
.withAdditionalProperties({
|
||||
[TelemetryPropertyName.AuthLibrary]: this._authLibrary
|
||||
})
|
||||
.send();
|
||||
if (accountResult.errorCode && accountResult.errorMessage) {
|
||||
throw new Error(localize('addAccountFailedCodeMessage', `{0} \nError Message: {1}`, accountResult.errorCode, accountResult.errorMessage));
|
||||
} else if (accountResult.errorMessage) {
|
||||
throw new Error(localize('addAccountFailedMessage', `{0}`, accountResult.errorMessage));
|
||||
} else {
|
||||
throw new Error(genericAccountErrorMessage);
|
||||
throw new Error(accountResult.errorMessage ?? genericAccountErrorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
let result = await this._accountStore.addOrUpdate(accountResult);
|
||||
if (!result) {
|
||||
this._logService.error('adding account failed');
|
||||
this._logService.error('Adding account failed, no result received.');
|
||||
this._telemetryService.createErrorEvent(TelemetryView.LinkedAccounts, TelemetryError.AddAzureAccountErrorNoResult, '-1',
|
||||
this.getErrorType())
|
||||
.withAdditionalProperties({
|
||||
[TelemetryPropertyName.AuthLibrary]: this._authLibrary
|
||||
})
|
||||
.send();
|
||||
throw new Error(genericAccountErrorMessage);
|
||||
}
|
||||
if (result.accountAdded) {
|
||||
@@ -168,6 +181,11 @@ export class AccountManagementService implements IAccountManagementService {
|
||||
if (result.accountModified) {
|
||||
this.spliceModifiedAccount(provider, result.changedAccount);
|
||||
}
|
||||
this._telemetryService.createActionEvent(TelemetryView.LinkedAccounts, TelemetryAction.AddAzureAccount)
|
||||
.withAdditionalProperties({
|
||||
[TelemetryPropertyName.AuthLibrary]: this._authLibrary
|
||||
})
|
||||
.send();
|
||||
this.fireAccountListUpdate(provider, result.accountAdded);
|
||||
} finally {
|
||||
notificationHandler.close();
|
||||
@@ -207,6 +225,7 @@ export class AccountManagementService implements IAccountManagementService {
|
||||
* @return Promise to return an account
|
||||
*/
|
||||
public refreshAccount(account: azdata.Account): Promise<azdata.Account> {
|
||||
const genericAccountErrorMessage = localize('refreshAccountFailedGenericMessage', 'Refreshing account failed, check Azure Accounts log for more info.')
|
||||
return this.doWithProvider(account.key.providerId, async (provider) => {
|
||||
let refreshedAccount = await provider.provider.refresh(account);
|
||||
if (!this.isAccountResult(refreshedAccount)) {
|
||||
@@ -214,13 +233,33 @@ export class AccountManagementService implements IAccountManagementService {
|
||||
// Pattern here is to throw if this fails. Handled upstream.
|
||||
throw new Error(localize('refreshCanceled', "Refresh account was canceled by the user"));
|
||||
} else {
|
||||
throw new Error(localize('refreshFailed', `${0} \nError Message: ${1}`, refreshedAccount.errorCode, refreshedAccount.errorMessage));
|
||||
this._telemetryService.createErrorEvent(TelemetryView.LinkedAccounts, TelemetryError.RefreshAzureAccountError, refreshedAccount.errorCode,
|
||||
this.getErrorType(refreshedAccount.errorMessage))
|
||||
.withAdditionalProperties({
|
||||
[TelemetryPropertyName.AuthLibrary]: this._authLibrary
|
||||
})
|
||||
.send();
|
||||
if (refreshedAccount.errorCode && refreshedAccount.errorMessage) {
|
||||
throw new Error(localize('refreshFailed', `{0} \nError Message: {1}`, refreshedAccount.errorCode, refreshedAccount.errorMessage));
|
||||
} else {
|
||||
throw new Error(refreshedAccount.errorMessage ?? genericAccountErrorMessage);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
account = refreshedAccount;
|
||||
}
|
||||
|
||||
let result = await this._accountStore.addOrUpdate(account);
|
||||
if (!result) {
|
||||
this._logService.error('Refreshing account failed, no result received.');
|
||||
this._telemetryService.createErrorEvent(TelemetryView.LinkedAccounts, TelemetryError.RefreshAzureAccountErrorNoResult, '-1',
|
||||
this.getErrorType())
|
||||
.withAdditionalProperties({
|
||||
[TelemetryPropertyName.AuthLibrary]: this._authLibrary
|
||||
})
|
||||
.send();
|
||||
throw new Error(genericAccountErrorMessage);
|
||||
}
|
||||
if (result.accountAdded) {
|
||||
// Double check that there isn't a matching account
|
||||
let indexToRemove = this.findAccountIndex(provider.accounts, result.changedAccount);
|
||||
@@ -241,11 +280,30 @@ export class AccountManagementService implements IAccountManagementService {
|
||||
}
|
||||
}
|
||||
|
||||
this._telemetryService.createActionEvent(TelemetryView.LinkedAccounts, TelemetryAction.RefreshAzureAccount)
|
||||
.withAdditionalProperties({
|
||||
[TelemetryPropertyName.AuthLibrary]: this._authLibrary
|
||||
})
|
||||
.send();
|
||||
this.fireAccountListUpdate(provider, result.accountAdded);
|
||||
return result.changedAccount!;
|
||||
});
|
||||
}
|
||||
|
||||
private getErrorType(errorMessage?: string | undefined): string {
|
||||
let errorType: string = 'Unknown';
|
||||
if (errorMessage) {
|
||||
if (errorMessage.toLocaleLowerCase().includes('token')) {
|
||||
errorType = 'AccessToken';
|
||||
} else if (errorMessage.toLocaleLowerCase().includes('timeout')) {
|
||||
errorType = 'Timeout';
|
||||
} else if (errorMessage.toLocaleLowerCase().includes('cache')) {
|
||||
errorType = 'TokenCache'
|
||||
}
|
||||
}
|
||||
return errorType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves metadata of all providers that have been registered
|
||||
* @returns Registered account providers
|
||||
|
||||
@@ -19,6 +19,7 @@ import { TestNotificationService } from 'vs/platform/notification/test/common/te
|
||||
import { AccountDialog } from 'sql/workbench/services/accountManagement/browser/accountDialog';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { TestConfigurationService } from 'sql/platform/connection/test/common/testConfigurationService';
|
||||
import { NullAdsTelemetryService } from 'sql/platform/telemetry/common/adsTelemetryService';
|
||||
|
||||
// SUITE CONSTANTS /////////////////////////////////////////////////////////
|
||||
const hasAccountProvider: azdata.AccountProviderMetadata = {
|
||||
@@ -538,10 +539,11 @@ function getTestState(): AccountManagementState {
|
||||
|
||||
const testNotificationService = new TestNotificationService();
|
||||
const testConfigurationService = new TestConfigurationService();
|
||||
const mockTelemetryService = new NullAdsTelemetryService();
|
||||
|
||||
// Create the account management service
|
||||
let ams = new AccountManagementService(mockInstantiationService.object, new TestStorageService(),
|
||||
undefined, undefined, undefined, testNotificationService, testConfigurationService);
|
||||
undefined, undefined, undefined, testNotificationService, testConfigurationService, mockTelemetryService);
|
||||
|
||||
// Wire up event handlers
|
||||
let evUpdate = new EventVerifierSingle<UpdateAccountListEventParams>();
|
||||
@@ -567,7 +569,6 @@ function getMockAccountProvider(): TypeMoq.Mock<azdata.AccountProvider> {
|
||||
mockProvider.setup(x => x.clear(TypeMoq.It.isAny())).returns(() => Promise.resolve());
|
||||
mockProvider.setup(x => x.initialize(TypeMoq.It.isAny())).returns(param => Promise.resolve(param));
|
||||
mockProvider.setup(x => x.prompt()).returns(() => Promise.resolve(account));
|
||||
|
||||
return mockProvider;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user