import * as vscode from "vscode" ; import TelemetryReporter from "vscode-extension-telemetry" ; import { OperationCanceledError } from "./common/Error/OperationCanceledError" ; import { ExceptionHelper } from "./common/Error/exceptionHelper" ; import { DevelopEnvironment } from "./constants" ; import { RemoteExtension } from "./Models/RemoteExtension" ; import { NSAT } from "./nsat" ; import { WorkbenchExtension } from "./WorkbenchExtension" ; interface PackageInfo { name : string ; version : string ; aiKey : string ; } /**
 * Operation result of telemetry
 */ export enum TelemetryResult { Succeeded = "Succeeded" , Failed = "Failed" , Cancelled = "Cancelled" } /**
 * Context of telemetry
 */ export interface TelemetryContext { properties : { [ key ] : string ; } ; measurements : { [ key ] : number ; } ; } export class TelemetryWorker { private _reporter : TelemetryReporter | undefined ; private _extensionContext : vscode . ExtensionContext | undefined ; private static _instance : TelemetryWorker | undefined ; private _isInternal = false ; private constructor ( context ) { this . _extensionContext = context ; const packageInfo = this . getPackageInfo ( context ) ; if ( ! packageInfo ) { console . log ( "Unable to initialize telemetry" ) ; return ; } if ( ! packageInfo . aiKey ) { console . log ( "Unable to initialize telemetry, please make sure AIKey is set in package.json" ) ; return ; } this . _reporter = new TelemetryReporter ( packageInfo . name , packageInfo . version , packageInfo . aiKey , true ) ; this . _isInternal = TelemetryWorker . isInternalUser ( ) ; } static getInstance ( context ) { if ( ! TelemetryWorker . _instance ) { TelemetryWorker . _instance = new TelemetryWorker ( context ) ; } return TelemetryWorker . _instance ; } /**
     * check if it is Microsoft internal user
     */ private static isInternalUser ( ) { const userDomain = process . env . USERDNSDOMAIN ? process . env . USERDNSDOMAIN . toLowerCase ( ) : "" ; return userDomain . endsWith ( "microsoft.com" ) ; } /**
     * Create telemetry context
     */ createContext ( ) { const context = { properties : { } , measurements : { } } ; context . properties . result = TelemetryResult . Succeeded ; context . properties . isInternal = this . _isInternal . toString ( ) ; if ( this . _extensionContext ) { context . properties . developEnvironment = RemoteExtension . isRemote ( this . _extensionContext ) ? DevelopEnvironment . RemoteEnv : DevelopEnvironment . LocalEnv ; } return context ; } param eventName param telemetryContext sendEvent ( eventName , telemetryContext ) { if ( ! this . _reporter ) { return ; } if ( ! telemetryContext ) { telemetryContext = this . createContext ( ) ; } if ( telemetryContext . properties . result === TelemetryResult . Succeeded ) { this . _reporter . sendTelemetryEvent ( eventName , telemetryContext . properties , telemetryContext . measurements ) ; } else { this . _reporter . sendTelemetryErrorEvent ( eventName , telemetryContext . properties , telemetryContext . measurements , [ "errorMessage" ] ) ; } } param context param telemetryContext param outputChannel param eventName param enableSurvey param callback param additionalProperties async callCommandWithTelemetry ( context , outputChannel , eventName , enableSurvey , callback , additionalProperties ? , ... commandArgs ) { const telemetryWorker = TelemetryWorker . getInstance ( context ) ; const telemetryContext = telemetryWorker . createContext ( ) ; const start = Date . now ( ) ; if ( additionalProperties ) { for ( const key of Object . keys ( additionalProperties ) ) { if ( ! Object . prototype . hasOwnProperty . call ( telemetryContext . properties , key ) ) { telemetryContext . properties [ key ] = additionalProperties [ key ] ; } } } try { return await callback ( context , outputChannel , telemetryContext , ... commandArgs ) ; } catch ( error ) { telemetryContext . properties . errorMessage = error . message ; let isPopupErrorMsg = true ; if ( error instanceof OperationCanceledError ) { telemetryContext . properties . result = TelemetryResult . Cancelled ; isPopupErrorMsg = false ; } else { telemetryContext . properties . result = TelemetryResult . Failed ; } ExceptionHelper . logError ( outputChannel , error , isPopupErrorMsg ) ; } finally { const end = Date . now ( ) ; telemetryContext . measurements . duration = ( end - start ) / 1000 ; try { this . sendEvent ( eventName , telemetryContext ) ; if ( enableSurvey ) { NSAT . takeSurvey ( context ) ; } } catch { } } } /**
     * dispose telemetry worker
     */ async dispose ( ) { if ( this . _reporter ) { await this . _reporter . dispose ( ) ; } } /**
     * Get extension information
     */ private getPackageInfo ( context ) { const extension = WorkbenchExtension . getExtension ( context ) ; if ( extension ) { const extensionPackage = extension . packageJSON ; if ( extensionPackage ) { const packageInfo = { name : extensionPackage . name , version : extensionPackage . version , aiKey : extensionPackage . aiKey } ; return packageInfo ; } } return undefined ; } }