Show framework event metadata documentation in detail view and tree select
Reviewed By: lblasa Differential Revision: D48348090 fbshipit-source-id: e48547508b78178b278f72ce72fc579c9f015570
This commit is contained in:
committed by
Facebook GitHub Bot
parent
f5bc03c263
commit
4918d21df8
@@ -7,9 +7,11 @@
|
|||||||
* @format
|
* @format
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {TreeSelect} from 'antd';
|
import React, {ReactNode} from 'react';
|
||||||
import {FrameworkEventType} from '../../ClientTypes';
|
import {InfoCircleOutlined} from '@ant-design/icons';
|
||||||
import React from 'react';
|
import {Tooltip, TreeSelect} from 'antd';
|
||||||
|
import {Layout, theme} from 'flipper-plugin';
|
||||||
|
import {FrameworkEventMetadata, FrameworkEventType} from '../../ClientTypes';
|
||||||
|
|
||||||
export function FrameworkEventsTreeSelect({
|
export function FrameworkEventsTreeSelect({
|
||||||
treeData,
|
treeData,
|
||||||
@@ -55,7 +57,8 @@ export function FrameworkEventsTreeSelect({
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TreeSelectNode = {
|
type TreeSelectNode = {
|
||||||
title: string;
|
title: ReactNode;
|
||||||
|
titleValue: string;
|
||||||
key: string;
|
key: string;
|
||||||
value: string;
|
value: string;
|
||||||
children: TreeSelectNode[];
|
children: TreeSelectNode[];
|
||||||
@@ -84,8 +87,11 @@ export const frameworkEventSeparator = '.';
|
|||||||
/**
|
/**
|
||||||
* transformed flat event type data structure into tree
|
* transformed flat event type data structure into tree
|
||||||
*/
|
*/
|
||||||
export function buildTreeSelectData(eventTypes: string[]): TreeSelectNode[] {
|
export function buildTreeSelectData(
|
||||||
const root: TreeSelectNode = buildTreeSelectNode('root', 'root');
|
eventTypes: string[],
|
||||||
|
metadata: Map<FrameworkEventType, FrameworkEventMetadata>,
|
||||||
|
): TreeSelectNode[] {
|
||||||
|
const root: TreeSelectNode = buildTreeSelectNode('root', 'root', metadata);
|
||||||
|
|
||||||
eventTypes.forEach((eventType) => {
|
eventTypes.forEach((eventType) => {
|
||||||
const eventSubtypes = eventType.split(frameworkEventSeparator);
|
const eventSubtypes = eventType.split(frameworkEventSeparator);
|
||||||
@@ -95,7 +101,7 @@ export function buildTreeSelectData(eventTypes: string[]): TreeSelectNode[] {
|
|||||||
for (let i = 0; i < eventSubtypes.length - 1; i++) {
|
for (let i = 0; i < eventSubtypes.length - 1; i++) {
|
||||||
let foundChild = false;
|
let foundChild = false;
|
||||||
for (const child of currentNode.children) {
|
for (const child of currentNode.children) {
|
||||||
if (child.title === eventSubtypes[i]) {
|
if (child.titleValue === eventSubtypes[i]) {
|
||||||
currentNode = child;
|
currentNode = child;
|
||||||
foundChild = true;
|
foundChild = true;
|
||||||
break;
|
break;
|
||||||
@@ -105,6 +111,7 @@ export function buildTreeSelectData(eventTypes: string[]): TreeSelectNode[] {
|
|||||||
const newNode: TreeSelectNode = buildTreeSelectNode(
|
const newNode: TreeSelectNode = buildTreeSelectNode(
|
||||||
eventSubtypes[i],
|
eventSubtypes[i],
|
||||||
eventSubtypes.slice(0, i + 1).join(frameworkEventSeparator),
|
eventSubtypes.slice(0, i + 1).join(frameworkEventSeparator),
|
||||||
|
metadata,
|
||||||
);
|
);
|
||||||
|
|
||||||
currentNode.children.push(newNode);
|
currentNode.children.push(newNode);
|
||||||
@@ -118,6 +125,7 @@ export function buildTreeSelectData(eventTypes: string[]): TreeSelectNode[] {
|
|||||||
eventSubtypes
|
eventSubtypes
|
||||||
.slice(0, eventSubtypes.length)
|
.slice(0, eventSubtypes.length)
|
||||||
.join(frameworkEventSeparator),
|
.join(frameworkEventSeparator),
|
||||||
|
metadata,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -125,9 +133,29 @@ export function buildTreeSelectData(eventTypes: string[]): TreeSelectNode[] {
|
|||||||
return root.children;
|
return root.children;
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildTreeSelectNode(title: string, fullValue: string): TreeSelectNode {
|
function buildTreeSelectNode(
|
||||||
|
title: string,
|
||||||
|
fullValue: string,
|
||||||
|
metadata: Map<FrameworkEventType, FrameworkEventMetadata>,
|
||||||
|
): TreeSelectNode {
|
||||||
|
const documentation = metadata.get(fullValue)?.documentation;
|
||||||
return {
|
return {
|
||||||
title: title,
|
title: (
|
||||||
|
<Layout.Horizontal gap="small" center>
|
||||||
|
{title}
|
||||||
|
{documentation && (
|
||||||
|
<Tooltip title={documentation}>
|
||||||
|
<InfoCircleOutlined
|
||||||
|
style={{
|
||||||
|
color: theme.primaryColor,
|
||||||
|
fontSize: theme.fontSize.large,
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
)}
|
||||||
|
</Layout.Horizontal>
|
||||||
|
),
|
||||||
|
titleValue: title,
|
||||||
key: fullValue,
|
key: fullValue,
|
||||||
value: fullValue,
|
value: fullValue,
|
||||||
children: [],
|
children: [],
|
||||||
|
|||||||
@@ -43,6 +43,7 @@ export const Inspector: React.FC<Props> = ({
|
|||||||
const instance = usePlugin(plugin);
|
const instance = usePlugin(plugin);
|
||||||
const selectedNodeId = useValue(instance.uiState.selectedNode)?.id;
|
const selectedNodeId = useValue(instance.uiState.selectedNode)?.id;
|
||||||
|
|
||||||
|
const frameworkEventMetadata = useValue(instance.frameworkEventMetadata);
|
||||||
const selectedNode = selectedNodeId ? nodes.get(selectedNodeId) : undefined;
|
const selectedNode = selectedNodeId ? nodes.get(selectedNodeId) : undefined;
|
||||||
if (!selectedNode) {
|
if (!selectedNode) {
|
||||||
return <NoData message="Please select a node to view its details" />;
|
return <NoData message="Please select a node to view its details" />;
|
||||||
@@ -122,6 +123,7 @@ export const Inspector: React.FC<Props> = ({
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
}>
|
}>
|
||||||
<FrameworkEventsInspector
|
<FrameworkEventsInspector
|
||||||
|
frameworkEventMetadata={frameworkEventMetadata}
|
||||||
node={selectedNode}
|
node={selectedNode}
|
||||||
events={selectedFrameworkEvents}
|
events={selectedFrameworkEvents}
|
||||||
showExtra={showExtra}
|
showExtra={showExtra}
|
||||||
|
|||||||
@@ -14,7 +14,12 @@ import {
|
|||||||
theme,
|
theme,
|
||||||
TimelineDataDescription,
|
TimelineDataDescription,
|
||||||
} from 'flipper-plugin';
|
} from 'flipper-plugin';
|
||||||
import {FrameworkEvent, ClientNode} from '../../../ClientTypes';
|
import {
|
||||||
|
FrameworkEvent,
|
||||||
|
ClientNode,
|
||||||
|
FrameworkEventType,
|
||||||
|
FrameworkEventMetadata,
|
||||||
|
} from '../../../ClientTypes';
|
||||||
import React, {ReactNode, useState} from 'react';
|
import React, {ReactNode, useState} from 'react';
|
||||||
import {StackTraceInspector} from './StackTraceInspector';
|
import {StackTraceInspector} from './StackTraceInspector';
|
||||||
import {Collapse, Descriptions, Select, Tag} from 'antd';
|
import {Collapse, Descriptions, Select, Tag} from 'antd';
|
||||||
@@ -29,11 +34,13 @@ type Props = {
|
|||||||
node: ClientNode;
|
node: ClientNode;
|
||||||
events: readonly FrameworkEvent[];
|
events: readonly FrameworkEvent[];
|
||||||
showExtra?: (title: string, element: ReactNode) => void;
|
showExtra?: (title: string, element: ReactNode) => void;
|
||||||
|
frameworkEventMetadata: Map<FrameworkEventType, FrameworkEventMetadata>;
|
||||||
};
|
};
|
||||||
export const FrameworkEventsInspector: React.FC<Props> = ({
|
export const FrameworkEventsInspector: React.FC<Props> = ({
|
||||||
node,
|
node,
|
||||||
events,
|
events,
|
||||||
showExtra,
|
showExtra,
|
||||||
|
frameworkEventMetadata,
|
||||||
}) => {
|
}) => {
|
||||||
const allThreads = uniqBy(events, 'thread').map((event) => event.thread);
|
const allThreads = uniqBy(events, 'thread').map((event) => event.thread);
|
||||||
const [filteredThreads, setFilteredThreads] = useState<Set<string>>(
|
const [filteredThreads, setFilteredThreads] = useState<Set<string>>(
|
||||||
@@ -62,7 +69,10 @@ export const FrameworkEventsInspector: React.FC<Props> = ({
|
|||||||
<Layout.Container gap="tiny">
|
<Layout.Container gap="tiny">
|
||||||
<FrameworkEventsTreeSelect
|
<FrameworkEventsTreeSelect
|
||||||
placeholder="Select events types to filter by"
|
placeholder="Select events types to filter by"
|
||||||
treeData={buildTreeSelectData(allEventTypes)}
|
treeData={buildTreeSelectData(
|
||||||
|
allEventTypes,
|
||||||
|
frameworkEventMetadata,
|
||||||
|
)}
|
||||||
width={250}
|
width={250}
|
||||||
onSetEventSelected={(eventType, selected) => {
|
onSetEventSelected={(eventType, selected) => {
|
||||||
setFilteredEventTypes((cur) =>
|
setFilteredEventTypes((cur) =>
|
||||||
@@ -100,7 +110,11 @@ export const FrameworkEventsInspector: React.FC<Props> = ({
|
|||||||
const event = filteredEvents[idx];
|
const event = filteredEvents[idx];
|
||||||
showExtra?.(
|
showExtra?.(
|
||||||
'Event details',
|
'Event details',
|
||||||
<EventDetails event={event} node={node} />,
|
<EventDetails
|
||||||
|
frameworkEventMetadata={frameworkEventMetadata.get(event.type)}
|
||||||
|
event={event}
|
||||||
|
node={node}
|
||||||
|
/>,
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
timeline={{
|
timeline={{
|
||||||
@@ -122,7 +136,9 @@ export const FrameworkEventsInspector: React.FC<Props> = ({
|
|||||||
function EventDetails({
|
function EventDetails({
|
||||||
event,
|
event,
|
||||||
node,
|
node,
|
||||||
|
frameworkEventMetadata,
|
||||||
}: {
|
}: {
|
||||||
|
frameworkEventMetadata?: FrameworkEventMetadata;
|
||||||
event: FrameworkEvent;
|
event: FrameworkEvent;
|
||||||
node: ClientNode;
|
node: ClientNode;
|
||||||
}) {
|
}) {
|
||||||
@@ -138,6 +154,12 @@ function EventDetails({
|
|||||||
<Layout.Container>
|
<Layout.Container>
|
||||||
<Descriptions size="small" bordered column={1}>
|
<Descriptions size="small" bordered column={1}>
|
||||||
<Descriptions.Item label="Event type">{event.type}</Descriptions.Item>
|
<Descriptions.Item label="Event type">{event.type}</Descriptions.Item>
|
||||||
|
{frameworkEventMetadata && (
|
||||||
|
<Descriptions.Item label="Event documentation">
|
||||||
|
{frameworkEventMetadata?.documentation}
|
||||||
|
</Descriptions.Item>
|
||||||
|
)}
|
||||||
|
|
||||||
<Descriptions.Item label="Thread">
|
<Descriptions.Item label="Thread">
|
||||||
<Tag color={threadToColor(event.thread)}>{event.thread}</Tag>
|
<Tag color={threadToColor(event.thread)}>{event.thread}</Tag>
|
||||||
</Descriptions.Item>
|
</Descriptions.Item>
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import {
|
|||||||
SearchOutlined,
|
SearchOutlined,
|
||||||
} from '@ant-design/icons';
|
} from '@ant-design/icons';
|
||||||
import {usePlugin, useValue, Layout} from 'flipper-plugin';
|
import {usePlugin, useValue, Layout} from 'flipper-plugin';
|
||||||
import {FrameworkEventType} from '../../ClientTypes';
|
import {FrameworkEventMetadata, FrameworkEventType} from '../../ClientTypes';
|
||||||
import {
|
import {
|
||||||
buildTreeSelectData,
|
buildTreeSelectData,
|
||||||
FrameworkEventsTreeSelect,
|
FrameworkEventsTreeSelect,
|
||||||
@@ -35,6 +35,8 @@ export const TreeControls: React.FC = () => {
|
|||||||
instance.uiState.frameworkEventMonitoring,
|
instance.uiState.frameworkEventMonitoring,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const frameworkEventMetadata = useValue(instance.frameworkEventMetadata);
|
||||||
|
|
||||||
const [showFrameworkEventsModal, setShowFrameworkEventsModal] =
|
const [showFrameworkEventsModal, setShowFrameworkEventsModal] =
|
||||||
useState(false);
|
useState(false);
|
||||||
|
|
||||||
@@ -72,6 +74,7 @@ export const TreeControls: React.FC = () => {
|
|||||||
</Tooltip>
|
</Tooltip>
|
||||||
}></Button>
|
}></Button>
|
||||||
<FrameworkEventsMonitoringModal
|
<FrameworkEventsMonitoringModal
|
||||||
|
metadata={frameworkEventMetadata}
|
||||||
filterMainThreadMonitoring={filterMainThreadMonitoring}
|
filterMainThreadMonitoring={filterMainThreadMonitoring}
|
||||||
onSetFilterMainThreadMonitoring={
|
onSetFilterMainThreadMonitoring={
|
||||||
instance.uiActions.onSetFilterMainThreadMonitoring
|
instance.uiActions.onSetFilterMainThreadMonitoring
|
||||||
@@ -96,7 +99,9 @@ function FrameworkEventsMonitoringModal({
|
|||||||
onSetFilterMainThreadMonitoring,
|
onSetFilterMainThreadMonitoring,
|
||||||
filterMainThreadMonitoring,
|
filterMainThreadMonitoring,
|
||||||
frameworkEventTypes,
|
frameworkEventTypes,
|
||||||
|
metadata,
|
||||||
}: {
|
}: {
|
||||||
|
metadata: Map<FrameworkEventType, FrameworkEventMetadata>;
|
||||||
visible: boolean;
|
visible: boolean;
|
||||||
onCancel: () => void;
|
onCancel: () => void;
|
||||||
onSetEventMonitored: (
|
onSetEventMonitored: (
|
||||||
@@ -113,6 +118,7 @@ function FrameworkEventsMonitoringModal({
|
|||||||
|
|
||||||
const treeData = buildTreeSelectData(
|
const treeData = buildTreeSelectData(
|
||||||
frameworkEventTypes.map(([type]) => type),
|
frameworkEventTypes.map(([type]) => type),
|
||||||
|
metadata,
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -19,6 +19,7 @@ import {
|
|||||||
PerformanceStatsEvent,
|
PerformanceStatsEvent,
|
||||||
SnapshotInfo,
|
SnapshotInfo,
|
||||||
ClientNode,
|
ClientNode,
|
||||||
|
FrameworkEventMetadata,
|
||||||
} from './ClientTypes';
|
} from './ClientTypes';
|
||||||
import {
|
import {
|
||||||
UIState,
|
UIState,
|
||||||
@@ -50,6 +51,10 @@ export function plugin(client: PluginClient<Events>) {
|
|||||||
limit: 10000,
|
limit: 10000,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const frameworkEventMetadata = createState<
|
||||||
|
Map<FrameworkEventType, FrameworkEventMetadata>
|
||||||
|
>(new Map());
|
||||||
|
|
||||||
const uiState: UIState = createUIState();
|
const uiState: UIState = createUIState();
|
||||||
|
|
||||||
//this is the client data is what drives all of desktop UI
|
//this is the client data is what drives all of desktop UI
|
||||||
@@ -78,6 +83,11 @@ export function plugin(client: PluginClient<Events>) {
|
|||||||
draft.set(frameworkEventMeta.type, false);
|
draft.set(frameworkEventMeta.type, false);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
frameworkEventMetadata.update((draft) => {
|
||||||
|
event.frameworkEventMetadata?.forEach((frameworkEventMeta) => {
|
||||||
|
draft.set(frameworkEventMeta.type, frameworkEventMeta);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
client.onConnect(() => {
|
client.onConnect(() => {
|
||||||
@@ -301,6 +311,7 @@ export function plugin(client: PluginClient<Events>) {
|
|||||||
uiActions: uiActions(uiState, nodesAtom, snapshot, mutableLiveClientData),
|
uiActions: uiActions(uiState, nodesAtom, snapshot, mutableLiveClientData),
|
||||||
nodes: nodesAtom,
|
nodes: nodesAtom,
|
||||||
frameworkEvents,
|
frameworkEvents,
|
||||||
|
frameworkEventMetadata,
|
||||||
snapshot,
|
snapshot,
|
||||||
metadata,
|
metadata,
|
||||||
perfEvents,
|
perfEvents,
|
||||||
|
|||||||
Reference in New Issue
Block a user