From d7355c5e2f2e66956f2354872e649b91b47c0b85 Mon Sep 17 00:00:00 2001 From: Jiri Zbytovsky Date: Thu, 5 Dec 2024 15:47:34 +0100 Subject: [PATCH] feat(suite): add optional system information to analytics --- .../middlewares/suite/analyticsMiddleware.ts | 9 +- .../src/middlewares/suite/sentryMiddleware.ts | 5 +- packages/suite/src/utils/suite/analytics.ts | 92 ++++++++++++------- 3 files changed, 68 insertions(+), 38 deletions(-) diff --git a/packages/suite/src/middlewares/suite/analyticsMiddleware.ts b/packages/suite/src/middlewares/suite/analyticsMiddleware.ts index ba751a7019f..c2296c3741c 100644 --- a/packages/suite/src/middlewares/suite/analyticsMiddleware.ts +++ b/packages/suite/src/middlewares/suite/analyticsMiddleware.ts @@ -95,9 +95,12 @@ const analyticsMiddleware = switch (action.type) { case SUITE.READY: // reporting can start when analytics is properly initialized and enabled - analytics.report({ - type: EventType.SuiteReady, - payload: getSuiteReadyPayload(state), + // it is done async because ipcMain is queried for system info, if available + getSuiteReadyPayload(state).then(payload => { + analytics.report({ + type: EventType.SuiteReady, + payload, + }); }); break; case TRANSPORT.START: diff --git a/packages/suite/src/middlewares/suite/sentryMiddleware.ts b/packages/suite/src/middlewares/suite/sentryMiddleware.ts index 6d761268aaf..1de721d47e0 100644 --- a/packages/suite/src/middlewares/suite/sentryMiddleware.ts +++ b/packages/suite/src/middlewares/suite/sentryMiddleware.ts @@ -97,7 +97,10 @@ const sentryMiddleware = switch (action.type) { case SUITE.READY: - setSentryContext('suite-ready', getSuiteReadyPayload(state)); + // done async because ipcMain is queried for system info, if available + getSuiteReadyPayload(state).then(payload => + setSentryContext('suite-ready', payload), + ); break; case DEVICE.CONNECT: { const { features, mode } = action.payload.device; diff --git a/packages/suite/src/utils/suite/analytics.ts b/packages/suite/src/utils/suite/analytics.ts index 07f633d4e2a..e51863e9e7d 100644 --- a/packages/suite/src/utils/suite/analytics.ts +++ b/packages/suite/src/utils/suite/analytics.ts @@ -9,10 +9,12 @@ import { getWindowWidth, getWindowHeight, getPlatformLanguages, + isDesktop, } from '@trezor/env-utils'; import { getCustomBackends } from '@suite-common/wallet-utils'; import { UNIT_ABBREVIATIONS } from '@suite-common/suite-constants'; -import type { UpdateInfo } from '@trezor/suite-desktop-api'; +import { desktopApi, UpdateInfo } from '@trezor/suite-desktop-api'; +import { GetSystemInformationResponse } from '@trezor/suite-desktop-api/src/messages'; import { selectRememberedStandardWalletsCount, selectRememberedHiddenWalletsCount, @@ -23,6 +25,17 @@ import { AppState } from 'src/types/suite'; import { getIsTorEnabled } from './tor'; +const getOptionalSystemInformation = async (): Promise => { + if (!isDesktop()) return null; + try { + const response = await desktopApi.getSystemInformation(); + + return response.success ? response.payload : null; + } catch { + return null; + } +}; + // redact transaction id from account transaction anchor export const redactTransactionIdFromAnchor = (anchor?: string) => { if (!anchor) { @@ -35,39 +48,50 @@ export const redactTransactionIdFromAnchor = (anchor?: string) => { // 1. replace coinjoin by taproot export const redactRouterUrl = (url: string) => url.replace(/coinjoin/g, 'taproot'); -export const getSuiteReadyPayload = (state: AppState) => ({ - language: state.suite.settings.language, - enabledNetworks: state.wallet.settings.enabledNetworks, - customBackends: getCustomBackends(state.wallet.blockchain) - .map(({ coin }) => coin) - .filter(coin => state.wallet.settings.enabledNetworks.includes(coin)), - localCurrency: state.wallet.settings.localCurrency, - bitcoinUnit: UNIT_ABBREVIATIONS[state.wallet.settings.bitcoinAmountUnit], - discreetMode: state.wallet.settings.discreetMode, - screenWidth: getScreenWidth(), - screenHeight: getScreenHeight(), - platformLanguages: getPlatformLanguages().join(','), - tor: getIsTorEnabled(state.suite.torStatus), - // todo: duplicated with suite/src/utils/suite/logUtils - labeling: state.metadata.enabled - ? state.metadata.providers.find(p => p.clientId === state.metadata.selectedProvider.labels) - ?.type || 'missing-provider' - : '', - rememberedStandardWallets: selectRememberedStandardWalletsCount(state), - rememberedHiddenWallets: selectRememberedHiddenWalletsCount(state), - theme: state.suite.settings.theme.variant, - suiteVersion: process.env.VERSION || '', - earlyAccessProgram: state.desktopUpdate.allowPrerelease, - experimentalFeatures: state.suite.settings.experimental, - browserName: getBrowserName(), - browserVersion: getBrowserVersion(), - osName: getOsName(), - osVersion: getOsVersion(), - windowWidth: getWindowWidth(), - windowHeight: getWindowHeight(), - autodetectLanguage: state.suite.settings.autodetect.language, - autodetectTheme: state.suite.settings.autodetect.theme, -}); +export const getSuiteReadyPayload = async (state: AppState) => { + const systemInformation = await getOptionalSystemInformation(); + + return { + language: state.suite.settings.language, + enabledNetworks: state.wallet.settings.enabledNetworks, + customBackends: getCustomBackends(state.wallet.blockchain) + .map(({ coin }) => coin) + .filter(coin => state.wallet.settings.enabledNetworks.includes(coin)), + localCurrency: state.wallet.settings.localCurrency, + bitcoinUnit: UNIT_ABBREVIATIONS[state.wallet.settings.bitcoinAmountUnit], + discreetMode: state.wallet.settings.discreetMode, + screenWidth: getScreenWidth(), + screenHeight: getScreenHeight(), + platformLanguages: getPlatformLanguages().join(','), + tor: getIsTorEnabled(state.suite.torStatus), + // todo: duplicated with suite/src/utils/suite/logUtils + labeling: state.metadata.enabled + ? state.metadata.providers.find( + p => p.clientId === state.metadata.selectedProvider.labels, + )?.type || 'missing-provider' + : '', + rememberedStandardWallets: selectRememberedStandardWalletsCount(state), + rememberedHiddenWallets: selectRememberedHiddenWalletsCount(state), + theme: state.suite.settings.theme.variant, + suiteVersion: process.env.VERSION || '', + earlyAccessProgram: state.desktopUpdate.allowPrerelease, + experimentalFeatures: state.suite.settings.experimental, + browserName: getBrowserName(), + browserVersion: getBrowserVersion(), + osName: getOsName(), + // version from UA parser, which includes only the most basic info as it runs in renderer process + osVersion: getOsVersion(), + // detailed info obtained in main process, if available + desktopOsVersion: systemInformation?.osVersion, + desktopOsName: systemInformation?.osName, + desktopOsArchitecture: systemInformation?.osArchitecture, + + windowWidth: getWindowWidth(), + windowHeight: getWindowHeight(), + autodetectLanguage: state.suite.settings.autodetect.language, + autodetectTheme: state.suite.settings.autodetect.theme, + }; +}; export const getAppUpdatePayload = ( status: AppUpdateEvent['status'],