Skip to content

Commit cc81cd8

Browse files
feat: add transaction and span
1 parent b2c6c76 commit cc81cd8

File tree

8 files changed

+1040
-31
lines changed

8 files changed

+1040
-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: 951 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
@@ -42,6 +42,7 @@
4242
"commander": "^9.0.0",
4343
"deepmerge": "^4.2.2",
4444
"expect": "^27.0.2",
45+
"elastic-apm-node": "^3.31.0",
4546
"http-proxy": "^1.18.1",
4647
"kleur": "^4.1.4",
4748
"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
@@ -132,6 +132,7 @@ export default class Runner extends EventEmitter {
132132
hooks: SuiteHooks = { beforeAll: [], afterAll: [] };
133133
hookError: Error | undefined;
134134
static screenshotPath = join(CACHE_PATH, 'screenshots');
135+
traceparent: string;
135136

136137
static async createContext(options: RunOptions): Promise<JourneyContext> {
137138
const driver = await Gatherer.setupDriver(options);
@@ -240,6 +241,18 @@ export default class Runner extends EventEmitter {
240241
* step level plugins
241242
*/
242243
const traceEnabled = trace || filmstrips;
244+
this.traceparent = step.span.traceparent;
245+
const handler = (route, request) => {
246+
console.log('traceparent', this.traceparent);
247+
const headers = {
248+
traceparent: this.traceparent,
249+
...request.headers(),
250+
};
251+
route.continue({
252+
headers,
253+
});
254+
};
255+
context.driver.page.route(/index|unknown/, handler);
243256
pluginManager.onStep(step);
244257
traceEnabled && (await pluginManager.start('trace'));
245258
// call the step definition
@@ -256,6 +269,7 @@ export default class Runner extends EventEmitter {
256269
const traceOutput = await pluginManager.stop('trace');
257270
Object.assign(data, traceOutput);
258271
}
272+
context.driver.page.unroute(/index|unknown/, handler);
259273
} catch (error) {
260274
data.status = 'failed';
261275
data.error = error;
@@ -309,6 +323,7 @@ export default class Runner extends EventEmitter {
309323
if (options.pauseOnError && data.error) {
310324
await new Promise(r => process.stdin.on('data', r));
311325
}
326+
step.span.end();
312327
results.push(data);
313328
}
314329
return results;
@@ -353,6 +368,7 @@ export default class Runner extends EventEmitter {
353368
}
354369
// clear screenshots cache after each journey
355370
await rm(Runner.screenshotPath, { recursive: true, force: true });
371+
journey.transaction.end();
356372
}
357373

358374
/**
@@ -380,6 +396,7 @@ export default class Runner extends EventEmitter {
380396
if (options.reporter === 'json') {
381397
await once(this, 'journey:end:reported');
382398
}
399+
journey.transaction.end();
383400
return result;
384401
}
385402

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, Location } 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
location?: Location;
5355
steps: Step[] = [];
@@ -63,6 +65,7 @@ export class Journey {
6365
this.tags = options.tags;
6466
this.callback = callback;
6567
this.location = location;
68+
this.transaction = startTransaction(`Journey: ${this.name}`);
6669
}
6770

6871
addStep(name: string, callback: VoidCallback, location?: Location) {

src/dsl/step.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
*/
2525

2626
import { Location, VoidCallback } from '../common_types';
27+
import { startSpan, Span } from 'elastic-apm-node';
2728

2829
export class Step {
2930
name: string;
3031
index: number;
3132
callback: VoidCallback;
3233
location?: Location;
34+
span: Span;
3335

3436
constructor(
3537
name: string,
@@ -41,5 +43,6 @@ export class Step {
4143
this.index = index;
4244
this.callback = callback;
4345
this.location = location;
46+
this.span = startSpan(`Step: ${this.name}`);
4447
}
4548
}

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
import { runner } from './core';
2727
import { RunOptions } from './common_types';
28+
import './apm';
2829

2930
export async function run(options: RunOptions) {
3031
return runner.run(options);

0 commit comments

Comments
 (0)