@elastic/synthetics 1.0.0-beta.2 → 1.0.0-beta.22
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/CHANGELOG.md +235 -0
- package/NOTICE.txt +250 -0
- package/README.md +2 -1
- package/dist/cli.js +87 -56
- package/dist/cli.js.map +1 -1
- package/dist/common_types.d.ts +116 -14
- package/dist/common_types.d.ts.map +1 -1
- package/dist/config.d.ts +2 -5
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +5 -5
- package/dist/config.js.map +1 -1
- package/dist/core/browser-service.js +5 -5
- package/dist/core/browser-service.js.map +1 -1
- package/dist/core/expect.d.ts +177 -0
- package/dist/core/expect.d.ts.map +1 -0
- package/dist/core/expect.js +33 -0
- package/dist/core/expect.js.map +1 -0
- package/dist/core/gatherer.d.ts +4 -7
- package/dist/core/gatherer.d.ts.map +1 -1
- package/dist/core/gatherer.js +39 -12
- package/dist/core/gatherer.js.map +1 -1
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/index.js +2 -2
- 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 +54 -45
- package/dist/core/runner.d.ts.map +1 -1
- package/dist/core/runner.js +181 -71
- package/dist/core/runner.js.map +1 -1
- package/dist/dsl/journey.d.ts +13 -4
- package/dist/dsl/journey.d.ts.map +1 -1
- package/dist/dsl/journey.js +40 -1
- package/dist/dsl/journey.js.map +1 -1
- package/dist/formatter/javascript.d.ts +73 -0
- package/dist/formatter/javascript.d.ts.map +1 -0
- package/dist/formatter/javascript.js +274 -0
- package/dist/formatter/javascript.js.map +1 -0
- package/dist/helpers.d.ts +33 -12
- package/dist/helpers.d.ts.map +1 -1
- package/dist/helpers.js +108 -54
- package/dist/helpers.js.map +1 -1
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -7
- package/dist/index.js.map +1 -1
- package/dist/parse_args.d.ts +5 -2
- package/dist/parse_args.d.ts.map +1 -1
- package/dist/parse_args.js +59 -16
- package/dist/parse_args.js.map +1 -1
- package/dist/plugins/browser-console.d.ts +5 -8
- package/dist/plugins/browser-console.d.ts.map +1 -1
- package/dist/plugins/browser-console.js +27 -8
- package/dist/plugins/browser-console.js.map +1 -1
- package/dist/plugins/network.d.ts +23 -20
- package/dist/plugins/network.d.ts.map +1 -1
- package/dist/plugins/network.js +149 -124
- package/dist/plugins/network.js.map +1 -1
- package/dist/plugins/performance.d.ts +5 -5
- package/dist/plugins/performance.d.ts.map +1 -1
- package/dist/plugins/performance.js +5 -5
- package/dist/plugins/performance.js.map +1 -1
- package/dist/plugins/plugin-manager.d.ts +11 -11
- package/dist/plugins/plugin-manager.d.ts.map +1 -1
- package/dist/plugins/plugin-manager.js +40 -24
- package/dist/plugins/plugin-manager.js.map +1 -1
- package/dist/plugins/tracing.d.ts +10 -25
- package/dist/plugins/tracing.d.ts.map +1 -1
- package/dist/plugins/tracing.js +40 -26
- package/dist/plugins/tracing.js.map +1 -1
- package/dist/reporters/base.d.ts +0 -1
- package/dist/reporters/base.d.ts.map +1 -1
- package/dist/reporters/base.js +34 -32
- package/dist/reporters/base.js.map +1 -1
- package/dist/reporters/json.d.ts +46 -59
- package/dist/reporters/json.d.ts.map +1 -1
- package/dist/reporters/json.js +188 -70
- package/dist/reporters/json.js.map +1 -1
- package/dist/reporters/junit.d.ts.map +1 -1
- package/dist/reporters/junit.js +7 -7
- package/dist/reporters/junit.js.map +1 -1
- package/dist/sdk/lh-trace-processor.d.ts +304 -0
- package/dist/sdk/lh-trace-processor.d.ts.map +1 -0
- package/dist/sdk/lh-trace-processor.js +832 -0
- package/dist/sdk/lh-trace-processor.js.map +1 -0
- package/dist/sdk/trace-metrics.d.ts +61 -0
- package/dist/sdk/trace-metrics.d.ts.map +1 -0
- package/dist/sdk/trace-metrics.js +252 -0
- package/dist/sdk/trace-metrics.js.map +1 -0
- package/dist/sdk/trace-processor.d.ts +106 -0
- package/dist/sdk/trace-processor.d.ts.map +1 -0
- package/dist/sdk/trace-processor.js +74 -0
- package/dist/sdk/trace-processor.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1575
- package/package.json +27 -16
- package/src/cli.ts +68 -45
- package/src/common_types.ts +138 -14
- package/src/config.ts +2 -5
- package/src/core/expect.ts +187 -0
- package/src/core/gatherer.ts +48 -24
- package/src/core/index.ts +6 -6
- package/src/core/logger.ts +1 -12
- package/src/core/runner.ts +259 -112
- package/src/dsl/journey.ts +28 -6
- package/src/formatter/javascript.ts +330 -0
- package/src/helpers.ts +114 -24
- package/src/index.ts +7 -6
- package/src/parse_args.ts +97 -22
- package/src/plugins/browser-console.ts +30 -13
- package/src/plugins/network.ts +175 -159
- package/src/plugins/performance.ts +7 -7
- package/src/plugins/plugin-manager.ts +47 -36
- package/src/plugins/tracing.ts +43 -54
- package/src/reporters/base.ts +29 -23
- package/src/reporters/json.ts +259 -80
- package/src/reporters/junit.ts +1 -1
- package/src/sdk/lh-trace-processor.ts +1033 -0
- package/src/sdk/trace-metrics.ts +287 -0
- package/src/sdk/trace-processor.ts +147 -0
package/src/reporters/json.ts
CHANGED
|
@@ -23,13 +23,32 @@
|
|
|
23
23
|
*
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
+
import { readFileSync } from 'fs';
|
|
27
|
+
import { join } from 'path';
|
|
28
|
+
import sharp from 'sharp';
|
|
29
|
+
import { createHash } from 'crypto';
|
|
26
30
|
import BaseReporter from './base';
|
|
27
|
-
import {
|
|
31
|
+
import {
|
|
32
|
+
formatError,
|
|
33
|
+
getTimestamp,
|
|
34
|
+
CACHE_PATH,
|
|
35
|
+
totalist,
|
|
36
|
+
isDirectory,
|
|
37
|
+
getDurationInUs,
|
|
38
|
+
} from '../helpers';
|
|
28
39
|
import { Journey, Step } from '../dsl';
|
|
29
40
|
import snakeCaseKeys from 'snakecase-keys';
|
|
30
|
-
import {
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
import {
|
|
42
|
+
NetworkInfo,
|
|
43
|
+
SecurityDetails,
|
|
44
|
+
NetworkConditions,
|
|
45
|
+
TraceOutput,
|
|
46
|
+
StatusValue,
|
|
47
|
+
PerfMetrics,
|
|
48
|
+
Params,
|
|
49
|
+
Screenshot,
|
|
50
|
+
} from '../common_types';
|
|
51
|
+
import { PageMetrics } from '../plugins';
|
|
33
52
|
|
|
34
53
|
/* eslint-disable @typescript-eslint/no-var-requires */
|
|
35
54
|
const { version, name } = require('../../package.json');
|
|
@@ -38,10 +57,13 @@ type OutputType =
|
|
|
38
57
|
| 'synthetics/metadata'
|
|
39
58
|
| 'journey/register'
|
|
40
59
|
| 'journey/start'
|
|
60
|
+
| 'screenshot/block'
|
|
61
|
+
| 'step/screenshot_ref'
|
|
41
62
|
| 'step/screenshot'
|
|
63
|
+
| 'step/metrics'
|
|
64
|
+
| 'step/filmstrips'
|
|
42
65
|
| 'step/end'
|
|
43
66
|
| 'journey/network_info'
|
|
44
|
-
| 'journey/filmstrips'
|
|
45
67
|
| 'journey/browserconsole'
|
|
46
68
|
| 'journey/end';
|
|
47
69
|
|
|
@@ -50,27 +72,50 @@ type Payload = {
|
|
|
50
72
|
start?: number;
|
|
51
73
|
end?: number;
|
|
52
74
|
url?: string;
|
|
53
|
-
status?: StatusValue
|
|
54
|
-
|
|
55
|
-
params?:
|
|
75
|
+
status?: StatusValue;
|
|
76
|
+
pagemetrics?: PageMetrics;
|
|
77
|
+
params?: Params;
|
|
56
78
|
type?: OutputType;
|
|
57
79
|
text?: string;
|
|
58
80
|
index?: number;
|
|
81
|
+
network_conditions?: NetworkConditions;
|
|
59
82
|
};
|
|
60
83
|
|
|
61
84
|
type OutputFields = {
|
|
62
85
|
type: OutputType;
|
|
86
|
+
_id?: string;
|
|
63
87
|
journey?: Journey;
|
|
64
88
|
timestamp?: number;
|
|
65
89
|
url?: string;
|
|
66
|
-
step?: Partial<Step
|
|
90
|
+
step?: Partial<Step> & {
|
|
91
|
+
duration?: {
|
|
92
|
+
us: number;
|
|
93
|
+
};
|
|
94
|
+
};
|
|
67
95
|
error?: Error;
|
|
68
96
|
root_fields?: Record<string, unknown>;
|
|
69
|
-
payload?: Payload
|
|
97
|
+
payload?: Payload;
|
|
70
98
|
blob?: string;
|
|
71
99
|
blob_mime?: string;
|
|
72
100
|
};
|
|
73
101
|
|
|
102
|
+
type ScreenshotBlob = {
|
|
103
|
+
blob: string;
|
|
104
|
+
id: string;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
type ScreenshotReference = {
|
|
108
|
+
width: number;
|
|
109
|
+
height: number;
|
|
110
|
+
blocks: Array<{
|
|
111
|
+
hash: string;
|
|
112
|
+
top: number;
|
|
113
|
+
left: number;
|
|
114
|
+
width: number;
|
|
115
|
+
height: number;
|
|
116
|
+
}>;
|
|
117
|
+
};
|
|
118
|
+
|
|
74
119
|
function getMetadata() {
|
|
75
120
|
return {
|
|
76
121
|
os: {
|
|
@@ -98,41 +143,12 @@ function formatVersion(protocol: string | undefined) {
|
|
|
98
143
|
}
|
|
99
144
|
}
|
|
100
145
|
|
|
101
|
-
function
|
|
102
|
-
const postData = request.postData ? request.postData : '';
|
|
103
|
-
return {
|
|
104
|
-
...request,
|
|
105
|
-
body: {
|
|
106
|
-
bytes: postData.length,
|
|
107
|
-
content: postData,
|
|
108
|
-
},
|
|
109
|
-
referrer: request.headers?.Referer,
|
|
110
|
-
};
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function formatResponse(response: Protocol.Network.Response) {
|
|
114
|
-
if (!response) {
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
return {
|
|
118
|
-
...response,
|
|
119
|
-
body: {
|
|
120
|
-
bytes: response.encodedDataLength,
|
|
121
|
-
},
|
|
122
|
-
status_code: response.status,
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
function formatTLS(tls: Protocol.Network.SecurityDetails) {
|
|
146
|
+
function formatTLS(tls: SecurityDetails) {
|
|
127
147
|
if (!tls) {
|
|
128
148
|
return;
|
|
129
149
|
}
|
|
130
|
-
const cipher = `${tls.keyExchange ? tls.keyExchange + '_' : ''}${
|
|
131
|
-
tls.cipher
|
|
132
|
-
}_${tls.keyExchangeGroup}`;
|
|
133
150
|
const [name, version] = tls.protocol.toLowerCase().split(' ');
|
|
134
151
|
return {
|
|
135
|
-
cipher,
|
|
136
152
|
server: {
|
|
137
153
|
x509: {
|
|
138
154
|
issuer: {
|
|
@@ -146,7 +162,7 @@ function formatTLS(tls: Protocol.Network.SecurityDetails) {
|
|
|
146
162
|
},
|
|
147
163
|
},
|
|
148
164
|
version_protocol: name,
|
|
149
|
-
version
|
|
165
|
+
version,
|
|
150
166
|
};
|
|
151
167
|
}
|
|
152
168
|
|
|
@@ -162,16 +178,14 @@ export function formatNetworkFields(network: NetworkInfo) {
|
|
|
162
178
|
},
|
|
163
179
|
http: {
|
|
164
180
|
version: formatVersion(response?.protocol),
|
|
165
|
-
request
|
|
166
|
-
response
|
|
181
|
+
request,
|
|
182
|
+
response,
|
|
167
183
|
},
|
|
168
184
|
tls: formatTLS(response?.securityDetails),
|
|
169
185
|
};
|
|
170
186
|
|
|
171
187
|
const pickItems: Array<keyof NetworkInfo> = [
|
|
172
188
|
'browser',
|
|
173
|
-
'status',
|
|
174
|
-
'method',
|
|
175
189
|
'type',
|
|
176
190
|
'isNavigationRequest',
|
|
177
191
|
'requestSentTime',
|
|
@@ -200,6 +214,7 @@ function journeyInfo(
|
|
|
200
214
|
return {
|
|
201
215
|
name: journey.name,
|
|
202
216
|
id: journey.id,
|
|
217
|
+
tags: journey.tags,
|
|
203
218
|
status: type === 'journey/end' ? status : undefined,
|
|
204
219
|
};
|
|
205
220
|
}
|
|
@@ -216,21 +231,103 @@ function stepInfo(
|
|
|
216
231
|
name: step.name,
|
|
217
232
|
index: step.index,
|
|
218
233
|
status: type === 'step/end' ? status : undefined,
|
|
234
|
+
duration: step.duration,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
export async function getScreenshotBlocks(screenshot: Buffer) {
|
|
239
|
+
const img = sharp(screenshot, { sequentialRead: true });
|
|
240
|
+
const { width, height } = await img.metadata();
|
|
241
|
+
/**
|
|
242
|
+
* Chop the screenshot image (1280*720) which is the default
|
|
243
|
+
* viewport size in to 64 equal blocks for a given image
|
|
244
|
+
* which can be acheived by keeping the division to 8
|
|
245
|
+
*
|
|
246
|
+
* Changing division to 16 would yield us 256 smaller blocks, but it is not
|
|
247
|
+
* optimal for caching in the ES and proved out to be bad, so we stick to 8
|
|
248
|
+
*/
|
|
249
|
+
const divisions = 8;
|
|
250
|
+
const blockWidth = Math.floor(width / divisions);
|
|
251
|
+
const blockHeight = Math.floor(height / divisions);
|
|
252
|
+
const reference: ScreenshotReference = {
|
|
253
|
+
width,
|
|
254
|
+
height,
|
|
255
|
+
blocks: [],
|
|
219
256
|
};
|
|
257
|
+
const blocks: Array<ScreenshotBlob> = [];
|
|
258
|
+
|
|
259
|
+
for (let row = 0; row < divisions; row++) {
|
|
260
|
+
const top = row * blockHeight;
|
|
261
|
+
for (let col = 0; col < divisions; col++) {
|
|
262
|
+
const left = col * blockWidth;
|
|
263
|
+
const buf = await img
|
|
264
|
+
.extract({ top, left, width: blockWidth, height: blockHeight })
|
|
265
|
+
.jpeg()
|
|
266
|
+
.toBuffer();
|
|
267
|
+
|
|
268
|
+
const hash = createHash('sha1').update(buf).digest('hex');
|
|
269
|
+
blocks.push({
|
|
270
|
+
blob: buf.toString('base64'),
|
|
271
|
+
id: hash,
|
|
272
|
+
});
|
|
273
|
+
/**
|
|
274
|
+
* We dont write the width, height of individual blocks on the
|
|
275
|
+
* reference as we use similar sized blocks for each extraction,
|
|
276
|
+
* we would need to send the width and height here if we decide to
|
|
277
|
+
* go with dynamic block extraction.
|
|
278
|
+
*/
|
|
279
|
+
reference.blocks.push({
|
|
280
|
+
hash,
|
|
281
|
+
top,
|
|
282
|
+
left,
|
|
283
|
+
width: blockWidth,
|
|
284
|
+
height: blockHeight,
|
|
285
|
+
});
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
return { blocks, reference, blob_mime: 'image/jpeg' };
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Get all the screenshots from the cached screenshot location
|
|
294
|
+
* at the end of each journey and construct equally sized blocks out
|
|
295
|
+
* of the individual screenshot image.
|
|
296
|
+
*/
|
|
297
|
+
export async function gatherScreenshots(
|
|
298
|
+
screenshotsPath: string,
|
|
299
|
+
callback: (data: Screenshot) => Promise<void>
|
|
300
|
+
) {
|
|
301
|
+
if (isDirectory(screenshotsPath)) {
|
|
302
|
+
await totalist(screenshotsPath, async (_, absPath) => {
|
|
303
|
+
try {
|
|
304
|
+
const content = readFileSync(absPath, 'utf8');
|
|
305
|
+
const screenshot: Screenshot = JSON.parse(content);
|
|
306
|
+
await callback(screenshot);
|
|
307
|
+
} catch (_) {
|
|
308
|
+
// TODO: capture progarammatic synthetic errors under different type
|
|
309
|
+
}
|
|
310
|
+
});
|
|
311
|
+
}
|
|
220
312
|
}
|
|
221
313
|
|
|
222
314
|
export default class JSONReporter extends BaseReporter {
|
|
223
|
-
_registerListeners() {
|
|
315
|
+
override _registerListeners() {
|
|
224
316
|
/**
|
|
225
317
|
* report the number of journeys that exists on a suite which
|
|
226
318
|
* could be used for better sharding
|
|
227
319
|
*/
|
|
228
|
-
this.runner.on('start', ({ numJourneys }) => {
|
|
320
|
+
this.runner.on('start', ({ numJourneys, networkConditions }) => {
|
|
229
321
|
this.writeJSON({
|
|
230
322
|
type: 'synthetics/metadata',
|
|
231
323
|
root_fields: {
|
|
232
324
|
num_journeys: numJourneys,
|
|
233
325
|
},
|
|
326
|
+
payload: networkConditions
|
|
327
|
+
? {
|
|
328
|
+
network_conditions: networkConditions,
|
|
329
|
+
}
|
|
330
|
+
: undefined,
|
|
234
331
|
});
|
|
235
332
|
});
|
|
236
333
|
|
|
@@ -258,33 +355,47 @@ export default class JSONReporter extends BaseReporter {
|
|
|
258
355
|
start,
|
|
259
356
|
end,
|
|
260
357
|
error,
|
|
261
|
-
screenshot,
|
|
262
358
|
url,
|
|
263
359
|
status,
|
|
360
|
+
pagemetrics,
|
|
361
|
+
traces,
|
|
264
362
|
metrics,
|
|
363
|
+
filmstrips,
|
|
265
364
|
}) => {
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
365
|
+
this.writeMetrics(journey, step, 'relative_trace', traces);
|
|
366
|
+
this.writeMetrics(journey, step, 'experience', metrics);
|
|
367
|
+
if (filmstrips) {
|
|
368
|
+
// Write each filmstrip separately so that we don't get documents that are too large
|
|
369
|
+
filmstrips.forEach((strip, index) => {
|
|
370
|
+
this.writeJSON({
|
|
371
|
+
type: 'step/filmstrips',
|
|
372
|
+
journey,
|
|
373
|
+
step,
|
|
374
|
+
payload: { index },
|
|
375
|
+
root_fields: {
|
|
376
|
+
browser: { relative_trace: { start: strip.start } },
|
|
377
|
+
},
|
|
378
|
+
blob: strip.blob,
|
|
379
|
+
blob_mime: strip.mime,
|
|
380
|
+
});
|
|
273
381
|
});
|
|
274
382
|
}
|
|
275
383
|
this.writeJSON({
|
|
276
384
|
type: 'step/end',
|
|
277
385
|
journey,
|
|
278
|
-
step
|
|
386
|
+
step: {
|
|
387
|
+
...step,
|
|
388
|
+
duration: {
|
|
389
|
+
us: getDurationInUs(end - start),
|
|
390
|
+
},
|
|
391
|
+
},
|
|
279
392
|
url,
|
|
280
393
|
error,
|
|
281
394
|
payload: {
|
|
282
395
|
source: step.callback.toString(),
|
|
283
|
-
start,
|
|
284
|
-
end,
|
|
285
396
|
url,
|
|
286
397
|
status,
|
|
287
|
-
|
|
398
|
+
pagemetrics,
|
|
288
399
|
},
|
|
289
400
|
});
|
|
290
401
|
}
|
|
@@ -292,16 +403,45 @@ export default class JSONReporter extends BaseReporter {
|
|
|
292
403
|
|
|
293
404
|
this.runner.on(
|
|
294
405
|
'journey:end',
|
|
295
|
-
({
|
|
406
|
+
async ({
|
|
296
407
|
journey,
|
|
408
|
+
timestamp,
|
|
297
409
|
start,
|
|
298
410
|
end,
|
|
299
|
-
filmstrips,
|
|
300
411
|
networkinfo,
|
|
301
412
|
browserconsole,
|
|
302
413
|
status,
|
|
303
414
|
error,
|
|
415
|
+
options,
|
|
304
416
|
}) => {
|
|
417
|
+
const { ssblocks, screenshots } = options;
|
|
418
|
+
const writeScreenshots =
|
|
419
|
+
screenshots === 'on' ||
|
|
420
|
+
(screenshots === 'only-on-failure' && status === 'failed');
|
|
421
|
+
if (writeScreenshots) {
|
|
422
|
+
await gatherScreenshots(
|
|
423
|
+
join(CACHE_PATH, 'screenshots'),
|
|
424
|
+
async screenshot => {
|
|
425
|
+
const { data, timestamp, step } = screenshot;
|
|
426
|
+
if (!data) {
|
|
427
|
+
return;
|
|
428
|
+
}
|
|
429
|
+
if (ssblocks) {
|
|
430
|
+
await this.writeScreenshotBlocks(journey, screenshot);
|
|
431
|
+
} else {
|
|
432
|
+
this.writeJSON({
|
|
433
|
+
type: 'step/screenshot',
|
|
434
|
+
timestamp,
|
|
435
|
+
journey,
|
|
436
|
+
step,
|
|
437
|
+
blob: data,
|
|
438
|
+
blob_mime: 'image/jpeg',
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
);
|
|
443
|
+
}
|
|
444
|
+
|
|
305
445
|
if (networkinfo) {
|
|
306
446
|
networkinfo.forEach(ni => {
|
|
307
447
|
const { ecs, payload } = formatNetworkFields(ni);
|
|
@@ -315,37 +455,26 @@ export default class JSONReporter extends BaseReporter {
|
|
|
315
455
|
});
|
|
316
456
|
});
|
|
317
457
|
}
|
|
318
|
-
if (filmstrips) {
|
|
319
|
-
// Write each filmstrip separately so that we don't get documents that are too large
|
|
320
|
-
filmstrips.forEach((strip, index) => {
|
|
321
|
-
this.writeJSON({
|
|
322
|
-
type: 'journey/filmstrips',
|
|
323
|
-
journey,
|
|
324
|
-
payload: {
|
|
325
|
-
index,
|
|
326
|
-
...{
|
|
327
|
-
startTime: strip.startTime,
|
|
328
|
-
ts: strip.ts,
|
|
329
|
-
},
|
|
330
|
-
},
|
|
331
|
-
blob: strip.snapshot,
|
|
332
|
-
});
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
458
|
if (browserconsole) {
|
|
336
|
-
browserconsole.forEach(({ timestamp, text, type, step }) => {
|
|
459
|
+
browserconsole.forEach(({ timestamp, text, type, step, error }) => {
|
|
337
460
|
this.writeJSON({
|
|
338
461
|
type: 'journey/browserconsole',
|
|
339
462
|
journey,
|
|
340
463
|
timestamp,
|
|
341
464
|
step,
|
|
342
|
-
|
|
465
|
+
error,
|
|
466
|
+
payload: {
|
|
467
|
+
text,
|
|
468
|
+
type,
|
|
469
|
+
} as Payload,
|
|
343
470
|
});
|
|
344
471
|
});
|
|
345
472
|
}
|
|
473
|
+
|
|
346
474
|
this.writeJSON({
|
|
347
475
|
type: 'journey/end',
|
|
348
476
|
journey,
|
|
477
|
+
timestamp,
|
|
349
478
|
error,
|
|
350
479
|
payload: {
|
|
351
480
|
start,
|
|
@@ -353,16 +482,65 @@ export default class JSONReporter extends BaseReporter {
|
|
|
353
482
|
status,
|
|
354
483
|
},
|
|
355
484
|
});
|
|
485
|
+
process.nextTick(() => this.runner.emit('journey:end:reported', {}));
|
|
356
486
|
}
|
|
357
487
|
);
|
|
358
488
|
}
|
|
359
489
|
|
|
490
|
+
async writeScreenshotBlocks(journey: Journey, screenshot: Screenshot) {
|
|
491
|
+
const { blob_mime, blocks, reference } = await getScreenshotBlocks(
|
|
492
|
+
Buffer.from(screenshot.data, 'base64')
|
|
493
|
+
);
|
|
494
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
495
|
+
const block = blocks[i];
|
|
496
|
+
this.writeJSON({
|
|
497
|
+
type: 'screenshot/block',
|
|
498
|
+
timestamp: screenshot.timestamp,
|
|
499
|
+
_id: block.id,
|
|
500
|
+
blob: block.blob,
|
|
501
|
+
blob_mime,
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
this.writeJSON({
|
|
505
|
+
type: 'step/screenshot_ref',
|
|
506
|
+
timestamp: screenshot.timestamp,
|
|
507
|
+
journey,
|
|
508
|
+
step: screenshot.step,
|
|
509
|
+
root_fields: {
|
|
510
|
+
screenshot_ref: reference,
|
|
511
|
+
},
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
writeMetrics(
|
|
516
|
+
journey: Journey,
|
|
517
|
+
step: Step,
|
|
518
|
+
type: string,
|
|
519
|
+
events: Array<TraceOutput> | PerfMetrics
|
|
520
|
+
) {
|
|
521
|
+
const metrics = Array.isArray(events) ? events : [events];
|
|
522
|
+
metrics.forEach(event => {
|
|
523
|
+
event &&
|
|
524
|
+
this.writeJSON({
|
|
525
|
+
type: 'step/metrics',
|
|
526
|
+
journey,
|
|
527
|
+
step,
|
|
528
|
+
root_fields: {
|
|
529
|
+
browser: {
|
|
530
|
+
[type]: event,
|
|
531
|
+
},
|
|
532
|
+
},
|
|
533
|
+
});
|
|
534
|
+
});
|
|
535
|
+
}
|
|
536
|
+
|
|
360
537
|
// Writes a structured synthetics event
|
|
361
538
|
// Note that blob is ultimately stored in ES as a base64 encoded string. You must base 64 encode
|
|
362
539
|
// it before passing it into this function!
|
|
363
540
|
// The payload field is an un-indexed field with no ES mapping, so users can put arbitary structured
|
|
364
541
|
// stuff in there
|
|
365
542
|
writeJSON({
|
|
543
|
+
_id,
|
|
366
544
|
journey,
|
|
367
545
|
type,
|
|
368
546
|
timestamp,
|
|
@@ -376,6 +554,7 @@ export default class JSONReporter extends BaseReporter {
|
|
|
376
554
|
}: OutputFields) {
|
|
377
555
|
this.write({
|
|
378
556
|
type,
|
|
557
|
+
_id,
|
|
379
558
|
'@timestamp': timestamp || getTimestamp(),
|
|
380
559
|
journey: journeyInfo(journey, type, payload?.status),
|
|
381
560
|
step: stepInfo(step, type, payload?.status),
|
package/src/reporters/junit.ts
CHANGED
|
@@ -52,7 +52,7 @@ export default class JUnitReporter extends BaseReporter {
|
|
|
52
52
|
private totalFailures = 0;
|
|
53
53
|
private totalSkipped = 0;
|
|
54
54
|
|
|
55
|
-
_registerListeners() {
|
|
55
|
+
override _registerListeners() {
|
|
56
56
|
const journeyMap = new Map<string, XMLEntry>();
|
|
57
57
|
|
|
58
58
|
this.runner.on('journey:start', ({ journey }) => {
|