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:
Luke De Feo
2023-08-21 04:24:16 -07:00
committed by Facebook GitHub Bot
parent 3cd6079c24
commit f5bc03c263
3 changed files with 94 additions and 26 deletions

View File

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

View File

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

View File

@@ -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,20 +35,76 @@ 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 (
<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 = events[idx];
const event = filteredEvents[idx];
showExtra?.(
'Event details',
<EventDetails event={event} node={node} />,
);
}}
timeline={{
time: events.map((event, idx) => {
time: filteredEvents.map((event, idx) => {
return {
moment: event.timestamp,
display: `${eventTypeToName(event.type)}`,
@@ -53,6 +115,7 @@ export const FrameworkEventsInspector: React.FC<Props> = ({
current: 'initialNone',
}}
/>
</Layout.Container>
);
};