diff --git a/package-lock.json b/package-lock.json index 7ae850acae..70935a8107 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7701,9 +7701,9 @@ "integrity": "sha512-FjI8Zf+MAPwWu+ViXurGk2Ka3H7QDzLUqGulu22ONzmiidz63Lp3N2uzDQ/p7RAsIpC27ZLxomRlje4WhOjuXg==" }, "node_modules/@salesforce/vscode-service-provider": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@salesforce/vscode-service-provider/-/vscode-service-provider-1.0.4.tgz", - "integrity": "sha512-gEXLJ0ok36oWeG5HQqEmvZxgkn05lOxUFko3yIodAop425SuI8JrzjfzEbPp5SPJFIWjovVA+eMtTMBbwjRzAw==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@salesforce/vscode-service-provider/-/vscode-service-provider-1.1.1.tgz", + "integrity": "sha512-OyW8kHzAltNrlp30aUXDIdhwSLpkXmL+jNsk7+Z8u4perPzU0dLvie7l5GldYFH0JD1Ds4cDbhb/KeFXUPS27Q==", "engines": { "node": ">=18.18.2" } @@ -33583,6 +33583,7 @@ "@salesforce/core-bundle": "8.2.0", "@salesforce/source-deploy-retrieve-bundle": "12.1.5", "@salesforce/source-tracking-bundle": "7.0.6", + "@salesforce/vscode-service-provider": "1.1.1", "applicationinsights": "1.0.7", "cross-spawn": "7.0.3", "rxjs": "^5.4.1", @@ -33785,6 +33786,7 @@ "@salesforce/apex-tmlanguage": "1.8.0", "@salesforce/core-bundle": "8.2.0", "@salesforce/salesforcedx-utils-vscode": "61.12.0", + "@salesforce/vscode-service-provider": "1.1.1", "expand-home-dir": "0.0.3", "find-java-home": "0.2.0", "shelljs": "0.8.5", @@ -34229,7 +34231,7 @@ "@salesforce/source-deploy-retrieve-bundle": "12.1.5", "@salesforce/templates": "61.4.3", "@salesforce/ts-types": "2.0.10", - "@salesforce/vscode-service-provider": "1.0.4", + "@salesforce/vscode-service-provider": "1.1.1", "adm-zip": "0.5.10", "applicationinsights": "1.0.7", "glob": "^7.1.2", diff --git a/packages/salesforcedx-utils-vscode/package.json b/packages/salesforcedx-utils-vscode/package.json index 69645948a2..e8f8092ae5 100644 --- a/packages/salesforcedx-utils-vscode/package.json +++ b/packages/salesforcedx-utils-vscode/package.json @@ -13,6 +13,7 @@ "@salesforce/core-bundle": "8.2.0", "@salesforce/source-deploy-retrieve-bundle": "12.1.5", "@salesforce/source-tracking-bundle": "7.0.6", + "@salesforce/vscode-service-provider": "1.1.1", "applicationinsights": "1.0.7", "cross-spawn": "7.0.3", "rxjs": "^5.4.1", diff --git a/packages/salesforcedx-utils-vscode/src/commands/commandletExecutors.ts b/packages/salesforcedx-utils-vscode/src/commands/commandletExecutors.ts index 029f4c6216..71f77cb6a6 100644 --- a/packages/salesforcedx-utils-vscode/src/commands/commandletExecutors.ts +++ b/packages/salesforcedx-utils-vscode/src/commands/commandletExecutors.ts @@ -4,13 +4,11 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ +import { Properties, Measurements, TelemetryData } from '@salesforce/vscode-service-provider'; import * as vscode from 'vscode'; import { CliCommandExecutor, Command, CommandExecution } from '../cli'; import { - Measurements, - Properties, TelemetryBuilder, - TelemetryData, TelemetryService } from '../index'; import { nls } from '../messages'; @@ -120,8 +118,7 @@ export abstract class SfCommandletExecutor implements CommandletExecutor { } export abstract class LibraryCommandletExecutor - implements CommandletExecutor -{ + implements CommandletExecutor { protected cancellable: boolean = false; private cancelled: boolean = false; private readonly executionName: string; diff --git a/packages/salesforcedx-utils-vscode/src/helpers/activationTracker.ts b/packages/salesforcedx-utils-vscode/src/helpers/activationTracker.ts index 71a0ddb87a..95f99cb51b 100644 --- a/packages/salesforcedx-utils-vscode/src/helpers/activationTracker.ts +++ b/packages/salesforcedx-utils-vscode/src/helpers/activationTracker.ts @@ -5,38 +5,18 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { ExtensionContext, ExtensionKind, Uri } from 'vscode'; -import { TelemetryService } from '..'; +import { ActivationInfo, TelemetryServiceInterface } from '@salesforce/vscode-service-provider'; +import { ExtensionContext } from 'vscode'; import { getExtensionInfo } from './activationTrackerUtils'; -export type ExtensionInfo = { - isActive: boolean; - path: string; - kind: ExtensionKind; - uri: Uri; - loadStartDate: Date; -}; - -export type ExtensionsInfo = { - [extensionId: string]: ExtensionInfo; -}; - -export type ActivationInfo = Partial & { - startActivateHrTime: [number, number]; - activateStartDate: Date; - activateEndDate?: Date; - extensionActivationTime: number; - markEndTime?: number; -}; - export class ActivationTracker { private extensionContext: ExtensionContext; - private telemetryService: TelemetryService; + private telemetryService: TelemetryServiceInterface; private _activationInfo: ActivationInfo; constructor( extensionContext: ExtensionContext, - telemetryService: TelemetryService + telemetryService: TelemetryServiceInterface ) { this.extensionContext = extensionContext; this.telemetryService = telemetryService; diff --git a/packages/salesforcedx-utils-vscode/src/helpers/activationTrackerUtils.ts b/packages/salesforcedx-utils-vscode/src/helpers/activationTrackerUtils.ts index 95e3ec4d4d..8b6f463d22 100644 --- a/packages/salesforcedx-utils-vscode/src/helpers/activationTrackerUtils.ts +++ b/packages/salesforcedx-utils-vscode/src/helpers/activationTrackerUtils.ts @@ -5,11 +5,11 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ +import { ExtensionInfo, ExtensionsInfo } from '@salesforce/vscode-service-provider'; import { readFile } from 'fs/promises'; import { EOL } from 'os'; import { join, sep } from 'path'; import { extensions, ExtensionContext, Uri } from 'vscode'; -import { ExtensionInfo, ExtensionsInfo } from './activationTracker'; type ParsedLog = { dateTime: Date; diff --git a/packages/salesforcedx-utils-vscode/src/helpers/index.ts b/packages/salesforcedx-utils-vscode/src/helpers/index.ts index 217b90c972..bc61189813 100644 --- a/packages/salesforcedx-utils-vscode/src/helpers/index.ts +++ b/packages/salesforcedx-utils-vscode/src/helpers/index.ts @@ -32,8 +32,7 @@ export { } from './validations'; export { isSFContainerMode } from './env'; export { - ActivationInfo, - ActivationTracker, - ExtensionInfo, - ExtensionsInfo + ActivationTracker } from './activationTracker'; + + diff --git a/packages/salesforcedx-utils-vscode/src/index.ts b/packages/salesforcedx-utils-vscode/src/index.ts index f7e980d2c6..da9a3f8188 100644 --- a/packages/salesforcedx-utils-vscode/src/index.ts +++ b/packages/salesforcedx-utils-vscode/src/index.ts @@ -33,10 +33,7 @@ export { } from './context/workspaceContextUtil'; export { TelemetryService, - TelemetryBuilder, - TelemetryData, - Properties, - Measurements + TelemetryBuilder } from './services/telemetry'; export * from './helpers'; export { TraceFlags } from './helpers/traceFlags'; diff --git a/packages/salesforcedx-utils-vscode/src/services/telemetry.ts b/packages/salesforcedx-utils-vscode/src/services/telemetry.ts index ef49064db1..a5ac8f14e4 100644 --- a/packages/salesforcedx-utils-vscode/src/services/telemetry.ts +++ b/packages/salesforcedx-utils-vscode/src/services/telemetry.ts @@ -4,9 +4,16 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ +import { + Properties, + Measurements, + TelemetryData, + TelemetryServiceInterface, + TelemetryReporter, + ActivationInfo +} from '@salesforce/vscode-service-provider'; import * as util from 'util'; -import { ExtensionContext, ExtensionMode, workspace } from 'vscode'; -import { ActivationInfo } from '..'; +import { ExtensionContext, ExtensionMode, workspace, extensions } from 'vscode'; import { DEFAULT_AIKEY, SFDX_CORE_CONFIGURATION_NAME, @@ -18,7 +25,6 @@ import { disableCLITelemetry, isCLITelemetryAllowed } from '../telemetry/cliConfiguration'; -import { TelemetryReporter } from '../telemetry/interfaces/telemetryReporter'; import { AppInsights } from '../telemetry/reporters/appInsights'; import { LogStream } from '../telemetry/reporters/logStream'; import { LogStreamConfig } from '../telemetry/reporters/logStreamConfig'; @@ -31,19 +37,6 @@ type CommandMetric = { executionTime?: string; }; -export type Measurements = { - [key: string]: number; -}; - -export type Properties = { - [key: string]: string; -}; - -export type TelemetryData = { - properties?: Properties; - measurements?: Measurements; -}; - export class TelemetryBuilder { private properties?: Properties; private measurements?: Measurements; @@ -75,7 +68,7 @@ export class TelemetryBuilder { // export only for unit test export class TelemetryServiceProvider { public static instances = new Map(); // public only for unit test - public static getInstance(extensionName?: string): TelemetryService { + public static getInstance(extensionName?: string): TelemetryServiceInterface { // default if not present const name = extensionName || SFDX_CORE_EXTENSION_NAME; let service = TelemetryServiceProvider.instances.get(name); @@ -87,7 +80,7 @@ export class TelemetryServiceProvider { } } -export class TelemetryService { +export class TelemetryService implements TelemetryServiceInterface { private extensionContext: ExtensionContext | undefined; private reporters: TelemetryReporter[] = []; private aiKey = DEFAULT_AIKEY; @@ -97,7 +90,7 @@ export class TelemetryService { * If no extension name provided, return the instance for core extension by default * @param extensionName extension name */ - public static getInstance(extensionName?: string) { + public static getInstance(extensionName?: string): TelemetryServiceInterface { return TelemetryServiceProvider.getInstance(extensionName); } /** @@ -111,23 +104,27 @@ export class TelemetryService { * @param extensionContext extension context * @param extensionName extension name */ - public async initializeService( + public initializeService( extensionContext: ExtensionContext ): Promise { - const { name, version, aiKey } = extensionContext.extension.packageJSON; + const { name, version, aiKey } = extensionContext.extension.packageJSON as { name: string; version: string; aiKey: string }; + return this.initializeServiceWithAttributes(name, aiKey, version, extensionContext.extensionMode); + } + + public async initializeServiceWithAttributes(name: string, aiKey?: string, version?: string, extensionMode?: ExtensionMode): Promise { if (!name) { console.log('Extension name is not defined in package.json'); } if (!version) { console.log('Extension version is not defined in package.json'); } - this.extensionContext = extensionContext; + this.extensionContext = getExtensionContextByName(name); this.extensionName = name; - this.version = version; + this.version = version ?? ''; this.aiKey = aiKey || this.aiKey; this.checkCliTelemetry() - .then(async cliEnabled => { + .then(cliEnabled => { this.setCliTelemetryEnabled( this.isTelemetryExtensionConfigurationEnabled() && cliEnabled ); @@ -137,13 +134,13 @@ export class TelemetryService { }); const isDevMode = - extensionContext.extensionMode !== ExtensionMode.Production; + extensionMode !== ExtensionMode.Production; // TelemetryReporter is not initialized if user has disabled telemetry setting. if (this.reporters.length === 0 && (await this.isTelemetryEnabled())) { if (!isDevMode) { console.log('adding AppInsights reporter.'); - const userId = await UserService.getTelemetryUserId(this.extensionContext); + const userId = this.extensionContext ? await UserService.getTelemetryUserId(this.extensionContext) : 'unknown'; this.reporters.push( new AppInsights( this.getTelemetryReporterName(), @@ -182,7 +179,7 @@ export class TelemetryService { } } - this.extensionContext.subscriptions.push(...this.reporters); + this.extensionContext?.subscriptions.push(...this.reporters); } /** @@ -333,12 +330,12 @@ export class TelemetryService { } catch (error) { console.log( 'There was an error sending an exception report to: ' + - typeof reporter + - ' ' + - 'name: ' + - name + - ' message: ' + - message + typeof reporter + + ' ' + + 'name: ' + + name + + ' message: ' + + message ); } }); @@ -386,3 +383,11 @@ export class TelemetryService { } } } + +const getExtensionContextByName = (extensionName: string): ExtensionContext | undefined => { + const extension = extensions.getExtension(extensionName); + if (extension) { + // Access the extension's context + return extension.exports as ExtensionContext; + } +}; diff --git a/packages/salesforcedx-utils-vscode/src/telemetry/interfaces/telemetryReporter.ts b/packages/salesforcedx-utils-vscode/src/telemetry/interfaces/telemetryReporter.ts deleted file mode 100644 index 46f7a770dd..0000000000 --- a/packages/salesforcedx-utils-vscode/src/telemetry/interfaces/telemetryReporter.ts +++ /dev/null @@ -1,21 +0,0 @@ -/* eslint-disable header/header */ -/*--------------------------------------------------------- - * Copyright (C) Microsoft Corporation. All rights reserved. - *--------------------------------------------------------*/ -'use strict'; - -export type TelemetryReporter = { - sendTelemetryEvent( - eventName: string, - properties?: { [key: string]: string }, - measurements?: { [key: string]: number } - ): void; - - sendExceptionEvent( - exceptionName: string, - exceptionMessage: string, - measurements?: { [key: string]: number } - ): void; - - dispose(): Promise; -}; diff --git a/packages/salesforcedx-utils-vscode/src/telemetry/reporters/appInsights.ts b/packages/salesforcedx-utils-vscode/src/telemetry/reporters/appInsights.ts index 0b01939cd0..e71bb3617d 100644 --- a/packages/salesforcedx-utils-vscode/src/telemetry/reporters/appInsights.ts +++ b/packages/salesforcedx-utils-vscode/src/telemetry/reporters/appInsights.ts @@ -5,11 +5,11 @@ 'use strict'; +import { TelemetryReporter } from '@salesforce/vscode-service-provider'; import * as appInsights from 'applicationinsights'; import * as os from 'os'; import { Disposable, env, UIKind, version, workspace } from 'vscode'; import { WorkspaceContextUtil } from '../../context/workspaceContextUtil'; -import { TelemetryReporter } from '../interfaces'; type CommonProperties = { 'common.os': string; diff --git a/packages/salesforcedx-utils-vscode/src/telemetry/reporters/logStream.ts b/packages/salesforcedx-utils-vscode/src/telemetry/reporters/logStream.ts index 27db534801..8ac299e6c7 100644 --- a/packages/salesforcedx-utils-vscode/src/telemetry/reporters/logStream.ts +++ b/packages/salesforcedx-utils-vscode/src/telemetry/reporters/logStream.ts @@ -6,11 +6,11 @@ */ 'use strict'; +import { TelemetryReporter } from '@salesforce/vscode-service-provider'; import * as fs from 'fs'; import * as path from 'path'; import { Disposable, workspace } from 'vscode'; import { WorkspaceContextUtil } from '../../context/workspaceContextUtil'; -import { TelemetryReporter } from '../interfaces'; /** * Represents a telemetry reporter that logs telemetry events to a file. diff --git a/packages/salesforcedx-utils-vscode/src/telemetry/reporters/telemetryFile.ts b/packages/salesforcedx-utils-vscode/src/telemetry/reporters/telemetryFile.ts index be7f90a754..7cfb2f4f9a 100644 --- a/packages/salesforcedx-utils-vscode/src/telemetry/reporters/telemetryFile.ts +++ b/packages/salesforcedx-utils-vscode/src/telemetry/reporters/telemetryFile.ts @@ -4,11 +4,11 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ +import { TelemetryReporter } from '@salesforce/vscode-service-provider'; import * as fs from 'fs'; import * as path from 'path'; import { getRootWorkspacePath } from '../..'; import { LOCAL_TELEMETRY_FILE } from '../../constants'; -import { TelemetryReporter } from '../interfaces'; /** * Represents a telemetry file that logs telemetry events by appending to a local file. diff --git a/packages/salesforcedx-vscode-apex/package.json b/packages/salesforcedx-vscode-apex/package.json index 4f3f848839..2a38d515f1 100644 --- a/packages/salesforcedx-vscode-apex/package.json +++ b/packages/salesforcedx-vscode-apex/package.json @@ -28,6 +28,7 @@ "@salesforce/apex-tmlanguage": "1.8.0", "@salesforce/core-bundle": "8.2.0", "@salesforce/salesforcedx-utils-vscode": "61.12.0", + "@salesforce/vscode-service-provider": "1.1.1", "expand-home-dir": "0.0.3", "find-java-home": "0.2.0", "shelljs": "0.8.5", diff --git a/packages/salesforcedx-vscode-apex/src/index.ts b/packages/salesforcedx-vscode-apex/src/index.ts index 7e3e9d6231..f65217cf11 100644 --- a/packages/salesforcedx-vscode-apex/src/index.ts +++ b/packages/salesforcedx-vscode-apex/src/index.ts @@ -46,11 +46,15 @@ import { } from './languageUtils'; import { nls } from './messages'; import { retrieveEnableSyncInitJobs } from './settings'; -import { telemetryService } from './telemetry'; +import { getTelemetryService } from './telemetry/telemetry'; import { getTestOutlineProvider, TestNode } from './views/testOutlineProvider'; import { ApexTestRunner, TestRunType } from './views/testRunner'; export const activate = async (extensionContext: vscode.ExtensionContext) => { + const telemetryService = await getTelemetryService(); + if (!telemetryService) { + throw new Error('Could not fetch a telemetry service instance'); + } const activationTracker = new ActivationTracker( extensionContext, telemetryService @@ -294,6 +298,7 @@ const registerTestView = (): vscode.Disposable => { export const deactivate = async () => { await languageClientUtils.getClientInstance()?.stop(); + const telemetryService = await getTelemetryService(); telemetryService.sendExtensionDeactivationEvent(); }; @@ -301,6 +306,7 @@ const createLanguageClient = async ( extensionContext: vscode.ExtensionContext, languageServerStatusBarItem: ApexLSPStatusBarItem ): Promise => { + const telemetryService = await getTelemetryService(); // Resolve any found orphan language servers void lsoh.resolveAnyFoundOrphanLanguageServers(); // Initialize Apex language server diff --git a/packages/salesforcedx-vscode-apex/src/languageServer.ts b/packages/salesforcedx-vscode-apex/src/languageServer.ts index 39399fe7c9..7f9ebcbcfa 100644 --- a/packages/salesforcedx-vscode-apex/src/languageServer.ts +++ b/packages/salesforcedx-vscode-apex/src/languageServer.ts @@ -19,7 +19,7 @@ import { soqlMiddleware } from './embeddedSoql'; import { nls } from './messages'; import * as requirements from './requirements'; import { retrieveEnableSyncInitJobs } from './settings'; -import { telemetryService } from './telemetry'; +import { getTelemetryService } from './telemetry/telemetry'; const JDWP_DEBUG_PORT = 2739; const APEX_LANGUAGE_SERVER_MAIN = 'apex.jorje.lsp.ApexLanguageServerLauncher'; @@ -49,6 +49,7 @@ const DEBUG = typeof v8debug === 'object' || startedInDebugMode(); const createServer = async ( extensionContext: vscode.ExtensionContext ): Promise => { + const telemetryService = await getTelemetryService(); try { const requirementsData = await requirements.resolveRequirements(); const uberJar = path.resolve( @@ -90,8 +91,7 @@ const createServer = async ( args.push( '-Dtrace.protocol=false', `-Dapex.lsp.root.log.level=${LANGUAGE_SERVER_LOG_LEVEL}`, - `-agentlib:jdwp=transport=dt_socket,server=y,suspend=${ - SUSPEND_LANGUAGE_SERVER_STARTUP ? 'y' : 'n' + `-agentlib:jdwp=transport=dt_socket,server=y,suspend=${SUSPEND_LANGUAGE_SERVER_STARTUP ? 'y' : 'n' },address=*:${JDWP_DEBUG_PORT},quiet=y` ); if (process.env.YOURKIT_PROFILER_AGENT) { @@ -138,6 +138,7 @@ const protocol2CodeConverter = (value: string) => { export const createLanguageServer = async ( extensionContext: vscode.ExtensionContext ): Promise => { + const telemetryService = await getTelemetryService(); const server = await createServer(extensionContext); const client = new ApexLanguageClient( 'apex', diff --git a/packages/salesforcedx-vscode-apex/src/languageServerOrphanHandler.ts b/packages/salesforcedx-vscode-apex/src/languageServerOrphanHandler.ts index faa894be7e..ac24218df0 100644 --- a/packages/salesforcedx-vscode-apex/src/languageServerOrphanHandler.ts +++ b/packages/salesforcedx-vscode-apex/src/languageServerOrphanHandler.ts @@ -10,7 +10,7 @@ import { channelService } from './channels'; import { APEX_LSP_ORPHAN } from './constants'; import { languageServerUtils as lsu, ProcessDetail } from './languageUtils'; import { nls } from './messages'; -import { telemetryService } from './telemetry'; +import { getTelemetryService } from './telemetry/telemetry'; export const ADVICE = nls.localize('orphan_process_advice'); export const YES = nls.localize('yes'); @@ -31,7 +31,8 @@ export const TERMINATED_PROCESS = 'terminated_orphaned_process'; export const TERMINATE_FAILED = 'terminate_failed'; const resolveAnyFoundOrphanLanguageServers = async (): Promise => { - const orphanedProcesses = lsu.findAndCheckOrphanedProcesses(); + const telemetryService = await getTelemetryService(); + const orphanedProcesses = await lsu.findAndCheckOrphanedProcesses(); if (orphanedProcesses.length > 0) { if (await getResolutionForOrphanProcesses(orphanedProcesses)) { telemetryService.sendEventData(APEX_LSP_ORPHAN, undefined, { @@ -52,8 +53,8 @@ const resolveAnyFoundOrphanLanguageServers = async (): Promise => { typeof err === 'string' ? err : err?.message - ? err.message - : 'unknown' + ? err.message + : 'unknown' ); } } diff --git a/packages/salesforcedx-vscode-apex/src/languageUtils/languageServerUtils.ts b/packages/salesforcedx-vscode-apex/src/languageUtils/languageServerUtils.ts index c12dc8916f..c3441f24d2 100644 --- a/packages/salesforcedx-vscode-apex/src/languageUtils/languageServerUtils.ts +++ b/packages/salesforcedx-vscode-apex/src/languageUtils/languageServerUtils.ts @@ -12,7 +12,7 @@ import { POWERSHELL_NOT_FOUND, UBER_JAR_NAME } from '../constants'; -import { telemetryService } from '../telemetry'; +import { getTelemetryService } from '../telemetry/telemetry'; export type ProcessDetail = { pid: number; @@ -21,7 +21,8 @@ export type ProcessDetail = { orphaned: boolean; }; -const findAndCheckOrphanedProcesses = (): ProcessDetail[] => { +const findAndCheckOrphanedProcesses = async (): Promise => { + const telemetryService = await getTelemetryService(); const platform = process.platform.toLowerCase(); const isWindows = platform === 'win32'; @@ -86,7 +87,8 @@ const terminateProcess = (pid: number) => { process.kill(pid, SIGKILL); }; -const canRunCheck = (isWindows: boolean) => { +const canRunCheck = async (isWindows: boolean) => { + const telemetryService = await getTelemetryService(); if (isWindows) { try { // where command will return path if found and empty string if not diff --git a/packages/salesforcedx-vscode-apex/src/telemetry/index.ts b/packages/salesforcedx-vscode-apex/src/telemetry/index.ts deleted file mode 100644 index fea2e73958..0000000000 --- a/packages/salesforcedx-vscode-apex/src/telemetry/index.ts +++ /dev/null @@ -1,8 +0,0 @@ -/* - * Copyright (c) 2018, salesforce.com, inc. - * All rights reserved. - * Licensed under the BSD 3-Clause license. - * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause - */ -import { TelemetryService } from '@salesforce/salesforcedx-utils-vscode'; -export const telemetryService = TelemetryService.getInstance(); diff --git a/packages/salesforcedx-vscode-apex/src/telemetry/telemetry.ts b/packages/salesforcedx-vscode-apex/src/telemetry/telemetry.ts new file mode 100644 index 0000000000..2f09c08c51 --- /dev/null +++ b/packages/salesforcedx-vscode-apex/src/telemetry/telemetry.ts @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2024, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import { ServiceProvider, ServiceType, TelemetryServiceInterface } from '@salesforce/vscode-service-provider'; + +export const getTelemetryService = async (): Promise => { + return ServiceProvider.getService(ServiceType.Telemetry, 'salesforcedx-vscode-apex'); +}; diff --git a/packages/salesforcedx-vscode-apex/test/jest/index.test.ts b/packages/salesforcedx-vscode-apex/test/jest/index.test.ts index 35e7c66843..674c5b8373 100644 --- a/packages/salesforcedx-vscode-apex/test/jest/index.test.ts +++ b/packages/salesforcedx-vscode-apex/test/jest/index.test.ts @@ -9,9 +9,15 @@ import { API } from '../../src/constants'; import * as index from '../../src/index'; import { languageClientUtils } from '../../src/languageUtils'; import { extensionUtils } from '../../src/languageUtils/extensionUtils'; +import { getTelemetryService } from '../../src/telemetry/telemetry'; import ApexLSPStatusBarItem from './../../src/apexLspStatusBarItem'; +import { MockTelemetryService } from './telemetry/mockTelemetryService'; jest.mock('./../../src/apexLspStatusBarItem'); +jest.mock('../../src/telemetry/telemetry', () => ({ + getTelemetryService: jest.fn() +})); + describe('indexDoneHandler', () => { let setStatusSpy: jest.SpyInstance; let onNotificationSpy: jest.SpyInstance; @@ -74,6 +80,7 @@ describe('deactivate', () => { let stopSpy: jest.SpyInstance; beforeEach(() => { stopSpy = jest.fn(); + (getTelemetryService as jest.Mock).mockResolvedValue(new MockTelemetryService()); jest .spyOn(languageClientUtils, 'getClientInstance') .mockReturnValue({ stop: stopSpy } as unknown as ApexLanguageClient); diff --git a/packages/salesforcedx-vscode-apex/test/jest/languageUtils/languageServerUtils.test.ts b/packages/salesforcedx-vscode-apex/test/jest/languageUtils/languageServerUtils.test.ts index ce05e658d6..9a5c6775ba 100644 --- a/packages/salesforcedx-vscode-apex/test/jest/languageUtils/languageServerUtils.test.ts +++ b/packages/salesforcedx-vscode-apex/test/jest/languageUtils/languageServerUtils.test.ts @@ -8,36 +8,46 @@ import { expect } from 'chai'; import * as child_process from 'child_process'; import { UBER_JAR_NAME } from '../../../src/constants'; import { languageServerUtils } from '../../../src/languageUtils'; +import { getTelemetryService } from '../../../src/telemetry/telemetry'; +import { MockTelemetryService } from '../telemetry/mockTelemetryService'; + +jest.mock('../../../src/telemetry/telemetry', () => ({ + getTelemetryService: jest.fn() +})); describe('languageServerUtils', () => { describe('findAndCheckOrphanedProcesses', () => { - it('should return empty array if no processes found', () => { + beforeEach(() => { + (getTelemetryService as jest.Mock).mockResolvedValue(new MockTelemetryService()); + }); + + it('should return empty array if no processes found', async () => { jest.spyOn(child_process, 'execSync').mockReturnValue(Buffer.from('')); - jest.spyOn(languageServerUtils, 'canRunCheck').mockReturnValue(true); + jest.spyOn(languageServerUtils, 'canRunCheck').mockResolvedValue(true); - const result = languageServerUtils.findAndCheckOrphanedProcesses(); + const result = await languageServerUtils.findAndCheckOrphanedProcesses(); expect(result).to.have.lengthOf(0); }); - it('should return empty array if no orphaned processes found', () => { + it('should return empty array if no orphaned processes found', async () => { jest .spyOn(child_process, 'execSync') .mockReturnValueOnce(Buffer.from(`1234 5678 ${UBER_JAR_NAME}`)) .mockReturnValueOnce(Buffer.from('')); - jest.spyOn(languageServerUtils, 'canRunCheck').mockReturnValue(true); + jest.spyOn(languageServerUtils, 'canRunCheck').mockResolvedValue(true); - const result = languageServerUtils.findAndCheckOrphanedProcesses(); + const result = await languageServerUtils.findAndCheckOrphanedProcesses(); expect(result).to.have.lengthOf(0); }); - it('should return array of orphaned processes', () => { + it('should return array of orphaned processes', async () => { jest .spyOn(child_process, 'execSync') .mockReturnValueOnce(Buffer.from(`1234 5678 ${UBER_JAR_NAME}`)) .mockImplementationOnce(() => { throw new Error(); }); - jest.spyOn(languageServerUtils, 'canRunCheck').mockReturnValue(true); + jest.spyOn(languageServerUtils, 'canRunCheck').mockResolvedValue(true); - const result = languageServerUtils.findAndCheckOrphanedProcesses(); + const result = await languageServerUtils.findAndCheckOrphanedProcesses(); expect(result).to.have.lengthOf(1); expect(result[0]).to.have.property('pid', 1234); }); diff --git a/packages/salesforcedx-vscode-apex/test/jest/telemetry/mockTelemetryService.ts b/packages/salesforcedx-vscode-apex/test/jest/telemetry/mockTelemetryService.ts new file mode 100644 index 0000000000..0680eb343f --- /dev/null +++ b/packages/salesforcedx-vscode-apex/test/jest/telemetry/mockTelemetryService.ts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2024, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ +import { TelemetryService } from '@salesforce/salesforcedx-utils-vscode'; +import { TelemetryServiceInterface, ActivationInfo, TelemetryData, Properties, Measurements, TelemetryReporter } from '@salesforce/vscode-service-provider'; +import { ExtensionContext, ExtensionMode } from 'vscode'; + +export class MockTelemetryService extends TelemetryService implements TelemetryServiceInterface { + initializeService(extensionContext: ExtensionContext): Promise { + return Promise.resolve(); + } + initializeServiceWithAttributes(name: string, apiKey?: string, version?: string, extensionMode?: ExtensionMode): Promise { + return Promise.resolve(); + } + getReporters(): TelemetryReporter[] { + return []; + } + isTelemetryEnabled(): Promise { + return Promise.resolve(true); + } + checkCliTelemetry(): Promise { + return Promise.resolve(true); + } + isTelemetryExtensionConfigurationEnabled(): boolean { + return true; + } + setCliTelemetryEnabled(isEnabled: boolean): void { + // No-op implementation + } + sendActivationEventInfo(activationInfo: ActivationInfo): void { + // No-op implementation + } + sendExtensionActivationEvent(hrstart: [number, number], markEndTime?: number, telemetryData?: TelemetryData): void { + // No-op implementation + } + sendExtensionDeactivationEvent(): void { + // No-op implementation + } + sendCommandEvent(commandName?: string, hrstart?: [number, number], properties?: Properties, measurements?: Measurements): void { + // No-op implementation + } + sendException(name: string, message: string): void { + // No-op implementation + } + sendEventData(eventName: string, properties?: { [key: string]: string }, measures?: { [key: string]: number }): void { + // No-op implementation + } + dispose(): void { + // No-op implementation + } +} diff --git a/packages/salesforcedx-vscode-core/package.json b/packages/salesforcedx-vscode-core/package.json index b84ab979e9..8080ac0994 100644 --- a/packages/salesforcedx-vscode-core/package.json +++ b/packages/salesforcedx-vscode-core/package.json @@ -32,7 +32,7 @@ "@salesforce/source-deploy-retrieve-bundle": "12.1.5", "@salesforce/templates": "61.4.3", "@salesforce/ts-types": "2.0.10", - "@salesforce/vscode-service-provider": "1.0.4", + "@salesforce/vscode-service-provider": "1.1.1", "adm-zip": "0.5.10", "applicationinsights": "1.0.7", "glob": "^7.1.2", diff --git a/packages/salesforcedx-vscode-core/src/commands/templates/libraryBaseTemplateCommand.ts b/packages/salesforcedx-vscode-core/src/commands/templates/libraryBaseTemplateCommand.ts index 08d599c43a..ccec9e624d 100644 --- a/packages/salesforcedx-vscode-core/src/commands/templates/libraryBaseTemplateCommand.ts +++ b/packages/salesforcedx-vscode-core/src/commands/templates/libraryBaseTemplateCommand.ts @@ -5,13 +5,14 @@ * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { ConfigUtil, Properties } from '@salesforce/salesforcedx-utils-vscode'; +import { ConfigUtil } from '@salesforce/salesforcedx-utils-vscode'; import { ContinueResponse } from '@salesforce/salesforcedx-utils-vscode'; import { TemplateOptions, TemplateService, TemplateType } from '@salesforce/templates'; +import { Properties } from '@salesforce/vscode-service-provider'; import * as path from 'path'; import { ProgressLocation, window, workspace } from 'vscode'; import { channelService } from '../../channels'; diff --git a/packages/salesforcedx-vscode-core/src/commands/util/sfCommandletExecutor.ts b/packages/salesforcedx-vscode-core/src/commands/util/sfCommandletExecutor.ts index a61bc2c82f..bcbde4d1f0 100644 --- a/packages/salesforcedx-vscode-core/src/commands/util/sfCommandletExecutor.ts +++ b/packages/salesforcedx-vscode-core/src/commands/util/sfCommandletExecutor.ts @@ -9,11 +9,9 @@ import { CliCommandExecutor, Command, CommandExecution, - ContinueResponse, - Measurements, - Properties, - TelemetryData + ContinueResponse } from '@salesforce/salesforcedx-utils-vscode'; +import { Properties, Measurements, TelemetryData } from '@salesforce/vscode-service-provider'; import * as vscode from 'vscode'; import { channelService } from '../../channels'; import { diff --git a/packages/salesforcedx-vscode-core/src/index.ts b/packages/salesforcedx-vscode-core/src/index.ts index ad3b80e97c..52d830a9c1 100644 --- a/packages/salesforcedx-vscode-core/src/index.ts +++ b/packages/salesforcedx-vscode-core/src/index.ts @@ -118,7 +118,7 @@ import { orgBrowser } from './orgBrowser'; import { OrgList } from './orgPicker'; import { isSalesforceProjectOpened } from './predicates'; import { SalesforceProjectConfig } from './salesforceProject'; -import { getCoreLoggerService } from './services/getCoreLoggerService'; +import { getCoreLoggerService, registerGetTelemetryServiceCommand } from './services'; import { registerPushOrDeployOnSave, salesforceCoreSettings } from './settings'; import { taskViewService } from './statuses'; import { showTelemetryMessage, telemetryService } from './telemetry'; @@ -395,6 +395,8 @@ const registerCommands = ( getCoreLoggerService ); + const getTelemetryServiceForKeyCmd = registerGetTelemetryServiceCommand(); + return vscode.Disposable.from( renameLightningComponentCmd, diffFolder, @@ -454,7 +456,8 @@ const registerCommands = ( orgLogoutAllCmd, orgLogoutDefaultCmd, orgOpenCmd, - getCoreLoggerServiceCmd + getCoreLoggerServiceCmd, + getTelemetryServiceForKeyCmd ); }; @@ -567,7 +570,7 @@ export const activate = async (extensionContext: vscode.ExtensionContext) => { setNodeExtraCaCerts(); setSfLogLevel(); await telemetryService.initializeService(extensionContext); - showTelemetryMessage(extensionContext); + void showTelemetryMessage(extensionContext); // Task View const treeDataProvider = vscode.window.registerTreeDataProvider( @@ -579,7 +582,7 @@ export const activate = async (extensionContext: vscode.ExtensionContext) => { // Set internal dev context const internalDev = salesforceCoreSettings.getInternalDev(); - vscode.commands.executeCommand('setContext', 'sf:internal_dev', internalDev); + void vscode.commands.executeCommand('setContext', 'sf:internal_dev', internalDev); if (internalDev) { // Internal Dev commands @@ -715,7 +718,7 @@ const initializeProject = async (extensionContext: vscode.ExtensionContext) => { PersistentStorageService.initialize(extensionContext); // Register file watcher for push or deploy on save - await registerPushOrDeployOnSave(); + registerPushOrDeployOnSave(); await decorators.showOrg(); await setUpOrgExpirationWatcher(newOrgList); diff --git a/packages/salesforcedx-vscode-core/src/services/getCoreLoggerService.ts b/packages/salesforcedx-vscode-core/src/services/getCoreLoggerService.ts index f0b3c2d95e..e7c630afe4 100644 --- a/packages/salesforcedx-vscode-core/src/services/getCoreLoggerService.ts +++ b/packages/salesforcedx-vscode-core/src/services/getCoreLoggerService.ts @@ -10,12 +10,12 @@ import { FieldValue, Fields, - ILogger, + LoggerInterface, LogLine, LoggerLevelValue } from '@salesforce/vscode-service-provider'; -export class CoreLoggerService implements ILogger { +export class CoreLoggerService implements LoggerInterface { private level: LoggerLevelValue = 0; public constructor(private loggerName: string) { this.loggerName = loggerName; @@ -26,7 +26,7 @@ export class CoreLoggerService implements ILogger { getLevel(): LoggerLevelValue { return this.level; } - setLevel(level?: LoggerLevelValue): ILogger { + setLevel(level?: LoggerLevelValue): LoggerInterface { this.level = level ?? 0; return this; } @@ -39,32 +39,32 @@ export class CoreLoggerService implements ILogger { readLogContentsAsText(): string { return ''; } - child(name: string, fields?: Fields | undefined): ILogger { + child(name: string, fields?: Fields | undefined): LoggerInterface { return new CoreLoggerService(`${this.getName()}.childLogger`); } - addField(name: string, value: FieldValue): ILogger { + addField(name: string, value: FieldValue): LoggerInterface { throw new Error('Method not implemented.'); } - trace(...args: unknown[]): ILogger { + trace(...args: unknown[]): LoggerInterface { throw new Error('Method not implemented.'); } - debug(...args: unknown[]): ILogger { + debug(...args: unknown[]): LoggerInterface { throw new Error('Method not implemented.'); } - info(...args: unknown[]): ILogger { + info(...args: unknown[]): LoggerInterface { throw new Error('Method not implemented.'); } - warn(...args: unknown[]): ILogger { + warn(...args: unknown[]): LoggerInterface { throw new Error('Method not implemented.'); } - error(...args: unknown[]): ILogger { + error(...args: unknown[]): LoggerInterface { throw new Error('Method not implemented.'); } - fatal(...args: unknown[]): ILogger { + fatal(...args: unknown[]): LoggerInterface { throw new Error('Method not implemented.'); } } -export const getCoreLoggerService = (loggerName: string): ILogger => { +export const getCoreLoggerService = (loggerName: string): LoggerInterface => { return new CoreLoggerService(loggerName); }; diff --git a/packages/salesforcedx-vscode-core/src/services/index.ts b/packages/salesforcedx-vscode-core/src/services/index.ts index 6b460bedb6..817017d389 100644 --- a/packages/salesforcedx-vscode-core/src/services/index.ts +++ b/packages/salesforcedx-vscode-core/src/services/index.ts @@ -4,4 +4,5 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -export {CoreLoggerService} from './getCoreLoggerService'; \ No newline at end of file +export {CoreLoggerService, getCoreLoggerService} from './getCoreLoggerService'; +export * from './telemetry'; diff --git a/packages/salesforcedx-utils-vscode/src/telemetry/interfaces/index.ts b/packages/salesforcedx-vscode-core/src/services/telemetry/index.ts similarity index 84% rename from packages/salesforcedx-utils-vscode/src/telemetry/interfaces/index.ts rename to packages/salesforcedx-vscode-core/src/services/telemetry/index.ts index fca91f8d6d..79ee2e8751 100644 --- a/packages/salesforcedx-utils-vscode/src/telemetry/interfaces/index.ts +++ b/packages/salesforcedx-vscode-core/src/services/telemetry/index.ts @@ -4,4 +4,4 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -export * from './telemetryReporter'; +export* from './telemetryServiceProvider'; diff --git a/packages/salesforcedx-vscode-core/src/services/telemetry/telemetryServiceProvider.ts b/packages/salesforcedx-vscode-core/src/services/telemetry/telemetryServiceProvider.ts new file mode 100644 index 0000000000..8053c9cede --- /dev/null +++ b/packages/salesforcedx-vscode-core/src/services/telemetry/telemetryServiceProvider.ts @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2024, salesforce.com, inc. + * All rights reserved. + * Licensed under the BSD 3-Clause license. + * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause + */ + +import { TelemetryService } from '@salesforce/salesforcedx-utils-vscode'; +import { TelemetryServiceInterface } from '@salesforce/vscode-service-provider'; +import * as vscode from 'vscode'; + +export const getTelemetryServiceForKey = (key: string | undefined): Promise => { + console.log(`key: ${key}`); + return Promise.resolve(TelemetryService.getInstance(key)); +}; + +export const registerGetTelemetryServiceCommand = () => { + return vscode.commands.registerCommand( + 'sf.vscode.core.get.telemetry', + async (key: string | undefined): Promise => { + return (await getTelemetryServiceForKey(key)) as TelemetryService; + } + ); +}; diff --git a/packages/salesforcedx-vscode-core/src/telemetry/MetricsReporter.ts b/packages/salesforcedx-vscode-core/src/telemetry/MetricsReporter.ts index 936e6bed38..78b3fa4fdc 100644 --- a/packages/salesforcedx-vscode-core/src/telemetry/MetricsReporter.ts +++ b/packages/salesforcedx-vscode-core/src/telemetry/MetricsReporter.ts @@ -17,7 +17,7 @@ export enum EXT_PACK_TYPES { export class MetricsReporter { - public static extensionPackStatus = () => { + public static extensionPackStatus = (): void => { const extensionPackStatus = MetricsReporter.getExtensionPackStatus(); TelemetryService.getInstance().sendEventData( EXT_PACK_STATUS_EVENT_NAME, @@ -25,7 +25,7 @@ export class MetricsReporter { ); }; - private static getExtensionPackStatus = () => { + private static getExtensionPackStatus = (): EXT_PACK_TYPES => { const hasBasePack = this.isExtensionInstalled(BASE_EXTENSION); const hasExpandedPack = this.isExtensionInstalled(EXPANDED_EXTENSION); @@ -41,9 +41,9 @@ export class MetricsReporter { return status; }; - private static isExtensionInstalled = (extensionName: string) => { + private static isExtensionInstalled = (extensionName: string): boolean => { const extension = vscode.extensions.getExtension(extensionName); return extension !== undefined; }; -} \ No newline at end of file +} diff --git a/packages/salesforcedx-vscode-core/test/jest/telemetry/index.test.ts b/packages/salesforcedx-vscode-core/test/jest/telemetry/index.test.ts index 9ded1f82b9..5fa68ea42f 100644 --- a/packages/salesforcedx-vscode-core/test/jest/telemetry/index.test.ts +++ b/packages/salesforcedx-vscode-core/test/jest/telemetry/index.test.ts @@ -6,7 +6,7 @@ */ import { AppInsights } from '@salesforce/salesforcedx-utils-vscode'; import { UserService } from '@salesforce/salesforcedx-utils-vscode'; -import { ExtensionMode, window } from 'vscode'; +import { extensions, ExtensionMode, window, Extension } from 'vscode'; import { SalesforceCoreSettings } from '../../../src/settings/salesforceCoreSettings'; import { showTelemetryMessage, telemetryService } from '../../../src/telemetry'; import { MockExtensionContext } from './MockExtensionContext'; @@ -47,6 +47,8 @@ describe('Telemetry', () => { it('Should not initialize telemetry reporter', async () => { // create vscode extensionContext mockExtensionContext = new MockExtensionContext(true); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); await telemetryService.initializeService(mockExtensionContext); @@ -59,13 +61,15 @@ describe('Telemetry', () => { it('Should show telemetry info message', async () => { // create vscode extensionContext in which telemetry msg has never been previously shown mockExtensionContext = new MockExtensionContext(false); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); await telemetryService.initializeService(mockExtensionContext); const telemetryEnabled = await telemetryService.isTelemetryEnabled(); expect(telemetryEnabled).toEqual(true); - showTelemetryMessage(mockExtensionContext); + await showTelemetryMessage(mockExtensionContext); expect(mShowInformation).toHaveBeenCalledTimes(1); expect(teleSpy.mock.calls[0]).toEqual([true]); }); @@ -73,19 +77,23 @@ describe('Telemetry', () => { it('Should not show telemetry info message', async () => { // create vscode extensionContext in which telemetry msg has been previously shown mockExtensionContext = new MockExtensionContext(true); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); await telemetryService.initializeService(mockExtensionContext); const telemetryEnabled = await telemetryService.isTelemetryEnabled(); expect(telemetryEnabled).toEqual(true); - showTelemetryMessage(mockExtensionContext); + await showTelemetryMessage(mockExtensionContext); expect(mShowInformation).not.toHaveBeenCalled(); expect(teleSpy.mock.calls[0]).toEqual([true]); }); it('Should disable CLI telemetry', async () => { mockExtensionContext = new MockExtensionContext(true); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); cliSpy.mockResolvedValue(false); await telemetryService.initializeService(mockExtensionContext); @@ -127,13 +135,15 @@ describe('Telemetry', () => { false, ExtensionMode.Production ); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); await telemetryService.initializeService(mockExtensionContext); const telemetryEnabled = await telemetryService.isTelemetryEnabled(); expect(telemetryEnabled).toEqual(true); - showTelemetryMessage(mockExtensionContext); + await showTelemetryMessage(mockExtensionContext); expect(mShowInformation).toHaveBeenCalledTimes(1); expect(teleSpy.mock.calls[0]).toEqual([true]); }); @@ -144,13 +154,15 @@ describe('Telemetry', () => { true, ExtensionMode.Production ); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); await telemetryService.initializeService(mockExtensionContext); const telemetryEnabled = await telemetryService.isTelemetryEnabled(); expect(telemetryEnabled).toEqual(true); - showTelemetryMessage(mockExtensionContext); + await showTelemetryMessage(mockExtensionContext); expect(mShowInformation).not.toHaveBeenCalled(); expect(teleSpy.mock.calls[0]).toEqual([true]); }); @@ -161,6 +173,9 @@ describe('Telemetry', () => { true, ExtensionMode.Production ); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue(mockExtensionContext as unknown as Extension); + await telemetryService.initializeService(mockExtensionContext); const telemetryReporters = telemetryService.getReporters(); @@ -175,6 +190,9 @@ describe('Telemetry', () => { true, ExtensionMode.Production ); + jest.spyOn(extensions, 'getExtension') + .mockReturnValue({exports: mockExtensionContext} as unknown as Extension); + // Set reporters list to empty array so it will create a new appInsights reporter (telemetryService as any).reporters = []; const telemetryEnabled = await telemetryService.isTelemetryEnabled(); diff --git a/packages/salesforcedx-vscode-core/test/vscode-integration/telemetry/index.test.ts b/packages/salesforcedx-vscode-core/test/vscode-integration/telemetry/index.test.ts index 18af510111..721aac5f46 100644 --- a/packages/salesforcedx-vscode-core/test/vscode-integration/telemetry/index.test.ts +++ b/packages/salesforcedx-vscode-core/test/vscode-integration/telemetry/index.test.ts @@ -4,14 +4,72 @@ * Licensed under the BSD 3-Clause license. * For full license text, see LICENSE.txt file in the repo root or https://opensource.org/licenses/BSD-3-Clause */ -import { AppInsights } from '@salesforce/salesforcedx-utils-vscode'; +import { AppInsights, TelemetryService } from '@salesforce/salesforcedx-utils-vscode'; +import { ActivationInfo, Measurements, Properties, TelemetryData, TelemetryReporter, TelemetryServiceInterface } from '@salesforce/vscode-service-provider'; import { expect } from 'chai'; import { assert, SinonStub, stub } from 'sinon'; -import { window } from 'vscode'; +import { ExtensionContext, ExtensionMode, window } from 'vscode'; import { SalesforceCoreSettings } from '../../../src/settings/salesforceCoreSettings'; import { showTelemetryMessage, telemetryService } from '../../../src/telemetry'; import { MockExtensionContext } from './MockExtensionContext'; +class MockTelemetryService extends TelemetryService implements TelemetryServiceInterface { + public initializeService(extensionContext: ExtensionContext): Promise { + return Promise.resolve(); + } + public initializeServiceWithAttributes(name: string, apiKey?: string, version?: string, extensionMode?: ExtensionMode): Promise { + return Promise.resolve(); + } + public getReporters(): TelemetryReporter[] { + return []; + } + public isTelemetryEnabled(): Promise { + return Promise.resolve(true); + } + public checkCliTelemetry(): Promise { + return Promise.resolve(true); + } + public isTelemetryExtensionConfigurationEnabled(): boolean { + return true; + } + public setCliTelemetryEnabled(isEnabled: boolean): void { + // No-op implementation + } + public sendActivationEventInfo(activationInfo: ActivationInfo): void { + // No-op implementation + } + public sendExtensionActivationEvent(hrstart: [number, number], markEndTime?: number, telemetryData?: TelemetryData): void { + // No-op implementation + } + public sendExtensionDeactivationEvent(): void { + // No-op implementation + } + public sendCommandEvent(commandName?: string, hrstart?: [number, number], properties?: Properties, measurements?: Measurements): void { + // No-op implementation + } + public sendException(name: string, message: string): void { + // No-op implementation + } + public sendEventData(eventName: string, properties?: { [key: string]: string }, measures?: { [key: string]: number }): void { + // No-op implementation + } + public dispose(): void { + // No-op implementation + } +}; + +// Mock the ServiceProvider module +jest.mock('@salesforce/vscode-service-provider', () => ({ + ServiceProvider: { + getService: () => new MockTelemetryService() + }, + ServiceType: { + Telemetry: 'Telemetry' + } +})); + + + describe('Telemetry', () => { const machineId = '45678903'; let mShowInformation: SinonStub;