@react-native-windows/telemetry 0.0.0-canary.24 → 0.0.0-canary.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. package/lib-commonjs/index.d.ts +4 -2
  2. package/lib-commonjs/index.js +12 -6
  3. package/lib-commonjs/index.js.map +1 -1
  4. package/lib-commonjs/telemetry.d.ts +70 -20
  5. package/lib-commonjs/telemetry.js +254 -170
  6. package/lib-commonjs/telemetry.js.map +1 -1
  7. package/lib-commonjs/test/{sanitize.test.d.ts → basePropUtils.test.d.ts} +0 -0
  8. package/lib-commonjs/test/basePropUtils.test.js +116 -0
  9. package/lib-commonjs/test/basePropUtils.test.js.map +1 -0
  10. package/lib-commonjs/test/errorUtils.test.d.ts +7 -0
  11. package/lib-commonjs/test/errorUtils.test.js +161 -0
  12. package/lib-commonjs/test/errorUtils.test.js.map +1 -0
  13. package/lib-commonjs/test/projectUtils.test.d.ts +7 -0
  14. package/lib-commonjs/test/projectUtils.test.js +84 -0
  15. package/lib-commonjs/test/projectUtils.test.js.map +1 -0
  16. package/lib-commonjs/test/sanitizeUtils.test.d.ts +7 -0
  17. package/lib-commonjs/test/sanitizeUtils.test.js +88 -0
  18. package/lib-commonjs/test/sanitizeUtils.test.js.map +1 -0
  19. package/lib-commonjs/test/telemetry.test.d.ts +26 -0
  20. package/lib-commonjs/test/telemetry.test.js +469 -0
  21. package/lib-commonjs/test/telemetry.test.js.map +1 -0
  22. package/lib-commonjs/test/versionUtils.test.d.ts +7 -0
  23. package/lib-commonjs/test/versionUtils.test.js +122 -0
  24. package/lib-commonjs/test/versionUtils.test.js.map +1 -0
  25. package/lib-commonjs/utils/basePropUtils.d.ts +66 -0
  26. package/lib-commonjs/utils/basePropUtils.js +133 -0
  27. package/lib-commonjs/utils/basePropUtils.js.map +1 -0
  28. package/lib-commonjs/{CodedError.d.ts → utils/errorUtils.d.ts} +27 -8
  29. package/lib-commonjs/utils/errorUtils.js +164 -0
  30. package/lib-commonjs/utils/errorUtils.js.map +1 -0
  31. package/lib-commonjs/utils/optionUtils.d.ts +45 -0
  32. package/lib-commonjs/utils/optionUtils.js +96 -0
  33. package/lib-commonjs/utils/optionUtils.js.map +1 -0
  34. package/lib-commonjs/utils/projectUtils.d.ts +50 -0
  35. package/lib-commonjs/utils/projectUtils.js +187 -0
  36. package/lib-commonjs/utils/projectUtils.js.map +1 -0
  37. package/lib-commonjs/utils/sanitizeUtils.d.ts +12 -0
  38. package/lib-commonjs/utils/sanitizeUtils.js +80 -0
  39. package/lib-commonjs/utils/sanitizeUtils.js.map +1 -0
  40. package/lib-commonjs/utils/versionUtils.d.ts +38 -0
  41. package/lib-commonjs/utils/versionUtils.js +159 -0
  42. package/lib-commonjs/utils/versionUtils.js.map +1 -0
  43. package/package.json +14 -3
  44. package/CHANGELOG.json +0 -543
  45. package/CHANGELOG.md +0 -220
  46. package/lib-commonjs/CodedError.js +0 -77
  47. package/lib-commonjs/CodedError.js.map +0 -1
  48. package/lib-commonjs/test/sanitize.test.js +0 -259
  49. package/lib-commonjs/test/sanitize.test.js.map +0 -1
@@ -3,5 +3,7 @@
3
3
  * Licensed under the MIT License.
4
4
  * @format
5
5
  */
6
- export { Telemetry, isMSFTInternal, getDiskFreeSpace } from './telemetry';
7
- export { CodedError, CodedErrorType, CodedErrors } from './CodedError';
6
+ export { Telemetry, TelemetryOptions, CommandStartInfo, CommandEndInfo, } from './telemetry';
7
+ export { CodedError, CodedErrorType, CodedErrors } from './utils/errorUtils';
8
+ export { yargsOptionsToOptions, commanderNameToOptionName, commanderOptionsToOptions, optionsToArgs, OptionSanitizer, YargsOptionsType, CommanderOptionsType, } from './utils/optionUtils';
9
+ export { configToProjectInfo, getProjectFileFromConfig, AppProjectInfo, DependencyProjectInfo, } from './utils/projectUtils';
@@ -5,12 +5,18 @@
5
5
  * @format
