@react-native-windows/telemetry
Advanced tools
Comparing version
@@ -39,2 +39,9 @@ "use strict"; | ||
const versionUtils = __importStar(require("../utils/versionUtils")); | ||
class CustomTestError extends Error { | ||
constructor(message) { | ||
super(message); | ||
this.name = 'CustomTestError'; | ||
this.errno = '123'; | ||
} | ||
} | ||
class TelemetryTest extends telemetry_1.Telemetry { | ||
@@ -322,3 +329,9 @@ /** Run at the beginning of each test. */ | ||
: 'Unknown'); | ||
expect(codedError.data).toStrictEqual((_a = expectedError.data) !== null && _a !== void 0 ? _a : {}); | ||
// 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((_a = expectedError.data) !== null && _a !== void 0 ? _a : expectedCodedErrorData); | ||
} | ||
@@ -491,2 +504,74 @@ else { | ||
}); | ||
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 = []; | ||
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', | ||
fieldWithNoPath: 'Test Error data', | ||
fieldWithNoString: 14, | ||
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', | ||
fieldWithNoPath: 'Test Error data 2', | ||
fieldWithNoString: 16, | ||
nestedObject: { | ||
fieldWithPath: 'Test Error occurred at C:\\some\\file\\path4\\project.build.appxrecipe', | ||
fieldWithNoPath: 'Test Error data 3', | ||
fieldWithNoString: 17, // expectation: no changes to this value. | ||
}, | ||
}, | ||
}); | ||
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, | ||
}, | ||
}, | ||
}); | ||
const caughtErrors = []; | ||
TelemetryTest.addTelemetryInitializer(verifyTestCommandTelemetryProcessor(caughtErrors, expectedError.type, expectedError)); | ||
await runTestCommandE2E(() => testCommandBody(codedErrorInfo)); | ||
TelemetryTest.endTest(() => { | ||
// Check if any errors were thrown | ||
expect(caughtErrors).toHaveLength(0); | ||
}); | ||
}); | ||
//# sourceMappingURL=telemetry.test.js.map |
@@ -73,3 +73,4 @@ /** | ||
static convertErrorIntoExceptionData(error: Error): Record<string, any>; | ||
static sanitizeAny(data: any): any; | ||
} | ||
export {}; |
@@ -37,2 +37,3 @@ "use strict"; | ||
const errorUtils = __importStar(require("./utils/errorUtils")); | ||
const nameUtils = __importStar(require("./utils/nameUtils")); | ||
// 1DS instrumentation key | ||
@@ -184,6 +185,10 @@ const RNW_1DS_INSTRUMENTATION_KEY = '49ff6d3ef12f4578a7b75a2573d9dba8-026332b2-2d50-452f-ad0d-50f921c97a9d-7145'; | ||
} | ||
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; | ||
@@ -338,5 +343,7 @@ } | ||
if (error[f]) { | ||
codedErrorStruct.data.codedError.data[f] = error[f]; | ||
codedErrorStruct.data[f] = error[f]; | ||
} | ||
} | ||
// Scrub any potential PII present in codedError.data array, as long as the data is a string. | ||
codedErrorStruct.data = Telemetry.sanitizeAny(codedErrorStruct.data); | ||
// Break down TS Error object into Exception Data | ||
@@ -393,2 +400,24 @@ const exceptionData = Telemetry.convertErrorIntoExceptionData(error); | ||
} | ||
static sanitizeAny(data) { | ||
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 = {}; | ||
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; | ||
} | ||
} | ||
@@ -395,0 +424,0 @@ Telemetry.appInsightsCore = undefined; |
{ | ||
"name": "@react-native-windows/telemetry", | ||
"version": "0.76.0", | ||
"version": "0.76.1", | ||
"license": "MIT", | ||
@@ -5,0 +5,0 @@ "main": "lib-commonjs/index.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
307312
8.3%50
13.64%3122
7.03%