@elastic/synthetics 1.0.0-beta.8 → 1.0.0

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