6
6
  */
7
7
  Object.defineProperty(exports, "__esModule", { value: true });
8
- exports.CodedErrors = exports.CodedError = exports.getDiskFreeSpace = exports.isMSFTInternal = exports.Telemetry = void 0;
8
+ exports.getProjectFileFromConfig = exports.configToProjectInfo = exports.optionsToArgs = exports.commanderOptionsToOptions = exports.commanderNameToOptionName = exports.yargsOptionsToOptions = exports.CodedErrors = exports.CodedError = exports.Telemetry = void 0;
9
9
  var telemetry_1 = require("./telemetry");
10
10
  Object.defineProperty(exports, "Telemetry", { enumerable: true, get: function () { return telemetry_1.Telemetry; } });
11
- Object.defineProperty(exports, "isMSFTInternal", { enumerable: true, get: function () { return telemetry_1.isMSFTInternal; } });
12
- Object.defineProperty(exports, "getDiskFreeSpace", { enumerable: true, get: function () { return telemetry_1.getDiskFreeSpace; } });
13
- var CodedError_1 = require("./CodedError");
14
- Object.defineProperty(exports, "CodedError", { enumerable: true, get: function () { return CodedError_1.CodedError; } });
15
- Object.defineProperty(exports, "CodedErrors", { enumerable: true, get: function () { return CodedError_1.CodedErrors; } });
11
+ var errorUtils_1 = require("./utils/errorUtils");
12
+ Object.defineProperty(exports, "CodedError", { enumerable: true, get: function () { return errorUtils_1.CodedError; } });
13
+ Object.defineProperty(exports, "CodedErrors", { enumerable: true, get: function () { return errorUtils_1.CodedErrors; } });
14
+ var optionUtils_1 = require("./utils/optionUtils");
15
+ Object.defineProperty(exports, "yargsOptionsToOptions", { enumerable: true, get: function () { return optionUtils_1.yargsOptionsToOptions; } });
16
+ Object.defineProperty(exports, "commanderNameToOptionName", { enumerable: true, get: function () { return optionUtils_1.commanderNameToOptionName; } });
17
+ Object.defineProperty(exports, "commanderOptionsToOptions", { enumerable: true, get: function () { return optionUtils_1.commanderOptionsToOptions; } });
18
+ Object.defineProperty(exports, "optionsToArgs", { enumerable: true, get: function () { return optionUtils_1.optionsToArgs; } });
19
+ var projectUtils_1 = require("./utils/projectUtils");
20
+ Object.defineProperty(exports, "configToProjectInfo", { enumerable: true, get: function () { return projectUtils_1.configToProjectInfo; } });
21
+ Object.defineProperty(exports, "getProjectFileFromConfig", { enumerable: true, get: function () { return projectUtils_1.getProjectFileFromConfig; } });
16
22
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,yCAAwE;AAAhE,sGAAA,SAAS,OAAA;AAAE,2GAAA,cAAc,OAAA;AAAE,6GAAA,gBAAgB,OAAA;AACnD,2CAAqE;AAA7D,wGAAA,UAAU,OAAA;AAAkB,yGAAA,WAAW,OAAA","sourcesContent":["/**\n * Copyright (c) Microsoft Corporation.\n * Licensed under the MIT License.\n * @format\n */\n\nexport {Telemetry, isMSFTInternal, getDiskFreeSpace} from './telemetry';\nexport {CodedError, CodedErrorType, CodedErrors} from './CodedError';\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;GAIG;;;AAEH,yCAKqB;AAJnB,sGAAA,SAAS,OAAA;AAMX,iDAA2E;AAAnE,wGAAA,UAAU,OAAA;AAAkB,yGAAA,WAAW,OAAA;AAE/C,mDAQ6B;AAP3B,oHAAA,qBAAqB,OAAA;AACrB,wHAAA,yBAAyB,OAAA;AACzB,wHAAA,yBAAyB,OAAA;AACzB,4GAAA,aAAa,OAAA;AAMf,qDAK8B;AAJ5B,mHAAA,mBAAmB,OAAA;AACnB,wHAAA,wBAAwB,OAAA","sourcesContent":["/**\n * Copyright (c) Microsoft Corporation.\n * Licensed under the MIT License.\n * @format\n */\n\nexport {\n Telemetry,\n TelemetryOptions,\n CommandStartInfo,\n CommandEndInfo,\n} from './telemetry';\n\nexport {CodedError, CodedErrorType, CodedErrors} from './utils/errorUtils';\n\nexport {\n yargsOptionsToOptions,\n commanderNameToOptionName,\n commanderOptionsToOptions,\n optionsToArgs,\n OptionSanitizer,\n YargsOptionsType,\n CommanderOptionsType,\n} from './utils/optionUtils';\n\nexport {\n configToProjectInfo,\n getProjectFileFromConfig,\n AppProjectInfo,\n DependencyProjectInfo,\n} from './utils/projectUtils';\n"]}
@@ -4,26 +4,76 @@
4
4
  * @format
