Introduce useLogger hook

Summary: In the Flipper chrome there is a lot of `logger={logger}` prop drilling. Let's not do that anymore in the future by using a proper hook, which is exposed from `flipper-plugin`.

Reviewed By: passy

Differential Revision: D25421304

fbshipit-source-id: 01ec8563c67f7e2fac359c2f8216eba722bff8d9
This commit is contained in:
Michel Weststrate
2020-12-09 05:31:13 -08:00
committed by Facebook GitHub Bot
parent 083dbd3dbc
commit 4aff8c1bcf
7 changed files with 130 additions and 43 deletions

View File

@@ -7,33 +7,9 @@
* @format
*/
export type LogTypes = 'error' | 'warn' | 'info' | 'debug';
export type TrackType =
| 'duration'
| 'usage'
| 'performance'
| 'success-rate'
| 'operation-cancelled';
export {LogTypes, TrackType, Logger} from 'flipper-plugin';
export type Args = {
isHeadless?: boolean;
isTest?: boolean;
};
export interface Logger {
track(type: TrackType, event: string, data?: any, plugin?: string): void;
trackTimeSince(
mark: string,
eventName?: string | null | undefined,
data?: any,
): void;
info(data: any, category: string): void;
warn(data: any, category: string): void;
error(data: any, category: string): void;
debug(data: any, category: string): void;
}

View File

@@ -39,6 +39,8 @@ import {
_NuxManagerContext,
_createNuxManager,
_setGlobalInteractionReporter,
Logger,
_LoggerContext,
} from 'flipper-plugin';
import isProduction from './utils/isProduction';
import ReleaseChannel from './ReleaseChannel';
@@ -58,20 +60,22 @@ enableMapSet();
GK.init();
const AppFrame = () => (
<Provider store={store}>
<CacheProvider value={cache}>
<TooltipProvider>
<PopoverProvider>
<ContextMenuProvider>
<_NuxManagerContext.Provider value={_createNuxManager()}>
<App logger={logger} />
</_NuxManagerContext.Provider>
</ContextMenuProvider>
</PopoverProvider>
</TooltipProvider>
</CacheProvider>
</Provider>
const AppFrame = ({logger}: {logger: Logger}) => (
<_LoggerContext.Provider value={logger}>
<Provider store={store}>
<CacheProvider value={cache}>
<TooltipProvider>
<PopoverProvider>
<ContextMenuProvider>
<_NuxManagerContext.Provider value={_createNuxManager()}>
<App logger={logger} />
</_NuxManagerContext.Provider>
</ContextMenuProvider>
</PopoverProvider>
</TooltipProvider>
</CacheProvider>
</Provider>
</_LoggerContext.Provider>
);
function setProcessState(store: Store) {
@@ -107,7 +111,10 @@ function init() {
else console.error(msg, r.error);
}
});
ReactDOM.render(<AppFrame />, document.getElementById('root'));
ReactDOM.render(
<AppFrame logger={logger} />,
document.getElementById('root'),
);
initLauncherHooks(config(), store);
registerRecordingHooks(store);
enableConsoleHook();

View File

@@ -8,11 +8,10 @@
*/
import React, {useEffect, useState, useCallback} from 'react';
import {TrackingScope} from 'flipper-plugin';
import {TrackingScope, useLogger} from 'flipper-plugin';
import {styled} from '../ui';
import {Layout, Sidebar} from '../ui';
import {theme} from 'flipper-plugin';
import {Logger} from '../fb-interfaces/Logger';
import {LeftRail} from './LeftRail';
import {TemporarilyTitlebar} from './TemporarilyTitlebar';
@@ -44,7 +43,8 @@ export type ToplevelProps = {
setToplevelSelection: (_newSelection: ToplevelNavItem) => void;
};
export function SandyApp({logger}: {logger: Logger}) {
export function SandyApp() {
const logger = useLogger();
const dispatch = useDispatch();
const leftSidebarVisible = useStore(
(state) => state.application.leftSidebarVisible,

View File

@@ -38,6 +38,7 @@ test('Correct top level API exposed', () => {
"sleep",
"styled",
"theme",
"useLogger",
"usePlugin",
"useTrackedCallback",
"useValue",
@@ -57,9 +58,12 @@ test('Correct top level API exposed', () => {
"Draft",
"FlipperLib",
"LogLevel",
"LogTypes",
"Logger",
"MenuEntry",
"NormalizedMenuEntry",
"PluginClient",
"TrackType",
]
`);
});

View File

@@ -62,6 +62,13 @@ export {
} from './ui/Tracked';
export {sleep} from './utils/sleep';
export {
LogTypes,
TrackType,
Logger,
useLogger,
_LoggerContext,
} from './utils/Logger';
// It's not ideal that this exists in flipper-plugin sources directly,
// but is the least pain for plugin authors.

View File

@@ -0,0 +1,67 @@
/**
* 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 {createContext, useContext} from 'react';
export type LogTypes = 'error' | 'warn' | 'info' | 'debug';
export type TrackType =
| 'duration'
| 'usage'
| 'performance'
| 'success-rate'
| 'operation-cancelled';
export interface Logger {
track(type: TrackType, event: string, data?: any, plugin?: string): void;
trackTimeSince(
mark: string,
eventName?: string | null | undefined,
data?: any,
): void;
info(data: any, category: string): void;
warn(data: any, category: string): void;
error(data: any, category: string): void;
debug(data: any, category: string): void;
}
export const _LoggerContext = createContext<Logger>({
track() {},
trackTimeSince() {},
info() {
// eslint-disable-next-line
console.log.apply(console, arguments as any);
},
warn() {
// eslint-disable-next-line
console.warn.apply(console, arguments as any);
},
error() {
// eslint-disable-next-line
console.error.apply(console, arguments as any);
},
debug() {
// eslint-disable-next-line
console.debug.apply(console, arguments as any);
},
});
/**
* Provides the default logger that can be used for console logging,
* error reporting and performance measurements.
* In internal Facebook builds this is wired up to the internal statistic reporting.
* Prefer using `logger` over using `console` directly.
*/
export function useLogger(): Logger {
return useContext(_LoggerContext);
}

View File

@@ -361,6 +361,32 @@ Usage: `const currentValue = useValue(stateAtom)`
Returns the current value of a state atom, and also subscribes the current component to future changes of the atom (in contrast to using `stateAtom.get()` directly).
See the [tutorial](../tutorial/js-custom#building-an-user-interface-for-the-plugin) for how this hook is used in practice.
### useLogger
Usage: `const logger = useLogger()`
Provides the default logger that can be used for console logging, error reporting and performance measurements.
In internal Facebook builds this is wired up to the internal statistic reporting.
Prefer using `logger` over using `console` directly.
The logger API is defined as:
```typescript
interface Logger {
track(type: TrackType, event: string, data?: any, plugin?: string): void;
trackTimeSince(
mark: string,
eventName?: string | null | undefined,
data?: any,
): void;
info(data: any, category: string): void;
warn(data: any, category: string): void;
error(data: any, category: string): void;
debug(data: any, category: string): void;
}
```
## UI components
### Layout.*