in desktop/flipper-ui-core/src/dispatcher/tracking.tsx [75:250]
export default (store: Store, logger: Logger) => {
const renderHost = getRenderHostInstance();
sideEffect(
store,
{
name: 'pluginUsageTracking',
throttleMs: 0,
noTimeBudgetWarns: true,
runSynchronously: true,
},
getSelectionInfo,
(selection, store) => {
const time = Date.now();
store.dispatch(selectionChanged({selection, time}));
},
);
let droppedFrames: number = 0;
let largeFrameDrops: number = 0;
const oldExitData = loadExitData();
if (oldExitData) {
const isReload =
renderHost.serverConfig.environmentInfo.processId === oldExitData.pid;
const timeSinceLastStartup =
Date.now() - parseInt(oldExitData.lastSeen, 10);
// console.log(isReload ? 'reload' : 'restart', oldExitData);
logger.track('usage', isReload ? 'reload' : 'restart', {
...oldExitData,
pid: undefined,
timeSinceLastStartup,
});
// create fresh exit data
const {selectedDevice, selectedAppId, selectedPlugin} =
store.getState().connections;
persistExitData(
{
selectedDevice,
selectedAppId,
selectedPlugin,
},
false,
);
}
function droppedFrameDetection(
past: DOMHighResTimeStamp,
isWindowFocused: () => boolean,
) {
const now = performance.now();
requestAnimationFrame(() => droppedFrameDetection(now, isWindowFocused));
const delta = now - past;
const dropped = Math.round(delta / (1000 / 60) - 1);
fpsEmitter.emit('fps', delta > 1000 ? 0 : Math.round(1000 / (now - past)));
if (!isWindowFocused() || dropped < 1) {
return;
}
droppedFrames += dropped;
if (dropped > 3) {
largeFrameDrops++;
}
}
if (typeof window !== 'undefined') {
droppedFrameDetection(
performance.now(),
() => store.getState().application.windowIsFocused,
);
}
renderHost.onIpcEvent('trackUsage', (...args: any[]) => {
let state: State;
try {
state = store.getState();
} catch (e) {
// if trackUsage is called (indirectly) through a reducer, this will utterly die Flipper. Let's prevent that and log an error instead
console.error(
'trackUsage triggered indirectly as side effect of a reducer',
e,
);
return;
}
const {selectedDevice, selectedPlugin, selectedAppId, clients} =
state.connections;
persistExitData(
{selectedDevice, selectedPlugin, selectedAppId},
args[0] === 'exit',
);
const currentTime = Date.now();
const usageSummary = computeUsageSummary(state.usageTracking, currentTime);
store.dispatch(clearTimeline(currentTime));
logger.track('usage', TIME_SPENT_EVENT, usageSummary.total);
for (const key of Object.keys(usageSummary.plugin)) {
logger.track(
'usage',
TIME_SPENT_EVENT,
usageSummary.plugin[key],
usageSummary.plugin[key]?.plugin ?? 'none',
);
}
Object.entries(state.connections.enabledPlugins).forEach(
([app, plugins]) => {
// TODO: remove "starred-plugns" event in favor of "enabled-plugins" after some transition period
logger.track('usage', 'starred-plugins', {
app,
starredPlugins: plugins,
});
logger.track('usage', 'enabled-plugins', {
app,
enabledPugins: plugins,
});
},
);
const bgStats = getPluginBackgroundStats();
logger.track('usage', 'plugin-stats', {
cpuTime: bgStats.cpuTime,
bytesReceived: bgStats.bytesReceived,
});
for (const key of Object.keys(bgStats.byPlugin)) {
const {
cpuTimeTotal: _a,
messageCountTotal: _b,
bytesReceivedTotal: _c,
...dataWithoutTotal
} = bgStats.byPlugin[key];
if (Object.values(dataWithoutTotal).some((v) => v > 0)) {
logger.track('usage', 'plugin-stats-plugin', dataWithoutTotal, key);
}
}
resetPluginBackgroundStatsDelta();
if (
!state.application.windowIsFocused ||
!selectedDevice ||
!selectedPlugin
) {
return;
}
let app: string | null = null;
let sdkVersion: number | null = null;
if (selectedAppId) {
const client = clients.get(selectedAppId);
if (client) {
app = client.query.app;
sdkVersion = client.query.sdk_version || 0;
}
}
const info = {
droppedFrames,
largeFrameDrops,
os: selectedDevice.os,
device: selectedDevice.title,
plugin: selectedPlugin,
app,
sdkVersion,
isForeground: state.application.windowIsFocused,
usedJSHeapSize: (window.performance as any).memory.usedJSHeapSize,
cpuLoad: renderHost.getPercentCPUUsage?.() ?? 0,
};
// reset dropped frames counter
droppedFrames = 0;
largeFrameDrops = 0;
logger.track('usage', 'ping', info);
});
};