@nordicsemiconductor/pc-nrfconnect-shared 149.0.0 → 151.0.0
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.
- package/Changelog.md +45 -1
- package/ipc/infrastructure/mainToRenderer.ts +4 -0
- package/main/index.ts +4 -1
- package/nrfutil/sandbox.ts +10 -6
- package/package.json +2 -2
- package/src/App/App.test.tsx +11 -2
- package/src/App/App.tsx +3 -3
- package/src/Device/DeviceSelector/DeviceSelector.test.tsx +13 -0
- package/src/Device/DeviceSelector/DeviceSelector.tsx +6 -6
- package/src/Device/deviceLister.ts +4 -4
- package/src/ErrorBoundary/ErrorBoundary.test.tsx +5 -5
- package/src/ErrorBoundary/ErrorBoundary.tsx +14 -13
- package/src/Overlay/overlay.scss +6 -7
- package/src/Parsers/shellParser.ts +3 -3
- package/src/index.ts +2 -2
- package/src/telemetry/TelemetryMetadata.ts +9 -0
- package/src/telemetry/TelemetrySender.ts +80 -0
- package/src/telemetry/TelemetrySenderInMain.ts +80 -0
- package/src/telemetry/TelemetrySenderInRenderer.ts +86 -0
- package/src/telemetry/flatObject.test.ts +37 -0
- package/src/telemetry/flatObject.ts +19 -0
- package/src/telemetry/simplifyDevice.ts +20 -0
- package/src/telemetry/telemetry.ts +97 -0
- package/src/utils/persistentStore.ts +7 -7
- package/src/utils/systemReport.ts +1 -1
- package/src/utils/useHotKey.ts +2 -2
- package/typings/generated/ipc/infrastructure/mainToRenderer.d.ts +1 -0
- package/typings/generated/ipc/infrastructure/mainToRenderer.d.ts.map +1 -1
- package/typings/generated/main/index.d.ts +1 -1
- package/typings/generated/main/index.d.ts.map +1 -1
- package/typings/generated/nrfutil/sandbox.d.ts.map +1 -1
- package/typings/generated/src/ErrorBoundary/ErrorBoundary.d.ts +1 -1
- package/typings/generated/src/ErrorBoundary/ErrorBoundary.d.ts.map +1 -1
- package/typings/generated/src/index.d.ts +2 -2
- package/typings/generated/src/index.d.ts.map +1 -1
- package/typings/generated/src/telemetry/TelemetryMetadata.d.ts +4 -0
- package/typings/generated/src/telemetry/TelemetryMetadata.d.ts.map +1 -0
- package/typings/generated/src/telemetry/TelemetrySender.d.ts +24 -0
- package/typings/generated/src/telemetry/TelemetrySender.d.ts.map +1 -0
- package/typings/generated/src/telemetry/TelemetrySenderInMain.d.ts +15 -0
- package/typings/generated/src/telemetry/TelemetrySenderInMain.d.ts.map +1 -0
- package/typings/generated/src/telemetry/TelemetrySenderInRenderer.d.ts +15 -0
- package/typings/generated/src/telemetry/TelemetrySenderInRenderer.d.ts.map +1 -0
- package/typings/generated/src/telemetry/flatObject.d.ts +4 -0
- package/typings/generated/src/telemetry/flatObject.d.ts.map +1 -0
- package/typings/generated/src/telemetry/flatObject.test.d.ts +2 -0
- package/typings/generated/src/telemetry/flatObject.test.d.ts.map +1 -0
- package/typings/generated/src/{utils/usageDataCommon.d.ts → telemetry/simplifyDevice.d.ts} +2 -14
- package/typings/generated/src/telemetry/simplifyDevice.d.ts.map +1 -0
- package/typings/generated/src/telemetry/telemetry.d.ts +16 -0
- package/typings/generated/src/telemetry/telemetry.d.ts.map +1 -0
- package/typings/generated/src/utils/persistentStore.d.ts +4 -4
- package/typings/generated/src/utils/persistentStore.d.ts.map +1 -1
- package/src/utils/usageData.ts +0 -117
- package/src/utils/usageDataCommon.ts +0 -59
- package/src/utils/usageDataMain.ts +0 -119
- package/src/utils/usageDataRenderer.ts +0 -137
- package/typings/generated/src/utils/usageData.d.ts +0 -16
- package/typings/generated/src/utils/usageData.d.ts.map +0 -1
- package/typings/generated/src/utils/usageDataCommon.d.ts.map +0 -1
- package/typings/generated/src/utils/usageDataMain.d.ts +0 -10
- package/typings/generated/src/utils/usageDataMain.d.ts.map +0 -1
- package/typings/generated/src/utils/usageDataRenderer.d.ts +0 -10
- package/typings/generated/src/utils/usageDataRenderer.d.ts.map +0 -1
package/Changelog.md
CHANGED
|
@@ -7,6 +7,50 @@ This project does _not_ adhere to
|
|
|
7
7
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html) but contrary to it
|
|
8
8
|
every new version is a new major version.
|
|
9
9
|
|
|
10
|
+
## 151.0.0 - 2024-01-23
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
|
|
14
|
+
- Renamed exported object `usageData` to `telemetry` and type
|
|
15
|
+
`UsageDataMetadata` to `TelemetryMetadata`.
|
|
16
|
+
- Renamed several function in the `telemetry` object:
|
|
17
|
+
- `enable()` → `setUsersAgreedToTelemetry(true)`
|
|
18
|
+
- `disable()` → `setUsersAgreedToTelemetry(false)`
|
|
19
|
+
- `reset()` → `setUsersWithdrewTelemetryAgreement()`
|
|
20
|
+
- `isEnabled()` → `getIsSendingTelemetry()` (which now does not log
|
|
21
|
+
anymore)
|
|
22
|
+
- `sendUsageData()` → `sendEvent()`
|
|
23
|
+
- In the component `ErrorBoundary` the property `sendUsageData` is renamed to
|
|
24
|
+
`sendTelemetryEvent`.
|
|
25
|
+
|
|
26
|
+
### Steps to upgrade when using this package
|
|
27
|
+
|
|
28
|
+
- If they are imported from shared, rename `usageData` and `UsageDataMetadata`
|
|
29
|
+
as well as the renamed functions mentioned above.
|
|
30
|
+
- In usages of the component `ErrorBoundary`, rename the property
|
|
31
|
+
`sendUsageData` to `sendTelemetryEvent`.
|
|
32
|
+
|
|
33
|
+
## 150.0.0 - 2024-01-18
|
|
34
|
+
|
|
35
|
+
### Removed
|
|
36
|
+
|
|
37
|
+
- `Overlay` tooltip inner padding should be set by the content within it.
|
|
38
|
+
|
|
39
|
+
### Added
|
|
40
|
+
|
|
41
|
+
- Ability to remove the launcher window again. This is especially needed on
|
|
42
|
+
shutdown. Otherwise when at that time someone still tries to send IPC
|
|
43
|
+
messages to the launcher window, an exception is thrown.
|
|
44
|
+
|
|
45
|
+
### Fixed
|
|
46
|
+
|
|
47
|
+
- `Overlay` tooltips weren't centered due to incorrect sizing styles.
|
|
48
|
+
- When spawning the nrfutil process fails in certain ways, an uncaught
|
|
49
|
+
exception in the main process got thrown. The “certain ways” make this a bit
|
|
50
|
+
hard to reproduce: On macOS this happened, when the nrfutil executable did
|
|
51
|
+
not have the executable file mode. Usually this should not happen, because
|
|
52
|
+
we set that mode ourselves correctly.
|
|
53
|
+
|
|
10
54
|
## 149.0.0 - 2024-01-16
|
|
11
55
|
|
|
12
56
|
### Added
|
|
@@ -195,7 +239,7 @@ every new version is a new major version.
|
|
|
195
239
|
|
|
196
240
|
### Fixed
|
|
197
241
|
|
|
198
|
-
-
|
|
242
|
+
- Telemetry: Metadata was not removed on request, when being in the main
|
|
199
243
|
process. This is not critical because this code isn't yet executed in real
|
|
200
244
|
life.
|
|
201
245
|
|
|
@@ -12,6 +12,10 @@ export const registerLauncherWindowFromMain = (window: BrowserWindow) => {
|
|
|
12
12
|
launcherWindow = window;
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
+
export const removeLauncherWindowFromMain = () => {
|
|
16
|
+
launcherWindow = undefined;
|
|
17
|
+
};
|
|
18
|
+
|
|
15
19
|
export const send =
|
|
16
20
|
<T extends (...args: never[]) => void>(channel: string) =>
|
|
17
21
|
(...args: Parameters<T>) =>
|
package/main/index.ts
CHANGED
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
inRenderer as inRendererSerialPort,
|
|
16
16
|
} from '../ipc/serialPort';
|
|
17
17
|
|
|
18
|
-
export {
|
|
18
|
+
export {
|
|
19
|
+
registerLauncherWindowFromMain,
|
|
20
|
+
removeLauncherWindowFromMain,
|
|
21
|
+
} from '../ipc/infrastructure/mainToRenderer';
|
|
19
22
|
|
|
20
23
|
export const appDetails = { forRenderer: forRendererAppDetails };
|
|
21
24
|
export const apps = { forRenderer: forRendererApps };
|
package/nrfutil/sandbox.ts
CHANGED
|
@@ -11,8 +11,8 @@ import path from 'path';
|
|
|
11
11
|
import treeKill from 'tree-kill';
|
|
12
12
|
|
|
13
13
|
import describeError from '../src/logging/describeError';
|
|
14
|
+
import telemetry from '../src/telemetry/telemetry';
|
|
14
15
|
import { isDevelopment } from '../src/utils/environment';
|
|
15
|
-
import usageData from '../src/utils/usageData';
|
|
16
16
|
import { versionToInstall } from './moduleVersion';
|
|
17
17
|
import { getNrfutilLogger } from './nrfutilLogger';
|
|
18
18
|
import {
|
|
@@ -313,7 +313,7 @@ export class NrfutilSandbox {
|
|
|
313
313
|
}
|
|
314
314
|
|
|
315
315
|
error.message = error.message.replaceAll('Error: ', '');
|
|
316
|
-
|
|
316
|
+
telemetry.sendErrorReport(
|
|
317
317
|
`${
|
|
318
318
|
pid && this.logLevel === 'trace' ? `[PID:${pid}] ` : ''
|
|
319
319
|
}${describeError(error)}`
|
|
@@ -332,7 +332,7 @@ export class NrfutilSandbox {
|
|
|
332
332
|
) =>
|
|
333
333
|
new Promise<void>((resolve, reject) => {
|
|
334
334
|
let aborting = false;
|
|
335
|
-
|
|
335
|
+
telemetry.sendEvent(`running nrfutil ${this.module}`, {
|
|
336
336
|
args,
|
|
337
337
|
exec: command,
|
|
338
338
|
});
|
|
@@ -374,6 +374,10 @@ export class NrfutilSandbox {
|
|
|
374
374
|
onStdError(data, nrfutil.pid);
|
|
375
375
|
});
|
|
376
376
|
|
|
377
|
+
nrfutil.on('error', err => {
|
|
378
|
+
reject(err);
|
|
379
|
+
});
|
|
380
|
+
|
|
377
381
|
nrfutil.on('close', code => {
|
|
378
382
|
controller?.signal.removeEventListener('abort', listener);
|
|
379
383
|
if (aborting) {
|
|
@@ -490,7 +494,7 @@ export class NrfutilSandbox {
|
|
|
490
494
|
}
|
|
491
495
|
|
|
492
496
|
error.message = error.message.replaceAll('Error: ', '');
|
|
493
|
-
|
|
497
|
+
telemetry.sendErrorReport(
|
|
494
498
|
`${
|
|
495
499
|
pid && this.logLevel === 'trace' ? `[PID:${pid}] ` : ''
|
|
496
500
|
}${describeError(error)}`
|
|
@@ -509,7 +513,7 @@ export class NrfutilSandbox {
|
|
|
509
513
|
) =>
|
|
510
514
|
new Promise<void>((resolve, reject) => {
|
|
511
515
|
let aborting = false;
|
|
512
|
-
|
|
516
|
+
telemetry.sendEvent(`running nrfutil ${this.module}`, {
|
|
513
517
|
args,
|
|
514
518
|
exec: command,
|
|
515
519
|
});
|
|
@@ -607,7 +611,7 @@ export class NrfutilSandbox {
|
|
|
607
611
|
closedHandlers.forEach(callback => callback());
|
|
608
612
|
})
|
|
609
613
|
.catch(error => {
|
|
610
|
-
|
|
614
|
+
telemetry.sendErrorReport(describeError(error));
|
|
611
615
|
running = false;
|
|
612
616
|
closedHandlers.forEach(callback => callback(error));
|
|
613
617
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nordicsemiconductor/pc-nrfconnect-shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "151.0.0",
|
|
4
4
|
"description": "Shared commodities for developing pc-nrfconnect-* packages",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"prepare": "ts-node scripts/installHusky.ts",
|
|
26
26
|
"release-shared": "ts-node scripts/release-shared.ts",
|
|
27
27
|
"prepare-shared-release": "ts-node scripts/prepare-shared-release.ts",
|
|
28
|
-
"clean": "rimraf dist typings/generated
|
|
28
|
+
"clean": "rimraf dist typings/generated scripts/nordic-publish.js",
|
|
29
29
|
"postinstall": "ts-node scripts/postinstall.ts"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
package/src/App/App.test.tsx
CHANGED
|
@@ -5,8 +5,9 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
8
|
-
import { screen } from '@testing-library/react';
|
|
8
|
+
import { act, screen } from '@testing-library/react';
|
|
9
9
|
|
|
10
|
+
import { OFFICIAL } from '../../ipc/sources';
|
|
10
11
|
import packageJsonFromShared from '../../package.json';
|
|
11
12
|
import render from '../../test/testrenderer';
|
|
12
13
|
import App, { Pane } from './App';
|
|
@@ -26,6 +27,12 @@ jest.mock('../utils/packageJson', () => ({
|
|
|
26
27
|
packageJson: () => packageJsonFromShared,
|
|
27
28
|
}));
|
|
28
29
|
|
|
30
|
+
const appDetails = Promise.resolve({ source: OFFICIAL });
|
|
31
|
+
jest.mock('../utils/appDetails', () => ({
|
|
32
|
+
__esModule: true,
|
|
33
|
+
default: () => appDetails,
|
|
34
|
+
}));
|
|
35
|
+
|
|
29
36
|
const renderApp = (panes: Pane[]) => {
|
|
30
37
|
const dummyReducer = (s = null) => s;
|
|
31
38
|
const dummyNode = <div />;
|
|
@@ -50,9 +57,11 @@ const anotherPane = {
|
|
|
50
57
|
};
|
|
51
58
|
|
|
52
59
|
describe('App', () => {
|
|
53
|
-
it('automatically gets an About pane attached', () => {
|
|
60
|
+
it('automatically gets an About pane attached', async () => {
|
|
54
61
|
renderApp([aPane, anotherPane]);
|
|
55
62
|
|
|
56
63
|
expect(screen.getByText('About')).toBeInTheDocument();
|
|
64
|
+
|
|
65
|
+
await act(() => appDetails);
|
|
57
66
|
});
|
|
58
67
|
});
|
package/src/App/App.tsx
CHANGED
|
@@ -29,12 +29,12 @@ import FlashMessages from '../FlashMessage/FlashMessage';
|
|
|
29
29
|
import LogViewer from '../Log/LogViewer';
|
|
30
30
|
import logger from '../logging';
|
|
31
31
|
import NavBar from '../NavBar/NavBar';
|
|
32
|
+
import telemetry from '../telemetry/telemetry';
|
|
32
33
|
import classNames from '../utils/classNames';
|
|
33
34
|
import {
|
|
34
35
|
getPersistedCurrentPane,
|
|
35
36
|
getPersistedLogVisible,
|
|
36
37
|
} from '../utils/persistentStore';
|
|
37
|
-
import usageData from '../utils/usageData';
|
|
38
38
|
import useHotKey from '../utils/useHotKey';
|
|
39
39
|
import {
|
|
40
40
|
currentPane as currentPaneSelector,
|
|
@@ -87,7 +87,7 @@ const ConnectedApp: FC<ConnectedAppProps> = ({
|
|
|
87
87
|
if (!initApp.current) {
|
|
88
88
|
logger.initialise();
|
|
89
89
|
setNrfutilLogger(logger);
|
|
90
|
-
|
|
90
|
+
telemetry.setLogger(logger);
|
|
91
91
|
initApp.current = true;
|
|
92
92
|
}
|
|
93
93
|
|
|
@@ -110,7 +110,7 @@ const ConnectedApp: FC<ConnectedAppProps> = ({
|
|
|
110
110
|
}, [allPanes]);
|
|
111
111
|
|
|
112
112
|
useEffect(() => {
|
|
113
|
-
|
|
113
|
+
telemetry.sendPageView(paneName.current[currentPane]);
|
|
114
114
|
}, [currentPane]);
|
|
115
115
|
|
|
116
116
|
useEffect(() => {
|
|
@@ -7,6 +7,8 @@
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import { act, fireEvent, screen, waitFor } from '@testing-library/react';
|
|
9
9
|
|
|
10
|
+
import { OFFICIAL } from '../../../ipc/sources';
|
|
11
|
+
import packageJsonFromShared from '../../../package.json';
|
|
10
12
|
import render from '../../../test/testrenderer';
|
|
11
13
|
import { addDevice, Device, removeDevice } from '../deviceSlice';
|
|
12
14
|
import { jprogDeviceSetup } from '../jprogOperations';
|
|
@@ -14,6 +16,17 @@ import DeviceSelector from './DeviceSelector';
|
|
|
14
16
|
|
|
15
17
|
jest.mock('../../../nrfutil/device/device');
|
|
16
18
|
|
|
19
|
+
jest.mock('../../utils/packageJson', () => ({
|
|
20
|
+
isLauncher: () => false,
|
|
21
|
+
packageJson: () => packageJsonFromShared,
|
|
22
|
+
}));
|
|
23
|
+
|
|
24
|
+
const appDetails = Promise.resolve({ source: OFFICIAL });
|
|
25
|
+
jest.mock('../../utils/appDetails', () => ({
|
|
26
|
+
__esModule: true,
|
|
27
|
+
default: () => appDetails,
|
|
28
|
+
}));
|
|
29
|
+
|
|
17
30
|
const DEVICE_SERIAL_NUMBER = '000000001';
|
|
18
31
|
|
|
19
32
|
const testDevice: Device = {
|
|
@@ -10,8 +10,8 @@ import { useDispatch, useSelector } from 'react-redux';
|
|
|
10
10
|
import { NrfutilDeviceLib } from '../../../nrfutil/device';
|
|
11
11
|
import { DeviceTraits } from '../../../nrfutil/device/common';
|
|
12
12
|
import logger from '../../logging';
|
|
13
|
-
import
|
|
14
|
-
import
|
|
13
|
+
import simplifyDevice from '../../telemetry/simplifyDevice';
|
|
14
|
+
import telemetry from '../../telemetry/telemetry';
|
|
15
15
|
import useHotKey from '../../utils/useHotKey';
|
|
16
16
|
import {
|
|
17
17
|
clearWaitForDevice,
|
|
@@ -71,9 +71,9 @@ export default ({
|
|
|
71
71
|
const doDeselectDevice = useCallback(
|
|
72
72
|
(device?: Device) => {
|
|
73
73
|
if (device) {
|
|
74
|
-
|
|
74
|
+
telemetry.sendEvent(
|
|
75
75
|
'device deselected ',
|
|
76
|
-
|
|
76
|
+
simplifyDevice(device)
|
|
77
77
|
);
|
|
78
78
|
}
|
|
79
79
|
|
|
@@ -120,8 +120,8 @@ export default ({
|
|
|
120
120
|
dispatch(setSelectedDeviceInfo(deviceInfo));
|
|
121
121
|
onDeviceSelected(device, autoReselected);
|
|
122
122
|
|
|
123
|
-
|
|
124
|
-
device:
|
|
123
|
+
telemetry.sendEvent('device selected', {
|
|
124
|
+
device: simplifyDevice(device),
|
|
125
125
|
deviceInfo,
|
|
126
126
|
});
|
|
127
127
|
|
|
@@ -9,8 +9,8 @@ import { DeviceTraits, NrfutilDevice } from '../../nrfutil/device/common';
|
|
|
9
9
|
import NrfutilDeviceLib from '../../nrfutil/device/device';
|
|
10
10
|
import logger from '../logging';
|
|
11
11
|
import type { AppThunk, RootState } from '../store';
|
|
12
|
-
import
|
|
13
|
-
import
|
|
12
|
+
import simplifyDevice from '../telemetry/simplifyDevice';
|
|
13
|
+
import telemetry from '../telemetry/telemetry';
|
|
14
14
|
import {
|
|
15
15
|
clearWaitForDevice,
|
|
16
16
|
clearWaitForDeviceTimeout,
|
|
@@ -180,9 +180,9 @@ export const startWatchingDevices =
|
|
|
180
180
|
|
|
181
181
|
const action = async (device: Device) => {
|
|
182
182
|
if (hasValidDeviceTraits(device.traits, deviceListing)) {
|
|
183
|
-
|
|
183
|
+
telemetry.sendEvent(
|
|
184
184
|
'device connected',
|
|
185
|
-
|
|
185
|
+
simplifyDevice(device)
|
|
186
186
|
);
|
|
187
187
|
if (
|
|
188
188
|
!getState().device.devices.find(
|
|
@@ -13,8 +13,8 @@ import { generateSystemReport } from '../utils/systemReport';
|
|
|
13
13
|
import ErrorBoundary from './ErrorBoundary';
|
|
14
14
|
|
|
15
15
|
jest.mock('../utils/systemReport');
|
|
16
|
-
jest.mock('../
|
|
17
|
-
...jest.requireActual('../
|
|
16
|
+
jest.mock('../telemetry/telemetry', () => ({
|
|
17
|
+
...jest.requireActual('../telemetry/telemetry'),
|
|
18
18
|
sendErrorReport: jest.fn(),
|
|
19
19
|
isEnabled: () => true,
|
|
20
20
|
}));
|
|
@@ -44,14 +44,14 @@ describe('ErrorBoundary', () => {
|
|
|
44
44
|
});
|
|
45
45
|
|
|
46
46
|
it('can take custom reporting functions', () => {
|
|
47
|
-
const
|
|
47
|
+
const sendTelemetryEvent = jest.fn();
|
|
48
48
|
|
|
49
49
|
render(
|
|
50
|
-
<ErrorBoundary
|
|
50
|
+
<ErrorBoundary sendTelemetryEvent={sendTelemetryEvent}>
|
|
51
51
|
<Child />
|
|
52
52
|
</ErrorBoundary>
|
|
53
53
|
);
|
|
54
|
-
expect(
|
|
54
|
+
expect(sendTelemetryEvent).toHaveBeenCalled();
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
it('should render error boundary component when there is an error', () => {
|
|
@@ -12,21 +12,17 @@ import { Device } from '../Device/deviceSlice';
|
|
|
12
12
|
import FactoryResetButton from '../FactoryReset/FactoryResetButton';
|
|
13
13
|
import { CollapsibleGroup } from '../SidePanel/Group';
|
|
14
14
|
import Spinner from '../Spinner/Spinner';
|
|
15
|
+
import telemetry from '../telemetry/telemetry';
|
|
15
16
|
import { openUrl } from '../utils/open';
|
|
16
17
|
import { packageJson } from '../utils/packageJson';
|
|
17
18
|
import { getAppSpecificStore as store } from '../utils/persistentStore';
|
|
18
19
|
import { generateSystemReport } from '../utils/systemReport';
|
|
19
|
-
import usageData from '../utils/usageData';
|
|
20
20
|
import bugIcon from './bug.svg';
|
|
21
21
|
|
|
22
22
|
import './error-boundary.scss';
|
|
23
23
|
|
|
24
|
-
const
|
|
25
|
-
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
usageData.sendErrorReport(error);
|
|
24
|
+
const sendErrorReport = (error: string) => {
|
|
25
|
+
telemetry.sendErrorReport(error);
|
|
30
26
|
};
|
|
31
27
|
|
|
32
28
|
interface Props {
|
|
@@ -36,7 +32,7 @@ interface Props {
|
|
|
36
32
|
devices?: Device[];
|
|
37
33
|
appName?: string;
|
|
38
34
|
restoreDefaults?: () => void;
|
|
39
|
-
|
|
35
|
+
sendTelemetryEvent?: (message: string) => void;
|
|
40
36
|
}
|
|
41
37
|
|
|
42
38
|
const genericRestoreDefaults = () => {
|
|
@@ -65,11 +61,16 @@ class ErrorBoundary extends React.Component<
|
|
|
65
61
|
}
|
|
66
62
|
|
|
67
63
|
componentDidCatch(error: Error) {
|
|
68
|
-
const {
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
64
|
+
const {
|
|
65
|
+
devices,
|
|
66
|
+
selectedDevice,
|
|
67
|
+
selectedSerialNumber,
|
|
68
|
+
sendTelemetryEvent,
|
|
69
|
+
} = this.props;
|
|
70
|
+
|
|
71
|
+
sendTelemetryEvent != null
|
|
72
|
+
? sendTelemetryEvent(error.message)
|
|
73
|
+
: sendErrorReport(error.message);
|
|
73
74
|
|
|
74
75
|
generateSystemReport(
|
|
75
76
|
new Date().toISOString().replace(/:/g, '-'),
|
package/src/Overlay/overlay.scss
CHANGED
|
@@ -8,14 +8,14 @@
|
|
|
8
8
|
|
|
9
9
|
.shared-tooltip {
|
|
10
10
|
div.arrow:first-child {
|
|
11
|
-
width:
|
|
12
|
-
height:
|
|
11
|
+
width: 12px;
|
|
12
|
+
height: 12px;
|
|
13
13
|
pointer-events: none;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
&.bs-tooltip-top {
|
|
17
17
|
div.arrow:first-child {
|
|
18
|
-
bottom: -
|
|
18
|
+
bottom: -6px;
|
|
19
19
|
|
|
20
20
|
&::before {
|
|
21
21
|
border-top-color: $gray-900;
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
|
|
27
27
|
&.bs-tooltip-right {
|
|
28
28
|
div.arrow:first-child {
|
|
29
|
-
left: -
|
|
29
|
+
left: -6px;
|
|
30
30
|
|
|
31
31
|
&::before {
|
|
32
32
|
border-right-color: $gray-900;
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
|
|
38
38
|
&.bs-tooltip-bottom {
|
|
39
39
|
div.arrow:first-child {
|
|
40
|
-
top: -
|
|
40
|
+
top: -6px;
|
|
41
41
|
|
|
42
42
|
&::before {
|
|
43
43
|
border-bottom-color: $gray-900;
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
|
|
49
49
|
&.bs-tooltip-left {
|
|
50
50
|
div.arrow:first-child {
|
|
51
|
-
right: -
|
|
51
|
+
right: -6px;
|
|
52
52
|
|
|
53
53
|
&::before {
|
|
54
54
|
border-left-color: $gray-900;
|
|
@@ -59,7 +59,6 @@
|
|
|
59
59
|
|
|
60
60
|
.tooltip-inner {
|
|
61
61
|
background: $gray-900;
|
|
62
|
-
padding-top: 14px;
|
|
63
62
|
min-width: 240px;
|
|
64
63
|
}
|
|
65
64
|
}
|
|
@@ -39,15 +39,15 @@ export type XTerminalShellParser = ReturnType<
|
|
|
39
39
|
|
|
40
40
|
export const xTerminalShellParserWrapper = (terminal: Terminal) => ({
|
|
41
41
|
getTerminalData: () => {
|
|
42
|
-
let
|
|
42
|
+
let result = '';
|
|
43
43
|
for (let i = 0; i <= terminal.buffer.active.cursorY; i += 1) {
|
|
44
44
|
const line = terminal.buffer.active.getLine(i);
|
|
45
45
|
if (typeof line !== 'undefined') {
|
|
46
|
-
|
|
46
|
+
result += `\r\n${line.translateToString()}`;
|
|
47
47
|
}
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
return
|
|
50
|
+
return result.trim();
|
|
51
51
|
},
|
|
52
52
|
clear: () => terminal.clear(),
|
|
53
53
|
getLastLine: () => {
|
package/src/index.ts
CHANGED
|
@@ -77,8 +77,8 @@ export {
|
|
|
77
77
|
export { openUrl, openFile } from './utils/open';
|
|
78
78
|
export { default as systemReport } from './utils/systemReport';
|
|
79
79
|
|
|
80
|
-
export { default as
|
|
81
|
-
export { type
|
|
80
|
+
export { default as telemetry } from './telemetry/telemetry';
|
|
81
|
+
export { type default as TelemetryMetadata } from './telemetry/TelemetryMetadata';
|
|
82
82
|
export { default as classNames } from './utils/classNames';
|
|
83
83
|
export { truncateMiddle } from './utils/truncateMiddle';
|
|
84
84
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import si from 'systeminformation';
|
|
8
|
+
import { Logger } from 'winston';
|
|
9
|
+
|
|
10
|
+
import {
|
|
11
|
+
deleteHasUserAgreedToTelemetry,
|
|
12
|
+
getHasUserAgreedToTelemetry,
|
|
13
|
+
persistHasUserAgreedToTelemetry,
|
|
14
|
+
} from '../utils/persistentStore';
|
|
15
|
+
import TelemetryMetadata from './TelemetryMetadata';
|
|
16
|
+
|
|
17
|
+
type MaybePromise<T> = T | Promise<T>;
|
|
18
|
+
|
|
19
|
+
export default abstract class TelemetrySender {
|
|
20
|
+
readonly INSTRUMENTATION_KEY = '4b8b1a39-37c7-479e-a684-d4763c7c647c';
|
|
21
|
+
|
|
22
|
+
logger?: Logger;
|
|
23
|
+
setLogger = (logger: Logger) => {
|
|
24
|
+
this.logger = logger;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
isTelemetryAllowedForCurrentApp = false;
|
|
28
|
+
allowTelemetryForCurrentApp = () => {
|
|
29
|
+
this.isTelemetryAllowedForCurrentApp = true;
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
getIsSendingTelemetry = () =>
|
|
33
|
+
this.isTelemetryAllowedForCurrentApp &&
|
|
34
|
+
getHasUserAgreedToTelemetry() === true;
|
|
35
|
+
|
|
36
|
+
async sendAgreementEvent() {
|
|
37
|
+
this.sendEvent('Telemetry Opt-In');
|
|
38
|
+
|
|
39
|
+
const { platform, arch } = await si.osInfo();
|
|
40
|
+
this.sendEvent('Report OS info', { platform, arch });
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
sendDisagreementEvent() {
|
|
44
|
+
this.sendMinimalEvent('Telemetry Opt-Out');
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async setUsersAgreedToTelemetry(hasAgreed: boolean) {
|
|
48
|
+
persistHasUserAgreedToTelemetry(hasAgreed);
|
|
49
|
+
|
|
50
|
+
if (hasAgreed) {
|
|
51
|
+
await this.sendAgreementEvent();
|
|
52
|
+
} else {
|
|
53
|
+
this.sendDisagreementEvent();
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
this.logger?.debug(
|
|
57
|
+
`Telemetry has been ${hasAgreed ? 'enabled' : 'disabled'}`
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
setUsersWithdrewTelemetryAgreement() {
|
|
62
|
+
deleteHasUserAgreedToTelemetry();
|
|
63
|
+
this.sendMinimalEvent('Telemetry Opt-Reset');
|
|
64
|
+
this.logger?.debug('Telemetry has been reset');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
sendMinimalEvent(action: string) {
|
|
68
|
+
this.sendEvent(action, { removeAllMetadata: true });
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
abstract sendEvent(
|
|
72
|
+
action: string,
|
|
73
|
+
metadata?: TelemetryMetadata
|
|
74
|
+
): MaybePromise<void>;
|
|
75
|
+
abstract sendPageView(pageName: string): MaybePromise<void>;
|
|
76
|
+
abstract sendMetric(name: string, average: number): MaybePromise<void>;
|
|
77
|
+
abstract sendTrace(message: string): MaybePromise<void>;
|
|
78
|
+
abstract sendErrorReport(error: Error): MaybePromise<void>;
|
|
79
|
+
abstract flush(): MaybePromise<void>;
|
|
80
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { TelemetryClient } from 'applicationinsights';
|
|
8
|
+
|
|
9
|
+
import { isDevelopment } from '../utils/environment';
|
|
10
|
+
import { packageJson } from '../utils/packageJson';
|
|
11
|
+
import TelemetryMetadata from './TelemetryMetadata';
|
|
12
|
+
import TelemetrySender from './TelemetrySender';
|
|
13
|
+
|
|
14
|
+
export default class TelemetrySenderInMain extends TelemetrySender {
|
|
15
|
+
client?: TelemetryClient;
|
|
16
|
+
|
|
17
|
+
initClient() {
|
|
18
|
+
const appPackageJson = packageJson();
|
|
19
|
+
const applicationName = appPackageJson.name;
|
|
20
|
+
const applicationVersion = appPackageJson.version;
|
|
21
|
+
|
|
22
|
+
this.client = new TelemetryClient(this.INSTRUMENTATION_KEY);
|
|
23
|
+
this.client.config.enableAutoCollectConsole = false;
|
|
24
|
+
this.client.config.enableAutoCollectDependencies = false;
|
|
25
|
+
this.client.config.enableAutoCollectExceptions = false;
|
|
26
|
+
this.client.config.enableAutoCollectIncomingRequestAzureFunctions =
|
|
27
|
+
false;
|
|
28
|
+
this.client.config.enableAutoCollectHeartbeat = false;
|
|
29
|
+
this.client.config.enableAutoCollectPerformance = false;
|
|
30
|
+
this.client.config.enableAutoCollectPreAggregatedMetrics = false;
|
|
31
|
+
this.client.config.enableAutoCollectRequests = false;
|
|
32
|
+
this.client.config.enableAutoDependencyCorrelation = false;
|
|
33
|
+
|
|
34
|
+
// Add app name and version to every event
|
|
35
|
+
this.client.addTelemetryProcessor(envelope => {
|
|
36
|
+
if (envelope.data.baseData?.properties.removeAllMetadata) {
|
|
37
|
+
envelope.tags = [];
|
|
38
|
+
envelope.data.baseData = {
|
|
39
|
+
name: envelope.data?.baseData.name,
|
|
40
|
+
};
|
|
41
|
+
} else {
|
|
42
|
+
envelope.tags['ai.cloud.roleInstance'] = undefined; // remove PC name
|
|
43
|
+
if (envelope.data.baseData) {
|
|
44
|
+
envelope.data.baseData.properties = {
|
|
45
|
+
applicationName,
|
|
46
|
+
applicationVersion,
|
|
47
|
+
isDevelopment,
|
|
48
|
+
...envelope.data.baseData.properties,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return true;
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return this.client;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getClient = () => this.client ?? this.initClient();
|
|
60
|
+
|
|
61
|
+
sendEvent = (action: string, metadata?: TelemetryMetadata) => {
|
|
62
|
+
this.getClient().trackEvent({ name: action, properties: metadata });
|
|
63
|
+
this.logger?.debug(`Sending event ${JSON.stringify(action)}`);
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
sendPageView = (pageName: string) =>
|
|
67
|
+
this.getClient().trackPageView({ name: pageName });
|
|
68
|
+
|
|
69
|
+
sendMetric = (name: string, value: number) =>
|
|
70
|
+
this.getClient().trackMetric({ name, value });
|
|
71
|
+
|
|
72
|
+
sendTrace = (message: string) => this.getClient().trackTrace({ message });
|
|
73
|
+
|
|
74
|
+
sendErrorReport = (error: Error) => {
|
|
75
|
+
this.getClient().trackException({ exception: error });
|
|
76
|
+
this.logger?.error(error);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
flush = () => this.getClient().flush();
|
|
80
|
+
}
|