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