@elastic/synthetics 1.0.0-beta.3 → 1.0.0-beta.30

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.
Files changed (189) hide show
  1. package/README.md +4 -3
  2. package/dist/cli.js +99 -162
  3. package/dist/cli.js.map +1 -1
  4. package/dist/common_types.d.ts +156 -34
  5. package/dist/common_types.d.ts.map +1 -1
  6. package/dist/config.d.ts +2 -5
  7. package/dist/config.d.ts.map +1 -1
  8. package/dist/config.js +5 -5
  9. package/dist/config.js.map +1 -1
  10. package/dist/core/browser-service.js +5 -5
  11. package/dist/core/browser-service.js.map +1 -1
  12. package/dist/core/gatherer.d.ts +4 -8
  13. package/dist/core/gatherer.d.ts.map +1 -1
  14. package/dist/core/gatherer.js +46 -14
  15. package/dist/core/gatherer.js.map +1 -1
  16. package/dist/core/index.d.ts +5 -1
  17. package/dist/core/index.d.ts.map +1 -1
  18. package/dist/core/index.js +23 -11
  19. package/dist/core/index.js.map +1 -1
  20. package/dist/core/logger.d.ts +0 -1
  21. package/dist/core/logger.d.ts.map +1 -1
  22. package/dist/core/logger.js +3 -16
  23. package/dist/core/logger.js.map +1 -1
  24. package/dist/core/runner.d.ts +21 -65
  25. package/dist/core/runner.d.ts.map +1 -1
  26. package/dist/core/runner.js +211 -93
  27. package/dist/core/runner.js.map +1 -1
  28. package/dist/dsl/journey.d.ts +7 -3
  29. package/dist/dsl/journey.d.ts.map +1 -1
  30. package/dist/dsl/journey.js +22 -6
  31. package/dist/dsl/journey.js.map +1 -1
  32. package/{src/reporters/reporter.ts → dist/dsl/locations.d.ts} +12 -10
  33. package/dist/dsl/locations.d.ts.map +1 -0
  34. package/dist/dsl/locations.js +41 -0
  35. package/dist/dsl/locations.js.map +1 -0
  36. package/dist/dsl/monitor.d.ts +65 -0
  37. package/dist/dsl/monitor.d.ts.map +1 -0
  38. package/dist/dsl/monitor.js +63 -0
  39. package/dist/dsl/monitor.js.map +1 -0
  40. package/dist/dsl/step.d.ts +3 -2
  41. package/dist/dsl/step.d.ts.map +1 -1
  42. package/dist/dsl/step.js +2 -1
  43. package/dist/dsl/step.js.map +1 -1
  44. package/dist/formatter/javascript.d.ts +98 -0
  45. package/dist/formatter/javascript.d.ts.map +1 -0
  46. package/dist/formatter/javascript.js +295 -0
  47. package/dist/formatter/javascript.js.map +1 -0
  48. package/dist/generator/index.d.ts +21 -0
  49. package/dist/generator/index.d.ts.map +1 -0
  50. package/dist/generator/index.js +169 -0
  51. package/dist/generator/index.js.map +1 -0
  52. package/dist/{reporters/reporter.d.ts → generator/utils.d.ts} +4 -9
  53. package/dist/generator/utils.d.ts.map +1 -0
  54. package/dist/generator/utils.js +57 -0
  55. package/dist/generator/utils.js.map +1 -0
  56. package/dist/helpers.d.ts +20 -1
  57. package/dist/helpers.d.ts.map +1 -1
  58. package/dist/helpers.js +98 -18
  59. package/dist/helpers.js.map +1 -1
  60. package/dist/index.d.ts +5 -6
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +5 -26
  63. package/dist/index.js.map +1 -1
  64. package/dist/{parse_args.d.ts → loader.d.ts} +2 -5
  65. package/dist/loader.d.ts.map +1 -0
  66. package/dist/loader.js +144 -0
  67. package/dist/loader.js.map +1 -0
  68. package/dist/options.d.ts +34 -0
  69. package/dist/options.d.ts.map +1 -0
  70. package/dist/options.js +162 -0
  71. package/dist/options.js.map +1 -0
  72. package/dist/plugins/browser-console.d.ts +5 -4
  73. package/dist/plugins/browser-console.d.ts.map +1 -1
  74. package/dist/plugins/browser-console.js +27 -8
  75. package/dist/plugins/browser-console.js.map +1 -1
  76. package/dist/plugins/network.d.ts +20 -33
  77. package/dist/plugins/network.d.ts.map +1 -1
  78. package/dist/plugins/network.js +173 -214
  79. package/dist/plugins/network.js.map +1 -1
  80. package/dist/plugins/performance.d.ts +4 -19
  81. package/dist/plugins/performance.d.ts.map +1 -1
  82. package/dist/plugins/performance.js +5 -5
  83. package/dist/plugins/performance.js.map +1 -1
  84. package/dist/plugins/plugin-manager.d.ts +9 -5
  85. package/dist/plugins/plugin-manager.d.ts.map +1 -1
  86. package/dist/plugins/plugin-manager.js +44 -29
  87. package/dist/plugins/plugin-manager.js.map +1 -1
  88. package/dist/plugins/tracing.d.ts +6 -6
  89. package/dist/plugins/tracing.d.ts.map +1 -1
  90. package/dist/plugins/tracing.js +8 -7
  91. package/dist/plugins/tracing.js.map +1 -1
  92. package/dist/push/bundler.d.ts +34 -0
  93. package/dist/push/bundler.d.ts.map +1 -0
  94. package/dist/push/bundler.js +114 -0
  95. package/dist/push/bundler.js.map +1 -0
  96. package/dist/{reporters/reporter.js → push/index.d.ts} +4 -3
  97. package/dist/push/index.d.ts.map +1 -0
  98. package/dist/push/index.js +55 -0
  99. package/dist/push/index.js.map +1 -0
  100. package/dist/push/monitor.d.ts +32 -0
  101. package/dist/push/monitor.d.ts.map +1 -0
  102. package/dist/push/monitor.js +62 -0
  103. package/dist/push/monitor.js.map +1 -0
  104. package/dist/push/plugin.d.ts +33 -0
  105. package/dist/push/plugin.d.ts.map +1 -0
  106. package/dist/push/plugin.js +124 -0
  107. package/dist/push/plugin.js.map +1 -0
  108. package/dist/push/request.d.ts +42 -0
  109. package/dist/push/request.d.ts.map +1 -0
  110. package/dist/push/request.js +84 -0
  111. package/dist/push/request.js.map +1 -0
  112. package/dist/reporters/base.d.ts +14 -6
  113. package/dist/reporters/base.d.ts.map +1 -1
  114. package/dist/reporters/base.js +54 -48
  115. package/dist/reporters/base.js.map +1 -1
  116. package/dist/reporters/index.d.ts +18 -8
  117. package/dist/reporters/index.d.ts.map +1 -1
  118. package/dist/reporters/index.js.map +1 -1
  119. package/dist/reporters/json.d.ts +18 -67
  120. package/dist/reporters/json.d.ts.map +1 -1
  121. package/dist/reporters/json.js +153 -175
  122. package/dist/reporters/json.js.map +1 -1
  123. package/dist/reporters/junit.d.ts +7 -1
  124. package/dist/reporters/junit.d.ts.map +1 -1
  125. package/dist/reporters/junit.js +94 -89
  126. package/dist/reporters/junit.js.map +1 -1
  127. package/dist/sdk/lh-trace-processor.d.ts +35 -9
  128. package/dist/sdk/lh-trace-processor.d.ts.map +1 -1
  129. package/dist/sdk/lh-trace-processor.js +114 -53
  130. package/dist/sdk/lh-trace-processor.js.map +1 -1
  131. package/dist/sdk/trace-metrics.d.ts +4 -4
  132. package/dist/sdk/trace-metrics.d.ts.map +1 -1
  133. package/dist/sdk/trace-metrics.js +5 -6
  134. package/dist/sdk/trace-metrics.js.map +1 -1
  135. package/dist/sdk/trace-processor.d.ts +11 -3
  136. package/dist/sdk/trace-processor.d.ts.map +1 -1
  137. package/dist/sdk/trace-processor.js +17 -9
  138. package/dist/sdk/trace-processor.js.map +1 -1
  139. package/dist/tsconfig.tsbuildinfo +1 -1888
  140. package/package.json +31 -19
  141. package/src/cli.ts +187 -154
  142. package/src/common_types.ts +188 -34
  143. package/src/config.ts +2 -5
  144. package/src/core/gatherer.ts +55 -27
  145. package/src/core/index.ts +36 -15
  146. package/src/core/logger.ts +1 -12
  147. package/src/core/runner.ts +216 -152
  148. package/src/dsl/journey.ts +29 -5
  149. package/src/dsl/locations.ts +38 -0
  150. package/src/dsl/monitor.ts +87 -0
  151. package/src/dsl/step.ts +9 -2
  152. package/src/formatter/javascript.ts +367 -0
  153. package/src/generator/index.ts +212 -0
  154. package/src/generator/utils.ts +54 -0
  155. package/src/helpers.ts +106 -10
  156. package/src/index.ts +21 -22
  157. package/src/loader.ts +162 -0
  158. package/src/options.ts +173 -0
  159. package/src/plugins/browser-console.ts +30 -8
  160. package/src/plugins/network.ts +208 -267
  161. package/src/plugins/performance.ts +6 -22
  162. package/src/plugins/plugin-manager.ts +49 -31
  163. package/src/plugins/tracing.ts +8 -9
  164. package/src/push/bundler.ts +95 -0
  165. package/src/push/index.ts +59 -0
  166. package/src/push/monitor.ts +68 -0
  167. package/src/push/plugin.ts +114 -0
  168. package/src/push/request.ts +111 -0
  169. package/src/reporters/base.ts +63 -52
  170. package/src/reporters/index.ts +26 -3
  171. package/src/reporters/json.ts +203 -206
  172. package/src/reporters/junit.ts +98 -93
  173. package/src/sdk/lh-trace-processor.ts +132 -68
  174. package/src/sdk/trace-metrics.ts +10 -6
  175. package/src/sdk/trace-processor.ts +28 -13
  176. package/templates/.github/workflows/run-synthetics.yml +26 -0
  177. package/templates/README.md +21 -0
  178. package/templates/journeys/advanced-example-helpers.ts +54 -0
  179. package/templates/journeys/advanced-example.journey.ts +43 -0
  180. package/templates/journeys/example.journey.ts +18 -0
  181. package/templates/synthetics.config.ts +26 -0
  182. package/CHANGELOG.md +0 -102
  183. package/NOTICE.txt +0 -221
  184. package/dist/parse_args.d.ts.map +0 -1
  185. package/dist/parse_args.js +0 -89
  186. package/dist/parse_args.js.map +0 -1
  187. package/dist/reporters/reporter.d.ts.map +0 -1
  188. package/dist/reporters/reporter.js.map +0 -1
  189. package/src/parse_args.ts +0 -127
