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:
Pritesh Nandgaonkar
2018-11-30 05:26:46 -08:00
committed by Facebook Github Bot
parent d37fa7ba95
commit fd022e3c73
8 changed files with 168 additions and 13 deletions

View File

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

View File

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