@elastic/synthetics 1.0.0-beta.4 → 1.0.0-beta.41
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/dist/cli.js +137 -160
- package/dist/cli.js.map +1 -1
- package/dist/common_types.d.ts +161 -31
- package/dist/common_types.d.ts.map +1 -1
- package/dist/config.d.ts +3 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +7 -6
- package/dist/config.js.map +1 -1
- package/dist/core/browser-service.d.ts +1 -1
- package/dist/core/browser-service.d.ts.map +1 -1
- package/dist/core/browser-service.js +7 -6
- package/dist/core/browser-service.js.map +1 -1
- package/dist/core/expect.d.ts +25 -25
- package/dist/core/expect.d.ts.map +1 -1
- package/dist/core/expect.js.map +1 -1
- package/dist/core/gatherer.d.ts +4 -8
- package/dist/core/gatherer.d.ts.map +1 -1
- package/dist/core/gatherer.js +53 -15
- package/dist/core/gatherer.js.map +1 -1
- package/dist/core/index.d.ts +5 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +23 -11
- package/dist/core/index.js.map +1 -1
- package/dist/core/logger.d.ts +0 -1
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +3 -16
- package/dist/core/logger.js.map +1 -1
- package/dist/core/runner.d.ts +12 -63
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +156 -90
- package/dist/core/runner.js.map +1 -1
- package/dist/core/transform.d.ts +37 -0
- package/dist/core/transform.d.ts.map +1 -0
- package/dist/core/transform.js +148 -0
- package/dist/core/transform.js.map +1 -0
- package/dist/dsl/index.js +5 -1
- package/dist/dsl/index.js.map +1 -1
- package/dist/dsl/journey.d.ts +9 -4
- package/dist/dsl/journey.d.ts.map +1 -1
- package/dist/dsl/journey.js +37 -9
- package/dist/dsl/journey.js.map +1 -1
- package/dist/dsl/monitor.d.ts +83 -0
- package/dist/dsl/monitor.d.ts.map +1 -0
- package/dist/dsl/monitor.js +108 -0
- package/dist/dsl/monitor.js.map +1 -0
- package/dist/dsl/step.d.ts +3 -2
- package/dist/dsl/step.d.ts.map +1 -1
- package/dist/dsl/step.js +6 -1
- package/dist/dsl/step.js.map +1 -1
- package/dist/formatter/javascript.d.ts +98 -0
- package/dist/formatter/javascript.d.ts.map +1 -0
- package/dist/formatter/javascript.js +298 -0
- package/dist/formatter/javascript.js.map +1 -0
- package/dist/generator/index.d.ts +24 -0
- package/dist/generator/index.d.ts.map +1 -0
- package/dist/generator/index.js +241 -0
- package/dist/generator/index.js.map +1 -0
- package/dist/{reporters/reporter.js → generator/utils.d.ts} +5 -3
- package/dist/generator/utils.d.ts.map +1 -0
- package/dist/generator/utils.js +84 -0
- package/dist/generator/utils.js.map +1 -0
- package/dist/helpers.d.ts +28 -3
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +152 -20
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +6 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -26
- package/dist/index.js.map +1 -1
- package/dist/loader.d.ts +34 -0
- package/dist/loader.d.ts.map +1 -0
- package/dist/loader.js +149 -0
- package/dist/loader.js.map +1 -0
- package/dist/locations/index.d.ts +45 -0
- package/dist/locations/index.d.ts.map +1 -0
- package/dist/locations/index.js +83 -0
- package/dist/locations/index.js.map +1 -0
- package/dist/{reporters/reporter.d.ts → locations/public-locations.d.ts} +12 -8
- package/dist/locations/public-locations.d.ts.map +1 -0
- package/dist/locations/public-locations.js +41 -0
- package/dist/locations/public-locations.js.map +1 -0
- package/dist/options.d.ts +41 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +198 -0
- package/dist/options.js.map +1 -0
- package/dist/plugins/browser-console.d.ts +5 -4
- package/dist/plugins/browser-console.d.ts.map +1 -1
- package/dist/plugins/browser-console.js +44 -24
- package/dist/plugins/browser-console.js.map +1 -1
- package/dist/plugins/index.js +5 -1
- package/dist/plugins/index.js.map +1 -1
- package/dist/plugins/network.d.ts +20 -33
- package/dist/plugins/network.d.ts.map +1 -1
- package/dist/plugins/network.js +177 -216
- package/dist/plugins/network.js.map +1 -1
- package/dist/plugins/performance.d.ts +4 -19
- package/dist/plugins/performance.d.ts.map +1 -1
- package/dist/plugins/performance.js +6 -5
- package/dist/plugins/performance.js.map +1 -1
- package/dist/plugins/plugin-manager.d.ts +9 -5
- package/dist/plugins/plugin-manager.d.ts.map +1 -1
- package/dist/plugins/plugin-manager.js +46 -30
- package/dist/plugins/plugin-manager.js.map +1 -1
- package/dist/plugins/tracing.d.ts +6 -6
- package/dist/plugins/tracing.d.ts.map +1 -1
- package/dist/plugins/tracing.js +10 -7
- package/dist/plugins/tracing.js.map +1 -1
- package/dist/push/bundler.d.ts +35 -0
- package/dist/push/bundler.d.ts.map +1 -0
- package/dist/push/bundler.js +131 -0
- package/dist/push/bundler.js.map +1 -0
- package/dist/push/index.d.ts +9 -0
- package/dist/push/index.d.ts.map +1 -0
- package/dist/push/index.js +227 -0
- package/dist/push/index.js.map +1 -0
- package/dist/push/kibana_api.d.ts +56 -0
- package/dist/push/kibana_api.d.ts.map +1 -0
- package/dist/push/kibana_api.js +135 -0
- package/dist/push/kibana_api.js.map +1 -0
- package/dist/push/monitor.d.ts +51 -0
- package/dist/push/monitor.d.ts.map +1 -0
- package/dist/push/monitor.js +244 -0
- package/dist/push/monitor.js.map +1 -0
- package/dist/{parse_args.d.ts → push/plugin.d.ts} +9 -6
- package/dist/push/plugin.d.ts.map +1 -0
- package/dist/push/plugin.js +66 -0
- package/dist/push/plugin.js.map +1 -0
- package/dist/push/request.d.ts +45 -0
- package/dist/push/request.d.ts.map +1 -0
- package/dist/push/request.js +109 -0
- package/dist/push/request.js.map +1 -0
- package/dist/push/utils.d.ts +31 -0
- package/dist/push/utils.d.ts.map +1 -0
- package/dist/push/utils.js +64 -0
- package/dist/push/utils.js.map +1 -0
- package/dist/reporters/base.d.ts +14 -6
- package/dist/reporters/base.d.ts.map +1 -1
- package/dist/reporters/base.js +58 -50
- package/dist/reporters/base.js.map +1 -1
- package/dist/reporters/index.d.ts +18 -8
- package/dist/reporters/index.d.ts.map +1 -1
- package/dist/reporters/index.js.map +1 -1
- package/dist/reporters/json.d.ts +17 -62
- package/dist/reporters/json.d.ts.map +1 -1
- package/dist/reporters/json.js +149 -179
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/junit.d.ts +7 -1
- package/dist/reporters/junit.d.ts.map +1 -1
- package/dist/reporters/junit.js +90 -95
- package/dist/reporters/junit.js.map +1 -1
- package/dist/sdk/lh-trace-processor.d.ts +35 -9
- package/dist/sdk/lh-trace-processor.d.ts.map +1 -1
- package/dist/sdk/lh-trace-processor.js +114 -53
- package/dist/sdk/lh-trace-processor.js.map +1 -1
- package/dist/sdk/trace-metrics.d.ts +4 -4
- package/dist/sdk/trace-metrics.d.ts.map +1 -1
- package/dist/sdk/trace-metrics.js +3 -4
- package/dist/sdk/trace-metrics.js.map +1 -1
- package/dist/sdk/trace-processor.d.ts +11 -3
- package/dist/sdk/trace-processor.d.ts.map +1 -1
- package/dist/sdk/trace-processor.js +17 -9
- package/dist/sdk/trace-processor.js.map +1 -1
- package/package.json +39 -24
- package/src/cli.ts +219 -151
- package/src/common_types.ts +193 -31
- package/src/config.ts +3 -6
- package/src/core/expect.ts +58 -24
- package/src/core/gatherer.ts +64 -24
- package/src/core/index.ts +36 -15
- package/src/core/logger.ts +1 -12
- package/src/core/runner.ts +151 -136
- package/src/core/transform.ts +160 -0
- package/src/dsl/journey.ts +39 -6
- package/src/dsl/monitor.ts +140 -0
- package/src/dsl/step.ts +9 -2
- package/src/formatter/javascript.ts +367 -0
- package/src/generator/index.ts +308 -0
- package/src/generator/utils.ts +84 -0
- package/src/helpers.ts +159 -13
- package/src/index.ts +22 -22
- package/src/loader.ts +167 -0
- package/src/locations/index.ts +95 -0
- package/src/{reporters/reporter.ts → locations/public-locations.ts} +12 -9
- package/src/options.ts +227 -0
- package/src/plugins/browser-console.ts +30 -8
- package/src/plugins/network.ts +208 -267
- package/src/plugins/performance.ts +6 -22
- package/src/plugins/plugin-manager.ts +49 -31
- package/src/plugins/tracing.ts +8 -9
- package/src/push/bundler.ts +112 -0
- package/src/push/index.ts +282 -0
- package/src/push/kibana_api.ts +191 -0
- package/src/push/monitor.ts +276 -0
- package/src/push/plugin.ts +66 -0
- package/src/push/request.ts +141 -0
- package/src/push/utils.ts +77 -0
- package/src/reporters/base.ts +63 -52
- package/src/reporters/index.ts +26 -3
- package/src/reporters/json.ts +183 -202
- package/src/reporters/junit.ts +98 -93
- package/src/sdk/lh-trace-processor.ts +132 -68
- package/src/sdk/trace-metrics.ts +8 -4
- package/src/sdk/trace-processor.ts +28 -13
- package/templates/.github/workflows/run-synthetics.yml +27 -0
- package/templates/README.md +21 -0
- package/templates/journeys/advanced-example-helpers.ts +54 -0
- package/templates/journeys/advanced-example.journey.ts +43 -0
- package/templates/journeys/example.journey.ts +18 -0
- package/templates/lightweight/heartbeat.yml +8 -0
- package/templates/synthetics.config.ts +35 -0
- package/CHANGELOG.md +0 -131
- package/NOTICE.txt +0 -221
- package/dist/parse_args.d.ts.map +0 -1
- package/dist/parse_args.js +0 -95
- package/dist/parse_args.js.map +0 -1
- package/dist/reporters/reporter.d.ts.map +0 -1
- package/dist/reporters/reporter.js.map +0 -1
- package/dist/tsconfig.tsbuildinfo +0 -1888
- package/src/parse_args.ts +0 -135
package/src/plugins/network.ts
CHANGED
|
@@ -23,220 +23,185 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
import { NetworkInfo, BrowserInfo } from '../common_types';
|
|
26
|
+
import { Page, Request, Response } from 'playwright-chromium';
|
|
27
|
+
import { NetworkInfo, BrowserInfo, Driver } from '../common_types';
|
|
29
28
|
import { Step } from '../dsl';
|
|
30
29
|
import { getTimestamp } from '../helpers';
|
|
31
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Kibana UI expects the requestStartTime and loadEndTime to be baseline
|
|
33
|
+
* in seconds as they have the logic to convert it to milliseconds before
|
|
34
|
+
* using for offset calculation
|
|
35
|
+
*/
|
|
36
|
+
function epochTimeInSeconds() {
|
|
37
|
+
return getTimestamp() / 1e6;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Used as a key in each Network Request to identify the
|
|
42
|
+
* associated request across distinct lifecycle events
|
|
43
|
+
*/
|
|
44
|
+
export const NETWORK_ENTRY_SUMBOL = Symbol.for('NetworkEntry');
|
|
45
|
+
|
|
46
|
+
type RequestWithEntry = Request & {
|
|
47
|
+
NETWORK_ENTRY_SUMBOL?: symbol;
|
|
48
|
+
};
|
|
49
|
+
|
|
32
50
|
export class NetworkManager {
|
|
33
51
|
private _browser: BrowserInfo;
|
|
34
|
-
private
|
|
52
|
+
private _barrierPromises = new Set<Promise<void>>();
|
|
35
53
|
results: Array<NetworkInfo> = [];
|
|
36
54
|
_currentStep: Partial<Step> = null;
|
|
37
55
|
|
|
38
|
-
|
|
56
|
+
constructor(private driver: Driver) {}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Adds a protection barrier aganist all asynchronous extract operations from
|
|
60
|
+
* request/response object that are happening during page lifecycle, If the
|
|
61
|
+
* page is closed during the extraction, the barrier enforces those operations
|
|
62
|
+
* to not result in exception
|
|
63
|
+
*/
|
|
64
|
+
private _addBarrier(page: Page, promise: Promise<void>) {
|
|
65
|
+
if (!page) return;
|
|
66
|
+
const race = Promise.race([
|
|
67
|
+
new Promise<void>(resolve =>
|
|
68
|
+
page.on('close', () => {
|
|
69
|
+
this._barrierPromises.delete(race);
|
|
70
|
+
resolve();
|
|
71
|
+
})
|
|
72
|
+
),
|
|
73
|
+
promise,
|
|
74
|
+
]);
|
|
75
|
+
this._barrierPromises.add(race);
|
|
76
|
+
race.then(() => this._barrierPromises.delete(race));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
async start() {
|
|
80
|
+
const { client, context } = this.driver;
|
|
39
81
|
const { product } = await client.send('Browser.getVersion');
|
|
40
82
|
const [name, version] = product.split('/');
|
|
41
83
|
this._browser = { name, version };
|
|
42
84
|
await client.send('Network.enable');
|
|
43
85
|
/**
|
|
44
|
-
* Listen for all network events
|
|
86
|
+
* Listen for all network events from PW context
|
|
45
87
|
*/
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
);
|
|
50
|
-
client.on(
|
|
51
|
-
'Network.requestWillBeSentExtraInfo',
|
|
52
|
-
this._onRequestWillBeSentExtraInfo.bind(this)
|
|
53
|
-
);
|
|
54
|
-
client.on('Network.dataReceived', this._onDataReceived.bind(this));
|
|
55
|
-
client.on('Network.responseReceived', this._onResponseReceived.bind(this));
|
|
56
|
-
client.on('Network.loadingFinished', this._onLoadingFinished.bind(this));
|
|
57
|
-
client.on('Network.loadingFailed', this._onLoadingFailed.bind(this));
|
|
88
|
+
context.on('request', this._onRequest.bind(this));
|
|
89
|
+
context.on('response', this._onResponse.bind(this));
|
|
90
|
+
context.on('requestfinished', this._onRequestCompleted.bind(this));
|
|
91
|
+
context.on('requestfailed', this._onRequestCompleted.bind(this));
|
|
58
92
|
}
|
|
59
93
|
|
|
60
|
-
|
|
61
|
-
|
|
94
|
+
private _findNetworkEntry(
|
|
95
|
+
request: RequestWithEntry
|
|
96
|
+
): NetworkInfo | undefined {
|
|
97
|
+
return request[NETWORK_ENTRY_SUMBOL];
|
|
62
98
|
}
|
|
63
99
|
|
|
64
|
-
|
|
65
|
-
const
|
|
66
|
-
const { url, method } = request;
|
|
100
|
+
private _onRequest(request: Request) {
|
|
101
|
+
const url = request.url();
|
|
67
102
|
/**
|
|
68
103
|
* Data URI should not show up as network requests
|
|
69
104
|
*/
|
|
70
105
|
if (url.startsWith('data:')) {
|
|
71
106
|
return;
|
|
72
107
|
}
|
|
73
|
-
const isNavigationRequest = requestId == loaderId && type === 'Document';
|
|
74
|
-
const record = this._findNetworkRecord(requestId);
|
|
75
|
-
/**
|
|
76
|
-
* On redirects, another `requestWillBeSent` event will be fired for the
|
|
77
|
-
* same requestId. We calculate the timings for the redirect request using
|
|
78
|
-
* the `redirectedResponse` from the redirected request.
|
|
79
|
-
*/
|
|
80
|
-
if (record) {
|
|
81
|
-
if (event.redirectResponse) {
|
|
82
|
-
const response = event.redirectResponse;
|
|
83
|
-
const data = Object.assign(event, {
|
|
84
|
-
type: event.type,
|
|
85
|
-
response,
|
|
86
|
-
encodedDataLength: response.encodedDataLength,
|
|
87
|
-
});
|
|
88
|
-
this._onResponseReceived(data);
|
|
89
|
-
this._onLoadingFinished(data);
|
|
90
|
-
} else {
|
|
91
|
-
/**
|
|
92
|
-
* Edge case, we handle it to proceed with next navigation
|
|
93
|
-
*/
|
|
94
|
-
this._onLoadingFailed(
|
|
95
|
-
Object.assign(event, {
|
|
96
|
-
type: event.type,
|
|
97
|
-
errorText: 'redirectResponse data is not available',
|
|
98
|
-
})
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
const redirectedRecord = this._findNetworkRecord(requestId);
|
|
102
|
-
/**
|
|
103
|
-
* Rewrite the map with new redirect id to not reset
|
|
104
|
-
* the redirect request with original request
|
|
105
|
-
*/
|
|
106
|
-
this._InflightRequestMap.delete(requestId);
|
|
107
|
-
this._InflightRequestMap.set(
|
|
108
|
-
`redirect:${timestamp}:${requestId}`,
|
|
109
|
-
redirectedRecord
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
108
|
|
|
113
|
-
|
|
109
|
+
const timestamp = getTimestamp();
|
|
110
|
+
const networkEntry: NetworkInfo = {
|
|
114
111
|
browser: this._browser,
|
|
115
112
|
step: this._currentStep,
|
|
116
|
-
timestamp
|
|
113
|
+
timestamp,
|
|
117
114
|
url,
|
|
118
|
-
request,
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
115
|
+
type: request.resourceType(),
|
|
116
|
+
request: {
|
|
117
|
+
url,
|
|
118
|
+
method: request.method(),
|
|
119
|
+
headers: {},
|
|
120
|
+
body: {
|
|
121
|
+
bytes: request.postDataBuffer()?.length || 0,
|
|
122
|
+
},
|
|
123
|
+
},
|
|
124
|
+
response: {
|
|
125
|
+
status: -1,
|
|
126
|
+
headers: {},
|
|
127
|
+
mimeType: 'x-unknown',
|
|
128
|
+
redirectURL: '',
|
|
129
|
+
},
|
|
130
|
+
isNavigationRequest: request.isNavigationRequest(),
|
|
131
|
+
requestSentTime: epochTimeInSeconds(),
|
|
124
132
|
loadEndTime: -1,
|
|
125
133
|
responseReceivedTime: -1,
|
|
126
|
-
response: null,
|
|
127
134
|
resourceSize: 0,
|
|
128
135
|
transferSize: 0,
|
|
129
136
|
timings: null,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
_onRequestWillBeSentExtraInfo(
|
|
134
|
-
event: Protocol.Network.requestWillBeSentExtraInfoPayload
|
|
135
|
-
) {
|
|
136
|
-
const { requestId, headers } = event;
|
|
137
|
-
const record = this._findNetworkRecord(requestId);
|
|
138
|
-
if (!record) {
|
|
139
|
-
return;
|
|
140
|
-
}
|
|
141
|
-
/**
|
|
142
|
-
* Enhance request headers with additional information
|
|
143
|
-
*/
|
|
144
|
-
record.request.headers = {
|
|
145
|
-
...record.request.headers,
|
|
146
|
-
...headers,
|
|
147
137
|
};
|
|
148
|
-
}
|
|
149
138
|
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
if (!record) {
|
|
154
|
-
return;
|
|
139
|
+
if (request.redirectedFrom()) {
|
|
140
|
+
const fromEntry = this._findNetworkEntry(request.redirectedFrom());
|
|
141
|
+
if (fromEntry) fromEntry.response.redirectURL = request.url();
|
|
155
142
|
}
|
|
156
|
-
record.resourceSize += dataLength;
|
|
157
|
-
if (encodedDataLength >= 0) record.transferSize += encodedDataLength;
|
|
158
|
-
}
|
|
159
143
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
const record = this._findNetworkRecord(requestId);
|
|
163
|
-
if (!record) {
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
Object.assign(record, {
|
|
167
|
-
status: response.status,
|
|
168
|
-
response,
|
|
169
|
-
responseReceivedTime: timestamp,
|
|
170
|
-
transferSize: response.encodedDataLength,
|
|
171
|
-
});
|
|
144
|
+
request[NETWORK_ENTRY_SUMBOL] = networkEntry;
|
|
145
|
+
this.results.push(networkEntry);
|
|
172
146
|
}
|
|
173
147
|
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
this.
|
|
177
|
-
|
|
148
|
+
private async _onResponse(response: Response) {
|
|
149
|
+
const request = response.request();
|
|
150
|
+
const networkEntry = this._findNetworkEntry(request);
|
|
151
|
+
if (!networkEntry) return;
|
|
178
152
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
153
|
+
networkEntry.responseReceivedTime = epochTimeInSeconds();
|
|
154
|
+
networkEntry.response = {
|
|
155
|
+
url: response.url(),
|
|
156
|
+
status: response.status(),
|
|
157
|
+
statusText: response.statusText(),
|
|
158
|
+
headers: {},
|
|
159
|
+
mimeType: 'x-unknown',
|
|
160
|
+
redirectURL: networkEntry.response.redirectURL,
|
|
161
|
+
};
|
|
183
162
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
163
|
+
const page = request.frame().page();
|
|
164
|
+
this._addBarrier(
|
|
165
|
+
page,
|
|
166
|
+
request.allHeaders().then(reqHeaders => {
|
|
167
|
+
networkEntry.request.headers = reqHeaders;
|
|
168
|
+
networkEntry.request.referrer = reqHeaders?.referer;
|
|
169
|
+
})
|
|
170
|
+
);
|
|
171
|
+
this._addBarrier(
|
|
172
|
+
page,
|
|
173
|
+
response.serverAddr().then(server => {
|
|
174
|
+
networkEntry.response.remoteIPAddress = server?.ipAddress;
|
|
175
|
+
networkEntry.response.remotePort = server?.port;
|
|
176
|
+
})
|
|
177
|
+
);
|
|
178
|
+
this._addBarrier(
|
|
179
|
+
page,
|
|
180
|
+
response.securityDetails().then(details => {
|
|
181
|
+
if (details) networkEntry.response.securityDetails = details;
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
this._addBarrier(
|
|
185
|
+
page,
|
|
186
|
+
response.allHeaders().then(resHeaders => {
|
|
187
|
+
networkEntry.response.headers = resHeaders;
|
|
205
188
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
timing: Protocol.Network.Response['timing'],
|
|
212
|
-
responseReceivedTime: number
|
|
213
|
-
) {
|
|
214
|
-
if (timing == null) {
|
|
215
|
-
return responseReceivedTime;
|
|
216
|
-
}
|
|
217
|
-
const startTime = timing.requestTime;
|
|
218
|
-
const headersReceivedTime = startTime + timing.receiveHeadersEnd / 1000;
|
|
219
|
-
if (
|
|
220
|
-
responseReceivedTime < 0 ||
|
|
221
|
-
responseReceivedTime > headersReceivedTime
|
|
222
|
-
) {
|
|
223
|
-
responseReceivedTime = headersReceivedTime;
|
|
224
|
-
}
|
|
225
|
-
if (startTime > responseReceivedTime) {
|
|
226
|
-
responseReceivedTime = startTime;
|
|
227
|
-
}
|
|
228
|
-
return responseReceivedTime;
|
|
189
|
+
const contentType = resHeaders['content-type'];
|
|
190
|
+
if (contentType)
|
|
191
|
+
networkEntry.response.mimeType = contentType.split(';')[0];
|
|
192
|
+
})
|
|
193
|
+
);
|
|
229
194
|
}
|
|
230
195
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
const
|
|
196
|
+
private async _onRequestCompleted(request: Request) {
|
|
197
|
+
const networkEntry = this._findNetworkEntry(request);
|
|
198
|
+
if (!networkEntry) return;
|
|
199
|
+
|
|
200
|
+
networkEntry.loadEndTime = epochTimeInSeconds();
|
|
201
|
+
const timing = request.timing();
|
|
202
|
+
const { loadEndTime, requestSentTime } = networkEntry;
|
|
203
|
+
networkEntry.timings = {
|
|
237
204
|
blocked: -1,
|
|
238
|
-
queueing: -1,
|
|
239
|
-
proxy: -1,
|
|
240
205
|
dns: -1,
|
|
241
206
|
ssl: -1,
|
|
242
207
|
connect: -1,
|
|
@@ -245,28 +210,7 @@ export class NetworkManager {
|
|
|
245
210
|
receive: -1,
|
|
246
211
|
total: -1,
|
|
247
212
|
};
|
|
248
|
-
const { requestSentTime, loadEndTime, responseReceivedTime } = record;
|
|
249
213
|
|
|
250
|
-
/**
|
|
251
|
-
* Handle when request failed and no responseReceived event was
|
|
252
|
-
* fired for that particular request
|
|
253
|
-
* Eg: connection refused by remote host
|
|
254
|
-
*/
|
|
255
|
-
const response = record.response || {
|
|
256
|
-
timing: null,
|
|
257
|
-
fromServiceWorker: false,
|
|
258
|
-
};
|
|
259
|
-
|
|
260
|
-
const toMilliseconds = (time: number) => (time === -1 ? -1 : time * 1000);
|
|
261
|
-
const calculateDiffInMs = (
|
|
262
|
-
name: keyof NetworkInfo['timings'],
|
|
263
|
-
start: number,
|
|
264
|
-
end: number
|
|
265
|
-
) => {
|
|
266
|
-
if (start < Number.MAX_VALUE && start <= end) {
|
|
267
|
-
result[name] = toMilliseconds(end - start);
|
|
268
|
-
}
|
|
269
|
-
};
|
|
270
214
|
const firstPositive = (numbers: number[]) => {
|
|
271
215
|
for (let i = 0; i < numbers.length; ++i) {
|
|
272
216
|
if (numbers[i] > 0) {
|
|
@@ -275,91 +219,88 @@ export class NetworkManager {
|
|
|
275
219
|
}
|
|
276
220
|
return null;
|
|
277
221
|
};
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
* from the requestTime, so we calculate the offset from that
|
|
281
|
-
*/
|
|
282
|
-
const addOffsetRange = (
|
|
283
|
-
name: keyof NetworkInfo['timings'],
|
|
284
|
-
start: number,
|
|
285
|
-
end: number
|
|
286
|
-
) => {
|
|
287
|
-
if (start >= 0 && end >= 0) {
|
|
288
|
-
calculateDiffInMs(
|
|
289
|
-
name,
|
|
290
|
-
startTime + start / 1000,
|
|
291
|
-
startTime + end / 1000
|
|
292
|
-
);
|
|
293
|
-
}
|
|
222
|
+
const roundMilliSecs = (value: number): number => {
|
|
223
|
+
return Math.floor(value * 1000) / 1000;
|
|
294
224
|
};
|
|
295
|
-
const timing = response.timing;
|
|
296
|
-
const actResRcvdTime = this.getResponseReceivedTime(
|
|
297
|
-
timing,
|
|
298
|
-
responseReceivedTime
|
|
299
|
-
);
|
|
300
|
-
const issueTime = requestSentTime;
|
|
301
|
-
const startTime = timing == null ? -1 : timing.requestTime;
|
|
302
|
-
const endTime = firstPositive([loadEndTime, actResRcvdTime]) || startTime;
|
|
303
225
|
|
|
304
|
-
if (timing
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
calculateDiffInMs('total', start, end);
|
|
310
|
-
calculateDiffInMs('blocked', start, middle);
|
|
311
|
-
calculateDiffInMs('receive', middle, end);
|
|
312
|
-
// Check if the request is blocked/stalled for the whole timeframe and
|
|
313
|
-
// calculate timings appropriately for that request
|
|
314
|
-
if (!isFinite(result['blocked'])) {
|
|
315
|
-
result['blocked'] = result['total'];
|
|
316
|
-
}
|
|
317
|
-
return result;
|
|
318
|
-
}
|
|
319
|
-
calculateDiffInMs(
|
|
320
|
-
'total',
|
|
321
|
-
issueTime < startTime ? issueTime : startTime,
|
|
322
|
-
endTime
|
|
323
|
-
);
|
|
324
|
-
if (issueTime < startTime) {
|
|
325
|
-
calculateDiffInMs('queueing', issueTime, startTime);
|
|
226
|
+
if (timing.startTime === 0) {
|
|
227
|
+
// Convert to milliseconds before round off
|
|
228
|
+
const total = roundMilliSecs((loadEndTime - requestSentTime) * 1000);
|
|
229
|
+
networkEntry.timings.total = total;
|
|
230
|
+
return;
|
|
326
231
|
}
|
|
327
|
-
const responseReceived = toMilliseconds(actResRcvdTime - startTime);
|
|
328
232
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
addOffsetRange('wait', timing.sendEnd, responseReceived);
|
|
332
|
-
} else if (!timing.pushStart) {
|
|
333
|
-
const blockingEnd =
|
|
233
|
+
const blocked =
|
|
234
|
+
roundMilliSecs(
|
|
334
235
|
firstPositive([
|
|
335
|
-
timing.
|
|
236
|
+
timing.domainLookupStart,
|
|
336
237
|
timing.connectStart,
|
|
337
|
-
timing.
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
)
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
238
|
+
timing.requestStart,
|
|
239
|
+
])
|
|
240
|
+
) || -1;
|
|
241
|
+
const dns =
|
|
242
|
+
timing.domainLookupEnd !== -1
|
|
243
|
+
? roundMilliSecs(timing.domainLookupEnd - timing.domainLookupStart)
|
|
244
|
+
: -1;
|
|
245
|
+
const connect =
|
|
246
|
+
timing.connectEnd !== -1
|
|
247
|
+
? roundMilliSecs(timing.connectEnd - timing.connectStart)
|
|
248
|
+
: -1;
|
|
249
|
+
const ssl =
|
|
250
|
+
timing.secureConnectionStart !== -1
|
|
251
|
+
? roundMilliSecs(timing.connectEnd - timing.secureConnectionStart)
|
|
252
|
+
: -1;
|
|
253
|
+
const wait =
|
|
254
|
+
timing.responseStart !== -1
|
|
255
|
+
? roundMilliSecs(timing.responseStart - timing.requestStart)
|
|
256
|
+
: -1;
|
|
257
|
+
const receive =
|
|
258
|
+
timing.responseEnd !== -1
|
|
259
|
+
? roundMilliSecs(timing.responseEnd - timing.responseStart)
|
|
260
|
+
: -1;
|
|
261
|
+
const total = [blocked, dns, connect, wait, receive].reduce(
|
|
262
|
+
(pre, cur) => (cur > 0 ? cur + pre : pre),
|
|
263
|
+
0
|
|
264
|
+
);
|
|
265
|
+
networkEntry.timings = {
|
|
266
|
+
blocked,
|
|
267
|
+
dns,
|
|
268
|
+
connect,
|
|
269
|
+
ssl,
|
|
270
|
+
wait,
|
|
271
|
+
send: 0, // not exposed via RT api
|
|
272
|
+
receive,
|
|
273
|
+
total,
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const page = request.frame().page();
|
|
277
|
+
// For aborted/failed requests sizes will not be present
|
|
278
|
+
this._addBarrier(
|
|
279
|
+
page,
|
|
280
|
+
request.sizes().then(sizes => {
|
|
281
|
+
networkEntry.request.bytes =
|
|
282
|
+
sizes.requestHeadersSize + sizes.requestBodySize;
|
|
283
|
+
networkEntry.request.body = {
|
|
284
|
+
bytes: sizes.requestBodySize,
|
|
285
|
+
};
|
|
286
|
+
const transferSize = sizes.responseHeadersSize + sizes.responseBodySize;
|
|
287
|
+
networkEntry.transferSize = transferSize;
|
|
288
|
+
networkEntry.response.bytes = transferSize;
|
|
289
|
+
networkEntry.response.body = {
|
|
290
|
+
bytes: sizes.responseBodySize,
|
|
291
|
+
};
|
|
292
|
+
})
|
|
293
|
+
);
|
|
360
294
|
}
|
|
361
295
|
|
|
362
|
-
stop() {
|
|
296
|
+
async stop() {
|
|
297
|
+
await Promise.all(this._barrierPromises);
|
|
298
|
+
const context = this.driver.context;
|
|
299
|
+
context.off('request', this._onRequest.bind(this));
|
|
300
|
+
context.off('response', this._onResponse.bind(this));
|
|
301
|
+
context.off('requestfinished', this._onRequestCompleted.bind(this));
|
|
302
|
+
context.off('requestfailed', this._onRequestCompleted.bind(this));
|
|
303
|
+
this._barrierPromises.clear();
|
|
363
304
|
return this.results;
|
|
364
305
|
}
|
|
365
306
|
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import {
|
|
26
|
+
import { Driver, PageMetrics } from '../common_types';
|
|
27
27
|
|
|
28
28
|
const supportedMetrics = new Set<string>([
|
|
29
29
|
'Timestamp',
|
|
@@ -41,39 +41,23 @@ const supportedMetrics = new Set<string>([
|
|
|
41
41
|
'JSHeapTotalSize',
|
|
42
42
|
]);
|
|
43
43
|
|
|
44
|
-
export interface Metrics {
|
|
45
|
-
Timestamp?: number;
|
|
46
|
-
Documents?: number;
|
|
47
|
-
Frames?: number;
|
|
48
|
-
JSEventListeners?: number;
|
|
49
|
-
Nodes?: number;
|
|
50
|
-
LayoutCount?: number;
|
|
51
|
-
RecalcStyleCount?: number;
|
|
52
|
-
LayoutDuration?: number;
|
|
53
|
-
RecalcStyleDuration?: number;
|
|
54
|
-
ScriptDuration?: number;
|
|
55
|
-
TaskDuration?: number;
|
|
56
|
-
JSHeapUsedSize?: number;
|
|
57
|
-
JSHeapTotalSize?: number;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
44
|
export class PerformanceManager {
|
|
61
|
-
constructor(private
|
|
45
|
+
constructor(private driver: Driver) {}
|
|
62
46
|
|
|
63
47
|
async start() {
|
|
64
|
-
await this.client.send('Performance.enable');
|
|
48
|
+
await this.driver.client.send('Performance.enable');
|
|
65
49
|
}
|
|
66
50
|
|
|
67
51
|
async stop() {
|
|
68
|
-
await this.client.send('Performance.disable');
|
|
52
|
+
await this.driver.client.send('Performance.disable');
|
|
69
53
|
}
|
|
70
54
|
|
|
71
55
|
async getMetrics() {
|
|
72
|
-
const { metrics } = await this.client.send('Performance.getMetrics');
|
|
56
|
+
const { metrics } = await this.driver.client.send('Performance.getMetrics');
|
|
73
57
|
return this.buildMetricsObject(metrics);
|
|
74
58
|
}
|
|
75
59
|
|
|
76
|
-
private buildMetricsObject(metrics = []):
|
|
60
|
+
private buildMetricsObject(metrics = []): PageMetrics {
|
|
77
61
|
const result = {};
|
|
78
62
|
for (const metric of metrics) {
|
|
79
63
|
if (supportedMetrics.has(metric.name)) result[metric.name] = metric.value;
|