From 6be6a35fa4b92f885683d7b70a8674ced4954eb1 Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Mon, 28 Jul 2025 13:51:27 -0400 Subject: [PATCH 1/2] CHANGE: @W-19148450@: Add telemetry for detecting eslint legacy config --- package-lock.json | 2 +- packages/code-analyzer-eslint-engine/package.json | 4 ++-- packages/code-analyzer-eslint-engine/src/engine.ts | 4 ++++ .../test/end-to-end.test.ts | 14 ++++++++++++++ 4 files changed, 21 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index d39cf629..22295c2b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8776,7 +8776,7 @@ }, "packages/code-analyzer-eslint-engine": { "name": "@salesforce/code-analyzer-eslint-engine", - "version": "0.27.0", + "version": "0.28.0-SNAPSHOT", "license": "BSD-3-Clause", "dependencies": { "@eslint/js": "^9.31.0", diff --git a/packages/code-analyzer-eslint-engine/package.json b/packages/code-analyzer-eslint-engine/package.json index 5e6d2ef5..186b52e9 100644 --- a/packages/code-analyzer-eslint-engine/package.json +++ b/packages/code-analyzer-eslint-engine/package.json @@ -1,7 +1,7 @@ { "name": "@salesforce/code-analyzer-eslint-engine", "description": "Plugin package that adds 'eslint' as an engine into Salesforce Code Analyzer", - "version": "0.27.0", + "version": "0.28.0-SNAPSHOT", "author": "The Salesforce Code Analyzer Team", "license": "BSD-3-Clause", "homepage": "https://developer.salesforce.com/docs/platform/salesforce-code-analyzer/overview", @@ -76,4 +76,4 @@ "!src/index.ts" ] } -} \ No newline at end of file +} diff --git a/packages/code-analyzer-eslint-engine/src/engine.ts b/packages/code-analyzer-eslint-engine/src/engine.ts index 8d9f0cea..d73c7e94 100644 --- a/packages/code-analyzer-eslint-engine/src/engine.ts +++ b/packages/code-analyzer-eslint-engine/src/engine.ts @@ -68,6 +68,10 @@ export class ESLintEngine extends Engine { if (userConfigInfo.getState() === UserConfigState.LEGACY_USER_CONFIG) { this.emitLogEvent(LogLevel.Warn, getMessage('DetectedLegacyConfig', userConfigInfo.getChosenUserConfigFile() ?? /* istanbul ignore next */ userConfigInfo.getChosenUserIgnoreFile()!)); + this.emitTelemetryEvent('eslintLegacyConfigDetected', { + 'eslint_engine_version': await this.getEngineVersion(), + 'eslint8_engine_version': await this.delegateV8Engine.getEngineVersion() + }); return this.delegateV8Engine.describeRules(describeOptions); } diff --git a/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts b/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts index f1d3702b..3b353b50 100644 --- a/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts +++ b/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts @@ -9,12 +9,14 @@ import { LogEvent, LogLevel, RuleDescription, + TelemetryEvent, Violation, Workspace } from "@salesforce/code-analyzer-engine-api"; import path from "node:path"; import * as os from "node:os"; import process from "node:process"; +import {ESLint8EnginePlugin} from "@salesforce/code-analyzer-eslint8-engine"; jest.setTimeout(30_000); @@ -80,7 +82,9 @@ describe('End to end test', () => { const defaultConfig: ConfigObject = await plugin.createEngineConfig('eslint', configValueExtractor); const engine: Engine = await plugin.createEngine('eslint', defaultConfig); const logEvents: LogEvent[] = []; + const telemetryEvents: TelemetryEvent[] = []; engine.onEvent(EventType.LogEvent, (e: LogEvent) => logEvents.push(e)); + engine.onEvent(EventType.TelemetryEvent, (e: TelemetryEvent) => telemetryEvents.push(e)); const workspace: Workspace = new Workspace('id', [path.resolve('.')]); const ruleDescriptions: RuleDescription[] = await engine.describeRules({logFolder: os.tmpdir(), workspace: workspace}); const recommendedRuleNames: string[] = ruleDescriptions.filter(rd => rd.tags.includes('Recommended')).map(rd => rd.name); @@ -104,5 +108,15 @@ describe('End to end test', () => { const warnLogs: LogEvent[] = logEvents.filter(e => e.logLevel == LogLevel.Warn); expect(warnLogs).toHaveLength(1); expect(warnLogs[0].message).toContain('Using ESLint v8 instead of ESLint v9'); + + expect(telemetryEvents).toHaveLength(1); + expect(telemetryEvents[0]).toEqual({ + "type": "TelemetryEvent", + "eventName": "eslintLegacyConfigDetected", + "data": { + "eslint_engine_version": await engine.getEngineVersion(), + "eslint8_engine_version": await (await new ESLint8EnginePlugin().createEngine("eslint", {})).getEngineVersion() + } + }); }); }); From 0e18f9862a9efddc4b8846d90786be48be7b972b Mon Sep 17 00:00:00 2001 From: Stephen Carter Date: Mon, 28 Jul 2025 14:07:58 -0400 Subject: [PATCH 2/2] Respond to review feedback --- packages/code-analyzer-eslint-engine/test/end-to-end.test.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts b/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts index 3b353b50..22e9a6a4 100644 --- a/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts +++ b/packages/code-analyzer-eslint-engine/test/end-to-end.test.ts @@ -48,6 +48,8 @@ describe('End to end test', () => { const defaultConfig: ConfigObject = await plugin.createEngineConfig(availableEngineNames[0], configValueExtractor); const engine: Engine = await plugin.createEngine(availableEngineNames[0], defaultConfig); const logEvents: LogEvent[] = []; + const telemetryEvents: TelemetryEvent[] = []; + engine.onEvent(EventType.TelemetryEvent, (e: TelemetryEvent) => telemetryEvents.push(e)); engine.onEvent(EventType.LogEvent, (e: LogEvent) => logEvents.push(e)); const workspace: Workspace = new Workspace('id', [path.resolve('.')]); const ruleDescriptions: RuleDescription[] = await engine.describeRules({logFolder: os.tmpdir(), workspace: workspace}); @@ -70,6 +72,8 @@ describe('End to end test', () => { const warnLogs: LogEvent[] = logEvents.filter(e => e.logLevel == LogLevel.Warn); expect(warnLogs).toHaveLength(0); + + expect(telemetryEvents).toHaveLength(0); }); it('Test that we delegate to eslint v8 engine when user has specified legacy eslint config file', async () => {