Add framework event node level event filtering
Summary: Lets you filter a nodes events by thread or type Reviewed By: lblasa Differential Revision: D48346955 fbshipit-source-id: 455d65ad21c54c5ad26782ac6a446f7ae15a4356
This commit is contained in:
committed by
Facebook GitHub Bot
parent
3cd6079c24
commit
f5bc03c263
@@ -45,6 +45,9 @@ export class TimelineDataDescription extends Component<Props, State> {
|
||||
|
||||
render(): ReactNode {
|
||||
const moments = Object.values(this.props.timeline.time);
|
||||
if (moments == null || moments.length === 0) {
|
||||
return null;
|
||||
}
|
||||
const firstMoment = moments[0].moment;
|
||||
const points = moments.map((value) => ({
|
||||
label: value.display,
|
||||
|
||||
@@ -16,7 +16,9 @@ export function FrameworkEventsTreeSelect({
|
||||
onSetEventSelected,
|
||||
selected,
|
||||
placeholder,
|
||||
width,
|
||||
}: {
|
||||
width?: number;
|
||||
placeholder: string;
|
||||
selected: string[];
|
||||
treeData: TreeSelectNode[];
|
||||
@@ -33,7 +35,7 @@ export function FrameworkEventsTreeSelect({
|
||||
placeholder={placeholder}
|
||||
virtual={false} //for scrollbar
|
||||
style={{
|
||||
width: '100%',
|
||||
width: width ?? '100%',
|
||||
}}
|
||||
treeData={treeData}
|
||||
treeDefaultExpandAll
|
||||
|
||||
@@ -10,14 +10,20 @@
|
||||
import {
|
||||
DataInspector,
|
||||
Layout,
|
||||
produce,
|
||||
theme,
|
||||
TimelineDataDescription,
|
||||
} from 'flipper-plugin';
|
||||
import {FrameworkEvent, ClientNode} from '../../../ClientTypes';
|
||||
import React, {ReactNode} from 'react';
|
||||
import React, {ReactNode, useState} from 'react';
|
||||
import {StackTraceInspector} from './StackTraceInspector';
|
||||
import {Descriptions, Tag} from 'antd';
|
||||
import {Collapse, Descriptions, Select, Tag} from 'antd';
|
||||
import {frameworkEventSeparator} from '../../shared/FrameworkEventsTreeSelect';
|
||||
import {
|
||||
buildTreeSelectData,
|
||||
FrameworkEventsTreeSelect,
|
||||
} from '../../shared/FrameworkEventsTreeSelect';
|
||||
import {uniqBy} from 'lodash';
|
||||
|
||||
type Props = {
|
||||
node: ClientNode;
|
||||
@@ -29,30 +35,87 @@ export const FrameworkEventsInspector: React.FC<Props> = ({
|
||||
events,
|
||||
showExtra,
|
||||
}) => {
|
||||
const allThreads = uniqBy(events, 'thread').map((event) => event.thread);
|
||||
const [filteredThreads, setFilteredThreads] = useState<Set<string>>(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
const allEventTypes = uniqBy(events, 'type').map((event) => event.type);
|
||||
const [filteredEventTypes, setFilteredEventTypes] = useState<Set<string>>(
|
||||
new Set(),
|
||||
);
|
||||
|
||||
const filteredEvents = events
|
||||
.filter(
|
||||
(event) =>
|
||||
filteredEventTypes.size === 0 || filteredEventTypes.has(event.type),
|
||||
)
|
||||
.filter(
|
||||
(event) =>
|
||||
filteredThreads.size === 0 || filteredThreads.has(event.thread!),
|
||||
);
|
||||
|
||||
return (
|
||||
<TimelineDataDescription
|
||||
key={node.id}
|
||||
canSetCurrent={false}
|
||||
onClick={(current) => {
|
||||
const idx = parseInt(current, 10);
|
||||
const event = events[idx];
|
||||
showExtra?.(
|
||||
'Event details',
|
||||
<EventDetails event={event} node={node} />,
|
||||
);
|
||||
}}
|
||||
timeline={{
|
||||
time: events.map((event, idx) => {
|
||||
return {
|
||||
moment: event.timestamp,
|
||||
display: `${eventTypeToName(event.type)}`,
|
||||
color: threadToColor(event.thread),
|
||||
key: idx.toString(),
|
||||
};
|
||||
}),
|
||||
current: 'initialNone',
|
||||
}}
|
||||
/>
|
||||
<Layout.Container gap="small" padv="small">
|
||||
<Collapse>
|
||||
<Collapse.Panel header="Filter events" key="1">
|
||||
<Layout.Container gap="tiny">
|
||||
<FrameworkEventsTreeSelect
|
||||
placeholder="Select events types to filter by"
|
||||
treeData={buildTreeSelectData(allEventTypes)}
|
||||
width={250}
|
||||
onSetEventSelected={(eventType, selected) => {
|
||||
setFilteredEventTypes((cur) =>
|
||||
produce(cur, (draft) => {
|
||||
if (selected) {
|
||||
draft.add(eventType);
|
||||
} else {
|
||||
draft.delete(eventType);
|
||||
}
|
||||
}),
|
||||
);
|
||||
}}
|
||||
selected={[...filteredEventTypes]}
|
||||
/>
|
||||
<Select
|
||||
mode="multiple"
|
||||
style={{width: '250px'}}
|
||||
placeholder="Select threads to filter by"
|
||||
defaultValue={[] as string[]}
|
||||
options={allThreads.map((thread) => ({
|
||||
value: thread,
|
||||
label: thread,
|
||||
}))}
|
||||
onChange={(value) => setFilteredThreads(new Set(value))}
|
||||
/>
|
||||
</Layout.Container>
|
||||
</Collapse.Panel>
|
||||
</Collapse>
|
||||
|
||||
<TimelineDataDescription
|
||||
key={node.id}
|
||||
canSetCurrent={false}
|
||||
onClick={(current) => {
|
||||
const idx = parseInt(current, 10);
|
||||
const event = filteredEvents[idx];
|
||||
showExtra?.(
|
||||
'Event details',
|
||||
<EventDetails event={event} node={node} />,
|
||||
);
|
||||
}}
|
||||
timeline={{
|
||||
time: filteredEvents.map((event, idx) => {
|
||||
return {
|
||||
moment: event.timestamp,
|
||||
display: `${eventTypeToName(event.type)}`,
|
||||
color: threadToColor(event.thread),
|
||||
key: idx.toString(),
|
||||
};
|
||||
}),
|
||||
current: 'initialNone',
|
||||
}}
|
||||
/>
|
||||
</Layout.Container>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user