-
Notifications
You must be signed in to change notification settings - Fork 9.4k
/
devtools-log.js
122 lines (100 loc) · 2.86 KB
/
devtools-log.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
/**
* @license
* Copyright 2021 Google LLC
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @fileoverview
* This gatherer collects all network and page devtools protocol traffic during the timespan/navigation.
* This protocol log can be used to recreate the network records using lib/network-recorder.js.
*/
import BaseGatherer from '../base-gatherer.js';
class DevtoolsLog extends BaseGatherer {
static symbol = Symbol('DevtoolsLog');
/** @type {LH.Gatherer.GathererMeta} */
meta = {
symbol: DevtoolsLog.symbol,
supportedModes: ['timespan', 'navigation'],
};
constructor() {
super();
this._messageLog = new DevtoolsMessageLog(/^(Page|Network|Target|Runtime)\./);
/** @param {LH.Protocol.RawEventMessage} e */
this._onProtocolMessage = e => this._messageLog.record(e);
}
/**
* @param {LH.Gatherer.Context} passContext
*/
async startSensitiveInstrumentation({driver}) {
this._messageLog.reset();
this._messageLog.beginRecording();
driver.targetManager.on('protocolevent', this._onProtocolMessage);
await driver.defaultSession.sendCommand('Page.enable');
}
/**
* @param {LH.Gatherer.Context} passContext
*/
async stopSensitiveInstrumentation({driver}) {
this._messageLog.endRecording();
driver.targetManager.off('protocolevent', this._onProtocolMessage);
}
/**
* @return {LH.Artifacts['DevtoolsLog']}
*/
getDebugData() {
return this._messageLog.messages;
}
/**
* @return {Promise<LH.Artifacts['DevtoolsLog']>}
*/
async getArtifact() {
return this._messageLog.messages;
}
}
/**
* This class saves all protocol messages whose method match a particular
* regex filter. Used when saving assets for later analysis by another tool such as
* Webpagetest.
*/
class DevtoolsMessageLog {
/**
* @param {RegExp=} regexFilter
*/
constructor(regexFilter) {
this._filter = regexFilter;
/** @type {LH.DevtoolsLog} */
this._messages = [];
this._isRecording = false;
}
/**
* @return {LH.DevtoolsLog}
*/
get messages() {
return this._messages;
}
reset() {
this._messages = [];
}
beginRecording() {
this._isRecording = true;
}
endRecording() {
this._isRecording = false;
}
/**
* Records a message if method matches filter and recording has been started.
* @param {LH.Protocol.RawEventMessage} message
*/
record(message) {
// We're not recording, skip the rest of the checks.
if (!this._isRecording) return;
// The event was likely an internal puppeteer method that uses Symbols.
if (typeof message.method !== 'string') return;
// The event didn't pass our filter, do not record it.
if (this._filter && !this._filter.test(message.method)) return;
// We passed all the checks, record the message.
this._messages.push(message);
}
}
export default DevtoolsLog;
export {DevtoolsMessageLog};