Crash reporter plugin
Summary: This diff adds a static function `onRegisterDevice` which is being called whenever an device gets registered. This callback is used to add loglisterner for android. I even moved the logic of iOS from `onRegisterPlugin` to this callback. The reason for not adding android log listener in `onRegisterPlugin` was that there were cases when baseDevice was not yet registered before calling `onRegisterPlugin`. For android, I want the instance of `BaseDevice` so that I can add logListener on it. Reviewed By: danielbuechele Differential Revision: D13563282 fbshipit-source-id: b5be40f3dbc808bdaeabae28423c563cf2345a22
This commit is contained in:
committed by
Facebook Github Bot
parent
c6efea991d
commit
0048fc6e4a
@@ -11,6 +11,7 @@ import promiseRetry from 'promise-retry';
|
||||
import type {Store} from '../reducers/index.js';
|
||||
import type BaseDevice from '../devices/BaseDevice';
|
||||
import type Logger from '../fb-stubs/Logger.js';
|
||||
import {registerDeviceCallbackOnPlugins} from '../utils/onRegisterDevice.js';
|
||||
const adb = require('adbkit-fb');
|
||||
|
||||
function createDevice(adbClient, device): Promise<AndroidDevice> {
|
||||
@@ -165,6 +166,13 @@ export default (store: Store, logger: Logger) => {
|
||||
type: 'REGISTER_DEVICE',
|
||||
payload: androidDevice,
|
||||
});
|
||||
|
||||
registerDeviceCallbackOnPlugins(
|
||||
store,
|
||||
store.getState().plugins.devicePlugins,
|
||||
store.getState().plugins.clientPlugins,
|
||||
androidDevice,
|
||||
);
|
||||
}
|
||||
|
||||
async function unregisterDevices(deviceIds: Array<string>) {
|
||||
|
||||
@@ -18,7 +18,7 @@ import IOSDevice from '../devices/IOSDevice';
|
||||
import iosUtil from '../fb-stubs/iOSContainerUtility';
|
||||
import isProduction from '../utils/isProduction.js';
|
||||
import GK from '../fb-stubs/GK';
|
||||
|
||||
import {registerDeviceCallbackOnPlugins} from '../utils/onRegisterDevice.js';
|
||||
type iOSSimulatorDevice = {|
|
||||
state: 'Booted' | 'Shutdown' | 'Shutting Down',
|
||||
availability?: string,
|
||||
@@ -70,10 +70,17 @@ function queryDevices(store: Store, logger: Logger): Promise<void> {
|
||||
name: name,
|
||||
serial: udid,
|
||||
});
|
||||
const iOSDevice = new IOSDevice(udid, type, name);
|
||||
store.dispatch({
|
||||
type: 'REGISTER_DEVICE',
|
||||
payload: new IOSDevice(udid, type, name),
|
||||
payload: iOSDevice,
|
||||
});
|
||||
registerDeviceCallbackOnPlugins(
|
||||
store,
|
||||
store.getState().plugins.devicePlugins,
|
||||
store.getState().plugins.clientPlugins,
|
||||
iOSDevice,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -56,26 +56,6 @@ export default (store: Store, logger: Logger) => {
|
||||
store.dispatch(addFailedPlugins(failedPlugins));
|
||||
store.dispatch(registerPlugins(initialPlugins));
|
||||
|
||||
initialPlugins.forEach(p => {
|
||||
if (p.onRegisterPlugin) {
|
||||
p.onRegisterPlugin(store, (pluginKey: string, newPluginState: any) => {
|
||||
const persistedState = getPersistedState(
|
||||
pluginKey,
|
||||
p,
|
||||
store.getState().pluginStates,
|
||||
);
|
||||
if (newPluginState && newPluginState !== persistedState) {
|
||||
store.dispatch(
|
||||
setPluginState({
|
||||
pluginKey: pluginKey,
|
||||
state: newPluginState,
|
||||
}),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
let state: ?State = null;
|
||||
store.subscribe(() => {
|
||||
const newState = store.getState().plugins;
|
||||
|
||||
@@ -26,7 +26,7 @@ export type {Store} from './reducers/index.js';
|
||||
export {
|
||||
default as SidebarExtensions,
|
||||
} from './fb-stubs/LayoutInspectorSidebarExtensions.js';
|
||||
|
||||
export {DeviceLogListener, DeviceLogEntry} from './devices/BaseDevice.js';
|
||||
export {createTablePlugin} from './createTablePlugin.js';
|
||||
export {default as DetailSidebar} from './chrome/DetailSidebar.js';
|
||||
|
||||
|
||||
@@ -70,8 +70,9 @@ export class FlipperBasePlugin<
|
||||
static getActiveNotifications: ?(
|
||||
persistedState: PersistedState,
|
||||
) => Array<Notification>;
|
||||
static onRegisterPlugin: ?(
|
||||
static onRegisterDevice: ?(
|
||||
store: Store,
|
||||
baseDevice: BaseDevice,
|
||||
setPersistedState: (
|
||||
pluginKey: string,
|
||||
newPluginState: ?PersistedState,
|
||||
|
||||
@@ -26,7 +26,7 @@ import os from 'os';
|
||||
import util from 'util';
|
||||
import path from 'path';
|
||||
import type {Notification} from '../../plugin';
|
||||
import type {Store} from 'flipper';
|
||||
import type {Store, DeviceLogEntry} from 'flipper';
|
||||
|
||||
export type Crash = {|
|
||||
notificationID: string,
|
||||
@@ -107,6 +107,7 @@ export function parseCrashLogAndUpdateState(
|
||||
!shouldShowCrashNotification(
|
||||
store.getState().connections.selectedDevice,
|
||||
content,
|
||||
store.getState().connections.selectedDevice?.os,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@@ -140,7 +141,11 @@ export function parseCrashLogAndUpdateState(
|
||||
export function shouldShowCrashNotification(
|
||||
baseDevice: ?BaseDevice,
|
||||
content: string,
|
||||
os: ?string,
|
||||
): boolean {
|
||||
if (os && os.includes('Android')) {
|
||||
return true;
|
||||
}
|
||||
const appPath = parsePath(content);
|
||||
const serial: string = baseDevice?.serial || 'unknown';
|
||||
if (!appPath || !appPath.includes(serial)) {
|
||||
@@ -253,19 +258,6 @@ export default class CrashReporterPlugin extends FlipperDevicePlugin<
|
||||
return persistedState;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function gets called whenever plugin is registered
|
||||
*/
|
||||
static onRegisterPlugin = (
|
||||
store: Store,
|
||||
setPersistedState: (
|
||||
pluginKey: string,
|
||||
newPluginState: ?PersistedState,
|
||||
) => void,
|
||||
): void => {
|
||||
addFileWatcherForiOSCrashLogs(store, setPersistedState);
|
||||
};
|
||||
|
||||
static trimCallStackIfPossible = (callstack: string): string => {
|
||||
let regex = /Application Specific Information:/;
|
||||
const query = regex.exec(callstack);
|
||||
@@ -289,6 +281,45 @@ export default class CrashReporterPlugin extends FlipperDevicePlugin<
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
* This function gets called whenever the device is registered
|
||||
*/
|
||||
static onRegisterDevice = (
|
||||
store: Store,
|
||||
baseDevice: BaseDevice,
|
||||
setPersistedState: (
|
||||
pluginKey: string,
|
||||
newPluginState: ?PersistedState,
|
||||
) => void,
|
||||
): void => {
|
||||
if (baseDevice.os.includes('iOS')) {
|
||||
addFileWatcherForiOSCrashLogs(store, setPersistedState);
|
||||
} else {
|
||||
const referenceDate = new Date();
|
||||
(function(
|
||||
store: Store,
|
||||
date: Date,
|
||||
setPersistedState: (
|
||||
pluginKey: string,
|
||||
newPluginState: ?PersistedState,
|
||||
) => void,
|
||||
) {
|
||||
baseDevice.addLogListener((entry: DeviceLogEntry) => {
|
||||
if (
|
||||
entry.type === 'error' &&
|
||||
entry.tag === 'AndroidRuntime' &&
|
||||
entry.date.getTime() - date.getTime() > 0
|
||||
) {
|
||||
parseCrashLogAndUpdateState(
|
||||
store,
|
||||
entry.message,
|
||||
setPersistedState,
|
||||
);
|
||||
}
|
||||
});
|
||||
})(store, referenceDate, setPersistedState);
|
||||
}
|
||||
};
|
||||
openInLogs = (callstack: string) => {
|
||||
this.props.selectPlugin('DeviceLogs', callstack);
|
||||
};
|
||||
|
||||
44
src/utils/onRegisterDevice.js
Normal file
44
src/utils/onRegisterDevice.js
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Copyright 2018-present Facebook.
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
* @format
|
||||
*/
|
||||
import type {Store} from '../reducers/index.js';
|
||||
import {FlipperPlugin, FlipperDevicePlugin} from '../plugin.js';
|
||||
import type BaseDevice from '../devices/BaseDevice.js';
|
||||
import {setPluginState} from '../reducers/pluginStates.js';
|
||||
import {getPersistedState} from '../utils/pluginUtils.js';
|
||||
|
||||
export function registerDeviceCallbackOnPlugins(
|
||||
store: Store,
|
||||
devicePlugins: Map<string, Class<FlipperDevicePlugin<>>>,
|
||||
clientPlugins: Map<string, Class<FlipperPlugin<>>>,
|
||||
device: BaseDevice,
|
||||
) {
|
||||
const callRegisterDeviceHook = plugin => {
|
||||
if (plugin.onRegisterDevice) {
|
||||
plugin.onRegisterDevice(
|
||||
store,
|
||||
device,
|
||||
(pluginKey: string, newPluginState: any) => {
|
||||
const persistedState = getPersistedState(
|
||||
pluginKey,
|
||||
plugin,
|
||||
store.getState().pluginStates,
|
||||
);
|
||||
if (newPluginState && newPluginState !== persistedState) {
|
||||
store.dispatch(
|
||||
setPluginState({
|
||||
pluginKey,
|
||||
state: newPluginState,
|
||||
}),
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
};
|
||||
devicePlugins.forEach(callRegisterDeviceHook);
|
||||
clientPlugins.forEach(callRegisterDeviceHook);
|
||||
}
|
||||
Reference in New Issue
Block a user