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/change/react-native-windows-5790d408-91e7-41d2-8fe7-073c1b784e98.json b/change/react-native-windows-5790d408-91e7-41d2-8fe7-073c1b784e98.json new file mode 100644 index 00000000000..2758f35796d --- /dev/null +++ b/change/react-native-windows-5790d408-91e7-41d2-8fe7-073c1b784e98.json @@ -0,0 +1,7 @@ +{ + "type": "patch", + "comment": "Introducing telemetry collection for 0.75", + "packageName": "react-native-windows", + "email": "14967941+danielayala94@users.noreply.github.com", + "dependentChangeType": "patch" +} diff --git a/packages/@react-native-windows/telemetry/package.json b/packages/@react-native-windows/telemetry/package.json index 53f41ccd15e..2ddf634b134 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.75.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..ab238b6b14a 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,11 +16,24 @@ import { CommandEventName, CodedErrorEventName, } from '../telemetry'; + import * as basePropUtils from '../utils/basePropUtils'; import * as errorUtils from '../utils/errorUtils'; import * as projectUtils from '../utils/projectUtils'; import * as versionUtils from '../utils/versionUtils'; +class CustomTestError extends Error { + // Declare a mock errno field, so it is picked up by trackException() (see syscallExceptionFieldsToCopy) + // to copy it into codedError.data. + errno: string; + + constructor(message: string) { + super(message); + this.name = 'CustomTestError'; + this.errno = '123'; + } +} + export class TelemetryTest extends Telemetry { protected static hasTestTelemetryProviders: boolean; protected static testTelemetryProvidersRan: boolean; @@ -35,22 +48,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 +73,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 +89,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; - }, - ) => boolean, + static addTelemetryInitializer( + telemetryInitializer: (envelope: coreOneDS.ITelemetryItem) => boolean, ): void { - TelemetryTest.client?.addTelemetryProcessor(telemetryProcessor); + TelemetryTest.appInsightsCore?.addTelemetryInitializer( + telemetryInitializer, + ); TelemetryTest.hasTestTelemetryProviders = true; } } @@ -126,13 +135,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', }; @@ -345,58 +353,48 @@ function verifyTestCommandTelemetryProcessor( caughtErrors: Error[], expectedResultCode?: errorUtils.CodedErrorType, expectedError?: Error, -): ( - envelope: appInsights.Contracts.EnvelopeTelemetry, - contextObjects?: { - [name: string]: any; - }, -) => boolean { - return (envelope, _) => { +): (envelope: coreOneDS.ITelemetryItem) => boolean { + 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( @@ -405,18 +403,25 @@ function verifyTestCommandTelemetryProcessor( : 'Unknown', ); + // If the exception type is not CodedError but any data got copied into envelope.CodedError.data, + // for instance autolinking error info, build the expected CodedError.data. + let expectedCodedErrorData = {}; + if (expectedError instanceof CustomTestError) { + expectedCodedErrorData = {errno: expectedError.errno}; + } + expect(codedError.data).toStrictEqual( - (expectedError as errorUtils.CodedError).data ?? {}, + (expectedError as errorUtils.CodedError).data ?? + expectedCodedErrorData, ); } 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 +433,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 +450,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 +479,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, expectedError.type, @@ -503,7 +508,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, expectedError.type, @@ -533,7 +538,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, expectedError.type, @@ -559,7 +564,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, 'Unknown', @@ -585,7 +590,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( verifyTestCommandTelemetryProcessor( caughtErrors, 'Unknown', @@ -614,45 +619,39 @@ function a(s: string) { function getVerifyStackTelemetryProcessor( caughtErrors: Error[], expectedError: Error, -): ( - envelope: appInsights.Contracts.EnvelopeTelemetry, - contextObjects?: { - [name: string]: any; - }, -) => boolean { - return (envelope, _) => { +): (envelope: coreOneDS.ITelemetryItem) => boolean { + 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 +674,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( getVerifyStackTelemetryProcessor(caughtErrors, expectedError), ); @@ -700,7 +699,7 @@ test.each(testTelemetryOptions)( // AI eats errors thrown in telemetry processors const caughtErrors: Error[] = []; - TelemetryTest.addTelemetryProcessor( + TelemetryTest.addTelemetryInitializer( getVerifyStackTelemetryProcessor(caughtErrors, expectedError), ); @@ -715,3 +714,111 @@ test.each(testTelemetryOptions)( }); }, ); + +test.each(testTelemetryOptions)( + 'A custom Error-based object with MS Build error info is copied into codedError.data appropriately by trackException()', + async options => { + await TelemetryTest.startTest(options); + + const expectedError = new CustomTestError('some message'); + + // AI eats errors thrown in telemetry processors + const caughtErrors: Error[] = []; + TelemetryTest.addTelemetryInitializer( + verifyTestCommandTelemetryProcessor( + caughtErrors, + 'Unknown', + expectedError, + ), + ); + + await runTestCommandE2E(() => testCommandBody(expectedError)); + + TelemetryTest.endTest(() => { + // Check if any errors were thrown + expect(caughtErrors).toHaveLength(0); + }); + }, +); + +test.each(testTelemetryOptions)( + 'Telemetry run test command end to end with CodedError, verifies PII is scrubbed if present in CodedError.', + async options => { + await TelemetryTest.startTest(options); + + const codedErrorInfo = new errorUtils.CodedError( + 'MSBuildError', // type + 'test error', // message + { + fieldWithPath: + 'Test Error occurred at C:\\some\\file\\path\\project.build.appxrecipe', // expectation: replace the whole C:\\... thing with "[path]". + fieldWithNoPath: 'Test Error data', // expectation: no changes to this string. + fieldWithNoString: 14, // expectation: no changes to this value. + arrayField: [ + 'No path', + 15, + 'Clean this path: C:\\some\\file\\path2\\project.build.appxrecipe', + [ + 'No path', + 150, + 'Also clean this: C:\\some\\file\\path2\\project.build.appxrecipe', + ], + ], + someObject: { + fieldWithPath: + 'Test Error occurred at C:\\some\\file\\path3\\project.build.appxrecipe', // expectation: replace the whole C:\\... thing with "[path]". + fieldWithNoPath: 'Test Error data 2', // expectation: no changes to this string. + fieldWithNoString: 16, // expectation: no changes to this value. + nestedObject: { + fieldWithPath: + 'Test Error occurred at C:\\some\\file\\path4\\project.build.appxrecipe', // expectation: replace the whole C:\\... thing with "[path]". + fieldWithNoPath: 'Test Error data 3', // expectation: no changes to this string. + fieldWithNoString: 17, // expectation: no changes to this value. + }, + }, + }, // data + ); + + const expectedError = new errorUtils.CodedError( + 'MSBuildError', // type + 'test error', // message + { + fieldWithPath: 'Test Error occurred at [path]', + fieldWithNoPath: 'Test Error data', + fieldWithNoString: 14, + arrayField: [ + 'No path', + 15, + 'Clean this path: [path]', + ['No path', 150, 'Also clean this: [path]'], + ], + someObject: { + fieldWithPath: 'Test Error occurred at [path]', + fieldWithNoPath: 'Test Error data 2', + fieldWithNoString: 16, + nestedObject: { + fieldWithPath: 'Test Error occurred at [path]', + fieldWithNoPath: 'Test Error data 3', + fieldWithNoString: 17, + }, + }, + }, // data + ); + + const caughtErrors: Error[] = []; + TelemetryTest.addTelemetryInitializer( + verifyTestCommandTelemetryProcessor( + caughtErrors, + expectedError.type, + expectedError, + ), + ); + + await runTestCommandE2E(() => testCommandBody(codedErrorInfo)); + + TelemetryTest.endTest(() => { + // Check if any errors were thrown + expect(caughtErrors).toHaveLength(0); + }); + }, +); diff --git a/packages/@react-native-windows/telemetry/src/telemetry.ts b/packages/@react-native-windows/telemetry/src/telemetry.ts index 9d27fc58f3d..eb51e9e8cec 100644 --- a/packages/@react-native-windows/telemetry/src/telemetry.ts +++ b/packages/@react-native-windows/telemetry/src/telemetry.ts @@ -4,12 +4,14 @@ * @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'; import * as errorUtils from './utils/errorUtils'; import * as projectUtils from './utils/projectUtils'; +import * as nameUtils from './utils/nameUtils'; export interface TelemetryOptions { setupString: string; @@ -35,8 +37,9 @@ 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 = + '49ff6d3ef12f4578a7b75a2573d9dba8-026332b2-2d50-452f-ad0d-50f921c97a9d-7145'; // Environment variable to override the default setup string const ENV_SETUP_OVERRIDE = 'RNW_TELEMETRY_SETUP'; @@ -76,30 +79,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 +125,7 @@ export class Telemetry { } static isEnabled(): boolean { - return Telemetry.client !== undefined; + return Telemetry.appInsightsCore !== undefined; } static getSessionId(): string { @@ -123,13 +134,17 @@ 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 +154,82 @@ 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); + const postChannel: PostChannel = new PostChannel(); - Telemetry.client = new appInsights.TelemetryClient( - Telemetry.options.setupString, - ); + const coreConfiguration: coreOneDS.IExtendedConfiguration = { + instrumentationKey: Telemetry.getDefaultSetupString(), + }; - // 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 postChannelConfig: IChannelConfiguration = { + eventsLimitInMem: 5000, + }; - Telemetry.client.config.disableAppInsights = Telemetry.isTest; - Telemetry.client.config.disableStatsbeat = true; + coreConfiguration.extensionConfig = {}; + coreConfiguration.extensionConfig[postChannel.identifier] = + postChannelConfig; - // 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 + // Allow overriding the endpoint URL via an environment variable. + if (process.env[ENV_PROXY_OVERRIDE] !== undefined) { + coreConfiguration.endpointUrl = process.env[ENV_PROXY_OVERRIDE]; + } - Telemetry.client.getStatsbeat()?.enable(false); + 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 = - await basePropUtils.deviceId(); - Telemetry.client!.commonProperties.deviceArchitecture = + Telemetry.commonProperties.deviceId = await basePropUtils.deviceId(); + 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,92 +237,25 @@ 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; } - if (forceRefresh === true || !Telemetry.versionsProp[name]) { + // Process the package name to comply with the backend requirements + const packageName = nameUtils.isValidTelemetryPackageName(name) + ? name + : nameUtils.cleanTelemetryPackageName(name); + + if (forceRefresh === true || !Telemetry.versionsProp[packageName]) { const value = await getValue(); if (value) { - Telemetry.versionsProp[name] = value; + Telemetry.versionsProp[packageName] = value; return true; } } @@ -360,7 +319,7 @@ export class Telemetry { static setProjectInfo( info: projectUtils.AppProjectInfo | projectUtils.DependencyProjectInfo, ) { - if (!Telemetry.client) { + if (!Telemetry.appInsightsCore) { return; } @@ -368,10 +327,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 +340,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 +359,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, }; - // Set command props - props.command = { + // 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}; + + // 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 +418,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 +451,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 +469,97 @@ 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[f] = (error as any)[f]; } } - // Set remaining common props - props.project = Telemetry.projectProp; - props.versions = Telemetry.versionsProp; + // Scrub any potential PII present in codedError.data array, as long as the data is a string. + codedErrorStruct.data = Telemetry.sanitizeAny(codedErrorStruct.data); - // Set extra props - props.extraProps = {}; - Object.assign(props.extraProps, extraProps); + // Break down TS Error object into Exception Data + const exceptionData = Telemetry.convertErrorIntoExceptionData(error); - // Fire event - Telemetry.client!.trackException({ - exception: error, - properties: props, + telemetryItem.data = { + codedError: codedErrorStruct, + exceptionData: exceptionData, + }; + + Telemetry.trackEvent(telemetryItem); + } + + static convertErrorIntoExceptionData(error: Error): Record { + 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; + } + + static sanitizeAny(data: any): any { + if (Array.isArray(data)) { + // This is an array, sanitize each element recursively. + return data.map(item => Telemetry.sanitizeAny(item)); + } else if (typeof data === 'object' && data !== null) { + // This is an object, sanitize each field recursively. + const sanitizedObject: Record = {}; + for (const key in data) { + if (Object.prototype.hasOwnProperty.call(data, key)) { + sanitizedObject[key] = Telemetry.sanitizeAny(data[key]); + } + } + return sanitizedObject; + } else if (typeof data === 'string') { + // The base case: this is a string, sanitize it. + return errorUtils.sanitizeErrorMessage(data); + } + + // Not a string, return the data unchanged. + return data; } } 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..1db8560608b 100644 --- a/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts +++ b/packages/@react-native-windows/telemetry/src/test/basePropUtils.test.ts @@ -32,8 +32,15 @@ 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(); @@ -67,12 +74,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 +136,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(); +}); 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..1f982ef21af 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/test/nameUtils.test.ts b/packages/@react-native-windows/telemetry/src/test/nameUtils.test.ts new file mode 100644 index 00000000000..e5c3cf49789 --- /dev/null +++ b/packages/@react-native-windows/telemetry/src/test/nameUtils.test.ts @@ -0,0 +1,62 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * + * @format + */ + +import * as nameUtils from '../utils/nameUtils'; + +test('Verify telemetry package name is valid', () => { + expect(nameUtils.isValidTelemetryPackageName('package')).toBe(true); + expect(nameUtils.isValidTelemetryPackageName('@react')).toBe(false); + expect(nameUtils.isValidTelemetryPackageName('react-native')).toBe(false); + expect(nameUtils.isValidTelemetryPackageName('react_native')).toBe(true); + expect(nameUtils.isValidTelemetryPackageName('react_native/cli')).toBe(false); + + // Check for size limits. A valid package name has 100 characters or less. + expect( + nameUtils.isValidTelemetryPackageName( + 'react_native_react_native_react_native_react_native_react_native_react_native_react_native_react_nat', + ), + ).toBe(true); + expect( + nameUtils.isValidTelemetryPackageName( + 'react_native_react_native_react_native_react_native_react_native_react_native_react_native_react_nati', + ), + ).toBe(false); +}); + +test('Verify telemetry package name cleaning', () => { + expect(nameUtils.cleanTelemetryPackageName('package')).toBe('package'); + expect(nameUtils.cleanTelemetryPackageName('@react')).toBe('_react'); + expect(nameUtils.cleanTelemetryPackageName('react-native')).toBe( + 'react_native', + ); + expect(nameUtils.cleanTelemetryPackageName('react_native')).toBe( + 'react_native', + ); + expect(nameUtils.cleanTelemetryPackageName('react_native/cli')).toBe( + 'react_native_cli', + ); + expect(nameUtils.cleanTelemetryPackageName('@react-native-windows/cli')).toBe( + '_react_native_windows_cli', + ); + + expect( + nameUtils.cleanTelemetryPackageName( + 'react_native_react_native_react_native_react_native_react_native_react_native_react_native_react_nat', + ), + ).toBe( + 'react_native_react_native_react_native_react_native_react_native_react_native_react_native_react_nat', + ); + + // Truncate a package name with 101 characters, to the first 100. + expect( + nameUtils.cleanTelemetryPackageName( + 'react_native_react_native_react_native_react_native_react_native_react_native_react_native_react_nati', + ), + ).toBe( + 'react_native_react_native_react_native_react_native_react_native_react_native_react_native_react_nat', + ); +}); diff --git a/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts b/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts index d3dc4bf73e7..807fcd1bf49 100644 --- a/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/basePropUtils.ts @@ -14,20 +14,44 @@ 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 {} + + return ''; +} - const result = output.match(/\{([0-9A-Fa-f-]{36})\}/); +/** + * 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 +59,27 @@ 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 +104,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 +173,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..570ea0ea04c 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. @@ -155,17 +160,19 @@ export function sanitizeErrorMessage(msg: string): string { * Sanitizes an error stack frame. * @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 +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(); + } 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/nameUtils.ts b/packages/@react-native-windows/telemetry/src/utils/nameUtils.ts new file mode 100644 index 00000000000..31c5c563ce1 --- /dev/null +++ b/packages/@react-native-windows/telemetry/src/utils/nameUtils.ts @@ -0,0 +1,18 @@ +/** + * Copyright (c) Microsoft Corporation. + * Licensed under the MIT License. + * @format + */ + +export function isValidTelemetryPackageName(name: string): boolean { + // Accepted characters: alphanumeric, underscore, dot, starts with letter. + // Size: 1-100 characters. + if (name.match(/^[a-zA-Z][a-zA-Z0-9_.]{0,99}$/gi)) { + return true; + } + return false; +} + +export function cleanTelemetryPackageName(str: string): string { + return str.replace(/[^a-zA-Z0-9_.]/g, '_').slice(0, 100); +} diff --git a/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts b/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts index 1314988e0d9..f92cb1e350e 100644 --- a/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts +++ b/packages/@react-native-windows/telemetry/src/utils/sanitizeUtils.ts @@ -24,9 +24,13 @@ 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/vnext/PropertySheets/OutputMSBuildProperties.targets b/vnext/PropertySheets/OutputMSBuildProperties.targets index ebb0f3714ff..dd1b7cf6d04 100644 --- a/vnext/PropertySheets/OutputMSBuildProperties.targets +++ b/vnext/PropertySheets/OutputMSBuildProperties.targets @@ -18,7 +18,9 @@ "WindowsTargetPlatformVersion": "$(WindowsTargetPlatformVersion)", "UseExperimentalNuGet": "$(UseExperimentalNuGet)", "UseHermes": "$(UseHermes)", - "UseWinUI3": "$(UseWinUI3)" + "UseWinUI3": "$(UseWinUI3)", + "UseFabric": "$(UseFabric)", + "RnwNewArch": "$(RnwNewArch)" } diff --git a/yarn.lock b/yarn.lock index 88fb38c002f..fe8113f54be 100644 --- a/yarn.lock +++ b/yarn.lock @@ -38,79 +38,20 @@ "@azure/core-util" "^1.1.0" tslib "^2.2.0" -"@azure/core-auth@^1.4.0", "@azure/core-auth@^1.5.0": - version "1.6.0" - resolved "https://registry.yarnpkg.com/@azure/core-auth/-/core-auth-1.6.0.tgz#1dd09338db12f39d45416746e23d44d76e05ecf8" - integrity sha512-3X9wzaaGgRaBCwhLQZDtFp5uLIXCPrGbwJNWPPugvL4xbIGgScv77YzzxToKGLAKvG9amDoofMoP+9hsH1vs1w== - dependencies: - "@azure/abort-controller" "^2.0.0" - "@azure/core-util" "^1.1.0" - tslib "^2.2.0" - -"@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.0.1" - resolved "https://registry.yarnpkg.com/@azure/core-tracing/-/core-tracing-1.0.1.tgz#352a38cbea438c4a83c86b314f48017d70ba9503" - integrity sha512-I5CGMoLtX+pI17ZdiFJZgxMJApsK6jjfm85hpgp3oazCdq5Wxgh4wMr7ge/TTWW1B5WBuvIOI1fMU/FrOAMKrw== - dependencies: - tslib "^2.2.0" - -"@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": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@azure/core-util/-/core-util-1.7.0.tgz#3a2f73e8c7eed0666e8b6ff9ca2c1951e175feba" - integrity sha512-Zq2i3QO6k9DA8vnm29mYM4G8IE9u1mhF1GUabVEqPNX8Lj833gdxQ2NAFxt2BZsfAL+e9cT8SyVN7dFVJ/Hf0g== +"@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== dependencies: "@azure/abort-controller" "^2.0.0" - tslib "^2.2.0" - -"@azure/logger@^1.0.0": - version "1.0.4" - resolved "https://registry.yarnpkg.com/@azure/logger/-/logger-1.0.4.tgz#28bc6d0e5b3c38ef29296b32d35da4e483593fa1" - integrity sha512-ustrPY8MryhloQj7OWGe+HrYx+aoiOxzbXTtgblbV3xwCqpzUK36phH3XNHQKj3EPonyFUuDTfR3qFhTEAuZEg== - dependencies: - tslib "^2.2.0" - -"@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" + 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": - 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== + 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.24.7": @@ -430,6 +371,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.22.15", "@babel/helper-validator-option@^7.24.7": version "7.24.7" resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz#24c3bb77c7a425d1742eec8fb433b5a1b38e62f6" @@ -453,12 +399,12 @@ "@babel/template" "^7.24.7" "@babel/types" "^7.24.7" -"@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" @@ -1914,25 +1860,37 @@ resolved "https://registry.yarnpkg.com/@kwsites/promise-deferred/-/promise-deferred-1.1.1.tgz#8ace5259254426ccef57f3175bc64ed7095ed919" integrity sha512-GaHYm+c0O9MjZRu0ongGBRbinu8gVAMd2UZjji6jVmqKtZluZnptXGWhz1E8j8D2HJ3f/yMxKAUC0b+57wncIw== -"@microsoft/applicationinsights-common@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-common/-/applicationinsights-common-3.1.0.tgz#df265a8b1832975fa197ec6322bc24fd5f123665" - integrity sha512-PpWdCbTPsH5MSDIkHKaIBpEJcsnPcnAjlTCk+ls0DOfIB/T6bTn3TuKsDfSu/sxdLhDQiJeUXu8G3qOQ3L0nBA== +"@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.1.0" + "@microsoft/applicationinsights-core-js" "3.3.0" "@microsoft/applicationinsights-shims" "3.0.1" "@microsoft/dynamicproto-js" "^2.0.3" - "@nevware21/ts-utils" ">= 0.10.5 < 2.x" + "@nevware21/ts-async" ">= 0.5.2 < 2.x" + "@nevware21/ts-utils" ">= 0.11.3 < 2.x" -"@microsoft/applicationinsights-core-js@3.1.0": - version "3.1.0" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-core-js/-/applicationinsights-core-js-3.1.0.tgz#f8ef9fe591044c3df4dce9f8f242c4fe8be1820c" - integrity sha512-pHaZ3CQx+KdfRV3yV/xuMEvIEJ1KxlK6klnFcuz4AMXOOPeuvWy1FsUIQ/sVA97TXEDl87LqV6QDnH99bLZpMg== +"@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.3.0 < 2.x" - "@nevware21/ts-utils" ">= 0.10.5 < 2.x" + "@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" @@ -1941,14 +1899,6 @@ dependencies: "@nevware21/ts-utils" ">= 0.9.4 < 2.x" -"@microsoft/applicationinsights-web-snippet@^1.0.1": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@microsoft/applicationinsights-web-snippet/-/applicationinsights-web-snippet-1.1.0.tgz#3352edb2f16aed82139baf086c90b1ef114fecc8" - integrity sha512-4P/5kSwJKvugTA0V01Or8sRagAgUnCUHx3TMIdsT9bzCP5Zm0gkqS81l3HlD81z5z49g54FVPEDJDAGuJy3/Gw== - dependencies: - "@microsoft/applicationinsights-common" "3.1.0" - "@microsoft/dynamicproto-js" "^2.0.3" - "@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" @@ -1965,18 +1915,23 @@ eslint-plugin-react "7.33.0" eslint-plugin-security "1.4.0" -"@nevware21/ts-async@>= 0.3.0 < 2.x": - version "0.4.0" - resolved "https://registry.yarnpkg.com/@nevware21/ts-async/-/ts-async-0.4.0.tgz#2a581f0dd436379ec9f448cfab9e5a6a4c349d11" - integrity sha512-dbV826TTehQIBIJjh8GDSbwn1Z6+cnkyNbRlpcpdBPH8mROD2zabIUKqWcw9WRdTjjUIm21K+OR4DXWlAyOVTQ== +"@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.10.0 < 2.x" + "@nevware21/ts-utils" ">= 0.11.3 < 2.x" -"@nevware21/ts-utils@>= 0.10.0 < 2.x", "@nevware21/ts-utils@>= 0.10.4 < 2.x", "@nevware21/ts-utils@>= 0.10.5 < 2.x", "@nevware21/ts-utils@>= 0.9.4 < 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" @@ -2122,51 +2077,6 @@ dependencies: "@octokit/openapi-types" "^12.11.0" -"@opentelemetry/api@^1.4.1": - version "1.7.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/api/-/api-1.7.0.tgz#b139c81999c23e3c8d3c0a7234480e945920fc40" - integrity sha512-AdY5wvN0P2vXBi3b29hxZgSFvdhdxPB9+f0B6s//P9Q8nibRWeA3cHm8UmLpio9ABigkVHJ5NMPk+Mz8VCCyrw== - -"@opentelemetry/core@1.21.0", "@opentelemetry/core@^1.15.2": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/core/-/core-1.21.0.tgz#8c16faf16edf861b073c03c9d45977b3f4003ee1" - integrity sha512-KP+OIweb3wYoP7qTYL/j5IpOlu52uxBv5M4+QhSmmUfLyTgu1OIS71msK3chFo1D6Y61BIH3wMiMYRCxJCQctA== - dependencies: - "@opentelemetry/semantic-conventions" "1.21.0" - -"@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.21.0": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/resources/-/resources-1.21.0.tgz#e773e918cc8ca26493a987dfbfc6b8a315a2ab45" - integrity sha512-1Z86FUxPKL6zWVy2LdhueEGl9AHDJcx+bvHStxomruz6Whd02mE3lNUMjVJ+FGRoktx/xYQcxccYb03DiUP6Yw== - dependencies: - "@opentelemetry/core" "1.21.0" - "@opentelemetry/semantic-conventions" "1.21.0" - -"@opentelemetry/sdk-trace-base@^1.15.2": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/sdk-trace-base/-/sdk-trace-base-1.21.0.tgz#ffad912e453a92044fb220bd5d2f6743bf37bb8a" - integrity sha512-yrElGX5Fv0umzp8Nxpta/XqU71+jCAyaLk34GmBzNcrW43nqbrqvdPs4gj4MVy/HcTjr6hifCDCYA3rMkajxxA== - dependencies: - "@opentelemetry/core" "1.21.0" - "@opentelemetry/resources" "1.21.0" - "@opentelemetry/semantic-conventions" "1.21.0" - -"@opentelemetry/semantic-conventions@1.21.0", "@opentelemetry/semantic-conventions@^1.15.2": - version "1.21.0" - resolved "https://registry.yarnpkg.com/@opentelemetry/semantic-conventions/-/semantic-conventions-1.21.0.tgz#83f7479c524ab523ac2df702ade30b9724476c72" - integrity sha512-lkC8kZYntxVKr7b8xmjCVUgE0a8xgDakPyDo9uSWavXPyYqLgYYGdEd2j8NxihRyb6UwpX3G/hFUF4/9q2V+/g== - "@pkgjs/parseargs@^0.11.0": version "0.11.0" resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" @@ -2879,11 +2789,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" @@ -3243,11 +3148,6 @@ "@types/glob" "~7.2.0" "@types/node" "*" -"@types/shimmer@^1.0.2": - version "1.0.5" - resolved "https://registry.yarnpkg.com/@types/shimmer/-/shimmer-1.0.5.tgz#491d8984d4510e550bfeb02d518791d7f59d2b88" - integrity sha512-9Hp0ObzwwO57DpLFF0InUjUm/II8GmKAvzbefxQTihCb7KI6yc9yzf0nLc4mVdby5N4DRCgQM2wCup9KTieeww== - "@types/ssri@*": version "7.1.5" resolved "https://registry.yarnpkg.com/@types/ssri/-/ssri-7.1.5.tgz#7147b5ba43957cb0f639a3309a3943fc1829d5e8" @@ -3703,11 +3603,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" @@ -3847,25 +3742,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" @@ -4158,26 +4034,11 @@ async-done@^2.0.0: once "^1.4.0" stream-exhaust "^1.0.2" -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@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/async-settle/-/async-settle-1.0.0.tgz#1d0a914bb02575bec8a8f3a74e5080f72b2c0c6b" @@ -4893,10 +4754,10 @@ 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: - version "1.2.3" - resolved "https://registry.yarnpkg.com/cjs-module-lexer/-/cjs-module-lexer-1.2.3.tgz#6c370ab19f8a3394e318fe682686ec0ac684d107" - integrity sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ== +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== clang-format@^1.7.0, clang-format@^1.8.0: version "1.8.0" @@ -5000,15 +4861,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" @@ -5184,14 +5036,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" @@ -5561,18 +5405,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" @@ -5647,13 +5479,6 @@ electron-to-chromium@^1.4.668: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.673.tgz#1f077d9a095761804aec7ec6346c3f4b69b56534" integrity sha512-zjqzx4N7xGdl5468G+vcgzDhaHkaYgVcf9MqgexcTqsl2UHSCmOj/Bi3HAprg4BZCpC7HyD8a6nZl6QAZf72gw== -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" @@ -7269,15 +7094,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: version "7.0.2" resolved "https://registry.yarnpkg.com/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz#9a8b1f246866c028509486585f62b8f2c18c270e" @@ -7412,16 +7228,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" @@ -9403,11 +9209,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" @@ -10691,15 +10492,6 @@ require-directory@^2.1.1: resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== -require-in-the-middle@^7.1.1: - version "7.2.0" - resolved "https://registry.yarnpkg.com/require-in-the-middle/-/require-in-the-middle-7.2.0.tgz#b539de8f00955444dc8aed95e17c69b0a4f10fcf" - integrity sha512-3TLx5TGyAY6AOqLBoXmHkNql0HIf2RGbuMgCDT2WO/uGVAPJs6h7Kl+bN6TIZGd9bWhWPwnDnTHGtW8Iu77sdw== - dependencies: - debug "^4.1.1" - module-details-from-path "^1.0.3" - resolve "^1.22.1" - 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" @@ -10750,7 +10542,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.1, resolve@^1.22.3, 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== @@ -10960,12 +10752,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: - version "7.6.2" - resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.2.tgz#1e3b34759f896e8f14d6134732ce798aeb0c6e13" - integrity sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w== +"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: + 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== @@ -11112,17 +10904,12 @@ 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: - version "1.0.5" - resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.5.tgz#9a84546599b48909fb6af1211708d23b1946221b" - integrity sha512-QcgiIWV4WV7qWExbN5llt6frQB/lBven9pqliLXfGPB+K9ZYXxDozp0wLkHS24kWCm+6YXH/f0HhnObZnZOBnQ== + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== dependencies: - call-bind "^1.0.6" + call-bind "^1.0.7" es-errors "^1.3.0" get-intrinsic "^1.2.4" object-inspect "^1.13.1" @@ -11295,11 +11082,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" @@ -11744,6 +11526,11 @@ tslib@^2.0.1, tslib@^2.2.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.6.2: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tslint@5.14.0: version "5.14.0" resolved "https://registry.yarnpkg.com/tslint/-/tslint-5.14.0.tgz#be62637135ac244fc9b37ed6ea5252c9eba1616e"