feat[react-devtools-extensions/logging]: initialize session id on the client for logging (#27517)
This code is executed once React DevTools panels are mounted, basically when user opens browser's DevTools. Based on this fact, session in this case is defined by browser's DevTools session, while they are open. A session can involve debugging multiple React pages. `crypto.randomUUID` is used to generate random user id. Corresponding logger config changes - [D50267871](https://www.internalfb.com/diff/D50267871).
Ruslan Lesiutin committed
Oct 17, 2023 at 15:23 UTC
9abf6fa31cd7ff4c6e54de75950620e203c59ebf
1 file changed
+23
-27
packages/react-devtools-shared/src/registerDevToolsEventLogger.js
+23
-27
@@ -12,7 +12,8 @@ import type {LoggerEvent} from 'react-devtools-shared/src/Logger';
12
import {registerEventLogger} from 'react-devtools-shared/src/Logger';
13
import {enableLogger} from 'react-devtools-feature-flags';
14
15
-let loggingIFrame = null;
15
+let currentLoggingIFrame = null;
16
+let currentSessionId = null;
17
let missedEvents: Array<LoggerEvent> = [];
18
19
type LoggerContext = {
@@ -21,32 +22,27 @@ type LoggerContext = {
22
23
export function registerDevToolsEventLogger(
24
surface: string,
24
- fetchAdditionalContext: ?() =>
25
- | LoggerContext
26
- | ?(() => Promise<LoggerContext>),
25
+ fetchAdditionalContext?:
26
+ | (() => LoggerContext)
27
+ | (() => Promise<LoggerContext>),
28
): void {
29
async function logEvent(event: LoggerEvent) {
30
if (enableLogger) {
30
- if (loggingIFrame != null) {
31
- let metadata = null;
32
- if (event.metadata != null) {
33
- metadata = event.metadata;
34
- // $FlowFixMe[cannot-write]: metadata is not writable and nullable
35
- // $FlowFixMe[prop-missing]
36
- delete event.metadata;
37
- }
38
- loggingIFrame.contentWindow.postMessage(
31
+ if (currentLoggingIFrame != null && currentSessionId != null) {
32
+ const {metadata, ...eventWithoutMetadata} = event;
33
+ const additionalContext: LoggerContext | {} =
34
+ fetchAdditionalContext != null ? await fetchAdditionalContext() : {};
35
+
36
+ currentLoggingIFrame?.contentWindow?.postMessage(
37
{
38
source: 'react-devtools-logging',
41
- event: event,
39
+ event: eventWithoutMetadata,
40
context: {
41
+ ...additionalContext,
42
+ metadata: metadata != null ? JSON.stringify(metadata) : '',
43
+ session_id: currentSessionId,
44
surface,
45
version: process.env.DEVTOOLS_VERSION,
45
- metadata: metadata !== null ? JSON.stringify(metadata) : '',
46
- ...(fetchAdditionalContext != null
47
- ? // $FlowFixMe[not-an-object]
48
- await fetchAdditionalContext()
49
- : {}),
46
},
47
},
48
'*',
@@ -58,11 +54,8 @@ export function registerDevToolsEventLogger(
54
}
55
56
function handleLoggingIFrameLoaded(iframe: HTMLIFrameElement) {
61
- if (loggingIFrame != null) {
62
- return;
63
- }
57
+ currentLoggingIFrame = iframe;
58
65
- loggingIFrame = iframe;
59
if (missedEvents.length > 0) {
60
missedEvents.forEach(event => logEvent(event));
61
missedEvents = [];
@@ -74,18 +67,21 @@ export function registerDevToolsEventLogger(
67
if (enableLogger) {
68
const loggingUrl = process.env.LOGGING_URL;
69
const body = document.body;
70
+
71
if (
72
typeof loggingUrl === 'string' &&
73
loggingUrl.length > 0 &&
80
- body != null
74
+ body != null &&
75
+ currentLoggingIFrame == null
76
) {
77
registerEventLogger(logEvent);
78
+ currentSessionId = window.crypto.randomUUID();
79
80
const iframe = document.createElement('iframe');
81
+
82
+ iframe.onload = () => handleLoggingIFrameLoaded(iframe);
83
iframe.src = loggingUrl;
86
- iframe.onload = function (...args) {
87
- handleLoggingIFrameLoaded(iframe);
88
- };
84
+
85
body.appendChild(iframe);
86
}
87
}