import * as os from 'os' ; import { Logger , Messages } from '@salesforce/core' ; import { AsyncCreatable , Env } from '@salesforce/kit' ; import { isBoolean , isNumber , isString , JsonPrimitive } from '@salesforce/ts-types' ; import * as appInsights from 'applicationinsights' ; export { TelemetryClient } from 'applicationinsights' ; export type Properties = { [ key ] : string ; } ; export type Measurements = { [ key ] : number ; } ; export type Attributes = { [ key ] : JsonPrimitive | undefined ; } ; export interface TelemetryOptions { project : string ; key : string ; commonProperties ? : Properties ; contextTags ? : Properties ; env ? : Env ; gdprSensitiveKeys ? : string [ ] ; userId ? : string ; sessionId ? : string ; waitForConnection ? : boolean ; } Messages . importMessagesDirectory ( __dirname ) ; export function getPlatformVersion ( ) { return ( os . release ( ) || '' ) . replace ( /^(\d+)(\.\d+)?(\.\d+)?(.*)/ , '$1$2$3' ) ; } export function getCpus ( ) { const cpus = os . cpus ( ) ; if ( cpus && cpus . length > 0 ) { return `${ cpus [ 0 ] . model }(${ cpus . length } x ${ cpus [ 0 ] . speed })` ; } else { return '' ; } } function getSystemMemory ( ) { return `${ ( os . totalmem ( ) / ( 1024 * 1024 * 1024 ) ) . toFixed ( 2 ) } GB` ; } function isAsimovKey ( key ) { return ! ! ( key && key . startsWith ( 'AIF-' ) ) ; } export function buildPropertiesAndMeasurements ( attributes ) { const properties = { } ; const measurements = { } ; Object . keys ( attributes ) . forEach ( ( key ) => { const value = attributes [ key ] ; if ( isString ( value ) ) { properties [ key ] = value ; } else if ( isNumber ( value ) ) { measurements [ key ] = value ; } else if ( isBoolean ( value ) ) { properties [ key ] = value . toString ( ) ; } } ) ; return { properties , measurements } ; } /**
 * This is a wrapper around appinsights sdk for convenience.
 *
 * NOTE: THis should not be used directly. Use TelemetryReporter which
 * will check if telemetry is disabled and do GDPR checks.
 */ export class AppInsights extends AsyncCreatable < TelemetryOptions > { public static GDPR_HIDDEN = '<GDPR_HIDDEN>' ; public static APP_INSIGHTS_SERVER = 'https://dc.services.visualstudio.com' ; private static ASIMOV_ENDPOINT = 'https://vortex.data.microsoft.com/collect/v1' ; public appInsightsClient ! : appInsights . TelemetryClient ; private options : TelemetryOptions ; private logger ! : Logger ; private env ! : Env ; private gdprSensitiveKeys : string [ ] = [ ] ; public constructor ( options ) { super ( options ) ; this . options = options ; this . env = this . options . env || new Env ( ) ; if ( this . options . gdprSensitiveKeys ) { this . gdprSensitiveKeys = this . options . gdprSensitiveKeys ; } else { const keys = new appInsights . Contracts . ContextTagKeys ( ) ; this . gdprSensitiveKeys = [ keys . cloudRoleInstance ] ; } } public async init ( ) { this . logger = await Logger . child ( 'AppInsights' ) ; this . createAppInsightsClient ( ) ; } param eventName { string } param attributes { Attributes } public sendTelemetryEvent ( eventName , attributes = { } ) { const name = `${ this . options . project }/${ eventName }` ; this . logger . debug ( `Sending telemetry event: ${ name }` ) ; const { properties , measurements } = buildPropertiesAndMeasurements ( attributes ) ; this . appInsightsClient . trackEvent ( { name , properties , measurements } ) ; } param exception { Error } param attributes { Attributes } public sendTelemetryException ( exception , attributes = { } ) { this . logger . debug ( `Sending telemetry exception: ${ exception . message }` ) ; const { properties , measurements } = buildPropertiesAndMeasurements ( attributes ) ; this . appInsightsClient . trackException ( { exception , properties , measurements } ) ; } param message { string } param properties { Properties } public sendTelemetryTrace ( traceMessage , properties ? ) { this . logger . debug ( `Sending telemetry: trace ${ traceMessage }` ) ; this . appInsightsClient . trackTrace ( { message : traceMessage , properties } ) ; } param name { string } param value { number } param properties { Properties } public sendTelemetryMetric ( metricName , value , properties ? ) { this . logger . debug ( `Sending telemetry metric: ${ metricName }` ) ; this . appInsightsClient . trackMetric ( { name : metricName , value , properties } ) ; } public start ( ) { appInsights . start ( ) ; } public stop ( ) { this . appInsightsClient . flush ( ) ; appInsights . dispose ( ) ; } /**
     * Initiates the app insights client
     */ private createAppInsightsClient ( ) { this . logger . debug ( 'creating appInsightsClient' ) ; appInsights . setup ( this . options . key ) ; this . appInsightsClient = appInsights . defaultClient ; this . appInsightsClient . commonProperties = this . buildCommonProperties ( ) ; this . appInsightsClient . context . tags = this . buildContextTags ( ) ; if ( isAsimovKey ( this . options . key ) ) { this . appInsightsClient . config . endpointUrl = AppInsights . ASIMOV_ENDPOINT ; } if ( this . options . userId ) { this . appInsightsClient . context . tags [ 'ai.user.id' ] = this . options . userId ; } if ( this . options . sessionId ) { this . appInsightsClient . context . tags [ 'ai.session.id' ] = this . options . sessionId ; } } return { Properties } private buildCommonProperties ( ) { const baseProperties = { 'common.cpus' : getCpus ( ) , 'common.os' : os . platform ( ) , 'common.platformversion' : getPlatformVersion ( ) , 'common.systemmemory' : getSystemMemory ( ) , 'common.usertype' : this . env . getString ( 'SFDX_USER_TYPE' ) || 'normal' } ; return Object . assign ( baseProperties , this . options . commonProperties ) ; } return { Properties } private buildContextTags ( ) { const currentTags = this . appInsightsClient ? this . appInsightsClient . context . tags : { } ; const cleanedTags = this . hideGDPRdata ( currentTags ) ; return Object . assign ( { } , cleanedTags , this . options . contextTags ) ; } private hideGDPRdata ( tags ) { this . gdprSensitiveKeys . forEach ( ( key ) => { tags [ key ] = AppInsights . GDPR_HIDDEN ; } ) ; return tags ; } }