diff --git a/packages/dev-middleware/src/inspector-proxy/Device.js b/packages/dev-middleware/src/inspector-proxy/Device.js index 3879cf6bcfa..e8534a2b941 100644 --- a/packages/dev-middleware/src/inspector-proxy/Device.js +++ b/packages/dev-middleware/src/inspector-proxy/Device.js @@ -108,7 +108,11 @@ export default class Device { this._deviceSocket = socket; this._projectRoot = projectRoot; this._deviceEventReporter = eventReporter - ? new DeviceEventReporter(eventReporter) + ? new DeviceEventReporter(eventReporter, { + deviceId: id, + deviceName: name, + appId: app, + }) : null; // $FlowFixMe[incompatible-call] @@ -167,7 +171,13 @@ export default class Device { // 2. Forwards all messages from the debugger to device as wrappedEvent // 3. Sends disconnect event to device when debugger connection socket closes. handleDebuggerConnection(socket: WS, pageId: string) { - this._deviceEventReporter?.logConnection('debugger'); + // Clear any commands we were waiting on. + this._deviceEventReporter?.logDisconnection('debugger'); + + this._deviceEventReporter?.logConnection('debugger', { + pageId: pageId, + }); + // Disconnect current debugger if we already have debugger connected. if (this._debuggerConnection) { this._debuggerConnection.socket.close(); @@ -190,14 +200,13 @@ export default class Device { }, }); - // Clear any commands we were waiting on. - this._deviceEventReporter?.logDisconnection('debugger'); - // $FlowFixMe[incompatible-call] socket.on('message', (message: string) => { debug('(Debugger) -> (Proxy) (Device): ' + message); const debuggerRequest = JSON.parse(message); - this._deviceEventReporter?.logRequest(debuggerRequest, 'debugger'); + this._deviceEventReporter?.logRequest(debuggerRequest, 'debugger', { + pageId: this._debuggerConnection?.pageId ?? null, + }); const handled = this._interceptMessageFromDebugger( debuggerRequest, debuggerInfo, @@ -322,7 +331,9 @@ export default class Device { const parsedPayload = JSON.parse(message.payload.wrappedEvent); if ('id' in parsedPayload) { - this._deviceEventReporter?.logResponse(parsedPayload, 'device'); + this._deviceEventReporter?.logResponse(parsedPayload, 'device', { + pageId: this._debuggerConnection?.pageId ?? null, + }); } if (this._debuggerConnection) { @@ -401,7 +412,9 @@ export default class Device { ]; for (const message of toSend) { - this._deviceEventReporter?.logRequest(message, 'proxy'); + this._deviceEventReporter?.logRequest(message, 'proxy', { + pageId: this._debuggerConnection?.pageId ?? null, + }); this._sendMessageToDevice({ event: 'wrappedEvent', payload: { @@ -495,7 +508,9 @@ export default class Device { // This is not an issue in VSCode/Nuclide where the IDE knows to resume // at its convenience. const resumeMessage = {method: 'Debugger.resume', id: 0}; - this._deviceEventReporter?.logRequest(resumeMessage, 'proxy'); + this._deviceEventReporter?.logRequest(resumeMessage, 'proxy', { + pageId: this._debuggerConnection?.pageId ?? null, + }); this._sendMessageToDevice({ event: 'wrappedEvent', payload: { @@ -562,7 +577,9 @@ export default class Device { const result: GetScriptSourceResponse = {scriptSource}; const response = {id: req.id, result}; socket.send(JSON.stringify(response)); - this._deviceEventReporter?.logResponse(response, 'proxy'); + this._deviceEventReporter?.logResponse(response, 'proxy', { + pageId: this._debuggerConnection?.pageId ?? null, + }); }; const sendErrorResponse = (error: string) => { // Tell the client that the request failed @@ -572,7 +589,9 @@ export default class Device { // Send to the console as well, so the user can see it this._sendErrorToDebugger(error); - this._deviceEventReporter?.logResponse(response, 'proxy'); + this._deviceEventReporter?.logResponse(response, 'proxy', { + pageId: this._debuggerConnection?.pageId ?? null, + }); }; const pathToSource = this._scriptIdToSourcePathMapping.get( diff --git a/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js b/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js index b42a8b14745..8ce1dd7466e 100644 --- a/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js +++ b/packages/dev-middleware/src/inspector-proxy/DeviceEventReporter.js @@ -15,8 +15,19 @@ type PendingCommand = { method: string, requestOrigin: 'proxy' | 'debugger', requestTime: number, + metadata: RequestMetadata, }; +type DeviceMetadata = $ReadOnly<{ + appId: string, + deviceId: string, + deviceName: string, +}>; + +type RequestMetadata = $ReadOnly<{ + pageId: string | null, +}>; + class DeviceEventReporter { _eventReporter: EventReporter; @@ -35,18 +46,23 @@ class DeviceEventReporter { }, }); - constructor(eventReporter: EventReporter) { + _metadata: DeviceMetadata; + + constructor(eventReporter: EventReporter, metadata: DeviceMetadata) { this._eventReporter = eventReporter; + this._metadata = metadata; } logRequest( req: $ReadOnly<{id: number, method: string, ...}>, origin: 'debugger' | 'proxy', + metadata: RequestMetadata, ): void { this._pendingCommands.set(req.id, { method: req.method, requestOrigin: origin, requestTime: Date.now(), + metadata, }); } @@ -57,6 +73,9 @@ class DeviceEventReporter { ... }>, origin: 'device' | 'proxy', + metadata: $ReadOnly<{ + pageId: string | null, + }>, ): void { const pendingCommand = this._pendingCommands.get(res.id); if (!pendingCommand) { @@ -69,6 +88,10 @@ class DeviceEventReporter { errorCode: 'UNMATCHED_REQUEST_ID', responseOrigin: 'proxy', timeSinceStart: null, + appId: this._metadata.appId, + deviceId: this._metadata.deviceId, + deviceName: this._metadata.deviceName, + pageId: metadata.pageId, }); return; } @@ -89,6 +112,10 @@ class DeviceEventReporter { errorDetails: message, responseOrigin: origin, timeSinceStart, + appId: this._metadata.appId, + deviceId: this._metadata.deviceId, + deviceName: this._metadata.deviceName, + pageId: pendingCommand.metadata.pageId, }); return; } @@ -100,17 +127,32 @@ class DeviceEventReporter { status: 'success', responseOrigin: origin, timeSinceStart, + appId: this._metadata.appId, + deviceId: this._metadata.deviceId, + deviceName: this._metadata.deviceName, + pageId: pendingCommand.metadata.pageId, }); } - logConnection(connectedEntity: 'debugger') { - this._eventReporter?.logEvent({ + logConnection( + connectedEntity: 'debugger', + metadata: $ReadOnly<{pageId: string}>, + ) { + this._eventReporter.logEvent({ type: 'connect_debugger_frontend', status: 'success', + appId: this._metadata.appId, + deviceName: this._metadata.deviceName, + deviceId: this._metadata.deviceId, + pageId: metadata.pageId, }); } logDisconnection(disconnectedEntity: 'device' | 'debugger') { + const eventReporter = this._eventReporter; + if (!eventReporter) { + return; + } const errorCode = disconnectedEntity === 'device' ? 'DEVICE_DISCONNECTED' @@ -125,6 +167,10 @@ class DeviceEventReporter { errorCode, responseOrigin: 'proxy', timeSinceStart: Date.now() - pendingCommand.requestTime, + appId: this._metadata.appId, + deviceId: this._metadata.deviceId, + deviceName: this._metadata.deviceName, + pageId: pendingCommand.metadata.pageId, }); } this._pendingCommands.clear(); @@ -140,6 +186,10 @@ class DeviceEventReporter { errorCode: 'TIMED_OUT', responseOrigin: 'proxy', timeSinceStart: Date.now() - pendingCommand.requestTime, + appId: this._metadata.appId, + deviceId: this._metadata.deviceId, + deviceName: this._metadata.deviceName, + pageId: pendingCommand.metadata.pageId, }); } } diff --git a/packages/dev-middleware/src/types/EventReporter.js b/packages/dev-middleware/src/types/EventReporter.js index 3f097989d6d..ff922f7ac7d 100644 --- a/packages/dev-middleware/src/types/EventReporter.js +++ b/packages/dev-middleware/src/types/EventReporter.js @@ -24,6 +24,13 @@ type CodedErrorResult = { errorDetails?: string, }; +type DebuggerSessionIDs = { + appId: string, + deviceName: string, + deviceId: string, + pageId: string | null, +}; + export type ReportableEvent = | { type: 'launch_debugger_frontend', @@ -34,7 +41,7 @@ export type ReportableEvent = } | { type: 'connect_debugger_frontend', - ...SuccessResult | ErrorResult, + ...SuccessResult | ErrorResult, } | { type: 'debugger_command', @@ -44,6 +51,7 @@ export type ReportableEvent = requestOrigin: 'proxy' | 'debugger' | null, responseOrigin: 'proxy' | 'device', timeSinceStart: number | null, + ...DebuggerSessionIDs, ... | SuccessResult | CodedErrorResult<