Path: blob/main/extensions/microsoft-authentication/src/common/telemetryReporter.ts
5237 views
/*---------------------------------------------------------------------------------------------1* Copyright (c) Microsoft Corporation. All rights reserved.2* Licensed under the MIT License. See License.txt in the project root for license information.3*--------------------------------------------------------------------------------------------*/45import { AuthError, ClientAuthError } from '@azure/msal-node';6import TelemetryReporter, { TelemetryEventProperties } from '@vscode/extension-telemetry';7import { IExperimentationTelemetry } from 'vscode-tas-client';89export const enum MicrosoftAccountType {10AAD = 'aad',11MSA = 'msa',12Unknown = 'unknown'13}1415export class MicrosoftAuthenticationTelemetryReporter implements IExperimentationTelemetry {16private sharedProperties: Record<string, string> = {};17protected _telemetryReporter: TelemetryReporter;18constructor(aiKey: string) {19this._telemetryReporter = new TelemetryReporter(aiKey);20}2122get telemetryReporter(): TelemetryReporter {23return this._telemetryReporter;24}2526setSharedProperty(name: string, value: string): void {27this.sharedProperties[name] = value;28}2930postEvent(eventName: string, props: Map<string, string>): void {31const eventProperties: TelemetryEventProperties = { ...this.sharedProperties, ...Object.fromEntries(props) };32this._telemetryReporter.sendTelemetryEvent(33eventName,34eventProperties35);36}3738sendActivatedWithMsalNoBrokerEvent(): void {39/* __GDPR__40"activatingMsalNoBroker" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users use the msal-no-broker login flow. This only fires if the user explictly opts in to this." }41*/42this._telemetryReporter.sendTelemetryEvent('activatingmsalnobroker');43}4445sendLoginEvent(scopes: readonly string[]): void {46/* __GDPR__47"login" : {48"owner": "TylerLeonhardt",49"comment": "Used to determine the usage of the Microsoft Auth Provider.",50"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }51}52*/53this._telemetryReporter.sendTelemetryEvent('login', {54// Get rid of guids from telemetry.55scopes: JSON.stringify(this._scrubGuids(scopes)),56});57}58sendLoginFailedEvent(): void {59/* __GDPR__60"loginFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }61*/62this._telemetryReporter.sendTelemetryEvent('loginFailed');63}64sendLogoutEvent(): void {65/* __GDPR__66"logout" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." }67*/68this._telemetryReporter.sendTelemetryEvent('logout');69}70sendLogoutFailedEvent(): void {71/* __GDPR__72"logoutFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." }73*/74this._telemetryReporter.sendTelemetryEvent('logoutFailed');75}7677sendTelemetryErrorEvent(error: Error | string): void {78let errorMessage: string | undefined;79let errorName: string | undefined;80let errorCode: string | undefined;81let errorCorrelationId: string | undefined;82if (typeof error === 'string') {83errorMessage = error;84} else {85const authError: AuthError = error as AuthError;86// don't set error message or stack because it contains PII87errorCode = authError.errorCode;88errorCorrelationId = authError.correlationId;89errorName = authError.name;90}9192/* __GDPR__93"msalError" : {94"owner": "TylerLeonhardt",95"comment": "Used to determine how often users run into issues with the login flow.",96"errorMessage": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error message." },97"errorName": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The name of the error." },98"errorCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error code." },99"errorCorrelationId": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The error correlation id." }100}101*/102this._telemetryReporter.sendTelemetryErrorEvent('msalError', {103errorMessage,104errorName,105errorCode,106errorCorrelationId,107});108}109110sendTelemetryClientAuthErrorEvent(error: AuthError): void {111const errorCode = error.errorCode;112const correlationId = error.correlationId;113const errorName = error.name;114let brokerErrorCode: string | undefined;115let brokerStatusCode: string | undefined;116let brokerTag: string | undefined;117118// Extract platform broker error information if available119if (error.platformBrokerError) {120brokerErrorCode = error.platformBrokerError.errorCode;121brokerStatusCode = `${error.platformBrokerError.statusCode}`;122brokerTag = error.platformBrokerError.tag;123}124125/* __GDPR__126"msalClientAuthError" : {127"owner": "TylerLeonhardt",128"comment": "Used to determine how often users run into client auth errors during the login flow.",129"errorName": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The name of the client auth error." },130"errorCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The client auth error code." },131"correlationId": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The client auth error correlation id." },132"brokerErrorCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The broker error code." },133"brokerStatusCode": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The broker error status code." },134"brokerTag": { "classification": "SystemMetaData", "purpose": "FeatureInsight", "comment": "The broker error tag." }135}136*/137this._telemetryReporter.sendTelemetryErrorEvent('msalClientAuthError', {138errorName,139errorCode,140correlationId,141brokerErrorCode,142brokerStatusCode,143brokerTag144});145}146147/**148* Sends an event for an account type available at startup.149* @param scopes The scopes for the session150* @param accountType The account type for the session151* @todo Remove the scopes since we really don't care about them.152*/153sendAccountEvent(scopes: string[], accountType: MicrosoftAccountType): void {154/* __GDPR__155"account" : {156"owner": "TylerLeonhardt",157"comment": "Used to determine the usage of the Microsoft Auth Provider.",158"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." },159"accountType": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what account types are being used." }160}161*/162this._telemetryReporter.sendTelemetryEvent('account', {163// Get rid of guids from telemetry.164scopes: JSON.stringify(this._scrubGuids(scopes)),165accountType166});167}168169protected _scrubGuids(scopes: readonly string[]): string[] {170return scopes.map(s => s.replace(/[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}/i, '{guid}'));171}172}173174export class MicrosoftSovereignCloudAuthenticationTelemetryReporter extends MicrosoftAuthenticationTelemetryReporter {175override sendLoginEvent(scopes: string[]): void {176/* __GDPR__177"loginMicrosoftSovereignCloud" : {178"owner": "TylerLeonhardt",179"comment": "Used to determine the usage of the Microsoft Auth Provider.",180"scopes": { "classification": "PublicNonPersonalData", "purpose": "FeatureInsight", "comment": "Used to determine what scope combinations are being requested." }181}182*/183this._telemetryReporter.sendTelemetryEvent('loginMicrosoftSovereignCloud', {184// Get rid of guids from telemetry.185scopes: JSON.stringify(this._scrubGuids(scopes)),186});187}188override sendLoginFailedEvent(): void {189/* __GDPR__190"loginMicrosoftSovereignCloudFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users run into issues with the login flow." }191*/192this._telemetryReporter.sendTelemetryEvent('loginMicrosoftSovereignCloudFailed');193}194override sendLogoutEvent(): void {195/* __GDPR__196"logoutMicrosoftSovereignCloud" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often users log out." }197*/198this._telemetryReporter.sendTelemetryEvent('logoutMicrosoftSovereignCloud');199}200override sendLogoutFailedEvent(): void {201/* __GDPR__202"logoutMicrosoftSovereignCloudFailed" : { "owner": "TylerLeonhardt", "comment": "Used to determine how often fail to log out." }203*/204this._telemetryReporter.sendTelemetryEvent('logoutMicrosoftSovereignCloudFailed');205}206}207208209