@@ -40,12 +40,19 @@ import { Journey, Step } from '../dsl';
40
40
  import snakeCaseKeys from 'snakecase-keys';
41
41
  import {
42
42
  NetworkInfo,
43
+ SecurityDetails,
44
+ NetworkConditions,
43
45
  TraceOutput,
44
46
  StatusValue,
45
47
  PerfMetrics,
48
+ Params,
49
+ Screenshot,
50
+ StartEvent,
51
+ JourneyStartResult,
52
+ StepEndResult,
53
+ JourneyEndResult,
54
+ PageMetrics,
46
55
  } from '../common_types';
47
- import { Protocol } from 'playwright-chromium/types/protocol';
48
- import { Metrics } from '../plugins';
49
56
 
50
57
  /* eslint-disable @typescript-eslint/no-var-requires */
51
58
  const { version, name } = require('../../package.json');
@@ -57,11 +64,11 @@ type OutputType =
57
64
  | 'screenshot/block'
58
65
  | 'step/screenshot_ref'
59
66
  | 'step/screenshot'
67
+ | 'step/metrics'
68
+ | 'step/filmstrips'
60
69
  | 'step/end'
61
70
  | 'journey/network_info'
62
- | 'journey/filmstrips'
63
71
  | 'journey/browserconsole'
