@nordicsemiconductor/pc-nrfconnect-shared 150.0.0 → 152.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 +31 -1
- package/nrfutil/sandbox.ts +6 -6
- package/package.json +4 -4
- 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/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/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,36 @@ 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
|
+
## 152.0.0 - 2024-01-26
|
|
11
|
+
|
|
12
|
+
### Updated
|
|
13
|
+
|
|
14
|
+
- Electron version to `28.1.4`
|
|
15
|
+
- @electron/remote to `2.1.1`
|
|
16
|
+
|
|
17
|
+
## 151.0.0 - 2024-01-23
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Renamed exported object `usageData` to `telemetry` and type
|
|
22
|
+
`UsageDataMetadata` to `TelemetryMetadata`.
|
|
23
|
+
- Renamed several function in the `telemetry` object:
|
|
24
|
+
- `enable()` → `setUsersAgreedToTelemetry(true)`
|
|
25
|
+
- `disable()` → `setUsersAgreedToTelemetry(false)`
|
|
26
|
+
- `reset()` → `setUsersWithdrewTelemetryAgreement()`
|
|
27
|
+
- `isEnabled()` → `getIsSendingTelemetry()` (which now does not log
|
|
28
|
+
anymore)
|
|
29
|
+
- `sendUsageData()` → `sendEvent()`
|
|
30
|
+
- In the component `ErrorBoundary` the property `sendUsageData` is renamed to
|
|
31
|
+
`sendTelemetryEvent`.
|
|
32
|
+
|
|
33
|
+
### Steps to upgrade when using this package
|
|
34
|
+
|
|
35
|
+
- If they are imported from shared, rename `usageData` and `UsageDataMetadata`
|
|
36
|
+
as well as the renamed functions mentioned above.
|
|
37
|
+
- In usages of the component `ErrorBoundary`, rename the property
|
|
38
|
+
`sendUsageData` to `sendTelemetryEvent`.
|
|
39
|
+
|
|
10
40
|
## 150.0.0 - 2024-01-18
|
|
11
41
|
|
|
12
42
|
### Removed
|
|
@@ -216,7 +246,7 @@ every new version is a new major version.
|
|
|
216
246
|
|
|
217
247
|
### Fixed
|
|
218
248
|
|
|
219
|
-
-
|
|
249
|
+
- Telemetry: Metadata was not removed on request, when being in the main
|
|
220
250
|
process. This is not critical because this code isn't yet executed in real
|
|
221
251
|
life.
|
|
222
252
|
|
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
|
});
|
|
@@ -494,7 +494,7 @@ export class NrfutilSandbox {
|
|
|
494
494
|
}
|
|
495
495
|
|
|
496
496
|
error.message = error.message.replaceAll('Error: ', '');
|
|
497
|
-
|
|
497
|
+
telemetry.sendErrorReport(
|
|
498
498
|
`${
|
|
499
499
|
pid && this.logLevel === 'trace' ? `[PID:${pid}] ` : ''
|
|
500
500
|
}${describeError(error)}`
|
|
@@ -513,7 +513,7 @@ export class NrfutilSandbox {
|
|
|
513
513
|
) =>
|
|
514
514
|
new Promise<void>((resolve, reject) => {
|
|
515
515
|
let aborting = false;
|
|
516
|
-
|
|
516
|
+
telemetry.sendEvent(`running nrfutil ${this.module}`, {
|
|
517
517
|
args,
|
|
518
518
|
exec: command,
|
|
519
519
|
});
|
|
@@ -611,7 +611,7 @@ export class NrfutilSandbox {
|
|
|
611
611
|
closedHandlers.forEach(callback => callback());
|
|
612
612
|
})
|
|
613
613
|
.catch(error => {
|
|
614
|
-
|
|
614
|
+
telemetry.sendErrorReport(describeError(error));
|
|
615
615
|
running = false;
|
|
616
616
|
closedHandlers.forEach(callback => callback(error));
|
|
617
617
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nordicsemiconductor/pc-nrfconnect-shared",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "152.0.0",
|
|
4
4
|
"description": "Shared commodities for developing pc-nrfconnect-* packages",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -25,11 +25,11 @@
|
|
|
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": {
|
|
32
|
-
"@electron/remote": "^2.
|
|
32
|
+
"@electron/remote": "^2.1.1",
|
|
33
33
|
"@mdi/font": "7.2.96",
|
|
34
34
|
"@mdi/js": "^7.2.96",
|
|
35
35
|
"@mdi/react": "^1.6.1",
|
|
@@ -62,7 +62,7 @@
|
|
|
62
62
|
"bootstrap": "4.6.2",
|
|
63
63
|
"commander": "10.0.0",
|
|
64
64
|
"date-fns": "2.29.3",
|
|
65
|
-
"electron": "
|
|
65
|
+
"electron": "^28.1.4",
|
|
66
66
|
"electron-store": "8.1.0",
|
|
67
67
|
"esbuild": "0.19.2",
|
|
68
68
|
"esbuild-sass-plugin": "2.13.0",
|
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, '-'),
|
|
@@ -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
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023 Nordic Semiconductor ASA
|
|
3
|
+
*
|
|
4
|
+
* SPDX-License-Identifier: LicenseRef-Nordic-4-Clause
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { ApplicationInsights } from '@microsoft/applicationinsights-web';
|
|
8
|
+
|
|
9
|
+
import appDetails from '../utils/appDetails';
|
|
10
|
+
import { isDevelopment } from '../utils/environment';
|
|
11
|
+
import { isLauncher, packageJson } from '../utils/packageJson';
|
|
12
|
+
import { getTelemetryClientId } from '../utils/persistentStore';
|
|
13
|
+
import TelemetryMetadata from './TelemetryMetadata';
|
|
14
|
+
import TelemetrySender from './TelemetrySender';
|
|
15
|
+
|
|
16
|
+
export default class TelemetrySenderInRenderer extends TelemetrySender {
|
|
17
|
+
client?: ApplicationInsights;
|
|
18
|
+
|
|
19
|
+
async initClient() {
|
|
20
|
+
const source = isLauncher() ? undefined : (await appDetails()).source;
|
|
21
|
+
|
|
22
|
+
const applicationName = packageJson().name;
|
|
23
|
+
const applicationVersion = packageJson().version;
|
|
24
|
+
|
|
25
|
+
const accountId = getTelemetryClientId();
|
|
26
|
+
|
|
27
|
+
this.client = new ApplicationInsights({
|
|
28
|
+
config: {
|
|
29
|
+
instrumentationKey: this.INSTRUMENTATION_KEY,
|
|
30
|
+
accountId, // to hide with removeAllMetadata
|
|
31
|
+
isStorageUseDisabled: true, // fix issue with duplicate events being sent https://github.com/microsoft/ApplicationInsights-JS/issues/796
|
|
32
|
+
namePrefix: applicationName, // fix issue with duplicate events being sent https://github.com/microsoft/ApplicationInsights-JS/issues/796
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
this.client.loadAppInsights();
|
|
37
|
+
|
|
38
|
+
// Add app name and version to every event
|
|
39
|
+
this.client.addTelemetryInitializer(envelope => {
|
|
40
|
+
if (envelope.data?.removeAllMetadata) {
|
|
41
|
+
envelope.data = {};
|
|
42
|
+
envelope.baseData = { name: envelope.baseData?.name };
|
|
43
|
+
envelope.ext = {};
|
|
44
|
+
envelope.tags = [];
|
|
45
|
+
} else {
|
|
46
|
+
const trace = {
|
|
47
|
+
...(envelope.ext?.trace ?? {}),
|
|
48
|
+
name: applicationName,
|
|
49
|
+
};
|
|
50
|
+
envelope.ext = { ...envelope.ext, trace };
|
|
51
|
+
envelope.data = {
|
|
52
|
+
...envelope.data,
|
|
53
|
+
applicationName,
|
|
54
|
+
applicationVersion,
|
|
55
|
+
isDevelopment,
|
|
56
|
+
source,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
return this.client;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
getClient = () => this.client ?? this.initClient();
|
|
65
|
+
|
|
66
|
+
sendEvent = async (action: string, metadata?: TelemetryMetadata) => {
|
|
67
|
+
(await this.getClient()).trackEvent({ name: action }, metadata);
|
|
68
|
+
this.logger?.debug(`Sending event ${JSON.stringify(action)}`);
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
sendPageView = async (pageName: string) =>
|
|
72
|
+
(await this.getClient()).trackPageView({ name: pageName });
|
|
73
|
+
|
|
74
|
+
sendMetric = async (name: string, average: number) =>
|
|
75
|
+
(await this.getClient()).trackMetric({ name, average });
|
|
76
|
+
|
|
77
|
+
sendTrace = async (message: string) =>
|
|
78
|
+
(await this.getClient()).trackTrace({ message });
|
|
79
|
+
|
|
80
|
+
sendErrorReport = async (error: Error) => {
|
|
81
|
+
(await this.getClient()).trackException({ exception: error });
|
|
82
|
+
this.logger?.error(error);
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
flush = async () => (await this.getClient()).flush();
|
|
86
|
+
}
|