Connectivity Logs moved outside from TroubleshootingHub

Summary: Move it to its own space.

Reviewed By: antonk52

Differential Revision: D47914495

fbshipit-source-id: 8d655a8f0fc9ed87adbb4c31dfb04e72aa6f5770
This commit is contained in:
Lorenzo Blasa
2023-07-31 07:02:16 -07:00
committed by Facebook GitHub Bot
parent 778eaf2038
commit 9ba93ad26b
3 changed files with 190 additions and 179 deletions

View File

@@ -0,0 +1,185 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
*/
import {Layout} from '../ui';
import React, {CSSProperties, useState} from 'react';
import {
createDataSource,
DataFormatter,
DataInspector,
DataTable,
DataTableColumn,
theme,
styled,
} from 'flipper-plugin';
import {CloseCircleFilled, DeleteOutlined} from '@ant-design/icons';
import {
CommandRecordEntry,
ConnectionRecordEntry,
FlipperServer,
} from 'flipper-common';
import {Button} from 'antd';
const rows = createDataSource<ConnectionRecordEntry>([], {
limit: 200000,
persist: 'connectivity-logs',
});
export function enableConnectivityHook(flipperServer: FlipperServer) {
flipperServer.on(
'connectivity-troubleshoot-log',
(entry: ConnectionRecordEntry) => {
rows.append(entry);
},
);
flipperServer.on(
'connectivity-troubleshoot-cmd',
(entry: CommandRecordEntry) => {
rows.append(entry);
},
);
}
const iconStyle = {
fontSize: '16px',
};
const baseRowStyle = {
...theme.monospace,
};
const logTypes: {
[level: string]: {
label: string;
icon?: React.ReactNode;
style?: CSSProperties;
enabled: boolean;
};
} = {
log: {
label: 'Log',
enabled: true,
},
cmd: {
label: 'Shell',
enabled: true,
style: {
...baseRowStyle,
color: theme.primaryColor,
},
icon: <CloseCircleFilled style={iconStyle} />,
},
error: {
label: 'Error',
style: {
...baseRowStyle,
color: theme.errorColor,
},
icon: <CloseCircleFilled style={iconStyle} />,
enabled: true,
},
};
function createColumnConfig(): DataTableColumn<ConnectionRecordEntry>[] {
return [
{
key: 'time',
title: 'Time',
width: 160,
},
{
key: 'device',
title: 'Device',
width: 160,
},
{
key: 'app',
title: 'App',
width: 160,
visible: true,
},
{
key: 'medium',
title: 'Medium',
width: 80,
visible: true,
},
{
key: 'message',
title: 'Message',
wrap: true,
formatters: [
DataFormatter.truncate(400),
DataFormatter.prettyPrintJson,
DataFormatter.linkify,
],
},
];
}
const columns = createColumnConfig();
function getRowStyle(entry: ConnectionRecordEntry): CSSProperties | undefined {
return (logTypes[entry.type]?.style as any) ?? baseRowStyle;
}
const Placeholder = styled(Layout.Container)({
center: true,
color: theme.textColorPlaceholder,
fontSize: 18,
});
function Sidebar({selection}: {selection: undefined | ConnectionRecordEntry}) {
return (
<Layout.ScrollContainer pad>
{selection != null ? (
<DataInspector data={selection} expandRoot />
) : (
<Placeholder grow pad="large">
Select an entry to visualize details
</Placeholder>
)}
</Layout.ScrollContainer>
);
}
function clearMessages() {
rows.clear();
}
export const ConnectivityLogs = () => {
const [selection, setSelection] = useState<
ConnectionRecordEntry | undefined
>();
const clearButton = (
<Button
title="Clear logs"
onClick={() => {
setSelection(undefined);
clearMessages();
}}>
<DeleteOutlined />
</Button>
);
return (
<Layout.Right resizable width={400}>
<DataTable<ConnectionRecordEntry>
dataSource={rows}
columns={columns}
enableAutoScroll
onRowStyle={getRowStyle}
onSelect={setSelection}
extraActions={clearButton}
/>
<Sidebar selection={selection} />
</Layout.Right>
);
};

View File