64
- | 'journey/metrics'
65
72
  | 'journey/end';
66
73
 
67
74
  type Payload = {
@@ -69,12 +76,13 @@ type Payload = {
69
76
  start?: number;
70
77
  end?: number;
71
78
  url?: string;
72
- status?: StatusValue | number;
73
- metrics?: Metrics;
74
- params?: Record<string, unknown>;
79
+ status?: StatusValue;
80
+ pagemetrics?: PageMetrics;
81
+ params?: Params;
75
82
  type?: OutputType;
76
83
  text?: string;
77
84
  index?: number;
85
+ network_conditions?: NetworkConditions;
78
86
  };
79
87
 
80
88
  type OutputFields = {
@@ -90,7 +98,7 @@ type OutputFields = {
90
98
  };
91
99
  error?: Error;
92
100
  root_fields?: Record<string, unknown>;
93
- payload?: Payload | NetworkInfo;
101
+ payload?: Payload;
94
102
  blob?: string;
95
103
  blob_mime?: string;
96
104
  };
@@ -112,13 +120,6 @@ type ScreenshotReference = {
112
120
  }>;
113
121
  };
114
122
 
115
- type ScreenshotOutput = {
116
- step: Step;
117
- blob_mime: string;
118
- blocks: Array<ScreenshotBlob>;
119
- reference: ScreenshotReference;
120
- };
121
-
122
123
  function getMetadata() {
123
124
  return {
124
125
  os: {
@@ -131,56 +132,12 @@ function getMetadata() {
131
132
  };
132
133
  }
133
134
 
134
- function formatVersion(protocol: string | undefined) {
135
- if (!protocol) {
136
- return;
137
- }
138
- if (protocol === 'h2') {
139
- return 2;
140
- } else if (protocol === 'http/1.1') {
141
- return 1.1;
142
- } else if (protocol === 'http/1.0') {
143
- return 1.0;
144
- } else if (protocol.startsWith('h3')) {
145
- return 3;
146
- }
147
- }
148
-
149
- function formatRequest(request: Protocol.Network.Request) {
150
- const postData = request.postData ? request.postData : '';
151
- return {
152
- ...request,
153
- body: {
154
- bytes: postData.length,
155
- content: postData,
156
- },
157
- referrer: request.headers?.Referer,
158
- };
159
- }
160
-
161
- function formatResponse(response: Protocol.Network.Response) {
162
- if (!response) {
135
+ function formatTLS(tls: SecurityDetails) {
136
+ if (!tls || !tls.protocol) {
163
137
  return;
164
138
  }
165
- return {
166
- ...response,
167
- body: {
168
- bytes: response.encodedDataLength,
169
- },
170
- status_code: response.status,
171
- };
172
- }
173
-
174
- function formatTLS(tls: Protocol.Network.SecurityDetails) {
175
- if (!tls) {
176
- return;
177
- }
178
- const cipher = `${tls.keyExchange ? tls.keyExchange + '_' : ''}${
179
- tls.cipher
180
- }_${tls.keyExchangeGroup}`;
181
139
  const [name, version] = tls.protocol.toLowerCase().split(' ');
182
140
  return {
183
- cipher,
184
141
  server: {
185
142
  x509: {
186
143
  issuer: {
@@ -194,7 +151,7 @@ function formatTLS(tls: Protocol.Network.SecurityDetails) {
194
151
  },
195
152
  },
196
153
  version_protocol: name,
197
- version: version,
154
+ version,
198
155
  };
199
156
  }
200
157
 
@@ -209,17 +166,14 @@ export function formatNetworkFields(network: NetworkInfo) {
209
166
  original: request.headers?.['User-Agent'],
210
167
  },
211
168
  http: {
212
- version: formatVersion(response?.protocol),
213
- request: formatRequest(request),
214
- response: formatResponse(response),
169
+ request,
170
+ response,
215
171
  },
216
172
  tls: formatTLS(response?.securityDetails),
217
173
  };
218
174
 
219
175
  const pickItems: Array<keyof NetworkInfo> = [
220
176
  'browser',
221
- 'status',
222
- 'method',
223
177
  'type',
224
178
  'isNavigationRequest',
225
179
  'requestSentTime',
@@ -281,8 +235,8 @@ export async function getScreenshotBlocks(screenshot: Buffer) {
281
235
  * optimal for caching in the ES and proved out to be bad, so we stick to 8
282
236
  */
283
237
  const divisions = 8;
284
- const blockWidth = width / divisions;
285
- const blockHeight = height / divisions;
238
+ const blockWidth = Math.floor(width / divisions);
239
+ const blockHeight = Math.floor(height / divisions);
286
240
  const reference: ScreenshotReference = {
287
241
  width,
288
242
  height,
@@ -330,187 +284,229 @@ export async function getScreenshotBlocks(screenshot: Buffer) {
330
284
  */
331
285
  export async function gatherScreenshots(
332
286
  screenshotsPath: string,
333
- callback: (step: Step, data: string) => Promise<void>
287
+ callback: (data: Screenshot) => Promise<void>
334
288
  ) {
335
- const screenshots: Array<ScreenshotOutput> = [];
336
289
  if (isDirectory(screenshotsPath)) {
337
290
  await totalist(screenshotsPath, async (_, absPath) => {
338
291
  try {
339
292
  const content = readFileSync(absPath, 'utf8');
340
- const { step, data } = JSON.parse(content);
341
- await callback(step, data);
293
+ const screenshot: Screenshot = JSON.parse(content);
294
+ await callback(screenshot);
342
295
  } catch (_) {
343
296
  // TODO: capture progarammatic synthetic errors under different type
344
297
  }
345
298
  });
346
299
  }
347
- return screenshots;
348
300
  }
349
301
 
350
302
  export default class JSONReporter extends BaseReporter {
351
- _registerListeners() {
303
+ onStart(params: StartEvent) {
352
304
  /**
353
305
  * report the number of journeys that exists on a suite which
354
306
  * could be used for better sharding
355
307
  */
356
- this.runner.on('start', ({ numJourneys }) => {
357
- this.writeJSON({
358
- type: 'synthetics/metadata',
359
- root_fields: {
360
- num_journeys: numJourneys,
361
- },
362
- });
308
+ this.writeJSON({
309
+ type: 'synthetics/metadata',
310
+ root_fields: {
311
+ num_journeys: params.numJourneys,
312
+ },
313
+ payload: params.networkConditions
314
+ ? {
315
+ network_conditions: params.networkConditions,
316
+ }
317
+ : undefined,
363
318
  });
319
+ }
364
320
 
365
- this.runner.on('journey:register', ({ journey }) => {
366
- this.writeJSON({
367
- type: 'journey/register',
368
- journey,
369
- });
321
+ onJourneyRegister(journey: Journey): void {
322
+ this.writeJSON({
323
+ type: 'journey/register',
324
+ journey,
370
325
  });
326
+ }
371
327
 
372
- this.runner.on('journey:start', ({ journey, timestamp, params }) => {
373
- this.writeJSON({
374
- type: 'journey/start',
375
- journey,
376
- timestamp,
377
- payload: { params, source: journey.callback.toString() },
378
- });
328
+ override onJourneyStart(
329
+ journey: Journey,
330
+ { timestamp, params }: JourneyStartResult
331
+ ) {
332
+ this.writeJSON({
333
+ type: 'journey/start',
334
+ journey,
335
+ timestamp,
336
+ payload: { params, source: journey.callback.toString() },
379
337
  });
338
+ }
380
339
 
381
- this.runner.on(
382
- 'step:end',
383
- ({ journey, step, start, end, error, url, status, metrics }) => {
340
+ override onStepEnd(
341
+ journey: Journey,
342
+ step: Step,
343
+ {
344
+ start,
345
+ end,
346
+ error,
347
+ url,
348
+ status,
349
+ pagemetrics,
350
+ traces,
351
+ metrics,
352
+ filmstrips,
353
+ }: StepEndResult
354
+ ) {
355
+ this.writeMetrics(journey, step, 'relative_trace', traces);
356
+ this.writeMetrics(journey, step, 'experience', metrics);
357
+ if (filmstrips) {
358
+ // Write each filmstrip separately so that we don't get documents that are too large
359
+ filmstrips.forEach((strip, index) => {
384
360
  this.writeJSON({
385
- type: 'step/end',
361
+ type: 'step/filmstrips',
386
362
  journey,
387
- step: {
388
- ...step,
389
- duration: {
390
- us: getDurationInUs(end - start),
391
- },
392
- },
393
- url,
394
- error,
395
- payload: {
396
- source: step.callback.toString(),
397
- url,
398
- status,
399
- metrics,
363
+ step,
364
+ payload: { index },
365
+ root_fields: {
366
+ browser: { relative_trace: { start: strip.start } },
400
367
  },
368
+ blob: strip.blob,
369
+ blob_mime: strip.mime,
401
370
  });
402
- }
403
- );
371
+ });
372
+ }
404
373
 
405
- this.runner.on(
406
- 'journey:end',
407
- async ({
408
- journey,
409
- start,
410
- end,
411
- filmstrips,
412
- networkinfo,
413
- browserconsole,
414
- traces,
415
- metrics,
374
+ this.writeJSON({
375
+ type: 'step/end',
376
+ journey,
377
+ step: {
378
+ ...step,
379
+ duration: {
380
+ us: getDurationInUs(end - start),
381
+ },
382
+ },
383
+ url,
384
+ error,
385
+ payload: {
386
+ source: step.callback.toString(),
387
+ url,
416
388
  status,
417
- error,
418
- ssblocks,
419
- }) => {
420
- await gatherScreenshots(
421
- join(CACHE_PATH, 'screenshots'),
422
- async (step, data) => {
423
- if (ssblocks) {
424
- const { blob_mime, blocks, reference } =
425
- await getScreenshotBlocks(Buffer.from(data, 'base64'));
426
- for (let i = 0; i < blocks.length; i++) {
427
- const block = blocks[i];
428
- this.writeJSON({
429
- type: 'screenshot/block',
430
- _id: block.id,
431
- blob: block.blob,
432
- blob_mime,
433
- });
434
- }
435
- this.writeJSON({
436
- type: 'step/screenshot_ref',
437
- journey,
438
- step,
439
- root_fields: {
440
- screenshot_ref: reference,
441
- },
442
- });
443
- } else {
444
- this.writeJSON({
445
- type: 'step/screenshot',
446
- journey,
447
- step,
448
- blob: data,
449
- blob_mime: 'image/jpeg',
450
- });
451
- }
452
- }
453
- );
389
+ pagemetrics,
390
+ },
391
+ });
392
+ }
454
393
 
455
- if (networkinfo) {
456
- networkinfo.forEach(ni => {
457
- const { ecs, payload } = formatNetworkFields(ni);
458
- this.writeJSON({
459
- type: 'journey/network_info',
460
- journey,
461
- timestamp: ni.timestamp,
462
- root_fields: snakeCaseKeys(ecs),
463
- step: ni.step,
464
- payload: snakeCaseKeys(payload),
465
- });
466
- });
467
- }
468
- if (filmstrips) {
469
- // Write each filmstrip separately so that we don't get documents that are too large
470
- filmstrips.forEach((strip, index) => {
471
- this.writeJSON({
472
- type: 'journey/filmstrips',
473
- journey,
474
- payload: { index },
475
- root_fields: {
476
- browser: { relative_trace: { start: strip.start } },
477
- },
478
- blob: strip.blob,
479
- blob_mime: strip.mime,
480
- });
481
- });
482
- }
483
- if (browserconsole) {
484
- browserconsole.forEach(({ timestamp, text, type, step }) => {
394
+ override async onJourneyEnd(
395
+ journey: Journey,
396
+ {
397
+ timestamp,
398
+ start,
399
+ end,
400
+ networkinfo,
401
+ browserconsole,
402
+ status,
403
+ error,
404
+ options,
405
+ }: JourneyEndResult
406
+ ) {
407
+ const { ssblocks, screenshots } = options;
408
+ const writeScreenshots =
409
+ screenshots === 'on' ||
410
+ (screenshots === 'only-on-failure' && status === 'failed');
411
+ if (writeScreenshots) {
412
+ await gatherScreenshots(
413
+ join(CACHE_PATH, 'screenshots'),
414
+ async screenshot => {
415
+ const { data, timestamp, step } = screenshot;
416
+ if (!data) {
417
+ return;
418
+ }
419
+ if (ssblocks) {
420
+ await this.writeScreenshotBlocks(journey, screenshot);
421
+ } else {
485
422
  this.writeJSON({
486
- type: 'journey/browserconsole',
487
- journey,
423
+ type: 'step/screenshot',
488
424
  timestamp,
425
+ journey,
489
426
  step,
490
- payload: { text, type } as Payload,
427
+ blob: data,
428
+ blob_mime: 'image/jpeg',
491
429
  });
492
- });
430
+ }
493
431
  }
494
- this.writeMetrics(journey, 'relative_trace', traces);
495
- this.writeMetrics(journey, 'experience', metrics);
432
+ );
433
+ }
496
434
 
435
+ if (networkinfo) {
436
+ networkinfo.forEach(ni => {
437
+ const { ecs, payload } = formatNetworkFields(ni);
497
438
  this.writeJSON({
498
- type: 'journey/end',
439
+ type: 'journey/network_info',
499
440
  journey,
441
+ timestamp: ni.timestamp,
442
+ root_fields: snakeCaseKeys(ecs),
443
+ step: ni.step,
444
+ payload: snakeCaseKeys(payload),
445
+ });
446
+ });
447
+ }
448
+
449
+ if (browserconsole) {
450
+ browserconsole.forEach(({ timestamp, text, type, step, error }) => {
451
+ this.writeJSON({
452
+ type: 'journey/browserconsole',
453
+ journey,
454
+ timestamp,
455
+ step,
500
456
  error,
501
457
  payload: {
502
- start,
503
- end,
504
- status,
505
- },
458
+ text,
459
+ type,
460
+ } as Payload,
506
461
  });
507
- this.runner.emit('journey:end:reported', {});
508
- }
462
+ });
463
+ }
464
+
465
+ this.writeJSON({
466
+ type: 'journey/end',
467
+ journey,
468
+ timestamp,
469
+ error,
470
+ payload: {
471
+ start,
472
+ end,
473
+ status,
474
+ },
475
+ });
476
+ }
477
+
478
+ override onEnd() {
479
+ this.stream.flushSync();
480
+ }
481
+
482
+ async writeScreenshotBlocks(journey: Journey, screenshot: Screenshot) {
483
+ const { blob_mime, blocks, reference } = await getScreenshotBlocks(
484
+ Buffer.from(screenshot.data, 'base64')
509
485
  );
486
+ for (let i = 0; i < blocks.length; i++) {
487
+ const block = blocks[i];
488
+ this.writeJSON({
489
+ type: 'screenshot/block',
490
+ timestamp: screenshot.timestamp,
491
+ _id: block.id,
492
+ blob: block.blob,
493
+ blob_mime,
494
+ });
495
+ }
496
+ this.writeJSON({
497
+ type: 'step/screenshot_ref',
498
+ timestamp: screenshot.timestamp,
499
+ journey,
500
+ step: screenshot.step,
501
+ root_fields: {
502
+ screenshot_ref: reference,
503
+ },
504
+ });
510
505
  }
511
506
 
512
507
  writeMetrics(
513
508
  journey: Journey,
509
+ step: Step,
514
510
  type: string,
515
511
  events: Array<TraceOutput> | PerfMetrics
516
512
  ) {
@@ -518,8 +514,9 @@ export default class JSONReporter extends BaseReporter {
518
514
  metrics.forEach(event => {
519
515
  event &&
520
516
  this.writeJSON({
521
- type: 'journey/metrics',
517
+ type: 'step/metrics',
522
518
  journey,
519
+ step,
523
520
  root_fields: {
524
521
  browser: {
525
522
  [type]: event,
@@ -529,7 +526,7 @@ export default class JSONReporter extends BaseReporter {
529
526
  });
530
527
  }
531
528
 
532
- // Writes a structered synthetics event
529
+ // Writes a structured synthetics event
533
530
  // Note that blob is ultimately stored in ES as a base64 encoded string. You must base 64 encode
534
531
  // it before passing it into this function!
535
532
  // The payload field is an un-indexed field with no ES mapping, so users can put arbitary structured