Skip to content

Commit 1250c04

Browse files
feat: add transaction and span
1 parent 874246a commit 1250c04

File tree

8 files changed

+995
-31
lines changed

8 files changed

+995
-31
lines changed

examples/todos/basic.journey.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,21 @@ journey('check if input placeholder is correct', ({ page, params }) => {
2323
);
2424
});
2525
});
26+
27+
journey('Synthetics + APM', ({ page }) => {
28+
step('go to index page', async () => {
29+
await page.goto('http://localhost:8080/index');
30+
// make sure RUM request has been successfully sent to APM server
31+
await page.waitForResponse(response =>
32+
response.url().includes('/rum/events')
33+
);
34+
});
35+
36+
step('go to unknown page', async () => {
37+
await page.goto('http://localhost:8080/unknown');
38+
// make sure RUM request has been successfully sent to APM server
39+
await page.waitForResponse(response =>
40+
response.url().includes('/rum/events')
41+
);
42+
});
43+
});

package-lock.json

Lines changed: 906 additions & 31 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
"commander": "^7.0.0",
4242
"deepmerge": "^4.2.2",
4343
"expect": "^27.0.2",
44+
"elastic-apm-node": "^3.29.0",
4445
"http-proxy": "^1.18.1",
4546
"kleur": "^4.1.3",
4647
"micromatch": "^4.0.4",

src/apm.ts

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
/**
2+
* MIT License
3+
*
4+
* Copyright (c) 2020-present, Elastic NV
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22+
* THE SOFTWARE.
23+
*
24+
*/
25+
26+
import agent from 'elastic-apm-node';
27+
28+
agent.start({
29+
serviceName: 'synthetics',
30+
instrument: false,
31+
metricsInterval: '0',
32+
centralConfig: false,
33+
captureSpanStackTraces: false,
34+
serverUrl: '',
35+
secretToken: '',
36+
});
37+
38+
agent.addFilter(payload => {
39+
console.log('Payload', payload);
40+
});
41+
42+
process.on('exit', () => {
43+
agent.flush(() => {
44+
console.log('flushed');
45+
});
46+
});

src/core/runner.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -152,6 +152,7 @@ export default class Runner extends EventEmitter {
152152
hooks: SuiteHooks = { beforeAll: [], afterAll: [] };
153153
hookError: Error | undefined;
154154
static screenshotPath = join(CACHE_PATH, 'screenshots');
155+
traceparent: string;
155156

156157
static async createContext(options: RunOptions): Promise<JourneyContext> {
157158
const driver = await Gatherer.setupDriver(options);
@@ -260,6 +261,18 @@ export default class Runner extends EventEmitter {
260261
* step level plugins
261262
*/
262263
const traceEnabled = trace || filmstrips;
264+
this.traceparent = step.span.traceparent;
265+
const handler = (route, request) => {
266+
console.log('traceparent', this.traceparent);
267+
const headers = {
268+
traceparent: this.traceparent,
269+
...request.headers(),
270+
};
271+
route.continue({
272+
headers,
273+
});
274+
};
275+
context.driver.page.route(/index|unknown/, handler);
263276
pluginManager.onStep(step);
264277
traceEnabled && (await pluginManager.start('trace'));
265278
// call the step definition
@@ -276,6 +289,7 @@ export default class Runner extends EventEmitter {
276289
const traceOutput = await pluginManager.stop('trace');
277290
Object.assign(data, traceOutput);
278291
}
292+
context.driver.page.unroute(/index|unknown/, handler);
279293
} catch (error) {
280294
data.status = 'failed';
281295
data.error = error;
@@ -329,6 +343,7 @@ export default class Runner extends EventEmitter {
329343
if (options.pauseOnError && data.error) {
330344
await new Promise(r => process.stdin.on('data', r));
331345
}
346+
step.span.end();
332347
results.push(data);
333348
}
334349
return results;
@@ -373,6 +388,7 @@ export default class Runner extends EventEmitter {
373388
}
374389
// clear screenshots cache after each journey
375390
await rm(Runner.screenshotPath, { recursive: true, force: true });
391+
journey.transaction.end();
376392
}
377393

378394
/**
@@ -400,6 +416,7 @@ export default class Runner extends EventEmitter {
400416
if (options.reporter === 'json') {
401417
await once(this, 'journey:end:reported');
402418
}
419+
journey.transaction.end();
403420
return result;
404421
}
405422

src/dsl/journey.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { Browser, Page, BrowserContext, CDPSession } from 'playwright-chromium';
2727
import micromatch, { isMatch } from 'micromatch';
2828
import { Step } from './step';
2929
import { VoidCallback, HooksCallback, Params } from '../common_types';
30+
import { startTransaction, Transaction } from 'elastic-apm-node';
3031

3132
export type JourneyOptions = {
3233
name: string;
@@ -48,6 +49,7 @@ export class Journey {
4849
name: string;
4950
id?: string;
5051
tags?: string[];
52+
transaction: Transaction;
5153
callback: JourneyCallback;
5254
steps: Step[] = [];
5355
hooks: Hooks = { before: [], after: [] };
@@ -57,6 +59,7 @@ export class Journey {
5759
this.id = options.id || options.name;
5860
this.tags = options.tags;
5961
this.callback = callback;
62+
this.transaction = startTransaction(`Journey: ${this.name}`);
6063
}
6164

6265
addStep(name: string, callback: VoidCallback) {

src/dsl/step.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,16 +23,19 @@
2323
*
2424
*/
2525

26+
import { startSpan, Span } from 'elastic-apm-node';
2627
import { VoidCallback } from '../common_types';
2728

2829
export class Step {
2930
name: string;
3031
index: number;
3132
callback: VoidCallback;
33+
span: Span;
3234

3335
constructor(name: string, index: number, callback: VoidCallback) {
3436
this.name = name;
3537
this.index = index;
3638
this.callback = callback;
39+
this.span = startSpan(`Step: ${this.name}`);
3740
}
3841
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import { runner } from './core';
2727
import { RunOptions } from './core/runner';
2828
import sourceMapSupport from 'source-map-support';
29+
import './apm';
2930

3031
export async function run(options: RunOptions) {
3132
/**

0 commit comments

Comments
 (0)