Skip to content

Commit

Permalink
feat: add traceparent header to all requests (#955)
Browse files Browse the repository at this point in the history
* feat: add traceparent header to all requests

* feat: update docs for traceparent
  • Loading branch information
Kabir-Ivan committed Jun 28, 2024
1 parent e96958d commit ef5a64e
Show file tree
Hide file tree
Showing 6 changed files with 62 additions and 6 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ The documentation is divided into several sections:
- [Testplane Events](docs/events.md)
- [Testplane Programmatic API](docs/programmatic-api.md)
- [Testplane Component Testing (experimental)](docs/component-testing.md)
- [Testplane Debugging](docs/debugging.md)

## Rename from "Hermione"

Expand Down
9 changes: 9 additions & 0 deletions docs/debugging.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<!-- DOCTOC SKIP -->
## Debugging

### Tracing

Testpalne supports [OpenTelemetry](https://opentelemetry.io) standard for tracing. A randomly generated `traceparent` header is added to all requests. It is generated according to [w3c](https://www.w3.org/TR/trace-context/#traceparent-header) specification.

You can use `traceparent` to trace the execution of individual tests.

3 changes: 3 additions & 0 deletions src/browser/browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ module.exports = class Browser {
this.state.testXReqId
}${X_REQUEST_ID_DELIMITER}${crypto.randomUUID()}`;
}
if (!req.headers["traceparent"] && this.state.traceparent) {
req.headers["traceparent"] = this.state.traceparent;
}

return req;
};
Expand Down
1 change: 1 addition & 0 deletions src/browser/existing-browser.js
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ module.exports = class ExistingBrowser extends Browser {
pid: process.pid,
browserVersion: this.version,
testXReqId: this.state.testXReqId,
traceparent: this.state.traceparent,
...this._config.meta,
};
}
Expand Down
19 changes: 17 additions & 2 deletions src/runner/test-runner/regular-test-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,14 +81,29 @@ module.exports = class RegularTestRunner extends Runner {
this._test.duration = Date.now() - this._test.startTime;
}

_getTraceparent() {
const version = "00";
const traceId = crypto.randomBytes(16).toString("hex");
const parentId = "00" + crypto.randomBytes(7).toString("hex");
const traceFlag = "01";

return `${version}-${traceId}-${parentId}-${traceFlag}`;
}

async _getBrowser() {
try {
const state = { testXReqId: crypto.randomUUID() };
const state = {
testXReqId: crypto.randomUUID(),
traceparent: this._getTraceparent(),
};

this._browser = await this._browserAgent.getBrowser({ state });

// TODO: move logic to caching pool (in order to use correct state for cached browsers)
if (this._browser.state.testXReqId !== state.testXReqId) {
if (
this._browser.state.testXReqId !== state.testXReqId ||
this._browser.state.traceparent !== state.traceparent
) {
this._browser.applyState(state);
}

Expand Down
35 changes: 31 additions & 4 deletions test/src/runner/test-runner/regular-test-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ describe("runner/test-runner/regular-test-runner", () => {
return runner.run(workers);
};

const applyStateSpy = sandbox.spy();

const stubBrowser_ = (opts = {}) => {
return _.defaults(opts, {
id: "default-id",
Expand All @@ -53,6 +55,7 @@ describe("runner/test-runner/regular-test-runner", () => {
state: { isBroken: false },
sessionId: "default-session-id",
applyState: sinon.stub().callsFake(function (state) {
applyStateSpy(state);
this.state = state;
}),
publicAPI: {
Expand All @@ -72,6 +75,9 @@ describe("runner/test-runner/regular-test-runner", () => {

sandbox.stub(logger, "warn");
sandbox.stub(crypto, "randomUUID").returns("");
sandbox.stub(crypto, "randomBytes").callsFake(size => {
return Buffer.from("11".repeat(size), "hex");
});
});

afterEach(() => sandbox.restore());
Expand All @@ -89,7 +95,10 @@ describe("runner/test-runner/regular-test-runner", () => {

describe("run", () => {
it("should get browser before running test", async () => {
const state = { testXReqId: "12345" };
const state = {
testXReqId: "12345",
traceparent: "00-11111111111111111111111111111111-0011111111111111-01",
};
crypto.randomUUID.returns(state.testXReqId);
BrowserAgent.prototype.getBrowser.withArgs({ state }).resolves(
stubBrowser_({
Expand Down Expand Up @@ -122,17 +131,35 @@ describe("runner/test-runner/regular-test-runner", () => {
});

it("should modify state if 'testXReqId' is not actual", async () => {
const state = { testXReqId: "12345" };
const state = {
testXReqId: "12345",
};
crypto.randomUUID.returns(state.testXReqId);
const browser = stubBrowser_({
state: { testXReqId: "67890", traceparent: "00-11111111111111111111111111111111-0011111111111111-01" },
});
BrowserAgent.prototype.getBrowser.withArgs({ state }).resolves(browser);
const workers = mkWorkers_();

await run_({ workers });

assert.calledWith(applyStateSpy, sinon.match(state));
});

it("should modify state if 'traceparent' is not actual", async () => {
const state = {
traceparent: "00-11111111111111111111111111111111-0011111111111111-01",
};
crypto.randomUUID.returns(state.testXReqId);
const browser = stubBrowser_({
state: { testXReqId: "67890" },
state: { traceparent: "00-22222222222222222222222222222222-0022222222222222-01" },
});
BrowserAgent.prototype.getBrowser.withArgs({ state }).resolves(browser);
const workers = mkWorkers_();

await run_({ workers });

assert.calledWith(browser.applyState.firstCall, state);
assert.calledWith(applyStateSpy, sinon.match(state));
});

it("should run test in workers", async () => {
Expand Down

0 comments on commit ef5a64e

Please sign in to comment.