-
Notifications
You must be signed in to change notification settings - Fork 29.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
lib: add tracing channel to diagnostics_channel
PR-URL: #44943 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]> Reviewed-By: Chengzhong Wu <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Gerhard Stöbich <[email protected]> Reviewed-By: Rafael Gonzaga <[email protected]> Reviewed-By: Bryan English <[email protected]>
- Loading branch information
Showing
13 changed files
with
1,309 additions
and
35 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const assert = require('assert'); | ||
const dc = require('diagnostics_channel'); | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
|
||
let n = 0; | ||
const thisArg = new Date(); | ||
const inputs = [ | ||
{ foo: 'bar' }, | ||
{ baz: 'buz' }, | ||
]; | ||
|
||
const channel = dc.channel('test'); | ||
|
||
// Bind a storage directly to published data | ||
const store1 = new AsyncLocalStorage(); | ||
channel.bindStore(store1); | ||
let store1bound = true; | ||
|
||
// Bind a store with transformation of published data | ||
const store2 = new AsyncLocalStorage(); | ||
channel.bindStore(store2, common.mustCall((data) => { | ||
assert.strictEqual(data, inputs[n]); | ||
return { data }; | ||
}, 4)); | ||
|
||
// Regular subscribers should see publishes from runStores calls | ||
channel.subscribe(common.mustCall((data) => { | ||
if (store1bound) { | ||
assert.deepStrictEqual(data, store1.getStore()); | ||
} | ||
assert.deepStrictEqual({ data }, store2.getStore()); | ||
assert.strictEqual(data, inputs[n]); | ||
}, 4)); | ||
|
||
// Verify stores are empty before run | ||
assert.strictEqual(store1.getStore(), undefined); | ||
assert.strictEqual(store2.getStore(), undefined); | ||
|
||
channel.runStores(inputs[n], common.mustCall(function(a, b) { | ||
// Verify this and argument forwarding | ||
assert.strictEqual(this, thisArg); | ||
assert.strictEqual(a, 1); | ||
assert.strictEqual(b, 2); | ||
|
||
// Verify store 1 state matches input | ||
assert.strictEqual(store1.getStore(), inputs[n]); | ||
|
||
// Verify store 2 state has expected transformation | ||
assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | ||
|
||
// Should support nested contexts | ||
n++; | ||
channel.runStores(inputs[n], common.mustCall(function() { | ||
// Verify this and argument forwarding | ||
assert.strictEqual(this, undefined); | ||
|
||
// Verify store 1 state matches input | ||
assert.strictEqual(store1.getStore(), inputs[n]); | ||
|
||
// Verify store 2 state has expected transformation | ||
assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | ||
})); | ||
n--; | ||
|
||
// Verify store 1 state matches input | ||
assert.strictEqual(store1.getStore(), inputs[n]); | ||
|
||
// Verify store 2 state has expected transformation | ||
assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | ||
}), thisArg, 1, 2); | ||
|
||
// Verify stores are empty after run | ||
assert.strictEqual(store1.getStore(), undefined); | ||
assert.strictEqual(store2.getStore(), undefined); | ||
|
||
// Verify unbinding works | ||
assert.ok(channel.unbindStore(store1)); | ||
store1bound = false; | ||
|
||
// Verify unbinding a store that is not bound returns false | ||
assert.ok(!channel.unbindStore(store1)); | ||
|
||
n++; | ||
channel.runStores(inputs[n], common.mustCall(() => { | ||
// Verify after unbinding store 1 will remain undefined | ||
assert.strictEqual(store1.getStore(), undefined); | ||
|
||
// Verify still bound store 2 receives expected data | ||
assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | ||
})); | ||
|
||
// Contain transformer errors and emit on next tick | ||
const fail = new Error('fail'); | ||
channel.bindStore(store1, () => { | ||
throw fail; | ||
}); | ||
|
||
let calledRunStores = false; | ||
process.once('uncaughtException', common.mustCall((err) => { | ||
assert.strictEqual(calledRunStores, true); | ||
assert.strictEqual(err, fail); | ||
})); | ||
|
||
channel.runStores(inputs[n], common.mustCall()); | ||
calledRunStores = true; |
46 changes: 46 additions & 0 deletions
46
test/parallel/test-diagnostics-channel-tracing-channel-async-error.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const dc = require('diagnostics_channel'); | ||
const assert = require('assert'); | ||
|
||
const channel = dc.tracingChannel('test'); | ||
|
||
const expectedError = new Error('test'); | ||
const input = { foo: 'bar' }; | ||
const thisArg = { baz: 'buz' }; | ||
|
||
function check(found) { | ||
assert.deepStrictEqual(found, input); | ||
} | ||
|
||
const handlers = { | ||
start: common.mustCall(check, 2), | ||
end: common.mustCall(check, 2), | ||
asyncStart: common.mustCall(check, 2), | ||
asyncEnd: common.mustCall(check, 2), | ||
error: common.mustCall((found) => { | ||
check(found); | ||
assert.deepStrictEqual(found.error, expectedError); | ||
}, 2) | ||
}; | ||
|
||
channel.subscribe(handlers); | ||
|
||
channel.traceCallback(function(cb, err) { | ||
assert.deepStrictEqual(this, thisArg); | ||
setImmediate(cb, err); | ||
}, 0, input, thisArg, common.mustCall((err, res) => { | ||
assert.strictEqual(err, expectedError); | ||
assert.strictEqual(res, undefined); | ||
}), expectedError); | ||
|
||
channel.tracePromise(function(value) { | ||
assert.deepStrictEqual(this, thisArg); | ||
return Promise.reject(value); | ||
}, input, thisArg, expectedError).then( | ||
common.mustNotCall(), | ||
common.mustCall((value) => { | ||
assert.deepStrictEqual(value, expectedError); | ||
}) | ||
); |
60 changes: 60 additions & 0 deletions
60
test/parallel/test-diagnostics-channel-tracing-channel-async.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const dc = require('diagnostics_channel'); | ||
const assert = require('assert'); | ||
|
||
const channel = dc.tracingChannel('test'); | ||
|
||
const expectedResult = { foo: 'bar' }; | ||
const input = { foo: 'bar' }; | ||
const thisArg = { baz: 'buz' }; | ||
|
||
function check(found) { | ||
assert.deepStrictEqual(found, input); | ||
} | ||
|
||
const handlers = { | ||
start: common.mustCall(check, 2), | ||
end: common.mustCall(check, 2), | ||
asyncStart: common.mustCall((found) => { | ||
check(found); | ||
assert.strictEqual(found.error, undefined); | ||
assert.deepStrictEqual(found.result, expectedResult); | ||
}, 2), | ||
asyncEnd: common.mustCall((found) => { | ||
check(found); | ||
assert.strictEqual(found.error, undefined); | ||
assert.deepStrictEqual(found.result, expectedResult); | ||
}, 2), | ||
error: common.mustNotCall() | ||
}; | ||
|
||
channel.subscribe(handlers); | ||
|
||
channel.traceCallback(function(cb, err, res) { | ||
assert.deepStrictEqual(this, thisArg); | ||
setImmediate(cb, err, res); | ||
}, 0, input, thisArg, common.mustCall((err, res) => { | ||
assert.strictEqual(err, null); | ||
assert.deepStrictEqual(res, expectedResult); | ||
}), null, expectedResult); | ||
|
||
channel.tracePromise(function(value) { | ||
assert.deepStrictEqual(this, thisArg); | ||
return Promise.resolve(value); | ||
}, input, thisArg, expectedResult).then( | ||
common.mustCall((value) => { | ||
assert.deepStrictEqual(value, expectedResult); | ||
}), | ||
common.mustNotCall() | ||
); | ||
|
||
let failed = false; | ||
try { | ||
channel.traceCallback(common.mustNotCall(), 0, input, thisArg, 1, 2, 3); | ||
} catch (err) { | ||
assert.ok(/"callback" argument must be of type function/.test(err.message)); | ||
failed = true; | ||
} | ||
assert.strictEqual(failed, true); |
29 changes: 29 additions & 0 deletions
29
test/parallel/test-diagnostics-channel-tracing-channel-callback-run-stores.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
const dc = require('diagnostics_channel'); | ||
const assert = require('assert'); | ||
|
||
const channel = dc.tracingChannel('test'); | ||
const store = new AsyncLocalStorage(); | ||
|
||
const firstContext = { foo: 'bar' }; | ||
const secondContext = { baz: 'buz' }; | ||
|
||
channel.start.bindStore(store, common.mustCall(() => { | ||
return firstContext; | ||
})); | ||
|
||
channel.asyncStart.bindStore(store, common.mustCall(() => { | ||
return secondContext; | ||
})); | ||
|
||
assert.strictEqual(store.getStore(), undefined); | ||
channel.traceCallback(common.mustCall((cb) => { | ||
assert.deepStrictEqual(store.getStore(), firstContext); | ||
setImmediate(cb); | ||
}), 0, {}, null, common.mustCall(() => { | ||
assert.deepStrictEqual(store.getStore(), secondContext); | ||
})); | ||
assert.strictEqual(store.getStore(), undefined); |
24 changes: 24 additions & 0 deletions
24
test/parallel/test-diagnostics-channel-tracing-channel-promise-run-stores.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const { setTimeout } = require('node:timers/promises'); | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
const dc = require('diagnostics_channel'); | ||
const assert = require('assert'); | ||
|
||
const channel = dc.tracingChannel('test'); | ||
const store = new AsyncLocalStorage(); | ||
|
||
const context = { foo: 'bar' }; | ||
|
||
channel.start.bindStore(store, common.mustCall(() => { | ||
return context; | ||
})); | ||
|
||
assert.strictEqual(store.getStore(), undefined); | ||
channel.tracePromise(common.mustCall(async () => { | ||
assert.deepStrictEqual(store.getStore(), context); | ||
await setTimeout(1); | ||
assert.deepStrictEqual(store.getStore(), context); | ||
})); | ||
assert.strictEqual(store.getStore(), undefined); |
21 changes: 21 additions & 0 deletions
21
test/parallel/test-diagnostics-channel-tracing-channel-run-stores.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const { AsyncLocalStorage } = require('async_hooks'); | ||
const dc = require('diagnostics_channel'); | ||
const assert = require('assert'); | ||
|
||
const channel = dc.tracingChannel('test'); | ||
const store = new AsyncLocalStorage(); | ||
|
||
const context = { foo: 'bar' }; | ||
|
||
channel.start.bindStore(store, common.mustCall(() => { | ||
return context; | ||
})); | ||
|
||
assert.strictEqual(store.getStore(), undefined); | ||
channel.traceSync(common.mustCall(() => { | ||
assert.deepStrictEqual(store.getStore(), context); | ||
})); | ||
assert.strictEqual(store.getStore(), undefined); |
39 changes: 39 additions & 0 deletions
39
test/parallel/test-diagnostics-channel-tracing-channel-sync-error.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
'use strict'; | ||
|
||
const common = require('../common'); | ||
const dc = require('diagnostics_channel'); | ||
const assert = require('assert'); | ||
|
||
const channel = dc.tracingChannel('test'); | ||
|
||
const expectedError = new Error('test'); | ||
const input = { foo: 'bar' }; | ||
const thisArg = { baz: 'buz' }; | ||
|
||
function check(found) { | ||
assert.deepStrictEqual(found, input); | ||
} | ||
|
||
const handlers = { | ||
start: common.mustCall(check), | ||
end: common.mustCall(check), | ||
asyncStart: common.mustNotCall(), | ||
asyncEnd: common.mustNotCall(), | ||
error: common.mustCall((found) => { | ||
check(found); | ||
assert.deepStrictEqual(found.error, expectedError); | ||
}) | ||
}; | ||
|
||
channel.subscribe(handlers); | ||
try { | ||
channel.traceSync(function(err) { | ||
assert.deepStrictEqual(this, thisArg); | ||
assert.strictEqual(err, expectedError); | ||
throw err; | ||
}, input, thisArg, expectedError); | ||
|
||
throw new Error('It should not reach this error'); | ||
} catch (error) { | ||
assert.deepStrictEqual(error, expectedError); | ||
} |
Oops, something went wrong.