Skip to content

Commit 75b9869

Browse files
author
Juan
authored
[DevTools] Extension reports logged events when feature flag is enabled (react#22475)
1 parent 4717724 commit 75b9869

5 files changed

Lines changed: 96 additions & 24 deletions

File tree

packages/react-devtools-extensions/src/main.js

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ import {
1818
localStorageRemoveItem,
1919
localStorageSetItem,
2020
} from 'react-devtools-shared/src/storage';
21-
import {registerEventLogger} from 'react-devtools-shared/src/Logger';
2221
import DevTools from 'react-devtools-shared/src/devtools/views/DevTools';
2322
import {__DEBUG__} from 'react-devtools-shared/src/constants';
23+
import {registerExtensionsEventLogger} from './registerExtensionsEventLogger';
2424

2525
const LOCAL_STORAGE_SUPPORTS_PROFILING_KEY =
2626
'React::DevTools::supportsProfiling';
@@ -88,9 +88,7 @@ function createPanelIfReactLoaded() {
8888

8989
const tabId = chrome.devtools.inspectedWindow.tabId;
9090

91-
registerEventLogger((event: LogEvent) => {
92-
// TODO: hook up event logging
93-
});
91+
registerExtensionsEventLogger();
9492

9593
function initBridgeAndStore() {
9694
const port = chrome.runtime.connect({
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
/**
2+
* Copyright (c) Facebook, Inc. and its affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*
7+
* @flow strict-local
8+
*/
9+
10+
import type {LogEvent} from 'react-devtools-shared/src/Logger';
11+
12+
import {registerEventLogger} from 'react-devtools-shared/src/Logger';
13+
import {enableLogger} from 'react-devtools-feature-flags';
14+
15+
let loggingIFrame = null;
16+
let missedEvents = [];
17+
function logEvent(event: LogEvent) {
18+
if (enableLogger) {
19+
if (loggingIFrame != null) {
20+
loggingIFrame.contentWindow.postMessage(
21+
{
22+
source: 'react-devtools-logging',
23+
event: event,
24+
context: {
25+
surface: 'extension',
26+
},
27+
},
28+
'*',
29+
);
30+
} else {
31+
missedEvents.push(event);
32+
}
33+
}
34+
}
35+
36+
function handleLoggingIFrameLoaded(iframe) {
37+
if (loggingIFrame != null) {
38+
return;
39+
}
40+
41+
loggingIFrame = iframe;
42+
if (missedEvents.length > 0) {
43+
missedEvents.forEach(logEvent);
44+
missedEvents = [];
45+
}
46+
}
47+
48+
export function registerExtensionsEventLogger() {
49+
// If logger is enabled, register a logger that captures logged events
50+
// and render iframe where the logged events will be reported to
51+
if (enableLogger) {
52+
const loggingUrl = process.env.LOGGING_URL;
53+
const body = document.body;
54+
if (
55+
typeof loggingUrl === 'string' &&
56+
loggingUrl.length > 0 &&
57+
body != null
58+
) {
59+
registerEventLogger(logEvent);
60+
61+
const iframe = document.createElement('iframe');
62+
iframe.src = loggingUrl;
63+
iframe.onload = function(...args) {
64+
handleLoggingIFrameLoaded(iframe);
65+
};
66+
body.appendChild(iframe);
67+
}
68+
}
69+
}

packages/react-devtools-extensions/webpack.config.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ const __DEV__ = NODE_ENV === 'development';
3232

3333
const DEVTOOLS_VERSION = getVersionString();
3434

35+
const LOGGING_URL = process.env.LOGGING_URL || null;
36+
3537
const featureFlagTarget = process.env.FEATURE_FLAG_TARGET || 'extension-oss';
3638

3739
const babelOptions = {
@@ -91,6 +93,7 @@ module.exports = {
9193
'process.env.DEVTOOLS_PACKAGE': `"react-devtools-extensions"`,
9294
'process.env.DEVTOOLS_VERSION': `"${DEVTOOLS_VERSION}"`,
9395
'process.env.GITHUB_URL': `"${GITHUB_URL}"`,
96+
'process.env.LOGGING_URL': `"${LOGGING_URL}"`,
9497
'process.env.NODE_ENV': `"${NODE_ENV}"`,
9598
'process.env.DARK_MODE_DIMMED_WARNING_COLOR': `"${DARK_MODE_DIMMED_WARNING_COLOR}"`,
9699
'process.env.DARK_MODE_DIMMED_ERROR_COLOR': `"${DARK_MODE_DIMMED_ERROR_COLOR}"`,

packages/react-devtools-shared/src/Logger.js

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,11 @@
1010
import {enableLogger} from 'react-devtools-feature-flags';
1111

1212
type LoadHookNamesEvent = {|
13-
+name: 'loadHookNames',
14-
+displayName: string | null,
15-
+numberOfHooks: number | null,
16-
+durationMs: number,
17-
+resolution: 'success' | 'error' | 'timeout' | 'unknown',
13+
+event_name: 'loadHookNames',
14+
+event_status: 'success' | 'error' | 'timeout' | 'unknown',
15+
+duration_ms: number,
16+
+inspected_element_display_name: string | null,
17+
+inspected_element_number_of_hooks: number | null,
1818
|};
1919

2020
// prettier-ignore
@@ -23,25 +23,27 @@ export type LogEvent =
2323

2424
export type LogFunction = LogEvent => void;
2525

26-
let loggers: Array<LogFunction> = [];
26+
let logFunctions: Array<LogFunction> = [];
2727
export const logEvent: LogFunction =
2828
enableLogger === true
2929
? function logEvent(event: LogEvent): void {
30-
loggers.forEach(log => {
30+
logFunctions.forEach(log => {
3131
log(event);
3232
});
3333
}
3434
: function logEvent() {};
3535

3636
export const registerEventLogger =
3737
enableLogger === true
38-
? function registerEventLogger(eventLogger: LogFunction): () => void {
38+
? function registerEventLogger(logFunction: LogFunction): () => void {
3939
if (enableLogger) {
40-
loggers.push(eventLogger);
40+
logFunctions.push(logFunction);
4141
return function unregisterEventLogger() {
42-
loggers = loggers.filter(logger => logger !== eventLogger);
42+
logFunctions = logFunctions.filter(log => log !== logFunction);
4343
};
4444
}
4545
return () => {};
4646
}
47-
: function registerEventLogger() {};
47+
: function registerEventLogger(logFunction: LogFunction) {
48+
return () => {};
49+
};

packages/react-devtools-shared/src/hookNamesCache.js

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ export function loadHookNames(
9999

100100
let timeoutID;
101101
let didTimeout = false;
102-
let resolution = 'unknown';
102+
let status = 'unknown';
103103
let resolvedHookNames: HookNames | null = null;
104104

105105
const wake = () => {
@@ -116,11 +116,11 @@ export function loadHookNames(
116116
const handleLoadComplete = (durationMs: number): void => {
117117
// Log duration for parsing hook names
118118
logEvent({
119-
name: 'loadHookNames',
120-
displayName: element.displayName,
121-
numberOfHooks: resolvedHookNames?.size ?? null,
122-
durationMs,
123-
resolution,
119+
event_name: 'loadHookNames',
120+
event_status: status,
121+
duration_ms: durationMs,
122+
inspected_element_display_name: element.displayName,
123+
inspected_element_number_of_hooks: resolvedHookNames?.size ?? null,
124124
});
125125
};
126126

@@ -152,7 +152,7 @@ export function loadHookNames(
152152
notFoundRecord.value = null;
153153
}
154154

155-
resolution = 'success';
155+
status = 'success';
156156
resolvedHookNames = hookNames;
157157
done();
158158
wake();
@@ -172,7 +172,7 @@ export function loadHookNames(
172172
thrownRecord.status = Rejected;
173173
thrownRecord.value = null;
174174

175-
resolution = 'error';
175+
status = 'error';
176176
done();
177177
wake();
178178
},
@@ -192,7 +192,7 @@ export function loadHookNames(
192192
timedoutRecord.status = Rejected;
193193
timedoutRecord.value = null;
194194

195-
resolution = 'timeout';
195+
status = 'timeout';
196196
done();
197197
wake();
198198
}, TIMEOUT);

0 commit comments

Comments
 (0)