@@ -8,186 +8,12 @@
*/ */
import {Layout} from '../ui'; import {Layout} from '../ui';
import React, {CSSProperties, useState} from 'react'; import React from 'react';
import { import {Tab, Tabs} from 'flipper-plugin';
createDataSource,
DataFormatter,
DataInspector,
DataTable,
DataTableColumn,
Tab,
Tabs,
theme,
styled,
} from 'flipper-plugin';
import {CloseCircleFilled, DeleteOutlined} from '@ant-design/icons';
import {
CommandRecordEntry,
ConnectionRecordEntry,
FlipperServer,
} from 'flipper-common';
import SetupDoctorScreen from '../sandy-chrome/SetupDoctorScreen'; import SetupDoctorScreen from '../sandy-chrome/SetupDoctorScreen';
import {ConsoleLogs} from './ConsoleLogs'; import {ConsoleLogs} from './ConsoleLogs';
import {FlipperMessages} from './FlipperMessages'; import {FlipperMessages} from './FlipperMessages';
import {Button} from 'antd'; import {ConnectivityLogs} from './ConnectivityLogs';
const rows = createDataSource<ConnectionRecordEntry>([], {
limit: 200000,
persist: 'connectivity-logs',
});
export function enableConnectivityHook(flipperServer: FlipperServer) {
flipperServer.on(
'connectivity-troubleshoot-log',
(entry: ConnectionRecordEntry) => {
rows.append(entry);
},
);
flipperServer.on(
'connectivity-troubleshoot-cmd',
(entry: CommandRecordEntry) => {
rows.append(entry);
},
);
}
const iconStyle = {
fontSize: '16px',
};
const baseRowStyle = {
...theme.monospace,
};
const logTypes: {
[level: string]: {
label: string;
icon?: React.ReactNode;
style?: CSSProperties;
enabled: boolean;
};
} = {
log: {
label: 'Log',
enabled: true,
},
cmd: {
label: 'Shell',
enabled: true,
style: {
...baseRowStyle,
color: theme.primaryColor,
},
icon: <CloseCircleFilled style={iconStyle} />,
},
error: {
label: 'Error',
style: {
...baseRowStyle,
color: theme.errorColor,
},
icon: <CloseCircleFilled style={iconStyle} />,
enabled: true,
},
};
function createColumnConfig(): DataTableColumn<ConnectionRecordEntry>[] {
return [
{
key: 'time',
title: 'Time',
width: 160,
},
{
key: 'device',
title: 'Device',
width: 160,
},
{
key: 'app',
title: 'App',
width: 160,
visible: true,
},
{
key: 'medium',
title: 'Medium',
width: 80,
visible: true,
},
{
key: 'message',
title: 'Message',
wrap: true,
formatters: [
DataFormatter.truncate(400),
DataFormatter.prettyPrintJson,
DataFormatter.linkify,
],
},
];
}
const columns = createColumnConfig();
function getRowStyle(entry: ConnectionRecordEntry): CSSProperties | undefined {
return (logTypes[entry.type]?.style as any) ?? baseRowStyle;
}
const Placeholder = styled(Layout.Container)({
center: true,
color: theme.textColorPlaceholder,
fontSize: 18,
});
function Sidebar({selection}: {selection: undefined | ConnectionRecordEntry}) {
return (
<Layout.ScrollContainer pad>
{selection != null ? (
<DataInspector data={selection} expandRoot />
) : (
<Placeholder grow pad="large">
Select an entry to visualize details
</Placeholder>
)}
</Layout.ScrollContainer>
);
}
function clearMessages() {
rows.clear();
}
const LogView = () => {
const [selection, setSelection] = useState<
ConnectionRecordEntry | undefined
>();
const clearButton = (
<Button
title="Clear logs"
onClick={() => {
setSelection(undefined);
clearMessages();
}}>
<DeleteOutlined />
</Button>
);
return (
<Layout.Right resizable width={400}>
<DataTable<ConnectionRecordEntry>
dataSource={rows}
columns={columns}
enableAutoScroll
onRowStyle={getRowStyle}
onSelect={setSelection}
extraActions={clearButton}
/>
<Sidebar selection={selection} />
</Layout.Right>
);
};
export function TroubleshootingHub() { export function TroubleshootingHub() {
return ( return (
@@ -197,7 +23,7 @@ export function TroubleshootingHub() {
<SetupDoctorScreen visible modal={false} onClose={() => {}} /> <SetupDoctorScreen visible modal={false} onClose={() => {}} />
</Tab> </Tab>
<Tab tab="Connectivity Logs" tabKey="connectivity-logs"> <Tab tab="Connectivity Logs" tabKey="connectivity-logs">
<LogView /> <ConnectivityLogs />
</Tab> </Tab>
<Tab tab="Console Logs" tabKey="console-logs"> <Tab tab="Console Logs" tabKey="console-logs">
<ConsoleLogs /> <ConsoleLogs />

View File

@@ -43,7 +43,7 @@ import {getRenderHostInstance} from 'flipper-frontend-core';
import {startGlobalErrorHandling} from './utils/globalErrorHandling'; import {startGlobalErrorHandling} from './utils/globalErrorHandling';
import {loadTheme} from './utils/loadTheme'; import {loadTheme} from './utils/loadTheme';
import {connectFlipperServerToStore} from './dispatcher/flipperServer'; import {connectFlipperServerToStore} from './dispatcher/flipperServer';
import {enableConnectivityHook} from './chrome/TroubleshootingHub'; import {enableConnectivityHook} from './chrome/ConnectivityLogs';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
class AppFrame extends React.Component< class AppFrame extends React.Component<