From ddf5df98c76b04e8e010b63fcb054357f00c0f9c Mon Sep 17 00:00:00 2001 From: Michel Weststrate Date: Thu, 19 Mar 2020 02:45:37 -0700 Subject: [PATCH] Track flipper crashes / restarts Summary: In this diff we persist data about the state of the app when exiting, and to make sure we capture it in crashes, do that as part of track-usage events as well. with the exit data we also capture what kind of device and plugin the user was using, so that we can detect anomalies like flipper needing restarting more often for certain plugins during startup, we will always send an event how long it was since the last startup, including the above information Reviewed By: passy Differential Revision: D20515200 fbshipit-source-id: ead971e05542e0ef58ed5e5b204af70b51a15b9b --- desktop/src/dispatcher/tracking.tsx | 63 +++++++++++++++++++++++++++++ desktop/static/main.ts | 1 + 2 files changed, 64 insertions(+) diff --git a/desktop/src/dispatcher/tracking.tsx b/desktop/src/dispatcher/tracking.tsx index f21ba1f4b..f9e90dd1e 100644 --- a/desktop/src/dispatcher/tracking.tsx +++ b/desktop/src/dispatcher/tracking.tsx @@ -24,6 +24,8 @@ import { State as UsageTrackingState, } from '../reducers/usageTracking'; import produce from 'immer'; +import {BaseDevice} from 'flipper'; +import {deconstructClientId} from '../utils/clientUtils'; const TIME_SPENT_EVENT = 'time-spent'; @@ -43,6 +45,17 @@ export const fpsEmitter = new EventEmitter(); export default (store: Store, logger: Logger) => { let droppedFrames: number = 0; let largeFrameDrops: number = 0; + + const oldExitData = loadExitData(); + if (oldExitData) { + const timeSinceLastStartup = + Date.now() - parseInt(oldExitData.lastSeen, 10); + logger.track('usage', 'restart', { + ...oldExitData, + timeSinceLastStartup, + }); + } + function droppedFrameDetection( past: DOMHighResTimeStamp, isWindowFocused: () => boolean, @@ -77,6 +90,8 @@ export default (store: Store, logger: Logger) => { clients, } = state.connections; + persistExitData({selectedDevice, selectedPlugin, selectedApp}); + const currentTime = Date.now(); const usageSummary = computeUsageSummary(state.usageTracking, currentTime); @@ -195,3 +210,51 @@ export function computeUsageSummary( }, ); } + +const flipperExitDataKey = 'FlipperExitData'; + +interface ExitData { + lastSeen: string; + deviceOs: string; + deviceType: string; + deviceTitle: string; + plugin: string; + app: string; +} + +function loadExitData(): ExitData | undefined { + if (!window.localStorage) { + return undefined; + } + const data = window.localStorage.getItem(flipperExitDataKey); + if (data) { + try { + return JSON.parse(data); + } catch (e) { + console.warn('Failed to parse flipperExitData', e); + } + } + return undefined; +} + +export function persistExitData(state: { + selectedDevice: BaseDevice | null; + selectedPlugin: string | null; + selectedApp: string | null; +}) { + if (!window.localStorage) { + return; + } + const exitData: ExitData = { + lastSeen: '' + Date.now(), + deviceOs: state.selectedDevice ? state.selectedDevice.os : '', + deviceType: state.selectedDevice ? state.selectedDevice.deviceType : '', + deviceTitle: state.selectedDevice ? state.selectedDevice.title : '', + plugin: state.selectedPlugin || '', + app: state.selectedApp ? deconstructClientId(state.selectedApp).app : '', + }; + window.localStorage.setItem( + flipperExitDataKey, + JSON.stringify(exitData, null, 2), + ); +} diff --git a/desktop/static/main.ts b/desktop/static/main.ts index cc6cbe2cf..aaaf79e37 100644 --- a/desktop/static/main.ts +++ b/desktop/static/main.ts @@ -305,6 +305,7 @@ function tryCreateWindow() { }); win.once('ready-to-show', () => win.show()); win.once('close', () => { + win.webContents.send('trackUsage'); if (process.env.NODE_ENV === 'development') { // Removes as a default protocol for debug builds. Because even when the // production application is installed, and one tries to deeplink through