Improvise UI of crash reporter plugin
Summary: - New improved UI - Instead of sending the callstack as a string from android, now sending it as an array - Deeplink to Logs support just for android. In iOS crash is not automatically logged in Logs plugin, atleast thats what happens in sample app Reviewed By: jknoxville Differential Revision: D13216477 fbshipit-source-id: d8b77549c83572d0442e431ce88a8f01f42c9565
This commit is contained in:
committed by
Facebook Github Bot
parent
d37fa7ba95
commit
fd022e3c73
@@ -6,7 +6,17 @@
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import {FlipperDevicePlugin, Device} from 'flipper';
|
||||
import {
|
||||
FlipperDevicePlugin,
|
||||
Device,
|
||||
View,
|
||||
styled,
|
||||
FlexColumn,
|
||||
FlexRow,
|
||||
ContextMenu,
|
||||
clipboard,
|
||||
Button,
|
||||
} from 'flipper';
|
||||
import type {Notification} from '../../plugin';
|
||||
|
||||
type Crash = {|
|
||||
@@ -19,6 +29,34 @@ type PersistedState = {|
|
||||
crashes: Array<Crash>,
|
||||
|};
|
||||
|
||||
const Title = styled(View)({
|
||||
fontWeight: 'bold',
|
||||
fontSize: '100%',
|
||||
color: 'red',
|
||||
});
|
||||
|
||||
const Value = styled(View)({
|
||||
paddingLeft: '8px',
|
||||
fontSize: '100%',
|
||||
fontFamily: 'Monospace',
|
||||
});
|
||||
|
||||
const RootColumn = styled(FlexColumn)({
|
||||
paddingLeft: '16px',
|
||||
paddingRight: '16px',
|
||||
paddingTop: '8px',
|
||||
});
|
||||
|
||||
const CrashRow = styled(FlexRow)({
|
||||
paddingTop: '8px',
|
||||
});
|
||||
|
||||
const CallStack = styled('pre')({
|
||||
fontFamily: 'Monospace',
|
||||
fontSize: '100%',
|
||||
paddingLeft: '8px',
|
||||
});
|
||||
|
||||
export default class CrashReporterPlugin extends FlipperDevicePlugin {
|
||||
static title = 'Crash Reporter';
|
||||
static id = 'CrashReporter';
|
||||
@@ -67,11 +105,70 @@ export default class CrashReporterPlugin extends FlipperDevicePlugin {
|
||||
message: crash.callStack,
|
||||
severity: 'error',
|
||||
title: 'CRASH: ' + crash.name + ' ' + crash.reason,
|
||||
action: 'Inspect',
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
convertCallstackToString(crash: Crash): string {
|
||||
return crash.callStack.reduce((acc, val) => acc.concat('\n', val));
|
||||
}
|
||||
|
||||
render() {
|
||||
return 'Dedicated space to debug crashes. Look out for crash notifications.';
|
||||
if (this.props.persistedState.crashes.length > 0) {
|
||||
const crash = this.props.persistedState.crashes.slice(-1)[0];
|
||||
const callStackString = this.convertCallstackToString(crash);
|
||||
return (
|
||||
<RootColumn>
|
||||
<CrashRow>
|
||||
<Title>Name</Title>
|
||||
<Value>{crash.name}</Value>
|
||||
</CrashRow>
|
||||
<CrashRow>
|
||||
<Title>Reason</Title>
|
||||
<Value>{crash.reason}</Value>
|
||||
</CrashRow>
|
||||
<CrashRow>
|
||||
<Title>CallStack</Title>
|
||||
</CrashRow>
|
||||
<CrashRow>
|
||||
<ContextMenu
|
||||
items={[
|
||||
{
|
||||
label: 'copy',
|
||||
click: () => {
|
||||
clipboard.writeText(callStackString);
|
||||
},
|
||||
},
|
||||
]}>
|
||||
<CallStack>{callStackString}</CallStack>
|
||||
</ContextMenu>
|
||||
</CrashRow>
|
||||
{this.device.os == 'Android' && (
|
||||
<CrashRow>
|
||||
<Button
|
||||
onClick={event => {
|
||||
this.props.selectPlugin(
|
||||
'DeviceLogs',
|
||||
JSON.stringify({
|
||||
...crash,
|
||||
callStackString: callStackString,
|
||||
}),
|
||||
);
|
||||
}}>
|
||||
Deeplink to Logs
|
||||
</Button>
|
||||
</CrashRow>
|
||||
)}
|
||||
</RootColumn>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<RootColumn>
|
||||
<Title>
|
||||
Dedicated space to debug crashes. Look out for crash notifications
|
||||
</Title>
|
||||
</RootColumn>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -280,6 +280,30 @@ export default class LogTable extends FlipperDevicePlugin<
|
||||
}));
|
||||
};
|
||||
|
||||
calculateHighlightedRows = (
|
||||
deeplinkPayload: ?string,
|
||||
rows: Array<TableBodyRow>,
|
||||
): Array<string> => {
|
||||
if (!deeplinkPayload) {
|
||||
return [];
|
||||
}
|
||||
const crash = JSON.parse(deeplinkPayload);
|
||||
let highlightedRows = rows.filter(x => {
|
||||
//$FlowFixMe: x.filterValue is not undefined
|
||||
let matched = x.filterValue.includes(crash.name);
|
||||
if (!matched) {
|
||||
return matched;
|
||||
}
|
||||
for (let i = 0; i < crash.callStack.length && matched; ++i) {
|
||||
//$FlowFixMe: x.filterValue is not undefined
|
||||
matched = x.filterValue.includes(crash.callStack[i]);
|
||||
}
|
||||
return matched;
|
||||
});
|
||||
highlightedRows = highlightedRows.map(x => x.key);
|
||||
return [highlightedRows.pop()];
|
||||
};
|
||||
|
||||
state = {
|
||||
rows: [],
|
||||
entries: [],
|
||||
@@ -390,7 +414,6 @@ export default class LogTable extends FlipperDevicePlugin<
|
||||
key: String(this.counter++),
|
||||
},
|
||||
};
|
||||
|
||||
// batch up logs to be processed every 250ms, if we have lots of log
|
||||
// messages coming in, then calling an setState 200+ times is actually
|
||||
// pretty expensive
|
||||
@@ -425,11 +448,15 @@ export default class LogTable extends FlipperDevicePlugin<
|
||||
|
||||
this.addRowIfNeeded(rows, row, entry, previousEntry);
|
||||
}
|
||||
|
||||
const highlightedRows = this.calculateHighlightedRows(
|
||||
this.props.deepLinkPayload,
|
||||
rows,
|
||||
);
|
||||
return {
|
||||
entries,
|
||||
rows,
|
||||
key2entry,
|
||||
highlightedRows: highlightedRows,
|
||||
};
|
||||
});
|
||||
}, 100);
|
||||
@@ -547,8 +574,7 @@ export default class LogTable extends FlipperDevicePlugin<
|
||||
});
|
||||
|
||||
render() {
|
||||
const {rows} = this.state;
|
||||
|
||||
const {rows, highlightedRows} = this.state;
|
||||
const contextMenuItems = [
|
||||
{
|
||||
type: 'separator',
|
||||
@@ -568,6 +594,9 @@ export default class LogTable extends FlipperDevicePlugin<
|
||||
columnOrder={this.columnOrder}
|
||||
columns={this.columns}
|
||||
rows={rows}
|
||||
highlightedRows={
|
||||
highlightedRows ? new Set(highlightedRows) : new Set([])
|
||||
}
|
||||
onRowHighlighted={this.onRowHighlighted}
|
||||
multiHighlight={true}
|
||||
defaultFilters={DEFAULT_FILTERS}
|
||||
|
||||
Reference in New Issue
Block a user