5
5
  */
6
6
  import * as appInsights from 'applicationinsights';
7
- export declare class Telemetry {
8
- static client?: appInsights.TelemetryClient | undefined;
9
- static disable(): void;
10
- static setup(preserveMessages?: boolean): void;
11
- static isCI(): boolean;
12
- static trackException(e: Error, properties?: Record<string, any>): void;
13
- static shouldDisable: boolean;
14
- static preserveMessages: boolean;
7
+ import * as errorUtils from './utils/errorUtils';
8
+ import * as projectUtils from './utils/projectUtils';
9
+ export interface TelemetryOptions {
10
+ setupString: string;
11
+ preserveErrorMessages: boolean;
15
12
  }
13
+ export interface CommandStartInfo {
14
+ commandName: string;
15
+ args: Record<string, any>;
16
+ options: Record<string, any>;
17
+ defaultOptions: Record<string, any>;
18
+ }
19
+ export interface CommandEndInfo {
20
+ resultCode: errorUtils.CodedErrorType;
21
+ }
22
+ interface CommandInfo {
23
+ startTime?: number;
24
+ endTime?: number;
25
+ startInfo?: CommandStartInfo;
26
+ endInfo?: CommandEndInfo;
27
+ }
28
+ export declare const NpmPackagesWeTrack: string[];
29
+ export declare const NuGetPackagesWeTrack: string[];
16
30
  /**
17
- * Sanitize any paths that appear between quotes (''), brackets ([]), or double quotes ("").
18
- * @param msg the string to sanitize
19
- */
20
- export declare function sanitizeMessage(msg: string): string;
21
- export declare function sanitizeFrame(frame: any): void;
22
- export declare function tryGetErrorCode(msg: string): string | undefined;
23
- /**
24
- * Remove PII from exceptions' stack traces and messages
25
- * @param envelope the telemetry envelope. Provided by AppInsights.
31
+ * The Telemetry class is responsible for reporting telemetry for RNW CLI.
26
32
  */
27
- export declare function sanitizeEnvelope(envelope: any): boolean;
28
- export declare function isMSFTInternal(): boolean;
29
- export declare function getDiskFreeSpace(drivePath: string | null): number;
33
+ export declare class Telemetry {
34
+ protected static client?: appInsights.TelemetryClient;
35
+ protected static options: TelemetryOptions;
36
+ protected static isTest: boolean;
37
+ protected static commandInfo: CommandInfo;
38
+ protected static versionsProp: Record<string, string>;
39
+ protected static projectProp?: projectUtils.AppProjectInfo | projectUtils.DependencyProjectInfo;
40
+ protected static reset(): void;
41
+ static isEnabled(): boolean;
42
+ static getSessionId(): string;
43
+ /** Sets up the Telemetry static to be used elsewhere. */
44
+ static setup(options?: Partial<TelemetryOptions>): Promise<void>;
45
+ /** Sets up Telemetry.client. */
46
+ private static setupClient;
47
+ /** Sets up any base properties that all telemetry events require. */
48
+ private static setupBaseProperties;
49
+ /** Sets up any telemetry processors. */
50
+ private static setupTelemetryProcessors;
51
+ /**
52
+ * Performs the processing necessary (mostly PII sanitization) for all events.
53
+ * @param envelope The ApplicationInsights event envelope.
54
+ * @param _contextObjects An optional context object.
55
+ * @returns Whether to kee
56
+ */
57
+ private static basicTelemetryProcessor;
58
+ /**
59
+ * Performs the processing necessary (mostly PII sanitization) for error events.
60
+ * @param envelope
61
+ * @param _contextObjects
62
+ * @returns
63
+ */
64
+ private static errorTelemetryProcessor;
65
+ /** Tries to update the version of the named package/tool by calling getValue(). */
66
+ static tryUpdateVersionsProp(name: string, getValue: () => Promise<string | null>, forceRefresh?: boolean): Promise<boolean>;
67
+ /** Populates the versions property of tools we care to track. */
68
+ static populateToolsVersions(refresh?: boolean): Promise<void>;
69
+ /** Populates the versions property of npm packages we care to track. */
70
+ static populateNpmPackageVersions(refresh?: boolean): Promise<void>;
71
+ /** Populates the versions property of nuget packages we care to track. */
72
+ static populateNuGetPackageVersions(projectFile: string, refresh?: boolean): Promise<void>;
73
+ static setProjectInfo(info: projectUtils.AppProjectInfo | projectUtils.DependencyProjectInfo): void;
74
+ static startCommand(info: CommandStartInfo): void;
75
+ static endCommand(info: CommandEndInfo, extraProps?: Record<string, any>): void;
76
+ private static trackCommandEvent;
77
+ static trackException(error: Error, extraProps?: Record<string, any>): void;
78
+ }
79
+ export {};
@@ -23,202 +23,286 @@ var __importStar = (this && this.__importStar) || function (mod) {
23
23
  __setModuleDefault(result, mod);
24
24
  return result;
25
25
  };
26
- var __importDefault = (this && this.__importDefault) || function (mod) {
27
- return (mod && mod.__esModule) ? mod : { "default": mod };
28
- };
29
26
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.getDiskFreeSpace = exports.isMSFTInternal = exports.sanitizeEnvelope = exports.tryGetErrorCode = exports.sanitizeFrame = exports.sanitizeMessage = exports.Telemetry = void 0;
31
- const path_1 = __importDefault(require("path"));
32
- const crypto_1 = require("crypto");
27
+ exports.Telemetry = exports.NuGetPackagesWeTrack = exports.NpmPackagesWeTrack = void 0;
33
28
  const appInsights = __importStar(require("applicationinsights"));
34
- const child_process_1 = require("child_process");
35
- const CodedError_1 = require("./CodedError");
29
+ const basePropUtils = __importStar(require("./utils/basePropUtils"));
30
+ const versionUtils = __importStar(require("./utils/versionUtils"));
31
+ const errorUtils = __importStar(require("./utils/errorUtils"));
32
+ // This is our key with the AI backend
33
+ const DefaultSetupString = '795006ca-cf54-40ee-8bc6-03deb91401c3';
34
+ // These are NPM packages we care about, in terms of capturing versions used
35
+ // and getting more details about when reporting errors
36
+ exports.NpmPackagesWeTrack = [
37
+ '@react-native-community/cli',
38
+ '@react-native-windows/cli',
39
+ '@react-native-windows/telemetry',
40
+ 'react',
41
+ 'react-native',
42
+ 'react-native-windows',
43
+ 'react-native-windows-init',
44
+ ];
45
+ // These are NPM packages we care about, in terms of capturing versions used
46
+ exports.NuGetPackagesWeTrack = [
47
+ 'Microsoft.UI.Xaml',
48
+ 'Microsoft.Windows.CppWinRT',
49
+ 'Microsoft.WinUI',
50
+ ];
51
+ /**
52
+ * The Telemetry class is responsible for reporting telemetry for RNW CLI.
53
+ */
36
54
  class Telemetry {
37
- static disable() {
55
+ static reset() {
56
+ // Reset client
38
57
  if (Telemetry.client) {
39
- Telemetry.client.config.disableAppInsights = true;
58
+ Telemetry.client.flush();
59
+ Telemetry.client = undefined;
40
60
  }
41
- Telemetry.shouldDisable = true;
61
+ // Reset local members
62
+ Telemetry.options = {
63
+ setupString: DefaultSetupString,
64
+ preserveErrorMessages: false,
65
+ };
66
+ Telemetry.commandInfo = {};
67
+ Telemetry.versionsProp = {};
68
+ Telemetry.projectProp = undefined;
69
+ }
70
+ static isEnabled() {
71
+ return Telemetry.client !== undefined;
42
72
  }
43
- static setup(preserveMessages) {
44
- if (Telemetry.isCI()) {
45
- this.disable();
73
+ static getSessionId() {
74
+ return basePropUtils.getSessionId();
75
+ }
76
+ /** Sets up the Telemetry static to be used elsewhere. */
77
+ static async setup(options) {
78
+ if (Telemetry.client) {
79
+ // Bail since we've already setup
46
80
  return;
47
81
  }
48
- if (Telemetry.client) {
82
+ // Bail if we're in CI and not capturing CI
83
+ if (!this.isTest && basePropUtils.isCI() && !basePropUtils.captureCI()) {
49
84
  return;
50
85
  }
51
- if (!process.env.RNW_CLI_TEST) {
52
- appInsights.Configuration.setInternalLogging(false, false);
86
+ // Save off options for later
87
+ Object.assign(Telemetry.options, options);
88
+ Telemetry.setupClient();
89
+ await Telemetry.setupBaseProperties();
90
+ Telemetry.setupTelemetryProcessors();
91
+ }
92
+ /** Sets up Telemetry.client. */
93
+ static setupClient() {
94
+ appInsights.Configuration.setInternalLogging(Telemetry.isTest, Telemetry.isTest);
95
+ Telemetry.client = new appInsights.TelemetryClient(Telemetry.options.setupString);
96
+ // Uncomment for Fiddler testing
97
+ // Telemetry.client.config.proxyHttpUrl = 'http://localhost:8888';
98
+ // Telemetry.client.config.proxyHttpsUrl = 'http://localhost:8888';
99
+ Telemetry.client.config.disableAppInsights = Telemetry.isTest;
100
+ Telemetry.client.channel.setUseDiskRetryCaching(!Telemetry.isTest);
101
+ }
102
+ /** Sets up any base properties that all telemetry events require. */
103
+ static async setupBaseProperties() {
104
+ Telemetry.client.commonProperties.deviceId = await basePropUtils.deviceId();
105
+ Telemetry.client.commonProperties.deviceLocale = await basePropUtils.deviceLocale();
106
+ Telemetry.client.commonProperties.deviceNumCPUs = basePropUtils
107
+ .deviceNumCPUs()
108
+ .toString();
109
+ Telemetry.client.commonProperties.deviceTotalMemory = basePropUtils
110
+ .deviceTotalMemory()
111
+ .toString();
112
+ Telemetry.client.commonProperties.deviceDiskFreeSpace = basePropUtils
113
+ .deviceDiskFreeSpace()
114
+ .toString();
115
+ Telemetry.client.commonProperties.ciCaptured = basePropUtils
116
+ .captureCI()
117
+ .toString();
118
+ Telemetry.client.commonProperties.ciType = basePropUtils.ciType();
119
+ Telemetry.client.commonProperties.isMsftInternal = basePropUtils
120
+ .isMsftInternal()
121
+ .toString();
122
+ Telemetry.client.config.samplingPercentage = basePropUtils.sampleRate();
123
+ if (Telemetry.isTest) {
124
+ Telemetry.client.commonProperties.isTest = true.toString();
53
125
  }
54
- appInsights.setup('795006ca-cf54-40ee-8bc6-03deb91401c3');
55
- Telemetry.client = appInsights.defaultClient;
56
- if (Telemetry.shouldDisable) {
57
- Telemetry.disable();
126
+ Telemetry.client.commonProperties.sessionId = Telemetry.getSessionId();
127
+ await Telemetry.populateToolsVersions();
128
+ await Telemetry.populateNpmPackageVersions();
129
+ }
130
+ /** Sets up any telemetry processors. */
131
+ static setupTelemetryProcessors() {
132
+ Telemetry.client.addTelemetryProcessor(Telemetry.basicTelemetryProcessor);
133
+ Telemetry.client.addTelemetryProcessor(Telemetry.errorTelemetryProcessor);
134
+ }
135
+ /**
136
+ * Performs the processing necessary (mostly PII sanitization) for all events.
137
+ * @param envelope The ApplicationInsights event envelope.
138
+ * @param _contextObjects An optional context object.
139
+ * @returns Whether to kee
140
+ */
141
+ static basicTelemetryProcessor(envelope, _contextObjects) {
142
+ delete envelope.tags['ai.cloud.roleInstance'];
143
+ return true;
144
+ }
145
+ /**
146
+ * Performs the processing necessary (mostly PII sanitization) for error events.
147
+ * @param envelope
148
+ * @param _contextObjects
149
+ * @returns
150
+ */
151
+ static errorTelemetryProcessor(envelope, _contextObjects) {
152
+ if (envelope.data.baseType === 'ExceptionData') {
153
+ const data = envelope.data.baseData;
154
+ if (data === null || data === void 0 ? void 0 : data.exceptions) {
155
+ for (const exception of data.exceptions) {
156
+ for (const frame of exception.parsedStack) {
157
+ errorUtils.sanitizeErrorStackFrame(frame);
158
+ }
159
+ // CodedError has non-PII information in its 'type' member, plus optionally some more info in its 'data'.
160
+ // The message may contain PII information. This can be sanitized, but for now delete it.
161
+ // Note that the type of data.exceptions[0] is always going to be ExceptionDetails. It is not the original thrown exception.
162
+ // https://github.com/microsoft/ApplicationInsights-node.js/issues/707
163
+ if (Telemetry.options.preserveErrorMessages) {
164
+ exception.message = errorUtils.sanitizeErrorMessage(exception.message);
165
+ }
166
+ else {
167
+ delete exception.message;
168
+ }
169
+ }
170
+ }
58
171
  }
59
- Telemetry.preserveMessages = preserveMessages ? true : false;
60
- if (process.env.RNW_CLI_TEST) {
61
- Telemetry.client.commonProperties.isTest = process.env.RNW_CLI_TEST;
172
+ return true;
173
+ }
174
+ /** Tries to update the version of the named package/tool by calling getValue(). */
175
+ static async tryUpdateVersionsProp(name, getValue, forceRefresh) {
176
+ if (!Telemetry.client) {
177
+ return true;
62
178
  }
63
- if (!Telemetry.client.commonProperties.sessionId) {
64
- Telemetry.client.commonProperties.sessionId = (0, crypto_1.randomBytes)(16).toString('hex');
65
- Telemetry.client.addTelemetryProcessor(sanitizeEnvelope);
179
+ if (forceRefresh === true || !Telemetry.versionsProp[name]) {
180
+ const value = await getValue();
181
+ if (value) {
182
+ Telemetry.versionsProp[name] = value;
183
+ return true;
184
+ }
66
185
  }
186
+ return false;
67
187
  }
68
- static isCI() {
69
- return (process.env.AGENT_NAME !== undefined || // Azure DevOps
70
- process.env.CIRCLECI === 'true' || // CircleCI
71
- process.env.TRAVIS === 'true' || // Travis
72
- process.env.CI === 'true' // other CIs
73
- );
188
+ /** Populates the versions property of tools we care to track. */
189
+ static async populateToolsVersions(refresh) {
190
+ await Telemetry.tryUpdateVersionsProp('node', versionUtils.getNodeVersion, refresh);
191
+ await Telemetry.tryUpdateVersionsProp('npm', versionUtils.getNpmVersion, refresh);
192
+ await Telemetry.tryUpdateVersionsProp('yarn', versionUtils.getYarnVersion, refresh);
193
+ await Telemetry.tryUpdateVersionsProp('VisualStudio', versionUtils.getVisualStudioVersion, refresh);
74
194
  }
75
- static trackException(e, properties) {
76
- var _a;
77
- const props = {};
78
- if (e instanceof CodedError_1.CodedError) {
79
- Object.assign(props, e.data);
195
+ /** Populates the versions property of npm packages we care to track. */
196
+ static async populateNpmPackageVersions(refresh) {
197
+ for (const npmPackage of exports.NpmPackagesWeTrack) {
198
+ await Telemetry.tryUpdateVersionsProp(npmPackage, async () => await versionUtils.getVersionOfNpmPackage(npmPackage), refresh);
80
199
  }
81
- const syscallExceptionFieldsToCopy = ['errno', 'syscall', 'code'];
82
- for (const f of syscallExceptionFieldsToCopy) {
83
- if (e[f]) {
84
- props[f] = [f];
85
- }
200
+ }
201
+ /** Populates the versions property of nuget packages we care to track. */
202
+ static async populateNuGetPackageVersions(projectFile, refresh) {
203
+ const nugetVersions = await versionUtils.getVersionsOfNuGetPackages(projectFile, exports.NuGetPackagesWeTrack);
204
+ for (const nugetPackage of exports.NuGetPackagesWeTrack) {
205
+ await Telemetry.tryUpdateVersionsProp(nugetPackage, async () => nugetVersions[nugetPackage], refresh);
86
206
  }
87
- Object.assign(props, props, properties);
88
- (_a = Telemetry.client) === null || _a === void 0 ? void 0 : _a.trackException({
89
- exception: e,
90
- properties: props,
91
- });
92
207
  }
93
- }
94
- exports.Telemetry = Telemetry;
95
- Telemetry.client = undefined;
96
- Telemetry.shouldDisable = false;
97
- Telemetry.preserveMessages = false;
98
- function getAnonymizedPath(filepath) {
99
- const projectRoot = process.cwd().toLowerCase();
100
- filepath = filepath.replace(/\//g, '\\');
101
- const knownPathsVars = ['AppData', 'LocalAppData', 'UserProfile'];
102
- if (filepath.toLowerCase().startsWith(projectRoot)) {
103
- const ext = path_1.default.extname(filepath);
104
- const rest = filepath.slice(projectRoot.length);
105
- const nodeModules = '\\node_modules\\';
106
- // this is in the project dir but not under node_modules
107
- if (rest.toLowerCase().startsWith('\\windows\\')) {
108
- return `[windows]\\???${ext}(${filepath.length})`;
109
- }
110
- else if (rest.toLowerCase().startsWith(nodeModules)) {
111
- return 'node_modules' + rest.slice(nodeModules.length - 1);
112
- }
113
- else {
114
- return `[project_dir]\\???${ext}(${filepath.length})`;
115
- }
116
- }
117
- else {
118
- for (const knownPath of knownPathsVars) {
119
- if (process.env[knownPath] &&
120
- filepath.toLowerCase().startsWith(process.env[knownPath].toLowerCase())) {
121
- return `[${knownPath}]\\???(${filepath.length})`;
122
- }
208
+ static setProjectInfo(info) {
209
+ if (!Telemetry.client) {
210
+ return;
123
211
  }
212
+ Telemetry.projectProp = info;
124
213
  }
125
- return '[path]';
126
- }
127
- /**
128
- * Sanitize any paths that appear between quotes (''), brackets ([]), or double quotes ("").
129
- * @param msg the string to sanitize
130
- */
131
- function sanitizeMessage(msg) {
132
- const cpuThreadId = /^\d+(:\d+)?>/g;
133
- msg = msg.replace(cpuThreadId, '');
134
- const parts = msg.split(/['[\]"]/g);
135
- const clean = [];
136
- const pathRegEx = /([A-Za-z]:|\\)[\\/]([^<>:;,?"*\t\r\n|/\\]+[\\/])+([^<>:;,?"*\t\r\n|]+\/?)/gi;
137
- for (const part of parts) {
138
- if (pathRegEx.test(part)) {
139
- pathRegEx.lastIndex = -1;
140
- let matches;
141
- let noPath = '';
142
- let last = 0;
143
- while ((matches = pathRegEx.exec(part))) {
144
- noPath +=
145
- part.substr(last, matches.index - last) +
146
- getAnonymizedPath(matches[0]);
147
- last = matches.index + matches[0].length;
148
- }
149
- clean.push(noPath);
214
+ static startCommand(info) {
215
+ if (!Telemetry.client) {
216
+ return;
150
217
  }
151
- else if (part !== '') {
152
- clean.push(part);
218
+ if (Telemetry.commandInfo.startInfo) {
219
+ return;
153
220
  }
221
+ Telemetry.commandInfo.startTime = Date.now();
222
+ Telemetry.commandInfo.startInfo = info;
223
+ // Set common command props
224
+ Telemetry.client.commonProperties.commandName = info.commandName;
154
225
  }
155
- return clean.join(' ').trim();
156
- }
157
- exports.sanitizeMessage = sanitizeMessage;
158
- function sanitizeFrame(frame) {
159
- const parens = frame.method.indexOf('(');
160
- if (parens !== -1) {
161
- // case 1: method === 'methodName (rootOfThePath'
162
- frame.method = frame.method.substr(0, parens).trim();
163
- }
164
- else {
165
- // case 2: method === <no_method> or something without '(', fileName is full path
166
- }
167
- // preserve only the last_directory/filename
168
- frame.fileName = path_1.default.join(path_1.default.basename(path_1.default.dirname(frame.fileName)), path_1.default.basename(frame.fileName));
169
- frame.assembly = '';
170
- }
171
- exports.sanitizeFrame = sanitizeFrame;
172
- function tryGetErrorCode(msg) {
173
- const errorRegEx = /error (\w+\d+):/gi;
174
- const m = errorRegEx.exec(msg);
175
- return m ? m[1] : undefined;
176
- }
177
- exports.tryGetErrorCode = tryGetErrorCode;
178
- /**
179
- * Remove PII from exceptions' stack traces and messages
180
- * @param envelope the telemetry envelope. Provided by AppInsights.
181
- */
182
- function sanitizeEnvelope(envelope /*context: any*/) {
183
- if (envelope.data.baseType === 'ExceptionData') {
184
- const data = envelope.data.baseData;
185
- for (const exception of data.exceptions || []) {
186
- for (const frame of exception.parsedStack) {
187
- sanitizeFrame(frame);
188
- }
189
- const errorCode = tryGetErrorCode(exception.message);
190
- data.properties.errorCode = errorCode;
191
- // CodedError has non-PII information in its 'type' member, plus optionally some more info in its 'data'.
192
- // The message may contain PII information. This can be sanitized, but for now delete it.
193
- // Note that the type of data.exceptions[0] is always going to be ExceptionDetails. It is not the original thrown exception.
194
- // https://github.com/microsoft/ApplicationInsights-node.js/issues/707
195
- if (Telemetry.preserveMessages) {
196
- exception.message = sanitizeMessage(exception.message);
197
- }
198
- else {
199
- delete exception.message;
226
+ static endCommand(info, extraProps) {
227
+ if (!Telemetry.client) {
228
+ return;
229
+ }
230
+ if (!Telemetry.commandInfo.startInfo) {
231
+ return;
232
+ }
233
+ Telemetry.commandInfo.endTime = Date.now();
234
+ Telemetry.commandInfo.endInfo = info;
235
+ Telemetry.trackCommandEvent(extraProps);
236
+ }
237
+ static trackCommandEvent(extraProps) {
238
+ var _a, _b, _c, _d;
239
+ const props = {
240
+ eventName: 'RNWCLI.Command',
241
+ };
242
+ // Set command props
243
+ props.command = {
244
+ options: (_a = Telemetry.commandInfo.startInfo) === null || _a === void 0 ? void 0 : _a.options,
245
+ defaultOptions: (_b = Telemetry.commandInfo.startInfo) === null || _b === void 0 ? void 0 : _b.defaultOptions,
246
+ args: (_c = Telemetry.commandInfo.startInfo) === null || _c === void 0 ? void 0 : _c.args,
247
+ durationInSecs: (Telemetry.commandInfo.endTime - Telemetry.commandInfo.startTime) /
248
+ 1000,
249
+ resultCode: (_d = Telemetry.commandInfo.endInfo) === null || _d === void 0 ? void 0 : _d.resultCode,
250
+ };
251
+ // Set remaining common props
252
+ Object.assign(props, extraProps);
253
+ props.project = Telemetry.projectProp;
254
+ props.versions = Telemetry.versionsProp;
255
+ // Fire event
256
+ Telemetry.client.trackEvent({ name: props.eventName, properties: props });
257
+ Telemetry.client.flush();
258
+ }
259
+ static trackException(error, extraProps) {
260
+ var _a, _b, _c;
261
+ if (!Telemetry.client) {
262
+ return;
263
+ }
264
+ const props = {
265
+ eventName: 'RNWCLI.CodedError',
266
+ };
267
+ // Save off CodedError info
268
+ const codedError = error instanceof errorUtils.CodedError
269
+ ? error
270
+ : null;
271
+ props.codedError = {
272
+ type: (_a = codedError === null || codedError === void 0 ? void 0 : codedError.type) !== null && _a !== void 0 ? _a : 'Unknown',
273
+ rawErrorCode: (_b = errorUtils.tryGetErrorCode(error.message)) !== null && _b !== void 0 ? _b : '',
274
+ data: (_c = codedError === null || codedError === void 0 ? void 0 : codedError.data) !== null && _c !== void 0 ? _c : {},
275
+ };
276
+ if (codedError === null || codedError === void 0 ? void 0 : codedError.data) {
277
+ Object.assign(props.codedError.data, codedError.data);
278
+ }
279
+ // Copy miscellaneous system error fields into the codedError.data object
280
+ const syscallExceptionFieldsToCopy = ['errno', 'syscall', 'code'];
281
+ for (const f of syscallExceptionFieldsToCopy) {
282
+ if (error[f]) {
283
+ props.codedError.data[f] = error[f];
200
284
  }
201
285
  }
286
+ // Set remaining common props
287
+ Object.assign(props, extraProps);
288
+ props.project = Telemetry.projectProp;
289
+ props.versions = Telemetry.versionsProp;
290
+ // Fire event
291
+ Telemetry.client.trackException({
292
+ exception: error,
293
+ properties: props,
294
+ });
295
+ Telemetry.client.flush();
202
296
  }
203
- delete envelope.tags['ai.cloud.roleInstance'];
204
- return true;
205
- }
206
- exports.sanitizeEnvelope = sanitizeEnvelope;
207
- function isMSFTInternal() {
208
- return (process.env.UserDNSDomain !== undefined &&
209
- process.env.UserDNSDomain.toLowerCase().endsWith('.microsoft.com'));
210
- }
211
- exports.isMSFTInternal = isMSFTInternal;
212
- function getDiskFreeSpace(drivePath) {
213
- const out = (0, child_process_1.execSync)(`dir /-C ${drivePath}`)
214
- .toString()
215
- .split('\r\n');
216
- const line = out[out.length - 2];
217
- const result = line.match(/(\d+) [^\d]+(\d+) /);
218
- if (result && result.length > 2) {
219
- return Number(result[2]);
220
- }
221
- return -1;
222
297
  }
223
- exports.getDiskFreeSpace = getDiskFreeSpace;
298
+ exports.Telemetry = Telemetry;
299
+ Telemetry.client = undefined;
300
+ Telemetry.options = {
301
+ setupString: DefaultSetupString,
302
+ preserveErrorMessages: false,
303
+ };
304
+ Telemetry.isTest = basePropUtils.isCliTest();
305
+ Telemetry.commandInfo = {};
306
+ Telemetry.versionsProp = {};
307
+ Telemetry.projectProp = undefined;
224
308
  //# sourceMappingURL=telemetry.js.map