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
This commit is contained in:
Michel Weststrate
2020-03-19 02:45:37 -07:00
committed by Facebook GitHub Bot
parent cfb82ad8c8
commit ddf5df98c7
2 changed files with 64 additions and 0 deletions

View File

@@ -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),
);
}

View File

@@ -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