From dc4ae2b82892ead6299b63e3a17f8b9d8cf9138c Mon Sep 17 00:00:00 2001 From: Daniel Ayala <14967941+danielayala94@users.noreply.github.com> Date: Fri, 11 Oct 2024 18:10:23 -0700 Subject: [PATCH 1/6] [Telemetry] Migration from AppInsights to 1DS (#13493) * Draft of telemetry refactoring * Better draft, including most (if not all?) properties * Various fixes, it now compiles * Refactor, and temporary commenting tests * All tests passing! But will need to clean up a few things * Polished some code, re-enabled some errorUtils tests * Change files * Update yarn.lock * Let yarn lint:fix cook * Simplifying * Nit: ordering * Avoid unnecessary JSON work * nit * Mostly placing some common props into Part A ext, plus adding/removing props * Distinguish between deviceClass and nodePlatform * Nit --- ...-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json | 7 + .../telemetry/package.json | 3 +- .../telemetry/src/e2etest/telemetry.test.ts | 145 ++++--- .../telemetry/src/telemetry.ts | 357 ++++++++++-------- .../telemetry/src/test/basePropUtils.test.ts | 25 +- .../telemetry/src/test/errorUtils.test.ts | 74 ++-- .../telemetry/src/utils/basePropUtils.ts | 76 +++- .../telemetry/src/utils/errorUtils.ts | 33 +- .../telemetry/src/utils/sanitizeUtils.ts | 7 +- yarn.lock | 316 ++++------------ 10 files changed, 476 insertions(+), 567 deletions(-) create mode 100644 change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json diff --git a/change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json b/change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json new file mode 100644 index 00000000000..3a9d8c4c481 --- /dev/null +++ b/change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Enables telemetry by migrating from AppInsights to 1DS", + "packageName": "@react-native-windows/telemetry", + "email": "14967941+danielayala94@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/@react-native-windows/telemetry/package.json b/packages/@react-native-windows/telemetry/package.json index 8966d11eea9..3577f90781a 100644 --- a/packages/@react-native-windows/telemetry/package.json +++ b/packages/@react-native-windows/telemetry/package.json @@ -20,8 +20,9 @@ "dependencies": { "@azure/core-auth": "1.5.0", "@react-native-windows/fs": "0.76.0-preview.2", + "@microsoft/1ds-core-js": "^4.3.0", + "@microsoft/1ds-post-js": "^4.3.0", "@xmldom/xmldom": "^0.7.7", - "applicationinsights": "2.9.1", "ci-info": "^3.2.0", "envinfo": "^7.8.1", "lodash": "^4.17.21", diff --git a/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts b/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts index 5dbd6e59ada..f919a27cc4e 100644 --- a/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts +++ b/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts @@ -5,7 +5,7 @@ * @format */ -import * as appInsights from 'applicationinsights'; +import * as coreOneDS from '@microsoft/1ds-core-js'; import * as path from 'path'; import { @@ -16,6 +16,7 @@ import { CommandEventName, CodedErrorEventName, } from '../telemetry'; + import * as basePropUtils from '../utils/basePropUtils'; import * as errorUtils from '../utils/errorUtils'; import * as projectUtils from '../utils/projectUtils'; @@ -35,22 +36,21 @@ export class TelemetryTest extends Telemetry { } // Ensure that we don't actually fire events when testing - Telemetry.isTest = true; + Telemetry.isTestEnvironment = true; await Telemetry.setup(options); } /** Run at the end of each test where telemetry was fired. */ static endTest(finalCallback?: () => void): void { - Telemetry.client?.flush({ - callback: _ => { - if (TelemetryTest.hasTestTelemetryProviders) { - expect(TelemetryTest.testTelemetryProvidersRan).toBe(true); - } - if (finalCallback) { - finalCallback(); - } - }, + Telemetry.appInsightsCore?.flush(undefined /* isAsync */, () => { + // Your callback logic here + if (TelemetryTest.hasTestTelemetryProviders) { + expect(TelemetryTest.testTelemetryProvidersRan).toBe(true); + } + if (finalCallback) { + finalCallback(); + } }); } @@ -61,7 +61,7 @@ export class TelemetryTest extends Telemetry { /** Retrieves the value of a common property.*/ static getCommonProperty(key: string): string | undefined { - return TelemetryTest.client?.commonProperties[key]; + return TelemetryTest.commonProperties[key]; } /** Retrieves the version of the specified tool/package. */ @@ -77,15 +77,12 @@ export class TelemetryTest extends Telemetry { } /** Adds a telemetry processor, usually for verifying the envelope. */ - static addTelemetryProcessor( - telemetryProcessor: ( - envelope: appInsights.Contracts.EnvelopeTelemetry, - contextObjects?: { - [name: string]: any; - }, + static addTelemetryInitializer( + telemetryInitializer: ( + envelope: coreOneDS.ITelemetryItem ) => boolean, ): void { - TelemetryTest.client?.addTelemetryProcessor(telemetryProcessor); + TelemetryTest.appInsightsCore?.addTelemetryInitializer(telemetryInitializer); TelemetryTest.hasTestTelemetryProviders = true; } } @@ -126,13 +123,12 @@ test('setup() verify static common property values with sync sources', async () const props: Record string | undefined> = { deviceArchitecture: () => basePropUtils.deviceArchitecture(), - devicePlatform: () => basePropUtils.devicePlatform(), + nodePlatform: () => basePropUtils.nodePlatform(), deviceNumCPUs: () => basePropUtils.deviceNumCPUs().toString(), deviceTotalMemory: () => basePropUtils.deviceTotalMemory().toString(), ciCaptured: () => basePropUtils.captureCI().toString(), ciType: () => basePropUtils.ciType(), isMsftInternal: () => basePropUtils.isMsftInternal().toString(), - sampleRate: () => basePropUtils.sampleRate().toString(), isTest: () => 'true', }; @@ -346,57 +342,49 @@ function verifyTestCommandTelemetryProcessor( expectedResultCode?: errorUtils.CodedErrorType, expectedError?: Error, ): ( - envelope: appInsights.Contracts.EnvelopeTelemetry, - contextObjects?: { - [name: string]: any; - }, + envelope: coreOneDS.ITelemetryItem ) => boolean { - return (envelope, _) => { + return (envelope) => { + TelemetryTest.setTestTelemetryProvidersRan(); + try { // Processor has run, so the test can (potentially) pass - TelemetryTest.setTestTelemetryProvidersRan(); - - // Verify roleInstance has been removed - expect(envelope.tags['ai.cloud.roleInstance']).toBeUndefined(); - - const properties = envelope.data.baseData?.properties; + const properties = envelope.baseData; expect(properties).toBeDefined(); // Verify basics - expect(properties.commandName).toBe('test-command'); + const commonProperties = properties!.common; + expect(commonProperties.commandName).toBe('test-command'); // Verify versions info - const versions = JSON.parse(properties.versions); + const versions = properties!.versions; expect(versions).toBeDefined(); - // Verify project info - const project = JSON.parse(properties.project); - expect(project).toStrictEqual(getTestCommandProjectInfo()); - expect(Object.keys(versions).length).toBeGreaterThan(0); for (const key of Object.keys(versions)) { expect(versions[key]).toBe(TelemetryTest.getVersion(key)); } - if (envelope.data.baseType === 'ExceptionData') { - // Verify event name - expect(properties.eventName).toBe(CodedErrorEventName); + // Verify project info + const project = properties!.project; + expect(project).toStrictEqual(getTestCommandProjectInfo()); + // Verify properties exclusive to error scenarios + if (envelope.name === CodedErrorEventName) { // Verify exception info - const exceptions = envelope.data.baseData?.exceptions; - expect(exceptions).toBeDefined(); - expect(exceptions.length).toBe(1); - expect(exceptions[0].message).toBeDefined(); - expect(exceptions[0].message).not.toBe(''); + const exceptionData = envelope.data!.exceptionData; + expect(exceptionData).toBeDefined(); + expect(exceptionData.message).toBeDefined(); + expect(exceptionData.message).not.toBe(''); - expect(exceptions[0].message).toBe( + expect(exceptionData.message).toBe( TelemetryTest.getPreserveErrorMessages() ? errorUtils.sanitizeErrorMessage(expectedError?.message || 'None') : '[Removed]', ); // Verify coded error info - const codedError = JSON.parse(properties.codedError); + const codedError = envelope.data!.codedError; expect(codedError).toBeDefined(); expect(codedError.type).toBe( @@ -409,14 +397,13 @@ function verifyTestCommandTelemetryProcessor( (expectedError as errorUtils.CodedError).data ?? {}, ); } else { - // Verify event name - expect(envelope.data.baseData?.name).toBe(CommandEventName); - expect(properties.eventName).toBe(CommandEventName); + // If this is not error scenario, it must be a command successful event. + expect(envelope.name).toBe(CommandEventName); // Verify command info const expectedInfo = getTestCommandStartInfo(); - const command = JSON.parse(properties.command); + const command = envelope.data!.command; expect(command).toBeDefined(); expect(command.args).toStrictEqual(expectedInfo.args); expect(command.options).toStrictEqual(expectedInfo.options); @@ -428,7 +415,7 @@ function verifyTestCommandTelemetryProcessor( // Verify extra props const extraProps = getExtraProps(); - expect(JSON.parse(properties.extraProps)).toStrictEqual(extraProps); + expect(envelope.data?.additionalData).toStrictEqual(extraProps); } } catch (ex) { caughtErrors.push( @@ -445,7 +432,7 @@ test('Telemetry run test command end to end, verify event fires', async () => { // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor(caughtErrors), ); @@ -474,7 +461,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, expectedError.type, @@ -503,7 +490,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, expectedError.type, @@ -533,7 +520,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, expectedError.type, @@ -559,7 +546,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, 'Unknown', @@ -585,7 +572,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, 'Unknown', @@ -615,44 +602,40 @@ function getVerifyStackTelemetryProcessor( caughtErrors: Error[], expectedError: Error, ): ( - envelope: appInsights.Contracts.EnvelopeTelemetry, - contextObjects?: { - [name: string]: any; - }, + envelope: coreOneDS.ITelemetryItem, ) => boolean { - return (envelope, _) => { + return (envelope) => { try { // Processor has run, so the test can (potentially) pass TelemetryTest.setTestTelemetryProvidersRan(); - if (envelope.data.baseType === 'ExceptionData') { - const data = (envelope.data as any).baseData; - expect(data.exceptions).toBeDefined(); - expect(data.exceptions.length).toBe(1); - expect(data.exceptions[0].message).toBeDefined(); - expect(data.exceptions[0].message).not.toBe(''); + if (envelope.name === CodedErrorEventName) { + const data = (envelope.data as any); + expect(data.exceptionData).toBeDefined(); + expect(data.exceptionData.message).toBeDefined(); + expect(data.exceptionData.message).not.toBe(''); - expect(data.exceptions[0].message).toBe( + expect(data.exceptionData.message).toBe( TelemetryTest.getPreserveErrorMessages() ? errorUtils.sanitizeErrorMessage(expectedError.message || 'None') : '[Removed]', ); - const stack = data.exceptions[0].parsedStack; + const stack = data.exceptionData.parsedStack; expect(stack).toBeDefined(); expect(stack.length).toBeGreaterThan(2); const filename = path.relative(process.cwd(), __filename); - expect(stack[0].method).toEqual('b'); - expect(stack[1].method).toEqual('b'); - expect(stack[2].method).toEqual('a'); - expect(stack[0].fileName).toEqual( + expect(stack[0].functionName).toEqual('b'); + expect(stack[1].functionName).toEqual('b'); + expect(stack[2].functionName).toEqual('a'); + expect(stack[0].filePath).toEqual( `[project_dir]\\???.ts(${filename.length})`, ); - expect(stack[1].fileName).toEqual( + expect(stack[1].filePath).toEqual( `[project_dir]\\???.ts(${filename.length})`, ); - expect(stack[2].fileName).toEqual( + expect(stack[2].filePath).toEqual( `[project_dir]\\???.ts(${filename.length})`, ); } @@ -675,7 +658,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( getVerifyStackTelemetryProcessor(caughtErrors, expectedError), ); @@ -700,7 +683,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( getVerifyStackTelemetryProcessor(caughtErrors, expectedError), ); @@ -714,4 +697,4 @@ test.each(testTelemetryOptions)( expect(caughtErrors).toHaveLength(0); }); }, -); +); \ No newline at end of file diff --git a/packages/@react-native-windows/telemetry/src/telemetry.ts b/packages/@react-native-windows/telemetry/src/telemetry.ts index 9d27fc58f3d..2757fede01f 100644 --- a/packages/@react-native-windows/telemetry/src/telemetry.ts +++ b/packages/@react-native-windows/telemetry/src/telemetry.ts @@ -4,7 +4,8 @@ * @format */ -import * as appInsights from 'applicationinsights'; +import * as coreOneDS from '@microsoft/1ds-core-js'; +import {PostChannel, IChannelConfiguration} from '@microsoft/1ds-post-js'; import * as basePropUtils from './utils/basePropUtils'; import * as versionUtils from './utils/versionUtils'; @@ -35,8 +36,8 @@ interface CommandInfo { endInfo?: CommandEndInfo; } -// This is our key with the AI backend -const RNWSetupString = '795006ca-cf54-40ee-8bc6-03deb91401c3'; +// 1DS instrumentation key +const RNW_1DS_INSTRUMENTATION_KEY = "" // Environment variable to override the default setup string const ENV_SETUP_OVERRIDE = 'RNW_TELEMETRY_SETUP'; @@ -76,30 +77,38 @@ export const NuGetPackagesWeTrack: string[] = [ * The Telemetry class is responsible for reporting telemetry for RNW CLI. */ export class Telemetry { - protected static client?: appInsights.TelemetryClient = undefined; + protected static appInsightsCore?: coreOneDS.AppInsightsCore = undefined; + protected static options: TelemetryOptions = { - setupString: Telemetry.getDefaultSetupString(), // We default to our AI key, but callers can easily override it in setup + setupString: Telemetry.getDefaultSetupString(), // We default to our 1DS instrumentation key, but callers can easily override it in setup. preserveErrorMessages: false, populateNpmPackageVersions: true, }; - protected static isTest: boolean = basePropUtils.isCliTest(); + protected static isTestEnvironment: boolean = basePropUtils.isCliTest(); + protected static commandInfo: CommandInfo = {}; + + // Stores the version of a list of packages used by the RNW app project. protected static versionsProp: Record = {}; + protected static projectProp?: | projectUtils.AppProjectInfo | projectUtils.DependencyProjectInfo = undefined; + // Store "Common Properties" in a single object. This will be logged in all telemetry events. + protected static commonProperties: {[key: string]: string} = {}; + protected static getDefaultSetupString(): string { // Enable overriding the default setup string via an environment variable - return process.env[ENV_SETUP_OVERRIDE] ?? RNWSetupString; + return process.env[ENV_SETUP_OVERRIDE] ?? RNW_1DS_INSTRUMENTATION_KEY; } protected static reset(): void { // Reset client - if (Telemetry.client) { - Telemetry.client.flush(); - Telemetry.client = undefined; + if (Telemetry.appInsightsCore) { + Telemetry.appInsightsCore.flush(); + Telemetry.appInsightsCore = undefined; } // Reset local members @@ -114,7 +123,7 @@ export class Telemetry { } static isEnabled(): boolean { - return Telemetry.client !== undefined; + return Telemetry.appInsightsCore !== undefined; } static getSessionId(): string { @@ -123,13 +132,13 @@ export class Telemetry { /** Sets up the Telemetry static to be used elsewhere. */ static async setup(options?: Partial) { - if (Telemetry.client) { + if (Telemetry.appInsightsCore) { // Bail since we've already setup return; } // Bail if we're in CI and not capturing CI - if (!this.isTest && basePropUtils.isCI() && !basePropUtils.captureCI()) { + if (!Telemetry.isTestEnvironment && basePropUtils.isCI() && !basePropUtils.captureCI()) { return; } @@ -139,71 +148,78 @@ export class Telemetry { Telemetry.setupClient(); await Telemetry.setupBaseProperties(); + } + + private static basicTelemetryInitializer(envelope: coreOneDS.ITelemetryItem) : boolean + { + // Filter out "legacy" events from older stable branches + if (envelope.name && EventNamesWeTrack.includes(envelope.name)) { + return true; + } - Telemetry.setupTelemetryProcessors(); + return false; } - /** Sets up Telemetry.client. */ + /** Sets up Telemetry.appInsightsCore. */ private static setupClient() { - appInsights.Configuration.setInternalLogging(false, false); - - Telemetry.client = new appInsights.TelemetryClient( - Telemetry.options.setupString, - ); + const postChannel: PostChannel = new PostChannel(); - // Allow overriding the proxy server via an environment variable - const proxyServer = process.env[ENV_PROXY_OVERRIDE]; - if (proxyServer) { - Telemetry.client.config.proxyHttpUrl = proxyServer; - Telemetry.client.config.proxyHttpsUrl = proxyServer; + const coreConfiguration: coreOneDS.IExtendedConfiguration = { + instrumentationKey: Telemetry.getDefaultSetupString() } - Telemetry.client.config.disableAppInsights = Telemetry.isTest; - Telemetry.client.config.disableStatsbeat = true; + const postChannelConfig: IChannelConfiguration = { + eventsLimitInMem: 5000 + }; - // Despite trying to disable the statsbeat, it might still be running: https://github.com/microsoft/ApplicationInsights-node.js/issues/943 - // So we want to disable it, and despite the method's typing, getStatsbeat() _can_ return undefined + coreConfiguration.extensionConfig = {}; + coreConfiguration.extensionConfig[postChannel.identifier] = postChannelConfig; - Telemetry.client.getStatsbeat()?.enable(false); + // Allow overriding the endpoint URL via an environment variable. + if (process.env[ENV_PROXY_OVERRIDE] !== undefined) { + coreConfiguration.endpointUrl = process.env[ENV_PROXY_OVERRIDE]; + } + + Telemetry.appInsightsCore = new coreOneDS.AppInsightsCore(); + Telemetry.appInsightsCore.initialize(coreConfiguration, [postChannel] /* extensions */); - Telemetry.client.channel.setUseDiskRetryCaching(!Telemetry.isTest); + Telemetry.appInsightsCore.addTelemetryInitializer(Telemetry.basicTelemetryInitializer); } /** Sets up any base properties that all telemetry events require. */ private static async setupBaseProperties() { - Telemetry.client!.commonProperties.deviceId = + Telemetry.commonProperties.deviceId = await basePropUtils.deviceId(); - Telemetry.client!.commonProperties.deviceArchitecture = + Telemetry.commonProperties.fullBuildInfo = + await basePropUtils.fullBuildInfo(); + Telemetry.commonProperties.deviceArchitecture = basePropUtils.deviceArchitecture(); - Telemetry.client!.commonProperties.nodeArchitecture = + Telemetry.commonProperties.nodeArchitecture = basePropUtils.nodeArchitecture(); - Telemetry.client!.commonProperties.devicePlatform = - basePropUtils.devicePlatform(); - Telemetry.client!.commonProperties.deviceLocale = + Telemetry.commonProperties.nodePlatform = + basePropUtils.nodePlatform(); + Telemetry.commonProperties.deviceClass = + basePropUtils.deviceClass(); + Telemetry.commonProperties.deviceLocale = await basePropUtils.deviceLocale(); - Telemetry.client!.commonProperties.deviceNumCPUs = basePropUtils + Telemetry.commonProperties.deviceNumCPUs = basePropUtils .deviceNumCPUs() .toString(); - Telemetry.client!.commonProperties.deviceTotalMemory = basePropUtils + Telemetry.commonProperties.deviceTotalMemory = basePropUtils .deviceTotalMemory() .toString(); - Telemetry.client!.commonProperties.deviceDiskFreeSpace = basePropUtils + Telemetry.commonProperties.deviceDiskFreeSpace = basePropUtils .deviceDiskFreeSpace() .toString(); - Telemetry.client!.commonProperties.ciCaptured = basePropUtils + Telemetry.commonProperties.ciCaptured = basePropUtils .captureCI() .toString(); - Telemetry.client!.commonProperties.ciType = basePropUtils.ciType(); - Telemetry.client!.commonProperties.isMsftInternal = basePropUtils + Telemetry.commonProperties.ciType = basePropUtils.ciType(); + Telemetry.commonProperties.isMsftInternal = basePropUtils .isMsftInternal() .toString(); - Telemetry.client!.commonProperties.sampleRate = basePropUtils - .sampleRate() - .toString(); - Telemetry.client!.commonProperties.isTest = Telemetry.isTest.toString(); - Telemetry.client!.commonProperties.sessionId = Telemetry.getSessionId(); - - Telemetry.client!.config.samplingPercentage = basePropUtils.sampleRate(); + Telemetry.commonProperties.isTest = Telemetry.isTestEnvironment.toString(); + Telemetry.commonProperties.sessionId = Telemetry.getSessionId(); await Telemetry.populateToolsVersions(); if (Telemetry.options.populateNpmPackageVersions) { @@ -211,85 +227,13 @@ export class Telemetry { } } - /** Sets up any telemetry processors. */ - private static setupTelemetryProcessors() { - Telemetry.client!.addTelemetryProcessor(Telemetry.basicTelemetryProcessor); - Telemetry.client!.addTelemetryProcessor(Telemetry.errorTelemetryProcessor); - } - - /** - * Performs the processing necessary (mostly PII sanitization) for all events. - * @param envelope The ApplicationInsights event envelope. - * @param _contextObjects An optional context object. - * @returns Whether to kee - */ - private static basicTelemetryProcessor( - envelope: appInsights.Contracts.EnvelopeTelemetry, - _contextObjects?: { - [name: string]: any; - }, - ): boolean { - delete envelope.tags['ai.cloud.roleInstance']; - - // Filter out "legacy" events from older stable branches - const properties = envelope.data.baseData?.properties; - if ( - properties?.eventName && - EventNamesWeTrack.includes(properties.eventName) - ) { - return true; - } - - return false; - } - - /** - * Performs the processing necessary (mostly PII sanitization) for error events. - * @param envelope - * @param _contextObjects - * @returns - */ - private static errorTelemetryProcessor( - envelope: appInsights.Contracts.EnvelopeTelemetry, - _contextObjects?: { - [name: string]: any; - }, - ): boolean { - if (envelope.data.baseType === 'ExceptionData') { - const data = envelope.data.baseData; - if (data?.exceptions) { - for (const exception of data.exceptions) { - for (const frame of exception.parsedStack) { - errorUtils.sanitizeErrorStackFrame(frame); - } - - // Exception message must never be blank, or AI will reject it - exception.message = exception.message || '[None]'; - - // CodedError has non-PII information in its 'type' member, plus optionally some more info in its 'data'. - // The message may contain PII information. This can be sanitized, but for now delete it. - // Note that the type of data.exceptions[0] is always going to be ExceptionDetails. It is not the original thrown exception. - // https://github.com/microsoft/ApplicationInsights-node.js/issues/707 - if (Telemetry.options.preserveErrorMessages) { - exception.message = errorUtils.sanitizeErrorMessage( - exception.message, - ); - } else { - exception.message = '[Removed]'; - } - } - } - } - return true; - } - /** Tries to update the version of the named package/tool by calling getValue(). */ static async tryUpdateVersionsProp( name: string, getValue: () => Promise, forceRefresh?: boolean, ): Promise { - if (!Telemetry.client) { + if (!Telemetry.appInsightsCore) { return true; } @@ -360,7 +304,7 @@ export class Telemetry { static setProjectInfo( info: projectUtils.AppProjectInfo | projectUtils.DependencyProjectInfo, ) { - if (!Telemetry.client) { + if (!Telemetry.appInsightsCore) { return; } @@ -368,10 +312,11 @@ export class Telemetry { } static startCommand(info: CommandStartInfo) { - if (!Telemetry.client) { + if (!Telemetry.appInsightsCore) { return; } + // startCommand() was called before invoking endCommand(), bail out. if (Telemetry.commandInfo.startInfo) { return; } @@ -380,14 +325,15 @@ export class Telemetry { Telemetry.commandInfo.startInfo = info; // Set common command props - Telemetry.client!.commonProperties.commandName = info.commandName; + Telemetry.commonProperties.commandName = info.commandName; } static endCommand(info: CommandEndInfo, extraProps?: Record) { - if (!Telemetry.client) { + if (!Telemetry.appInsightsCore) { return; } + // startCommand() wasn't called, bail out. if (!Telemetry.commandInfo.startInfo) { return; } @@ -398,13 +344,56 @@ export class Telemetry { Telemetry.trackCommandEvent(extraProps); } - private static trackCommandEvent(extraProps?: Record) { - const props: Record = { - eventName: CommandEventName, + private static trackEvent(telemetryItem: coreOneDS.ITelemetryItem) { + // Populate Part A + telemetryItem.ver = "4.0"; // Current Common Schema version + telemetryItem.time = new Date().toISOString(); + telemetryItem.iKey = RNW_1DS_INSTRUMENTATION_KEY; + + // Populate Part A extensions + telemetryItem.ext = {}; + telemetryItem.ext.device = { + id: Telemetry.commonProperties.deviceId, + deviceClass: Telemetry.commonProperties.deviceClass }; + telemetryItem.ext.os = { + locale: Telemetry.commonProperties.deviceLocale, + ver: Telemetry.commonProperties.fullBuildInfo, + }; + + // Populate most of "common" properties into Part B. + telemetryItem.baseData = { + common: { + device: { + architecture: Telemetry.commonProperties.deviceArchitecture, + numCPUs: Telemetry.commonProperties.numCPUs, + totalMemory: Telemetry.commonProperties.totalMemory, + diskFreeSpace: Telemetry.commonProperties.deviceDiskFreeSpace + }, + nodePlatform: Telemetry.commonProperties.nodePlatform, + nodeArchitecture: Telemetry.commonProperties.nodeArchitecture, + ciCaptured: Telemetry.commonProperties.ciCaptured, + ciType: Telemetry.commonProperties.ciType, + isMsftInternal: Telemetry.commonProperties.isMsftInternal, + isCliTest: Telemetry.commonProperties.isTest, + sessionId: Telemetry.commonProperties.sessionId, + commandName: Telemetry.commonProperties.commandName + }, + // Set project and versions props, belonging to Part B. + project: Telemetry.projectProp, + versions: Telemetry.versionsProp + }; + + // Send and post the telemetry event! + Telemetry.appInsightsCore!.track(telemetryItem); + Telemetry.appInsightsCore!.flush(); + } + + private static trackCommandEvent(extraProps?: Record) { + const telemetryItem: coreOneDS.ITelemetryItem = {name: CommandEventName}; - // Set command props - props.command = { + // This is logged in Part C. + const command = { options: Telemetry.commandInfo.startInfo?.options, defaultOptions: Telemetry.commandInfo.startInfo?.defaultOptions, args: Telemetry.commandInfo.startInfo?.args, @@ -414,34 +403,32 @@ export class Telemetry { resultCode: Telemetry.commandInfo.endInfo?.resultCode, }; - // Set remaining common props - props.project = Telemetry.projectProp; - props.versions = Telemetry.versionsProp; + telemetryItem.data = { + command: command + }; - // Set extra props - props.extraProps = {}; - Object.assign(props.extraProps, extraProps); + if (extraProps) { + telemetryItem.data.additionalData = extraProps; + } - // Fire event - Telemetry.client!.trackEvent({name: props.eventName, properties: props}); - Telemetry.client!.flush(); + // Populate common properties and fire event + Telemetry.trackEvent(telemetryItem); } static trackException(error: Error, extraProps?: Record) { - if (!Telemetry.client) { + if (!Telemetry.appInsightsCore) { return; } - const props: Record = { - eventName: CodedErrorEventName, - }; + const telemetryItem: coreOneDS.ITelemetryItem = {name: CodedErrorEventName}; - // Save off CodedError info + // Save off CodedError info in Part C. const codedError = error instanceof errorUtils.CodedError ? (error as errorUtils.CodedError) : null; - props.codedError = { + + const codedErrorStruct = { type: codedError?.type ?? 'Unknown', data: codedError?.data ?? {}, }; @@ -449,13 +436,13 @@ export class Telemetry { // Copy msBuildErrorMessages into the codedError.data object if ((error as any).msBuildErrorMessages) { // Always grab MSBuild error codes if possible - props.codedError.data.msBuildErrors = (error as any).msBuildErrorMessages + codedErrorStruct.data.msBuildErrors = (error as any).msBuildErrorMessages .map(errorUtils.tryGetErrorCode) .filter((msg: string | undefined) => msg); // Grab sanitized MSBuild error messages if we're preserving them if (Telemetry.options.preserveErrorMessages) { - props.codedError.data.msBuildErrorMessages = ( + codedErrorStruct.data.msBuildErrorMessages = ( error as any ).msBuildErrorMessages .map(errorUtils.sanitizeErrorMessage) @@ -467,23 +454,69 @@ export class Telemetry { const syscallExceptionFieldsToCopy = ['errno', 'syscall', 'code']; for (const f of syscallExceptionFieldsToCopy) { if ((error as any)[f]) { - props.codedError.data[f] = (error as any)[f]; + codedErrorStruct.data.codedError.data[f] = (error as any)[f]; } } - // Set remaining common props - props.project = Telemetry.projectProp; - props.versions = Telemetry.versionsProp; + // Break down TS Error object into Exception Data + const exceptionData = Telemetry.convertErrorIntoExceptionData(error); + + telemetryItem.data = { + codedError: codedErrorStruct, + exceptionData: exceptionData + }; + + Telemetry.trackEvent(telemetryItem); + } - // Set extra props - props.extraProps = {}; - Object.assign(props.extraProps, extraProps); + static convertErrorIntoExceptionData(error: Error) : Record { - // Fire event - Telemetry.client!.trackException({ - exception: error, - properties: props, + const exceptionData = { + hasFullStack: false, + message: error.message, + parsedStack: {} + }; + + exceptionData.message = exceptionData.message || '[None]'; + + // CodedError has non-PII information in its 'type' member, plus optionally some more info in its 'data'. + // The message may contain PII information. This can be sanitized, but for now delete it. + if (Telemetry.options.preserveErrorMessages) { + exceptionData.message = errorUtils.sanitizeErrorMessage( + exceptionData.message, + ); + } else { + exceptionData.message = '[Removed]'; + } + + const lines = error.stack?.split('\n'); + + const parsedStack = lines?.slice(1).map(line => { + const errorStackFrame : errorUtils.ErrorStackFrame = {}; + + const match = line.trim().match(/^\s*at\s+(?:(.*?)\s+\((.*):(\d+):(\d+)\)|(.*):(\d+):(\d+))$/); + if (match) { + errorStackFrame.functionName = match[1] || "N/A"; // Use a default value if no function name + errorStackFrame.filePath = match[2] || match[5]; + errorStackFrame.lineNumber = parseInt(match[3], 10) || parseInt(match[6], 10); + errorStackFrame.columnNumber = parseInt(match[4], 10) || parseInt(match[7], 10); + } + + return errorStackFrame; }); - Telemetry.client!.flush(); + + if (parsedStack) { + parsedStack.filter(Boolean); + + // Sanitize parsed error stack frames + for (const frame of parsedStack) { + errorUtils.sanitizeErrorStackFrame(frame); + } + + exceptionData.hasFullStack = true; + exceptionData.parsedStack = parsedStack; + } + + return exceptionData; } -} +} \ No newline at end of file diff --git a/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts index e70ca201bae..3c24807eed8 100644 --- a/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts @@ -32,13 +32,21 @@ test('nodeArchitecture() is valid', () => { expect(value).not.toBeNull(); }); -test('devicePlatform() is valid', () => { - const value = basePropUtils.devicePlatform(); +test('deviceClass() is valid', () => { + const value = basePropUtils.deviceClass(); expect(value).toBeDefined(); expect(value).not.toBe(''); expect(value).not.toBeNull(); }); +test('nodePlatform() is valid', () => { + const value = basePropUtils.nodePlatform(); + expect(value).toBeDefined(); + expect(value).not.toBe(''); + expect(value).not.toBeNull(); +}); + + test('deviceLocale() is valid', async () => { const value = await basePropUtils.deviceLocale(); expect(value).toBeDefined(); @@ -67,12 +75,6 @@ test('deviceDiskFreeSpace() is valid', () => { expect(value).toBeGreaterThanOrEqual(0); }); -test('sampleRate() is within valid range', () => { - const value = basePropUtils.sampleRate(); - expect(value).toBeGreaterThanOrEqual(0); - expect(value).toBeLessThanOrEqual(100); -}); - test('ciType() is valid', () => { const value = basePropUtils.ciType(); expect(value).toBeDefined(); @@ -135,3 +137,10 @@ test('getSessionId() is a guid', () => { test('getSessionId() does not change', () => { expect(basePropUtils.getSessionId()).toBe(basePropUtils.getSessionId()); }); + +test('fullBuildInfo() is valid', () => { + const value = basePropUtils.fullBuildInfo(); + expect(value).toBeDefined(); + expect(value).not.toBe(''); + expect(value).not.toBeNull(); +}); \ No newline at end of file diff --git a/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts index 565b1235214..24d10140e71 100644 --- a/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts @@ -5,8 +5,6 @@ * @format */ -import * as appInsights from 'applicationinsights'; - import * as errorUtils from '../utils/errorUtils'; test('tryGetErrorCode() with valid error code', () => { @@ -206,55 +204,49 @@ test('sanitizeErrorMessage() with standard MSBuild error', () => { }); test('sanitizeErrorStackFrame() with empty frame', () => { - const emptyFrame: appInsights.Contracts.StackFrame = { - level: 0, - method: '', - fileName: '', - assembly: 'asdf', - line: 0, + const stackFrame = { + functionName: '', + filePath: '', + lineNumber: 0, + columnNumber: 0 }; - errorUtils.sanitizeErrorStackFrame(emptyFrame); - expect(emptyFrame).toEqual({ - level: 0, - assembly: '', - fileName: '[path]', - method: '', - line: 0, + errorUtils.sanitizeErrorStackFrame(stackFrame); + expect(stackFrame).toEqual({ + functionName: '', + filePath: '[path]', + lineNumber: 0, + columnNumber: 0 }); }); test('sanitizeErrorStackFrame() with assembly name', () => { - const frame1: appInsights.Contracts.StackFrame = { - method: '', - fileName: `${process.cwd()}\\foo.js`, - assembly: 'asdf', - level: 0, - line: 0, + const stackFrame = { + functionName: '', + filePath: `${process.cwd()}\\foo.js`, + lineNumber: 10, + columnNumber: 14 }; - errorUtils.sanitizeErrorStackFrame(frame1); - expect(frame1).toEqual({ - assembly: '', - fileName: '[project_dir]\\???.js(6)', - method: '', - level: 0, - line: 0, + errorUtils.sanitizeErrorStackFrame(stackFrame); + expect(stackFrame).toEqual({ + functionName: '', + filePath: '[project_dir]\\???.js(6)', + lineNumber: 10, + columnNumber: 14 }); }); test('sanitizeErrorStackFrame() with method name', () => { - const frame2: appInsights.Contracts.StackFrame = { - method: `myMethod (something ${process.cwd()}`, - fileName: `${process.cwd()}\\telemetry\\foo.js`, - assembly: 'asdf', - level: 1, - line: 42, + const stackFrame = { + functionName: `myMethod (something ${process.cwd()}`, + filePath: `${process.cwd()}\\telemetry\\foo.js`, + lineNumber: 10, + columnNumber: 14 }; - errorUtils.sanitizeErrorStackFrame(frame2); - expect(frame2).toEqual({ - assembly: '', - fileName: '[project_dir]\\???.js(16)', - method: 'myMethod', - level: 1, - line: 42, + errorUtils.sanitizeErrorStackFrame(stackFrame); + expect(stackFrame).toEqual({ + functionName: 'myMethod', + filePath: '[project_dir]\\???.js(16)', + lineNumber: 10, + columnNumber: 14 }); }); diff --git a/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts b/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts index d3dc4bf73e7..782747a6c31 100644 --- a/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts @@ -14,20 +14,37 @@ import osLocale from 'os-locale'; const DeviceIdRegPath = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SQMClient'; const DeviceIdRegKey = 'MachineId'; +const DeviceIdBuildPath = '"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"'; +const DeviceIdBuildKey = 'BuildLabEx'; + /** - * Gets a telemetry-safe stable device ID. - * @returns A telemetry-safe stable device ID. + * Given a path and a key, retrieves the value from the Registry. + * @returns If the path and key exist, the requested value from the Registry; empty string otherwise. */ -export async function deviceId(): Promise { +export async function getValueFromRegistry(path: string, key: string): Promise { try { - let regCommand = `${process.env.windir}\\System32\\reg.exe query ${DeviceIdRegPath} /v ${DeviceIdRegKey}`; + let regCommand = `${process.env.windir}\\System32\\reg.exe query ${path} /v ${key}`; if (deviceArchitecture() === 'x64') { // Ensure we query the correct registry regCommand += ' /reg:64'; } + const output = execSync(regCommand).toString(); + return output; + } catch {} - const result = output.match(/\{([0-9A-Fa-f-]{36})\}/); + return ''; +} + +/** + * Gets a telemetry-safe stable device ID. + * @returns A telemetry-safe stable device ID. + */ +export async function deviceId(): Promise { + try { + const deviceIdValue = await getValueFromRegistry(DeviceIdRegPath, DeviceIdRegKey); + + const result = deviceIdValue.match(/\{([0-9A-Fa-f-]{36})\}/); if (result && result.length > 1) { return `s:${result[1]}`; } @@ -35,6 +52,24 @@ export async function deviceId(): Promise { return ''; } +/** + * Gets the Windows build name, number and architecture. + * @returns A string containing the Windows build name, number and architecture. + * e.g. 19569.1000.amd64fre.rs_prerelease.200214-1419 + */ +export async function fullBuildInfo(): Promise { + try { + const fullBuildValue = await getValueFromRegistry(DeviceIdBuildPath, DeviceIdBuildKey); + + // Retrieve the build info + const match = fullBuildValue.match(/BuildLabEx\s+REG_SZ\s+([^\r\n]+)/); + if (match && match.length > 1) { + return match[1]; + } + } catch {} + return ''; +} + /** * Gets the device architecture, like x86/x64/arm64. * @returns The device architecture. @@ -59,13 +94,32 @@ export function nodeArchitecture(): string { } /** - * Gets the device platform, like darwin/linux/win32. + * Gets the node platform, like darwin/linux/win32. * @returns The device platform. */ -export function devicePlatform(): string { +export function nodePlatform(): string { return platform(); } +/** + * Gets the OS name, to be filled in the PartA device.deviceClass field. + * @returns The device class. + */ +export function deviceClass(): string { + const node = nodePlatform(); + + switch (node) { + case 'darwin': + return 'Mac'; + case 'linux': + return 'Linux'; + case 'win32': + return 'Windows'; + default: + return node; + } +} + /** * Gets the device locale. * @returns The device locale. @@ -109,14 +163,6 @@ export function deviceDiskFreeSpace(drivePath?: string | null): number { return -1; } -/** - * Gets the telemetry sample rate. - * @returns The telemetry sample rate. - */ -export function sampleRate(): number { - return 100; -} - /** * Gets whether or not telemetry events are captured when running in CI. * @returns Whether or not telemetry events are captured when running in CI. diff --git a/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts b/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts index 1c3400df77e..7088b86b7a1 100644 --- a/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts @@ -4,8 +4,6 @@ * @format */ -import * as appInsights from 'applicationinsights'; - import * as sanitizeUtils from './sanitizeUtils'; // Note: All CLI commands will set process.exitCode to the numerical value of @@ -101,6 +99,13 @@ export class CodedError extends Error { } } +export interface ErrorStackFrame { + functionName?: string; + filePath?: string; + lineNumber?: number; + columnNumber?: number; +} + /** * Tries to parse an error code out of an error message. * @param msg An error message to process. @@ -156,16 +161,18 @@ export function sanitizeErrorMessage(msg: string): string { * @param frame */ export function sanitizeErrorStackFrame( - frame: appInsights.Contracts.StackFrame, -): void { - const parens = frame.method.indexOf('('); - if (parens !== -1) { - // case 1: method === 'methodName (rootOfThePath' - frame.method = frame.method.substr(0, parens).trim(); - } else { - // case 2: method === or something without '(', fileName is full path + frame: ErrorStackFrame): void { + + if (frame.functionName) { + const leftParenthesisIndex = frame.functionName.indexOf('('); + if (leftParenthesisIndex !== -1) { + // case 1: method === 'methodName (rootOfThePath' + frame.functionName = frame.functionName.substr(0, leftParenthesisIndex).trim(); + } else { + // case 2: method === or something without '(', fileName is full path + } } - // anonymize the filename - frame.fileName = sanitizeUtils.getAnonymizedPath(frame.fileName); - frame.assembly = ''; + + // anonymize the filePath + frame.filePath = sanitizeUtils.getAnonymizedPath(frame.filePath); } diff --git a/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts b/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts index 1314988e0d9..7437a2f8ab4 100644 --- a/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts @@ -24,9 +24,14 @@ const knownEnvironmentVariablePaths = [ * @returns The anonymized path. */ export function getAnonymizedPath( - filepath: string, + filepath: string | undefined, projectRoot?: string, ): string { + + if (filepath === undefined) { + return '[path]'; + } + projectRoot = (projectRoot ?? process.cwd()) .replace(/\//g, '\\') .toLowerCase(); diff --git a/yarn.lock b/yarn.lock index 664c6dc6f91..ad0a9c470c3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -33,47 +33,7 @@ "@azure/core-util" "^1.1.0" tslib "^2.2.0" -"@azure/core-auth@^1.4.0", "@azure/core-auth@^1.5.0": - version "1.7.2" - resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.7.2.tgz#558b7cb7dd12b00beec07ae5df5907d74df1ebd9" - integrity sha512-Igm/S3fDYmnMq1uKS38Ae1/m37B3zigdlZw+kocwEhh5GjyKjPrXKO2J6rzpC1wAxrNil/jX9BJRqBshyjnF3g== - dependencies: - "@azure/abort-controller" "^2.0.0" - "@azure/core-util" "^1.1.0" - tslib "^2.6.2" - -"@azure/core-rest-pipeline@1.10.1": - version "1.10.1" - resolved "https://registry.yarnpkg.com/@azure/core-rest-pipeline/-/core-rest-pipeline-1.10.1.tgz#348290847ca31b9eecf9cf5de7519aaccdd30968" - integrity sha512-Kji9k6TOFRDB5ZMTw8qUf2IJ+CeJtsuMdAHox9eqpTf1cefiNMpzrfnF6sINEBZJsaVaWgQ0o48B6kcUH68niA== - dependencies: - "@azure/abort-controller" "^1.0.0" - "@azure/core-auth" "^1.4.0" - "@azure/core-tracing" "^1.0.1" - "@azure/core-util" "^1.0.0" - "@azure/logger" "^1.0.0" - form-data "^4.0.0" - http-proxy-agent "^5.0.0" - https-proxy-agent "^5.0.0" - tslib "^2.2.0" - uuid "^8.3.0" - -"@azure/core-tracing@^1.0.0", "@azure/core-tracing@^1.0.1": - version "1.1.2" - resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.1.2.tgz#065dab4e093fb61899988a1cdbc827d9ad90b4ee" - integrity sha512-dawW9ifvWAWmUm9/h+/UQ2jrdvjCJ7VJEuCJ6XVNudzcOwm53BFZH4Q845vjfgoUAM8ZxokvVNxNxAITc502YA== - dependencies: - tslib "^2.6.2" - -"@azure/core-util@1.2.0": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.2.0.tgz#3499deba1fc36dda6f1912b791809b6f15d4a392" - integrity sha512-ffGIw+Qs8bNKNLxz5UPkz4/VBM/EZY07mPve1ZYFqYUdPwFqRj0RPk0U7LZMOfT7GCck9YjuT1Rfp1PApNl1ng== - dependencies: - "@azure/abort-controller" "^1.0.0" - tslib "^2.2.0" - -"@azure/core-util@^1.0.0", "@azure/core-util@^1.1.0": +"@azure/core-util@^1.1.0": version "1.9.1" resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.9.1.tgz#05ea9505c5cdf29c55ccf99a648c66ddd678590b" integrity sha512-OLsq0etbHO1MA7j6FouXFghuHrAFGk+5C1imcpQ2e+0oZhYF07WLA+NW2Vqs70R7d+zOAWiWM3tbE1sXcDN66g== @@ -81,29 +41,10 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@azure/logger@^1.0.0": - version "1.1.3" - resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.1.3.tgz#09a8fd4850b9112865756e92d5e8b728ee457345" - integrity sha512-J8/cIKNQB1Fc9fuYqBVnrppiUtW+5WWJPCj/tAokC5LdSTwkWWttN+jsRgw9BLYD7JDBx7PceiqOBxJJ1tQz3Q== - dependencies: - tslib "^2.6.2" - -"@azure/opentelemetry-instrumentation-azure-sdk@^1.0.0-beta.5": - version "1.0.0-beta.5" - resolved "https://registry.yarnpkg.com/@azure/opentelemetry-instrumentation-azure-sdk/-/opentelemetry-instrumentation-azure-sdk-1.0.0-beta.5.tgz#78809e6c005d08450701e5d37f087f6fce2f86eb" - integrity sha512-fsUarKQDvjhmBO4nIfaZkfNSApm1hZBzcvpNbSrXdcUBxu7lRvKsV5DnwszX7cnhLyVOW9yl1uigtRQ1yDANjA== - dependencies: - "@azure/core-tracing" "^1.0.0" - "@azure/logger" "^1.0.0" - "@opentelemetry/api" "^1.4.1" - "@opentelemetry/core" "^1.15.2" - "@opentelemetry/instrumentation" "^0.41.2" - tslib "^2.2.0" - -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.7.tgz#882fd9e09e8ee324e496bd040401c6f046ef4465" - integrity sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA== +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.25.7": + version "7.25.7" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.25.7.tgz#438f2c524071531d643c6f0188e1e28f130cebc7" + integrity sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g== dependencies: "@babel/highlight" "^7.24.7" picocolors "^1.0.0" @@ -1877,10 +1818,51 @@ resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919" integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw== -"@microsoft/applicationinsights-web-snippet@^1.0.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-snippet/-/applicationinsights-web-snippet-1.2.1.tgz#c158081f8c40ea9ad94475abac15f67182768882" - integrity sha512-+Cy9zFqdQgdAbMK1dpm7B+3DUnrByai0Tq6XG9v737HJpW6G1EiNNbTuFeXdPWyGaq6FIx9jxm/SUcxA6/Rxxg== +"@microsoft/1ds-core-js@4.3.0", "@microsoft/1ds-core-js@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-core-js/-/1ds-core-js-4.3.0.tgz#5c880614ce352fc66c34ae7fbb16cddb9e5c2fac" + integrity sha512-0aP0ko4j0E2HfMNG1TdctGxcX74c4nQMMMV2JyaBYRRlbg1qYSVCUTZO4Ap6Qf65cBjJUCoIzgDMXNSquANwDA== + dependencies: + "@microsoft/applicationinsights-core-js" "3.3.0" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.3" + "@nevware21/ts-async" ">= 0.5.2 < 2.x" + "@nevware21/ts-utils" ">= 0.11.3 < 2.x" + +"@microsoft/1ds-post-js@^4.3.0": + version "4.3.0" + resolved "https://registry.yarnpkg.com/@microsoft/1ds-post-js/-/1ds-post-js-4.3.0.tgz#14ff70dc5804b0fa9c23230f7b653a0fba1b2dc3" + integrity sha512-a1AflEuB313mfRiNNqkoVYDi4zxnG57zR8KotudtVoov6hiByBIS0KSuf3oE5/woDHWi9ZJjiCDvFwNqNH0YYw== + dependencies: + "@microsoft/1ds-core-js" "4.3.0" + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.3" + "@nevware21/ts-async" ">= 0.5.2 < 2.x" + "@nevware21/ts-utils" ">= 0.11.3 < 2.x" + +"@microsoft/applicationinsights-core-js@3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.3.0.tgz#b4e4da3bd49c3d14107f7beb6152d5214324b214" + integrity sha512-so0fFTqgZMjClH+MsiRYGspo5fpgwHEUYNMjyzpf9rjrY7FaUH8kkWzrQ3V0Cs4axZwf+WuIndtDOAws7aBmGQ== + dependencies: + "@microsoft/applicationinsights-shims" "3.0.1" + "@microsoft/dynamicproto-js" "^2.0.3" + "@nevware21/ts-async" ">= 0.5.2 < 2.x" + "@nevware21/ts-utils" ">= 0.11.3 < 2.x" + +"@microsoft/applicationinsights-shims@3.0.1": + version "3.0.1" + resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-shims/-/applicationinsights-shims-3.0.1.tgz#3865b73ace8405b9c4618cc5c571f2fe3876f06f" + integrity sha512-DKwboF47H1nb33rSUfjqI6ryX29v+2QWcTrRvcQDA32AZr5Ilkr7whOOSsD1aBzwqX0RJEIP1Z81jfE3NBm/Lg== + dependencies: + "@nevware21/ts-utils" ">= 0.9.4 < 2.x" + +"@microsoft/dynamicproto-js@^2.0.3": + version "2.0.3" + resolved "https://registry.yarnpkg.com/@microsoft/dynamicproto-js/-/dynamicproto-js-2.0.3.tgz#ae2b408061e3ff01a97078429fc768331e239256" + integrity sha512-JTWTU80rMy3mdxOjjpaiDQsTLZ6YSGGqsjURsY6AUQtIj0udlF/jYmhdLZu8693ZIC0T1IwYnFa0+QeiMnziBA== + dependencies: + "@nevware21/ts-utils" ">= 0.10.4 < 2.x" "@microsoft/eslint-plugin-sdl@^0.2.0": version "0.2.2" @@ -1891,6 +1873,23 @@ eslint-plugin-react "7.33.0" eslint-plugin-security "1.4.0" +"@nevware21/ts-async@>= 0.5.2 < 2.x": + version "0.5.2" + resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.5.2.tgz#a41883dc6ccc4666bdf156e92f35f3003fd3f6f0" + integrity sha512-Zf2vUNjCw2vJsiVKhWXA9hCNHsn59AOSGa5jGP4tWrp/vTH9XrI4eG/65khuoAgrS83migj0Xv5/j6fUAz69Zw== + dependencies: + "@nevware21/ts-utils" ">= 0.11.3 < 2.x" + +"@nevware21/ts-utils@>= 0.10.4 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 2.x": + version "0.10.5" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.10.5.tgz#2ec10c4b5d93db39136e8e11143e7feb311e47e0" + integrity sha512-+TEvP0+l/VBR5bJZoYFV+o6aQQ1O6y80uys5AVyyCKeWvrgWu/yNydqSBQNsk4BuEfkayg7R9+HCJRRRIvptTA== + +"@nevware21/ts-utils@>= 0.11.3 < 2.x": + version "0.11.3" + resolved "https://registry.yarnpkg.com/@nevware21/ts-utils/-/ts-utils-0.11.3.tgz#d0f032ade9540585a30a6453d962de613566d856" + integrity sha512-oipW+tyKN68bREjoESYAzOZiatM+1LF+ez1TX3BaeinhCkI18xsLgmpH9tvwHaVgKf1Tsth25sdbXVtYmgRYvQ== + "@nicolo-ribaudo/eslint-scope-5-internals@5.1.1-v1": version "5.1.1-v1" resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz#dbf733a965ca47b1973177dc0bb6c889edcfb129" @@ -2036,51 +2035,6 @@ dependencies: "@octokit/openapi-types" "^12.11.0" -"@opentelemetry/api@^1.4.1": - version "1.9.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.9.0.tgz#d03eba68273dc0f7509e2a3d5cba21eae10379fe" - integrity sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg== - -"@opentelemetry/core@1.25.1", "@opentelemetry/core@^1.15.2": - version "1.25.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.25.1.tgz#ff667d939d128adfc7c793edae2f6bca177f829d" - integrity sha512-GeT/l6rBYWVQ4XArluLVB6WWQ8flHbdb6r2FCHC3smtdOAbrJBIv35tpV/yp9bmYUJf+xmZpu9DRTIeJVhFbEQ== - dependencies: - "@opentelemetry/semantic-conventions" "1.25.1" - -"@opentelemetry/instrumentation@^0.41.2": - version "0.41.2" - resolved "https://registry.yarnpkg.com/@opentelemetry/instrumentation/-/instrumentation-0.41.2.tgz#cae11fa64485dcf03dae331f35b315b64bc6189f" - integrity sha512-rxU72E0pKNH6ae2w5+xgVYZLzc5mlxAbGzF4shxMVK8YC2QQsfN38B2GPbj0jvrKWWNUElfclQ+YTykkNg/grw== - dependencies: - "@types/shimmer" "^1.0.2" - import-in-the-middle "1.4.2" - require-in-the-middle "^7.1.1" - semver "^7.5.1" - shimmer "^1.2.1" - -"@opentelemetry/resources@1.25.1": - version "1.25.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.25.1.tgz#bb9a674af25a1a6c30840b755bc69da2796fefbb" - integrity sha512-pkZT+iFYIZsVn6+GzM0kSX+u3MSLCY9md+lIJOoKl/P+gJFfxJte/60Usdp8Ce4rOs8GduUpSPNe1ddGyDT1sQ== - dependencies: - "@opentelemetry/core" "1.25.1" - "@opentelemetry/semantic-conventions" "1.25.1" - -"@opentelemetry/sdk-trace-base@^1.15.2": - version "1.25.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.25.1.tgz#cbc1e60af255655d2020aa14cde17b37bd13df37" - integrity sha512-C8k4hnEbc5FamuZQ92nTOp8X/diCY56XUTnMiv9UTuJitCzaNNHAVsdm5+HLCdI8SLQsLWIrG38tddMxLVoftw== - dependencies: - "@opentelemetry/core" "1.25.1" - "@opentelemetry/resources" "1.25.1" - "@opentelemetry/semantic-conventions" "1.25.1" - -"@opentelemetry/semantic-conventions@1.25.1", "@opentelemetry/semantic-conventions@^1.15.2": - version "1.25.1" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.25.1.tgz#0deecb386197c5e9c2c28f2f89f51fb8ae9f145e" - integrity sha512-ZDjMJJQRlyk8A1KZFCc+bCbsyrn1wTwdNt56F7twdfUfnHUZUq77/WfONCj8p72NZOyP7pNTdUWSTYC3GTbuuQ== - "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -2704,11 +2658,6 @@ resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-1.1.2.tgz#ccb91445360179a04e7fe6aff78c00ffc1eeaf82" integrity sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw== -"@tootallnate/once@2": - version "2.0.0" - resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf" - integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A== - "@tootallnate/quickjs-emscripten@^0.23.0": version "0.23.0" resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c" @@ -3063,11 +3012,6 @@ "@types/glob" "~7.2.0" "@types/node" "*" -"@types/shimmer@^1.0.2": - version "1.2.0" - resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.2.0.tgz#9b706af96fa06416828842397a70dfbbf1c14ded" - integrity sha512-UE7oxhQLLd9gub6JKIAhDq06T0F6FnztwMNRvYgjeQSBeMc1ZG/tA47EwfduvkuQS8apbkM/lpLpWsaCeYsXVg== - "@types/ssri@*": version "7.1.5" resolved "https://registry.yarnpkg.com/@types/ssri/-/ssri-7.1.5.tgz#7147b5ba43957cb0f639a3309a3943fc1829d5e8" @@ -3513,11 +3457,6 @@ accepts@^1.3.7, accepts@~1.3.5, accepts@~1.3.7: mime-types "~2.1.34" negotiator "0.6.3" -acorn-import-assertions@^1.9.0: - version "1.9.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz#507276249d684797c84e0734ef84860334cfb1ac" - integrity sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA== - acorn-jsx@^5.3.2: version "5.3.2" resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" @@ -3687,25 +3626,6 @@ appdirsjs@^1.2.4: resolved "https://registry.yarnpkg.com/appdirsjs/-/appdirsjs-1.2.7.tgz#50b4b7948a26ba6090d4aede2ae2dc2b051be3b3" integrity sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw== -applicationinsights@2.9.1: - version "2.9.1" - resolved "https://registry.yarnpkg.com/applicationinsights/-/applicationinsights-2.9.1.tgz#769412f809d6a072487e4b41c4c3a29678344d82" - integrity sha512-hrpe/OvHFZlq+SQERD1fxaYICyunxzEBh9SolJebzYnIXkyA9zxIR87dZAh+F3+weltbqdIP8W038cvtpMNhQg== - dependencies: - "@azure/core-auth" "^1.5.0" - "@azure/core-rest-pipeline" "1.10.1" - "@azure/core-util" "1.2.0" - "@azure/opentelemetry-instrumentation-azure-sdk" "^1.0.0-beta.5" - "@microsoft/applicationinsights-web-snippet" "^1.0.1" - "@opentelemetry/api" "^1.4.1" - "@opentelemetry/core" "^1.15.2" - "@opentelemetry/sdk-trace-base" "^1.15.2" - "@opentelemetry/semantic-conventions" "^1.15.2" - cls-hooked "^4.2.2" - continuation-local-storage "^3.2.1" - diagnostic-channel "1.1.1" - diagnostic-channel-publishers "1.0.7" - aproba@^1.0.3: version "1.2.0" resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" @@ -3967,26 +3887,11 @@ async-done@~1.3.2: process-nextick-args "^2.0.0" stream-exhaust "^1.0.1" -async-hook-jl@^1.7.6: - version "1.7.6" - resolved "https://registry.yarnpkg.com/async-hook-jl/-/async-hook-jl-1.7.6.tgz#4fd25c2f864dbaf279c610d73bf97b1b28595e68" - integrity sha512-gFaHkFfSxTjvoxDMYqDuGHlcRyUuamF8s+ZTtJdDzqjws4mCt7v0vuV79/E2Wr2/riMQgtG4/yUtXWs1gZ7JMg== - dependencies: - stack-chain "^1.3.7" - async-limiter@~1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/async-limiter/-/async-limiter-1.0.1.tgz#dd379e94f0db8310b08291f9d64c3209766617fd" integrity sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ== -async-listener@^0.6.0: - version "0.6.10" - resolved "https://registry.yarnpkg.com/async-listener/-/async-listener-0.6.10.tgz#a7c97abe570ba602d782273c0de60a51e3e17cbc" - integrity sha512-gpuo6xOyF4D5DE5WvyqZdPA3NGhiT6Qf07l7DCB0wwDEsLvDIbCr6j9S5aj5Ch96dLace5tXVzWBZkxU/c5ohw== - dependencies: - semver "^5.3.0" - shimmer "^1.1.0" - async-settle@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-2.0.0.tgz#c695ad14e070f6a755d019d32d6eb38029020287" @@ -4711,7 +4616,7 @@ ci-info@^3.2.0: resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-3.9.0.tgz#4279a62028a7b1f262f3473fc9605f5e218c59b4" integrity sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ== -cjs-module-lexer@^1.0.0, cjs-module-lexer@^1.2.2: +cjs-module-lexer@^1.0.0: version "1.3.1" resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.3.1.tgz#c485341ae8fd999ca4ee5af2d7a1c9ae01e0099c" integrity sha512-a3KdPAANPbNE4ZUv9h6LckSl9zLsYOP4MBmhIPkRaeyybt+r4UghLvq+xw/YwUcC1gqylCkL4rdVs3Lwupjm4Q== @@ -4818,15 +4723,6 @@ clone@^1.0.2: resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg== -cls-hooked@^4.2.2: - version "4.2.2" - resolved "https://registry.yarnpkg.com/cls-hooked/-/cls-hooked-4.2.2.tgz#ad2e9a4092680cdaffeb2d3551da0e225eae1908" - integrity sha512-J4Xj5f5wq/4jAvcdgoGsL3G103BtWpZrMo8NEinRltN+xpTZdI+M38pyQqhuFU/P792xkMFvnKSf+Lm81U1bxw== - dependencies: - async-hook-jl "^1.7.6" - emitter-listener "^1.0.1" - semver "^5.4.1" - co@^4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184" @@ -4993,14 +4889,6 @@ console-control-strings@^1.0.0, console-control-strings@~1.1.0: resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" integrity sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ== -continuation-local-storage@^3.2.1: - version "3.2.1" - resolved "https://registry.yarnpkg.com/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz#11f613f74e914fe9b34c92ad2d28fe6ae1db7ffb" - integrity sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA== - dependencies: - async-listener "^0.6.0" - emitter-listener "^1.1.1" - convert-source-map@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" @@ -5389,18 +5277,6 @@ devtools@6.12.1: ua-parser-js "^0.7.21" uuid "^8.0.0" -diagnostic-channel-publishers@1.0.7: - version "1.0.7" - resolved "https://registry.yarnpkg.com/diagnostic-channel-publishers/-/diagnostic-channel-publishers-1.0.7.tgz#9b7f8d5ee1295481aee19c827d917e96fedf2c4a" - integrity sha512-SEECbY5AiVt6DfLkhkaHNeshg1CogdLLANA8xlG/TKvS+XUgvIKl7VspJGYiEdL5OUyzMVnr7o0AwB7f+/Mjtg== - -diagnostic-channel@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/diagnostic-channel/-/diagnostic-channel-1.1.1.tgz#44b60972de9ee055c16216535b0e9db3f6a0efd0" - integrity sha512-r2HV5qFkUICyoaKlBEpLKHjxMXATUf/l+h8UZPGBHGLy4DDiY2sOLcIctax4eRnTw5wH2jTMExLntGPJ8eOJxw== - dependencies: - semver "^7.5.3" - diff-match-patch@1.0.5, diff-match-patch@^1.0.4: version "1.0.5" resolved "https://registry.yarnpkg.com/diff-match-patch/-/diff-match-patch-1.0.5.tgz#abb584d5f10cd1196dfc55aa03701592ae3f7b37" @@ -5487,13 +5363,6 @@ electron-to-chromium@^1.5.4: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz#1abf0410c5344b2b829b7247e031f02810d442e6" integrity sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q== -emitter-listener@^1.0.1, emitter-listener@^1.1.1: - version "1.1.2" - resolved "https://registry.yarnpkg.com/emitter-listener/-/emitter-listener-1.1.2.tgz#56b140e8f6992375b3d7cb2cab1cc7432d9632e8" - integrity sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ== - dependencies: - shimmer "^1.2.0" - emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" @@ -7077,15 +6946,6 @@ http-proxy-agent@^4.0.1: agent-base "6" debug "4" -http-proxy-agent@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz#5129800203520d434f142bc78ff3c170800f2b43" - integrity sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w== - dependencies: - "@tootallnate/once" "2" - agent-base "6" - debug "4" - http-proxy-agent@^7.0.0, http-proxy-agent@^7.0.1: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" @@ -7220,16 +7080,6 @@ import-fresh@^3.2.1, import-fresh@^3.3.0: parent-module "^1.0.0" resolve-from "^4.0.0" -import-in-the-middle@1.4.2: - version "1.4.2" - resolved "https://registry.yarnpkg.com/import-in-the-middle/-/import-in-the-middle-1.4.2.tgz#2a266676e3495e72c04bbaa5ec14756ba168391b" - integrity sha512-9WOz1Yh/cvO/p69sxRmhyQwrIGGSp7EIdcb+fFNVi7CzQGQB8U1/1XrKVSbEd/GNOAeM0peJtmi7+qphe7NvAw== - dependencies: - acorn "^8.8.2" - acorn-import-assertions "^1.9.0" - cjs-module-lexer "^1.2.2" - module-details-from-path "^1.0.3" - import-lazy@~4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/import-lazy/-/import-lazy-4.0.0.tgz#e8eb627483a0a43da3c03f3e35548be5cb0cc153" @@ -9216,11 +9066,6 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== -module-details-from-path@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/module-details-from-path/-/module-details-from-path-1.0.3.tgz#114c949673e2a8a35e9d35788527aa37b679da2b" - integrity sha512-ySViT69/76t8VhE1xXHK6Ch4NcDd26gx0MzKXLO+F7NOtnqH68d9zF94nT8ZWSxXh8ELOERsnJO/sWt1xZYw5A== - ms@2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" @@ -10485,15 +10330,6 @@ require-from-string@^2.0.2: resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909" integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw== -require-in-the-middle@^7.1.1: - version "7.4.0" - resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.4.0.tgz#606977820d4b5f9be75e5a108ce34cfed25b3bb4" - integrity sha512-X34iHADNbNDfr6OTStIAHWSAvvKQRYgLO6duASaVf7J2VA3lvmNYboAHOuLC2huav1IwgZJtyEcJCKVzFxOSMQ== - dependencies: - debug "^4.3.5" - module-details-from-path "^1.0.3" - resolve "^1.22.8" - require-main-filename@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" @@ -10544,7 +10380,7 @@ resolve.exports@^2.0.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-2.0.2.tgz#f8c934b8e6a13f539e38b7098e2e36134f01e800" integrity sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg== -resolve@^1.1.6, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.3, resolve@^1.22.8, resolve@^1.3.2, resolve@~1.22.1: +resolve@^1.1.6, resolve@^1.10.1, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.22.3, resolve@^1.3.2, resolve@~1.22.1: version "1.22.8" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== @@ -10754,12 +10590,12 @@ semver-regex@^3.1.2: resolved "https://registry.yarnpkg.com/semver-regex/-/semver-regex-3.1.4.tgz#13053c0d4aa11d070a2f2872b6b1e3ae1e1971b4" integrity sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA== -"semver@2 >=2.2.1 || 3.x || 4 || 5 || 7", semver@^7.0.0, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.1, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: +"semver@2 >=2.2.1 || 3.x || 4 || 5 || 7", semver@^7.0.0, semver@^7.1.3, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.3.7, semver@^7.5.2, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3: version "7.6.3" resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.3.tgz#980f7b5550bc175fb4dc09403085627f9eb33143" integrity sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A== -semver@^5.3.0, semver@^5.4.1, semver@^5.5.0, semver@^5.6.0: +semver@^5.3.0, semver@^5.5.0, semver@^5.6.0: version "5.7.2" resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8" integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g== @@ -10907,11 +10743,6 @@ shellwords@^0.1.1: resolved "https://registry.yarnpkg.com/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b" integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww== -shimmer@^1.1.0, shimmer@^1.2.0, shimmer@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/shimmer/-/shimmer-1.2.1.tgz#610859f7de327b587efebf501fb43117f9aff337" - integrity sha512-sQTKC1Re/rM6XyFM6fIAGHRPVGvyXfgzIDvzoq608vM+jeyVD0Tu1E6Np0Kc2zAIFWIj963V2800iF/9LPieQw== - side-channel@^1.0.4, side-channel@^1.0.6: version "1.0.6" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" @@ -11098,11 +10929,6 @@ ssri@^8.0.0, ssri@^8.0.1: dependencies: minipass "^3.1.1" -stack-chain@^1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/stack-chain/-/stack-chain-1.3.7.tgz#d192c9ff4ea6a22c94c4dd459171e3f00cea1285" - integrity sha512-D8cWtWVdIe/jBA7v5p5Hwl5yOSOrmZPWDPe2KxQ5UAGD+nxbxU0lKXA4h85Ta6+qgdKVL3vUxsbIZjc1kBG7ug== - stack-utils@^2.0.3: version "2.0.6" resolved "https://registry.yarnpkg.com/stack-utils/-/stack-utils-2.0.6.tgz#aaf0748169c02fc33c8232abccf933f54a1cc34f" From 15578c4d28e619acbe949f122c87a2fb26fe3965 Mon Sep 17 00:00:00 2001 From: Daniel Ayala <14967941+danielayala94@users.noreply.github.com> Date: Thu, 7 Nov 2024 11:38:20 -0800 Subject: [PATCH 2/6] [Telemetry] Enable data uploading (#14039) * Set instrumentation key * Change files * Nit: Minor lint fix --- ...ows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json | 7 +++++++ packages/@react-native-windows/telemetry/src/telemetry.ts | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json diff --git a/change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json b/change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json new file mode 100644 index 00000000000..f9c56b8b4c6 --- /dev/null +++ b/change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Set instrumentation key", + "packageName": "@react-native-windows/telemetry", + "email": "14967941+danielayala94@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/@react-native-windows/telemetry/src/telemetry.ts b/packages/@react-native-windows/telemetry/src/telemetry.ts index 2757fede01f..afaf629f0e5 100644 --- a/packages/@react-native-windows/telemetry/src/telemetry.ts +++ b/packages/@react-native-windows/telemetry/src/telemetry.ts @@ -37,7 +37,8 @@ interface CommandInfo { } // 1DS instrumentation key -const RNW_1DS_INSTRUMENTATION_KEY = "" +const RNW_1DS_INSTRUMENTATION_KEY = + '49ff6d3ef12f4578a7b75a2573d9dba8-026332b2-2d50-452f-ad0d-50f921c97a9d-7145'; // Environment variable to override the default setup string const ENV_SETUP_OVERRIDE = 'RNW_TELEMETRY_SETUP'; From 922d1fb293ea51abd3b38e1ee3edaedfcd67f9ea Mon Sep 17 00:00:00 2001 From: Daniel Ayala <14967941+danielayala94@users.noreply.github.com> Date: Thu, 7 Nov 2024 13:59:38 -0800 Subject: [PATCH 3/6] Change files --- ...ws-telemetry-2dc2f58e-4343-45e6-a0cc-a955193e8882.json} | 6 +++--- ...ows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json | 7 ------- 2 files changed, 3 insertions(+), 10 deletions(-) rename change/{@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json => @react-native-windows-telemetry-2dc2f58e-4343-45e6-a0cc-a955193e8882.json} (53%) delete mode 100644 change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json diff --git a/change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json b/change/@react-native-windows-telemetry-2dc2f58e-4343-45e6-a0cc-a955193e8882.json similarity index 53% rename from change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json rename to change/@react-native-windows-telemetry-2dc2f58e-4343-45e6-a0cc-a955193e8882.json index f9c56b8b4c6..5828257e301 100644 --- a/change/@react-native-windows-telemetry-4abe7bcd-e858-4ab9-bc9c-3e2fd948acf2.json +++ b/change/@react-native-windows-telemetry-2dc2f58e-4343-45e6-a0cc-a955193e8882.json @@ -1,7 +1,7 @@ { - "type": "none", - "comment": "Set instrumentation key", + "type": "prerelease", + "comment": "Enabled telemetry collection", "packageName": "@react-native-windows/telemetry", "email": "14967941+danielayala94@users.noreply.github.com", - "dependentChangeType": "none" + "dependentChangeType": "patch" } diff --git a/change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json b/change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json deleted file mode 100644 index 3a9d8c4c481..00000000000 --- a/change/@react-native-windows-telemetry-a0c4007f-0fe6-4b25-8083-7476b6d51cae.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "type": "none", - "comment": "Enables telemetry by migrating from AppInsights to 1DS", - "packageName": "@react-native-windows/telemetry", - "email": "14967941+danielayala94@users.noreply.github.com", - "dependentChangeType": "none" -} From 684b64a7ed22c25d7aca9c4162f1c3818f83db22 Mon Sep 17 00:00:00 2001 From: Tatiana Kapos Date: Fri, 8 Nov 2024 13:51:34 -0800 Subject: [PATCH 4/6] update yarn --- yarn.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/yarn.lock b/yarn.lock index ad0a9c470c3..0016b30b2f3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -41,12 +41,12 @@ "@azure/abort-controller" "^2.0.0" tslib "^2.6.2" -"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.24.7", "@babel/code-frame@^7.25.7": +"@babel/code-frame@^7.0.0", "@babel/code-frame@^7.12.13", "@babel/code-frame@^7.16.0", "@babel/code-frame@^7.24.7": version "7.25.7" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.25.7.tgz#438f2c524071531d643c6f0188e1e28f130cebc7" integrity sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g== dependencies: - "@babel/highlight" "^7.24.7" + "@babel/highlight" "^7.25.7" picocolors "^1.0.0" "@babel/compat-data@^7.20.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.25.2", "@babel/compat-data@^7.25.4": From 22c42afbeaeced99c61679ba4c0dff58fede607f Mon Sep 17 00:00:00 2001 From: Tatiana Kapos Date: Fri, 8 Nov 2024 14:05:08 -0800 Subject: [PATCH 5/6] yarn again --- yarn.lock | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/yarn.lock b/yarn.lock index 0016b30b2f3..2ef312b0cac 100644 --- a/yarn.lock +++ b/yarn.lock @@ -303,6 +303,11 @@ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz#75b889cfaf9e35c2aaf42cf0d72c8e91719251db" integrity sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w== +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + "@babel/helper-validator-option@^7.24.7", "@babel/helper-validator-option@^7.24.8": version "7.24.8" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz#3725cdeea8b480e86d34df15304806a06975e33d" @@ -325,12 +330,12 @@ "@babel/template" "^7.25.0" "@babel/types" "^7.25.0" -"@babel/highlight@^7.24.7": - version "7.24.7" - resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.7.tgz#a05ab1df134b286558aae0ed41e6c5f731bf409d" - integrity sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw== +"@babel/highlight@^7.25.7": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.9.tgz#8141ce68fc73757946f983b343f1231f4691acc6" + integrity sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw== dependencies: - "@babel/helper-validator-identifier" "^7.24.7" + "@babel/helper-validator-identifier" "^7.25.9" chalk "^2.4.2" js-tokens "^4.0.0" picocolors "^1.0.0" From 2dbb7f171fc9b2430b4b94971984d459f203b323 Mon Sep 17 00:00:00 2001 From: Tatiana Kapos Date: Fri, 8 Nov 2024 14:28:23 -0800 Subject: [PATCH 6/6] lint:fix --- .../telemetry/src/e2etest/telemetry.test.ts | 24 +++--- .../telemetry/src/telemetry.ts | 81 +++++++++++-------- .../telemetry/src/test/basePropUtils.test.ts | 3 +- .../telemetry/src/test/errorUtils.test.ts | 12 +-- .../telemetry/src/utils/basePropUtils.ts | 20 +++-- .../telemetry/src/utils/errorUtils.ts | 10 +-- .../telemetry/src/utils/sanitizeUtils.ts | 1 - 7 files changed, 83 insertions(+), 68 deletions(-) diff --git a/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts b/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts index f919a27cc4e..00df0c63a14 100644 --- a/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts +++ b/packages/@react-native-windows/telemetry/src/e2etest/telemetry.test.ts @@ -78,11 +78,11 @@ export class TelemetryTest extends Telemetry { /** Adds a telemetry processor, usually for verifying the envelope. */ static addTelemetryInitializer( - telemetryInitializer: ( - envelope: coreOneDS.ITelemetryItem - ) => boolean, + telemetryInitializer: (envelope: coreOneDS.ITelemetryItem) => boolean, ): void { - TelemetryTest.appInsightsCore?.addTelemetryInitializer(telemetryInitializer); + TelemetryTest.appInsightsCore?.addTelemetryInitializer( + telemetryInitializer, + ); TelemetryTest.hasTestTelemetryProviders = true; } } @@ -341,10 +341,8 @@ function verifyTestCommandTelemetryProcessor( caughtErrors: Error[], expectedResultCode?: errorUtils.CodedErrorType, expectedError?: Error, -): ( - envelope: coreOneDS.ITelemetryItem -) => boolean { - return (envelope) => { +): (envelope: coreOneDS.ITelemetryItem) => boolean { + return envelope => { TelemetryTest.setTestTelemetryProvidersRan(); try { @@ -601,16 +599,14 @@ function a(s: string) { function getVerifyStackTelemetryProcessor( caughtErrors: Error[], expectedError: Error, -): ( - envelope: coreOneDS.ITelemetryItem, -) => boolean { - return (envelope) => { +): (envelope: coreOneDS.ITelemetryItem) => boolean { + return envelope => { try { // Processor has run, so the test can (potentially) pass TelemetryTest.setTestTelemetryProvidersRan(); if (envelope.name === CodedErrorEventName) { - const data = (envelope.data as any); + const data = envelope.data as any; expect(data.exceptionData).toBeDefined(); expect(data.exceptionData.message).toBeDefined(); expect(data.exceptionData.message).not.toBe(''); @@ -697,4 +693,4 @@ test.each(testTelemetryOptions)( expect(caughtErrors).toHaveLength(0); }); }, -); \ No newline at end of file +); diff --git a/packages/@react-native-windows/telemetry/src/telemetry.ts b/packages/@react-native-windows/telemetry/src/telemetry.ts index afaf629f0e5..c14ca9b4793 100644 --- a/packages/@react-native-windows/telemetry/src/telemetry.ts +++ b/packages/@react-native-windows/telemetry/src/telemetry.ts @@ -139,7 +139,11 @@ export class Telemetry { } // Bail if we're in CI and not capturing CI - if (!Telemetry.isTestEnvironment && basePropUtils.isCI() && !basePropUtils.captureCI()) { + if ( + !Telemetry.isTestEnvironment && + basePropUtils.isCI() && + !basePropUtils.captureCI() + ) { return; } @@ -151,8 +155,9 @@ export class Telemetry { await Telemetry.setupBaseProperties(); } - private static basicTelemetryInitializer(envelope: coreOneDS.ITelemetryItem) : boolean - { + private static basicTelemetryInitializer( + envelope: coreOneDS.ITelemetryItem, + ): boolean { // Filter out "legacy" events from older stable branches if (envelope.name && EventNamesWeTrack.includes(envelope.name)) { return true; @@ -166,41 +171,44 @@ export class Telemetry { const postChannel: PostChannel = new PostChannel(); const coreConfiguration: coreOneDS.IExtendedConfiguration = { - instrumentationKey: Telemetry.getDefaultSetupString() - } + instrumentationKey: Telemetry.getDefaultSetupString(), + }; const postChannelConfig: IChannelConfiguration = { - eventsLimitInMem: 5000 + eventsLimitInMem: 5000, }; coreConfiguration.extensionConfig = {}; - coreConfiguration.extensionConfig[postChannel.identifier] = postChannelConfig; + coreConfiguration.extensionConfig[postChannel.identifier] = + postChannelConfig; // Allow overriding the endpoint URL via an environment variable. if (process.env[ENV_PROXY_OVERRIDE] !== undefined) { coreConfiguration.endpointUrl = process.env[ENV_PROXY_OVERRIDE]; } - + Telemetry.appInsightsCore = new coreOneDS.AppInsightsCore(); - Telemetry.appInsightsCore.initialize(coreConfiguration, [postChannel] /* extensions */); + Telemetry.appInsightsCore.initialize( + coreConfiguration, + [postChannel] /* extensions */, + ); - Telemetry.appInsightsCore.addTelemetryInitializer(Telemetry.basicTelemetryInitializer); + Telemetry.appInsightsCore.addTelemetryInitializer( + Telemetry.basicTelemetryInitializer, + ); } /** Sets up any base properties that all telemetry events require. */ private static async setupBaseProperties() { - Telemetry.commonProperties.deviceId = - await basePropUtils.deviceId(); + Telemetry.commonProperties.deviceId = await basePropUtils.deviceId(); Telemetry.commonProperties.fullBuildInfo = await basePropUtils.fullBuildInfo(); Telemetry.commonProperties.deviceArchitecture = basePropUtils.deviceArchitecture(); Telemetry.commonProperties.nodeArchitecture = basePropUtils.nodeArchitecture(); - Telemetry.commonProperties.nodePlatform = - basePropUtils.nodePlatform(); - Telemetry.commonProperties.deviceClass = - basePropUtils.deviceClass(); + Telemetry.commonProperties.nodePlatform = basePropUtils.nodePlatform(); + Telemetry.commonProperties.deviceClass = basePropUtils.deviceClass(); Telemetry.commonProperties.deviceLocale = await basePropUtils.deviceLocale(); Telemetry.commonProperties.deviceNumCPUs = basePropUtils @@ -347,7 +355,7 @@ export class Telemetry { private static trackEvent(telemetryItem: coreOneDS.ITelemetryItem) { // Populate Part A - telemetryItem.ver = "4.0"; // Current Common Schema version + telemetryItem.ver = '4.0'; // Current Common Schema version telemetryItem.time = new Date().toISOString(); telemetryItem.iKey = RNW_1DS_INSTRUMENTATION_KEY; @@ -355,7 +363,7 @@ export class Telemetry { telemetryItem.ext = {}; telemetryItem.ext.device = { id: Telemetry.commonProperties.deviceId, - deviceClass: Telemetry.commonProperties.deviceClass + deviceClass: Telemetry.commonProperties.deviceClass, }; telemetryItem.ext.os = { locale: Telemetry.commonProperties.deviceLocale, @@ -369,7 +377,7 @@ export class Telemetry { architecture: Telemetry.commonProperties.deviceArchitecture, numCPUs: Telemetry.commonProperties.numCPUs, totalMemory: Telemetry.commonProperties.totalMemory, - diskFreeSpace: Telemetry.commonProperties.deviceDiskFreeSpace + diskFreeSpace: Telemetry.commonProperties.deviceDiskFreeSpace, }, nodePlatform: Telemetry.commonProperties.nodePlatform, nodeArchitecture: Telemetry.commonProperties.nodeArchitecture, @@ -378,11 +386,11 @@ export class Telemetry { isMsftInternal: Telemetry.commonProperties.isMsftInternal, isCliTest: Telemetry.commonProperties.isTest, sessionId: Telemetry.commonProperties.sessionId, - commandName: Telemetry.commonProperties.commandName + commandName: Telemetry.commonProperties.commandName, }, // Set project and versions props, belonging to Part B. project: Telemetry.projectProp, - versions: Telemetry.versionsProp + versions: Telemetry.versionsProp, }; // Send and post the telemetry event! @@ -405,7 +413,7 @@ export class Telemetry { }; telemetryItem.data = { - command: command + command: command, }; if (extraProps) { @@ -464,18 +472,17 @@ export class Telemetry { telemetryItem.data = { codedError: codedErrorStruct, - exceptionData: exceptionData + exceptionData: exceptionData, }; Telemetry.trackEvent(telemetryItem); } - static convertErrorIntoExceptionData(error: Error) : Record { - + static convertErrorIntoExceptionData(error: Error): Record { const exceptionData = { hasFullStack: false, message: error.message, - parsedStack: {} + parsedStack: {}, }; exceptionData.message = exceptionData.message || '[None]'; @@ -492,17 +499,21 @@ export class Telemetry { const lines = error.stack?.split('\n'); - const parsedStack = lines?.slice(1).map(line => { - const errorStackFrame : errorUtils.ErrorStackFrame = {}; + const parsedStack = lines?.slice(1).map(line => { + const errorStackFrame: errorUtils.ErrorStackFrame = {}; - const match = line.trim().match(/^\s*at\s+(?:(.*?)\s+\((.*):(\d+):(\d+)\)|(.*):(\d+):(\d+))$/); + const match = line + .trim() + .match(/^\s*at\s+(?:(.*?)\s+\((.*):(\d+):(\d+)\)|(.*):(\d+):(\d+))$/); if (match) { - errorStackFrame.functionName = match[1] || "N/A"; // Use a default value if no function name - errorStackFrame.filePath = match[2] || match[5]; - errorStackFrame.lineNumber = parseInt(match[3], 10) || parseInt(match[6], 10); - errorStackFrame.columnNumber = parseInt(match[4], 10) || parseInt(match[7], 10); + errorStackFrame.functionName = match[1] || 'N/A'; // Use a default value if no function name + errorStackFrame.filePath = match[2] || match[5]; + errorStackFrame.lineNumber = + parseInt(match[3], 10) || parseInt(match[6], 10); + errorStackFrame.columnNumber = + parseInt(match[4], 10) || parseInt(match[7], 10); } - + return errorStackFrame; }); @@ -520,4 +531,4 @@ export class Telemetry { return exceptionData; } -} \ No newline at end of file +} diff --git a/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts index 3c24807eed8..1db8560608b 100644 --- a/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts @@ -46,7 +46,6 @@ test('nodePlatform() is valid', () => { expect(value).not.toBeNull(); }); - test('deviceLocale() is valid', async () => { const value = await basePropUtils.deviceLocale(); expect(value).toBeDefined(); @@ -143,4 +142,4 @@ test('fullBuildInfo() is valid', () => { expect(value).toBeDefined(); expect(value).not.toBe(''); expect(value).not.toBeNull(); -}); \ No newline at end of file +}); diff --git a/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts index 24d10140e71..1f982ef21af 100644 --- a/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/errorUtils.test.ts @@ -208,14 +208,14 @@ test('sanitizeErrorStackFrame() with empty frame', () => { functionName: '', filePath: '', lineNumber: 0, - columnNumber: 0 + columnNumber: 0, }; errorUtils.sanitizeErrorStackFrame(stackFrame); expect(stackFrame).toEqual({ functionName: '', filePath: '[path]', lineNumber: 0, - columnNumber: 0 + columnNumber: 0, }); }); @@ -224,14 +224,14 @@ test('sanitizeErrorStackFrame() with assembly name', () => { functionName: '', filePath: `${process.cwd()}\\foo.js`, lineNumber: 10, - columnNumber: 14 + columnNumber: 14, }; errorUtils.sanitizeErrorStackFrame(stackFrame); expect(stackFrame).toEqual({ functionName: '', filePath: '[project_dir]\\???.js(6)', lineNumber: 10, - columnNumber: 14 + columnNumber: 14, }); }); @@ -240,13 +240,13 @@ test('sanitizeErrorStackFrame() with method name', () => { functionName: `myMethod (something ${process.cwd()}`, filePath: `${process.cwd()}\\telemetry\\foo.js`, lineNumber: 10, - columnNumber: 14 + columnNumber: 14, }; errorUtils.sanitizeErrorStackFrame(stackFrame); expect(stackFrame).toEqual({ functionName: 'myMethod', filePath: '[project_dir]\\???.js(16)', lineNumber: 10, - columnNumber: 14 + columnNumber: 14, }); }); diff --git a/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts b/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts index 782747a6c31..807fcd1bf49 100644 --- a/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts @@ -14,21 +14,25 @@ import osLocale from 'os-locale'; const DeviceIdRegPath = 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\SQMClient'; const DeviceIdRegKey = 'MachineId'; -const DeviceIdBuildPath = '"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"'; +const DeviceIdBuildPath = + '"HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"'; const DeviceIdBuildKey = 'BuildLabEx'; /** * Given a path and a key, retrieves the value from the Registry. * @returns If the path and key exist, the requested value from the Registry; empty string otherwise. */ -export async function getValueFromRegistry(path: string, key: string): Promise { +export async function getValueFromRegistry( + path: string, + key: string, +): Promise { try { let regCommand = `${process.env.windir}\\System32\\reg.exe query ${path} /v ${key}`; if (deviceArchitecture() === 'x64') { // Ensure we query the correct registry regCommand += ' /reg:64'; } - + const output = execSync(regCommand).toString(); return output; } catch {} @@ -42,7 +46,10 @@ export async function getValueFromRegistry(path: string, key: string): Promise { try { - const deviceIdValue = await getValueFromRegistry(DeviceIdRegPath, DeviceIdRegKey); + const deviceIdValue = await getValueFromRegistry( + DeviceIdRegPath, + DeviceIdRegKey, + ); const result = deviceIdValue.match(/\{([0-9A-Fa-f-]{36})\}/); if (result && result.length > 1) { @@ -59,7 +66,10 @@ export async function deviceId(): Promise { */ export async function fullBuildInfo(): Promise { try { - const fullBuildValue = await getValueFromRegistry(DeviceIdBuildPath, DeviceIdBuildKey); + const fullBuildValue = await getValueFromRegistry( + DeviceIdBuildPath, + DeviceIdBuildKey, + ); // Retrieve the build info const match = fullBuildValue.match(/BuildLabEx\s+REG_SZ\s+([^\r\n]+)/); diff --git a/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts b/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts index 7088b86b7a1..570ea0ea04c 100644 --- a/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/errorUtils.ts @@ -160,17 +160,17 @@ export function sanitizeErrorMessage(msg: string): string { * Sanitizes an error stack frame. * @param frame */ -export function sanitizeErrorStackFrame( - frame: ErrorStackFrame): void { - +export function sanitizeErrorStackFrame(frame: ErrorStackFrame): void { if (frame.functionName) { const leftParenthesisIndex = frame.functionName.indexOf('('); if (leftParenthesisIndex !== -1) { // case 1: method === 'methodName (rootOfThePath' - frame.functionName = frame.functionName.substr(0, leftParenthesisIndex).trim(); + frame.functionName = frame.functionName + .substr(0, leftParenthesisIndex) + .trim(); } else { // case 2: method === or something without '(', fileName is full path - } + } } // anonymize the filePath diff --git a/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts b/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts index 7437a2f8ab4..f92cb1e350e 100644 --- a/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts @@ -27,7 +27,6 @@ export function getAnonymizedPath( filepath: string | undefined, projectRoot?: string, ): string { - if (filepath === undefined) { return '[path]'; }