Introduced first class console to help users debugging issues (#1479)

Summary:
Handling issues typically start with: did you look at the Electron logs? Since Flipper is such an extensible tool, running in varying environments I think the console should be support as first class concept. Many errors are currently not shown to the user. This PR is a first attempt to fix that.

The implementation is based on https://github.com/samdenty/console-feed, which is used by quite some web based IDE like tools (like codesandbox), and offers a lot of goodies out of the box, like collapsing errors, objects, etc.

Edit: also added a counter keeping track of the amount of errors

N.B. no need to immediately review this diff, I'll import it to phabricator as soon as I can :)

## Changelog

changelog: Introduce 'Debug Logs' section to help users to troubleshoot issues or to provide more accurate reports.

Pull Request resolved: https://github.com/facebook/flipper/pull/1479

Test Plan: ![Screenshot from 2020-08-18 15-29-55](https://user-images.githubusercontent.com/1820292/90526011-c9b22d80-e167-11ea-88cf-7b4e07918a96.png)

Reviewed By: jknoxville

Differential Revision: D23198103

Pulled By: passy

fbshipit-source-id: a2505f9fa59e10676a44ffa33312efe83c7be55d
This commit is contained in:
Michel Weststrate
2020-08-20 13:26:39 -07:00
committed by Facebook GitHub Bot
parent baa29d0b49
commit dd15cffa64
8 changed files with 185 additions and 7 deletions

View File

@@ -23,6 +23,7 @@
"archiver": "^5.0.0", "archiver": "^5.0.0",
"async-mutex": "^0.1.3", "async-mutex": "^0.1.3",
"axios": "^0.19.2", "axios": "^0.19.2",
"console-feed": "^3.0.1",
"deep-equal": "^2.0.1", "deep-equal": "^2.0.1",
"emotion": "^10.0.23", "emotion": "^10.0.23",
"expand-tilde": "^2.0.2", "expand-tilde": "^2.0.2",

View File

@@ -0,0 +1,93 @@
/**
* Copyright (c) Facebook, Inc. and its 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 {useMemo} from 'react';
import {Button, Toolbar, ButtonGroup, Layout} from '../ui';
import React from 'react';
import {Console, Hook} from 'console-feed';
import type {Methods} from 'console-feed/lib/definitions/Methods';
import {createState, useValue} from 'flipper-plugin';
import {useLocalStorage} from '../utils/useLocalStorage';
const logsAtom = createState<any[]>([]);
export const errorCounterAtom = createState(0);
export function enableConsoleHook() {
console.log('enabling hooks');
Hook(
window.console,
(log) => {
logsAtom.set([...logsAtom.get(), log]);
if (log.method === 'error' || log.method === 'assert') {
errorCounterAtom.set(errorCounterAtom.get() + 1);
}
},
false,
);
}
function clearLogs() {
logsAtom.set([]);
errorCounterAtom.set(0);
}
const allLogLevels: Methods[] = [
'log',
'debug',
'info',
'warn',
'error',
'table',
'clear',
'time',
'timeEnd',
'count',
'assert',
];
const defaultLogLevels: Methods[] = ['warn', 'error', 'table', 'assert'];
export function ConsoleLogs() {
const logs = useValue(logsAtom);
const [logLevels, setLogLevels] = useLocalStorage<Methods[]>(
'console-logs-loglevels',
defaultLogLevels,
);
const dropdown = useMemo(() => {
return allLogLevels.map(
(l): Electron.MenuItemConstructorOptions => ({
label: l,
checked: logLevels.includes(l),
type: 'checkbox',
click() {
setLogLevels((state) =>
state.includes(l)
? state.filter((level) => level !== l)
: [l, ...state],
);
},
}),
);
}, [logLevels, setLogLevels]);
return (
<Layout.Top scrollable>
<Toolbar>
<ButtonGroup>
<Button onClick={clearLogs} icon="trash">
Clear Logs
</Button>
<Button dropdown={dropdown}>Log Levels</Button>
</ButtonGroup>
</Toolbar>
<Console logs={logs} filter={logLevels} variant="light" />
</Layout.Top>
);
}

View File

@@ -29,6 +29,8 @@ import {
} from './sidebarUtils'; } from './sidebarUtils';
import {Group} from '../../reducers/supportForm'; import {Group} from '../../reducers/supportForm';
import {getInstance} from '../../fb-stubs/Logger'; import {getInstance} from '../../fb-stubs/Logger';
import {ConsoleLogs, errorCounterAtom} from '../ConsoleLogs';
import {useValue} from 'flipper-plugin';
type OwnProps = {}; type OwnProps = {};
@@ -103,6 +105,7 @@ function MainSidebarUtilsSection({
/> />
Manage Plugins Manage Plugins
</ListItem> </ListItem>
<DebugLogsEntry staticView={staticView} setStaticView={setStaticView} />
{config.showLogin && <UserAccount />} {config.showLogin && <UserAccount />}
</div> </div>
); );
@@ -171,3 +174,26 @@ const RenderNotificationsEntry = connect<
</ListItem> </ListItem>
); );
}); });
function DebugLogsEntry({
staticView,
setStaticView,
}: {
staticView: StaticView;
setStaticView: (payload: StaticView) => void;
}) {
const active = isStaticViewActive(staticView, ConsoleLogs);
const errorCount = useValue(errorCounterAtom);
return (
<ListItem onClick={() => setStaticView(ConsoleLogs)} active={active}>
<PluginIcon
name="caution-octagon"
color={colors.light50}
isActive={active}
/>
<PluginName count={errorCount} isActive={active}>
Debug Logs
</PluginName>
</ListItem>
);
}

View File

@@ -85,6 +85,7 @@ const PluginShape = styled(FlexBox)<{
export const PluginName = styled(Text)<{isActive?: boolean; count?: number}>( export const PluginName = styled(Text)<{isActive?: boolean; count?: number}>(
(props) => ({ (props) => ({
cursor: 'default',
minWidth: 0, minWidth: 0,
textOverflow: 'ellipsis', textOverflow: 'ellipsis',
whiteSpace: 'nowrap', whiteSpace: 'nowrap',

View File

@@ -38,6 +38,7 @@ import os from 'os';
import QuickPerformanceLogger, {FLIPPER_QPL_EVENTS} from './fb-stubs/QPL'; import QuickPerformanceLogger, {FLIPPER_QPL_EVENTS} from './fb-stubs/QPL';
import {PopoverProvider} from './ui/components/PopoverProvider'; import {PopoverProvider} from './ui/components/PopoverProvider';
import {initializeFlipperLibImplementation} from './utils/flipperLibImplementation'; import {initializeFlipperLibImplementation} from './utils/flipperLibImplementation';
import {enableConsoleHook} from './chrome/ConsoleLogs';
if (process.env.NODE_ENV === 'development' && os.platform() === 'darwin') { if (process.env.NODE_ENV === 'development' && os.platform() === 'darwin') {
// By default Node.JS has its internal certificate storage and doesn't use // By default Node.JS has its internal certificate storage and doesn't use
@@ -119,6 +120,7 @@ function init() {
const sessionId = store.getState().application.sessionId; const sessionId = store.getState().application.sessionId;
initCrashReporter(sessionId || ''); initCrashReporter(sessionId || '');
registerRecordingHooks(store); registerRecordingHooks(store);
enableConsoleHook();
window.flipperGlobalStoreDispatch = store.dispatch; window.flipperGlobalStoreDispatch = store.dispatch;
} }

View File

@@ -27,13 +27,15 @@ import {getPluginKey, isDevicePluginDefinition} from '../utils/pluginUtils';
import {deconstructClientId} from '../utils/clientUtils'; import {deconstructClientId} from '../utils/clientUtils';
import {PluginDefinition} from '../plugin'; import {PluginDefinition} from '../plugin';
import {RegisterPluginAction} from './plugins'; import {RegisterPluginAction} from './plugins';
import {ConsoleLogs} from '../chrome/ConsoleLogs';
export type StaticView = export type StaticView =
| null | null
| typeof WelcomeScreen | typeof WelcomeScreen
| typeof NotificationScreen | typeof NotificationScreen
| typeof SupportRequestFormV2 | typeof SupportRequestFormV2
| typeof SupportRequestDetails; | typeof SupportRequestDetails
| typeof ConsoleLogs;
export type FlipperError = { export type FlipperError = {
occurrences?: number; occurrences?: number;

View File

@@ -50,6 +50,7 @@
16 16
], ],
"caution-octagon": [ "caution-octagon": [
12,
16, 16,
20 20
], ],

View File

@@ -1240,10 +1240,10 @@
"@emotion/utils" "0.11.3" "@emotion/utils" "0.11.3"
"@emotion/weak-memoize" "0.2.5" "@emotion/weak-memoize" "0.2.5"
"@emotion/core@^10.0.22": "@emotion/core@^10.0.10", "@emotion/core@^10.0.22":
version "10.0.28" version "10.0.35"
resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.28.tgz#bb65af7262a234593a9e952c041d0f1c9b9bef3d" resolved "https://registry.yarnpkg.com/@emotion/core/-/core-10.0.35.tgz#513fcf2e22cd4dfe9d3894ed138c9d7a859af9b3"
integrity sha512-pH8UueKYO5jgg0Iq+AmCLxBsvuGtvlmiDCOuv8fGNYn3cowFpLN98L8zO56U0H1PjDIyAlXymgL3Wu7u7v6hbA== integrity sha512-sH++vJCdk025fBlRZSAhkRlSUoqSqgCzYf5fMOmqqi3bM6how+sQpg3hkgJonj8GxXM4WbD7dRO+4tegDB9fUw==
dependencies: dependencies:
"@babel/runtime" "^7.5.5" "@babel/runtime" "^7.5.5"
"@emotion/cache" "^10.0.27" "@emotion/cache" "^10.0.27"
@@ -1304,7 +1304,7 @@
"@emotion/serialize" "^0.11.15" "@emotion/serialize" "^0.11.15"
"@emotion/utils" "0.11.3" "@emotion/utils" "0.11.3"
"@emotion/styled@^10.0.23": "@emotion/styled@^10.0.12", "@emotion/styled@^10.0.23":
version "10.0.27" version "10.0.27"
resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf" resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-10.0.27.tgz#12cb67e91f7ad7431e1875b1d83a94b814133eaf"
integrity sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q== integrity sha512-iK/8Sh7+NLJzyp9a5+vIQIXTYxfT4yB/OJbjzQanB2RZpvmzBQOHZWhpAMZWYEKRNNbsD6WfBw5sVWkb6WzS/Q==
@@ -4134,6 +4134,17 @@ connect@^3.6.5:
parseurl "~1.3.3" parseurl "~1.3.3"
utils-merge "1.0.1" utils-merge "1.0.1"
console-feed@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/console-feed/-/console-feed-3.0.1.tgz#2ca6dec57aee15ff3af300c323008fba542536a0"
integrity sha512-RD49E64OOm9qRAsbvTB0UnMFTtjEo7fKW8cSwqcgA9B45EraNFtFJjWppje+YPZpfhHHX579u+RtzLFm77mhTA==
dependencies:
"@emotion/core" "^10.0.10"
"@emotion/styled" "^10.0.12"
emotion-theming "^10.0.10"
linkifyjs "^2.1.6"
react-inspector "^3.0.2"
contains-path@^0.1.0: contains-path@^0.1.0:
version "0.1.0" version "0.1.0"
resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a" resolved "https://registry.yarnpkg.com/contains-path/-/contains-path-0.1.0.tgz#fe8cf184ff6670b6baef01a9d4861a5cbec4120a"
@@ -4966,6 +4977,15 @@ emoji-regex@^9.0.0:
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4" resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.0.0.tgz#48a2309cc8a1d2e9d23bc6a67c39b63032e76ea4"
integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w== integrity sha512-6p1NII1Vm62wni/VR/cUMauVQoxmLVb9csqQlvLz+hO2gk8U2UYDfXHQSUYIBKmZwAKz867IDqG7B+u0mj+M6w==
emotion-theming@^10.0.10:
version "10.0.27"
resolved "https://registry.yarnpkg.com/emotion-theming/-/emotion-theming-10.0.27.tgz#1887baaec15199862c89b1b984b79806f2b9ab10"
integrity sha512-MlF1yu/gYh8u+sLUqA0YuA9JX0P4Hb69WlKc/9OLo+WCXuX6sy/KoIa+qJimgmr2dWqnypYKYPX37esjDBbhdw==
dependencies:
"@babel/runtime" "^7.5.5"
"@emotion/weak-memoize" "0.2.5"
hoist-non-react-statics "^3.3.0"
emotion@^10.0.23: emotion@^10.0.23:
version "10.0.27" version "10.0.27"
resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.27.tgz#f9ca5df98630980a23c819a56262560562e5d75e" resolved "https://registry.yarnpkg.com/emotion/-/emotion-10.0.27.tgz#f9ca5df98630980a23c819a56262560562e5d75e"
@@ -6827,6 +6847,14 @@ is-docker@^2.0.0:
resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b" resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.0.0.tgz#2cb0df0e75e2d064fe1864c37cdeacb7b2dcf25b"
integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ== integrity sha512-pJEdRugimx4fBMra5z2/5iRdZ63OhYV0vr0Dwm5+xtW4D1FvRkB8hamMIhnWfyJeDdyr/aa7BDyNbtG38VxgoQ==
is-dom@^1.0.9:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-dom/-/is-dom-1.1.0.tgz#af1fced292742443bb59ca3f76ab5e80907b4e8a"
integrity sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ==
dependencies:
is-object "^1.0.1"
is-window "^1.0.2"
is-extendable@^0.1.0, is-extendable@^0.1.1: is-extendable@^0.1.0, is-extendable@^0.1.1:
version "0.1.1" version "0.1.1"
resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89" resolved "https://registry.yarnpkg.com/is-extendable/-/is-extendable-0.1.1.tgz#62b110e289a471418e3ec36a617d472e301dfc89"
@@ -6916,6 +6944,11 @@ is-obj@^2.0.0:
resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982" resolved "https://registry.yarnpkg.com/is-obj/-/is-obj-2.0.0.tgz#473fb05d973705e3fd9620545018ca8e22ef4982"
integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w== integrity sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==
is-object@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/is-object/-/is-object-1.0.1.tgz#8952688c5ec2ffd6b03ecc85e769e02903083470"
integrity sha1-iVJojF7C/9awPsyF52ngKQMINHA=
is-path-inside@^3.0.1: is-path-inside@^3.0.1:
version "3.0.2" version "3.0.2"
resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017" resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.2.tgz#f5220fc82a3e233757291dddc9c5877f2a1f3017"
@@ -7012,6 +7045,11 @@ is-whitespace-character@^1.0.0:
resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7" resolved "https://registry.yarnpkg.com/is-whitespace-character/-/is-whitespace-character-1.0.4.tgz#0858edd94a95594c7c9dd0b5c174ec6e45ee4aa7"
integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w== integrity sha512-SDweEzfIZM0SJV0EUga669UTKlmL0Pq8Lno0QDQsPnvECB3IM2aP0gdx5TrU0A01MAPfViaZiI2V1QMZLaKK5w==
is-window@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-window/-/is-window-1.0.2.tgz#2c896ca53db97de45d3c33133a65d8c9f563480d"
integrity sha1-LIlspT25feRdPDMTOmXYyfVjSA0=
is-windows@^1.0.2: is-windows@^1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d"
@@ -8194,6 +8232,11 @@ linked-list@0.1.0:
resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf" resolved "https://registry.yarnpkg.com/linked-list/-/linked-list-0.1.0.tgz#798b0ff97d1b92a4fd08480f55aea4e9d49d37bf"
integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78= integrity sha1-eYsP+X0bkqT9CEgPVa6k6dSdN78=
linkifyjs@^2.1.6:
version "2.1.9"
resolved "https://registry.yarnpkg.com/linkifyjs/-/linkifyjs-2.1.9.tgz#af06e45a2866ff06c4766582590d098a4d584702"
integrity sha512-74ivurkK6WHvHFozVaGtQWV38FzBwSTGNmJolEgFp7QgR2bl6ArUWlvT4GcHKbPe1z3nWYi+VUdDZk16zDOVug==
live-plugin-manager@^0.14.1: live-plugin-manager@^0.14.1:
version "0.14.1" version "0.14.1"
resolved "https://registry.yarnpkg.com/live-plugin-manager/-/live-plugin-manager-0.14.1.tgz#34b6bb8f3d2062ec2557c857ca028fea9dc2b6db" resolved "https://registry.yarnpkg.com/live-plugin-manager/-/live-plugin-manager-0.14.1.tgz#34b6bb8f3d2062ec2557c857ca028fea9dc2b6db"
@@ -9797,7 +9840,7 @@ prompts@^2.0.1:
kleur "^3.0.3" kleur "^3.0.3"
sisteransi "^1.0.3" sisteransi "^1.0.3"
prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2: prop-types@^15.5.10, prop-types@^15.5.6, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7.2:
version "15.7.2" version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5" resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ== integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -9995,6 +10038,15 @@ react-dom@^16.13.0:
prop-types "^15.6.2" prop-types "^15.6.2"
scheduler "^0.19.1" scheduler "^0.19.1"
react-inspector@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/react-inspector/-/react-inspector-3.0.2.tgz#c530a06101f562475537e47df428e1d7aff16ed8"
integrity sha512-PSR8xDoGFN8R3LKmq1NT+hBBwhxjd9Qwz8yKY+5NXY/CHpxXHm01CVabxzI7zFwFav/M3JoC/Z0Ro2kSX6Ef2Q==
dependencies:
babel-runtime "^6.26.0"
is-dom "^1.0.9"
prop-types "^15.6.1"
react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0: react-is@^16.12.0, react-is@^16.7.0, react-is@^16.8.1, react-is@^16.8.6, react-is@^16.9.0:
version "16.13.1" version "16.13.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4"