GeezerVison is showing github.com — lib: add tracing channel to diagnostics_channel · nodejs/node@7d37dcd
File treeExpand file treeCollapse file tree Open diff view settings Expand file treeCollapse file tree Open diff view settings Collapse file Copy file name to clipboardExpand all lines: doc/api/diagnostics_channel.md +647Lines changed: 647 additions & 0 deletions - Display the source diff
- Display the rich diff
Large diffs are not rendered by default. Collapse file Copy file name to clipboardExpand all lines: lib/diagnostics_channel.js +282-25Lines changed: 282 additions & 25 deletions Large diffs are not rendered by default. Collapse file Copy file name to clipboardExpand all lines: src/node_util.cc +4-9Lines changed: 4 additions & 9 deletions | Original file line number | Diff line number | Diff line change |
|---|
@@ -262,18 +262,13 @@ void WeakReference::Get(const FunctionCallbackInfo<Value>& args) { | 262 | 262 | args.GetReturnValue().Set(weak_ref->target_.Get(isolate)); | 263 | 263 | } | 264 | 264 |
| 265 | | -void WeakReference::GetRef(const FunctionCallbackInfo<Value>& args) { | 266 | | - WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder()); | 267 | | - Isolate* isolate = args.GetIsolate(); | 268 | | - args.GetReturnValue().Set( | 269 | | - v8::Number::New(isolate, weak_ref->reference_count_)); | 270 | | -} | 271 | | - | 272 | 265 | void WeakReference::IncRef(const FunctionCallbackInfo<Value>& args) { | 273 | 266 | WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder()); | 274 | 267 | weak_ref->reference_count_++; | 275 | 268 | if (weak_ref->target_.IsEmpty()) return; | 276 | 269 | if (weak_ref->reference_count_ == 1) weak_ref->target_.ClearWeak(); | | 270 | + args.GetReturnValue().Set( | | 271 | + v8::Number::New(args.GetIsolate(), weak_ref->reference_count_)); | 277 | 272 | } | 278 | 273 |
| 279 | 274 | void WeakReference::DecRef(const FunctionCallbackInfo<Value>& args) { | @@ -282,6 +277,8 @@ void WeakReference::DecRef(const FunctionCallbackInfo<Value>& args) { | 282 | 277 | weak_ref->reference_count_--; | 283 | 278 | if (weak_ref->target_.IsEmpty()) return; | 284 | 279 | if (weak_ref->reference_count_ == 0) weak_ref->target_.SetWeak(); | | 280 | + args.GetReturnValue().Set( | | 281 | + v8::Number::New(args.GetIsolate(), weak_ref->reference_count_)); | 285 | 282 | } | 286 | 283 |
| 287 | 284 | static void GuessHandleType(const FunctionCallbackInfo<Value>& args) { | @@ -365,7 +362,6 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) { | 365 | 362 | registry->Register(ArrayBufferViewHasBuffer); | 366 | 363 | registry->Register(WeakReference::New); | 367 | 364 | registry->Register(WeakReference::Get); | 368 | | - registry->Register(WeakReference::GetRef); | 369 | 365 | registry->Register(WeakReference::IncRef); | 370 | 366 | registry->Register(WeakReference::DecRef); | 371 | 367 | registry->Register(GuessHandleType); | @@ -457,7 +453,6 @@ void Initialize(Local<Object> target, | 457 | 453 | WeakReference::kInternalFieldCount); | 458 | 454 | weak_ref->Inherit(BaseObject::GetConstructorTemplate(env)); | 459 | 455 | SetProtoMethod(isolate, weak_ref, "get", WeakReference::Get); | 460 | | - SetProtoMethod(isolate, weak_ref, "getRef", WeakReference::GetRef); | 461 | 456 | SetProtoMethod(isolate, weak_ref, "incRef", WeakReference::IncRef); | 462 | 457 | SetProtoMethod(isolate, weak_ref, "decRef", WeakReference::DecRef); | 463 | 458 | SetConstructorFunction(context, target, "WeakReference", weak_ref); | |
Collapse file Copy file name to clipboardExpand all lines: src/node_util.h -1Lines changed: 0 additions & 1 deletion | Original file line number | Diff line number | Diff line change |
|---|
@@ -21,7 +21,6 @@ class WeakReference : public SnapshotableObject { | 21 | 21 | v8::Local<v8::Object> target); | 22 | 22 | static void New(const v8::FunctionCallbackInfo<v8::Value>& args); | 23 | 23 | static void Get(const v8::FunctionCallbackInfo<v8::Value>& args); | 24 | | - static void GetRef(const v8::FunctionCallbackInfo<v8::Value>& args); | 25 | 24 | static void IncRef(const v8::FunctionCallbackInfo<v8::Value>& args); | 26 | 25 | static void DecRef(const v8::FunctionCallbackInfo<v8::Value>& args); | 27 | 26 |
| |
Collapse file Copy file name to clipboard +108Lines changed: 108 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const assert = require('assert'); | | 5 | +const dc = require('diagnostics_channel'); | | 6 | +const { AsyncLocalStorage } = require('async_hooks'); | | 7 | + | | 8 | +let n = 0; | | 9 | +const thisArg = new Date(); | | 10 | +const inputs = [ | | 11 | + { foo: 'bar' }, | | 12 | + { baz: 'buz' }, | | 13 | +]; | | 14 | + | | 15 | +const channel = dc.channel('test'); | | 16 | + | | 17 | +// Bind a storage directly to published data | | 18 | +const store1 = new AsyncLocalStorage(); | | 19 | +channel.bindStore(store1); | | 20 | +let store1bound = true; | | 21 | + | | 22 | +// Bind a store with transformation of published data | | 23 | +const store2 = new AsyncLocalStorage(); | | 24 | +channel.bindStore(store2, common.mustCall((data) => { | | 25 | + assert.strictEqual(data, inputs[n]); | | 26 | + return { data }; | | 27 | +}, 4)); | | 28 | + | | 29 | +// Regular subscribers should see publishes from runStores calls | | 30 | +channel.subscribe(common.mustCall((data) => { | | 31 | + if (store1bound) { | | 32 | + assert.deepStrictEqual(data, store1.getStore()); | | 33 | + } | | 34 | + assert.deepStrictEqual({ data }, store2.getStore()); | | 35 | + assert.strictEqual(data, inputs[n]); | | 36 | +}, 4)); | | 37 | + | | 38 | +// Verify stores are empty before run | | 39 | +assert.strictEqual(store1.getStore(), undefined); | | 40 | +assert.strictEqual(store2.getStore(), undefined); | | 41 | + | | 42 | +channel.runStores(inputs[n], common.mustCall(function(a, b) { | | 43 | + // Verify this and argument forwarding | | 44 | + assert.strictEqual(this, thisArg); | | 45 | + assert.strictEqual(a, 1); | | 46 | + assert.strictEqual(b, 2); | | 47 | + | | 48 | + // Verify store 1 state matches input | | 49 | + assert.strictEqual(store1.getStore(), inputs[n]); | | 50 | + | | 51 | + // Verify store 2 state has expected transformation | | 52 | + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | | 53 | + | | 54 | + // Should support nested contexts | | 55 | + n++; | | 56 | + channel.runStores(inputs[n], common.mustCall(function() { | | 57 | + // Verify this and argument forwarding | | 58 | + assert.strictEqual(this, undefined); | | 59 | + | | 60 | + // Verify store 1 state matches input | | 61 | + assert.strictEqual(store1.getStore(), inputs[n]); | | 62 | + | | 63 | + // Verify store 2 state has expected transformation | | 64 | + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | | 65 | + })); | | 66 | + n--; | | 67 | + | | 68 | + // Verify store 1 state matches input | | 69 | + assert.strictEqual(store1.getStore(), inputs[n]); | | 70 | + | | 71 | + // Verify store 2 state has expected transformation | | 72 | + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | | 73 | +}), thisArg, 1, 2); | | 74 | + | | 75 | +// Verify stores are empty after run | | 76 | +assert.strictEqual(store1.getStore(), undefined); | | 77 | +assert.strictEqual(store2.getStore(), undefined); | | 78 | + | | 79 | +// Verify unbinding works | | 80 | +assert.ok(channel.unbindStore(store1)); | | 81 | +store1bound = false; | | 82 | + | | 83 | +// Verify unbinding a store that is not bound returns false | | 84 | +assert.ok(!channel.unbindStore(store1)); | | 85 | + | | 86 | +n++; | | 87 | +channel.runStores(inputs[n], common.mustCall(() => { | | 88 | + // Verify after unbinding store 1 will remain undefined | | 89 | + assert.strictEqual(store1.getStore(), undefined); | | 90 | + | | 91 | + // Verify still bound store 2 receives expected data | | 92 | + assert.deepStrictEqual(store2.getStore(), { data: inputs[n] }); | | 93 | +})); | | 94 | + | | 95 | +// Contain transformer errors and emit on next tick | | 96 | +const fail = new Error('fail'); | | 97 | +channel.bindStore(store1, () => { | | 98 | + throw fail; | | 99 | +}); | | 100 | + | | 101 | +let calledRunStores = false; | | 102 | +process.once('uncaughtException', common.mustCall((err) => { | | 103 | + assert.strictEqual(calledRunStores, true); | | 104 | + assert.strictEqual(err, fail); | | 105 | +})); | | 106 | + | | 107 | +channel.runStores(inputs[n], common.mustCall()); | | 108 | +calledRunStores = true; |
Collapse file Copy file name to clipboard +46Lines changed: 46 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const dc = require('diagnostics_channel'); | | 5 | +const assert = require('assert'); | | 6 | + | | 7 | +const channel = dc.tracingChannel('test'); | | 8 | + | | 9 | +const expectedError = new Error('test'); | | 10 | +const input = { foo: 'bar' }; | | 11 | +const thisArg = { baz: 'buz' }; | | 12 | + | | 13 | +function check(found) { | | 14 | + assert.deepStrictEqual(found, input); | | 15 | +} | | 16 | + | | 17 | +const handlers = { | | 18 | + start: common.mustCall(check, 2), | | 19 | + end: common.mustCall(check, 2), | | 20 | + asyncStart: common.mustCall(check, 2), | | 21 | + asyncEnd: common.mustCall(check, 2), | | 22 | + error: common.mustCall((found) => { | | 23 | + check(found); | | 24 | + assert.deepStrictEqual(found.error, expectedError); | | 25 | + }, 2) | | 26 | +}; | | 27 | + | | 28 | +channel.subscribe(handlers); | | 29 | + | | 30 | +channel.traceCallback(function(cb, err) { | | 31 | + assert.deepStrictEqual(this, thisArg); | | 32 | + setImmediate(cb, err); | | 33 | +}, 0, input, thisArg, common.mustCall((err, res) => { | | 34 | + assert.strictEqual(err, expectedError); | | 35 | + assert.strictEqual(res, undefined); | | 36 | +}), expectedError); | | 37 | + | | 38 | +channel.tracePromise(function(value) { | | 39 | + assert.deepStrictEqual(this, thisArg); | | 40 | + return Promise.reject(value); | | 41 | +}, input, thisArg, expectedError).then( | | 42 | + common.mustNotCall(), | | 43 | + common.mustCall((value) => { | | 44 | + assert.deepStrictEqual(value, expectedError); | | 45 | + }) | | 46 | +); |
Collapse file Copy file name to clipboard +60Lines changed: 60 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const dc = require('diagnostics_channel'); | | 5 | +const assert = require('assert'); | | 6 | + | | 7 | +const channel = dc.tracingChannel('test'); | | 8 | + | | 9 | +const expectedResult = { foo: 'bar' }; | | 10 | +const input = { foo: 'bar' }; | | 11 | +const thisArg = { baz: 'buz' }; | | 12 | + | | 13 | +function check(found) { | | 14 | + assert.deepStrictEqual(found, input); | | 15 | +} | | 16 | + | | 17 | +const handlers = { | | 18 | + start: common.mustCall(check, 2), | | 19 | + end: common.mustCall(check, 2), | | 20 | + asyncStart: common.mustCall((found) => { | | 21 | + check(found); | | 22 | + assert.strictEqual(found.error, undefined); | | 23 | + assert.deepStrictEqual(found.result, expectedResult); | | 24 | + }, 2), | | 25 | + asyncEnd: common.mustCall((found) => { | | 26 | + check(found); | | 27 | + assert.strictEqual(found.error, undefined); | | 28 | + assert.deepStrictEqual(found.result, expectedResult); | | 29 | + }, 2), | | 30 | + error: common.mustNotCall() | | 31 | +}; | | 32 | + | | 33 | +channel.subscribe(handlers); | | 34 | + | | 35 | +channel.traceCallback(function(cb, err, res) { | | 36 | + assert.deepStrictEqual(this, thisArg); | | 37 | + setImmediate(cb, err, res); | | 38 | +}, 0, input, thisArg, common.mustCall((err, res) => { | | 39 | + assert.strictEqual(err, null); | | 40 | + assert.deepStrictEqual(res, expectedResult); | | 41 | +}), null, expectedResult); | | 42 | + | | 43 | +channel.tracePromise(function(value) { | | 44 | + assert.deepStrictEqual(this, thisArg); | | 45 | + return Promise.resolve(value); | | 46 | +}, input, thisArg, expectedResult).then( | | 47 | + common.mustCall((value) => { | | 48 | + assert.deepStrictEqual(value, expectedResult); | | 49 | + }), | | 50 | + common.mustNotCall() | | 51 | +); | | 52 | + | | 53 | +let failed = false; | | 54 | +try { | | 55 | + channel.traceCallback(common.mustNotCall(), 0, input, thisArg, 1, 2, 3); | | 56 | +} catch (err) { | | 57 | + assert.ok(/"callback" argument must be of type function/.test(err.message)); | | 58 | + failed = true; | | 59 | +} | | 60 | +assert.strictEqual(failed, true); |
Collapse file Copy file name to clipboard +29Lines changed: 29 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const { AsyncLocalStorage } = require('async_hooks'); | | 5 | +const dc = require('diagnostics_channel'); | | 6 | +const assert = require('assert'); | | 7 | + | | 8 | +const channel = dc.tracingChannel('test'); | | 9 | +const store = new AsyncLocalStorage(); | | 10 | + | | 11 | +const firstContext = { foo: 'bar' }; | | 12 | +const secondContext = { baz: 'buz' }; | | 13 | + | | 14 | +channel.start.bindStore(store, common.mustCall(() => { | | 15 | + return firstContext; | | 16 | +})); | | 17 | + | | 18 | +channel.asyncStart.bindStore(store, common.mustCall(() => { | | 19 | + return secondContext; | | 20 | +})); | | 21 | + | | 22 | +assert.strictEqual(store.getStore(), undefined); | | 23 | +channel.traceCallback(common.mustCall((cb) => { | | 24 | + assert.deepStrictEqual(store.getStore(), firstContext); | | 25 | + setImmediate(cb); | | 26 | +}), 0, {}, null, common.mustCall(() => { | | 27 | + assert.deepStrictEqual(store.getStore(), secondContext); | | 28 | +})); | | 29 | +assert.strictEqual(store.getStore(), undefined); |
Collapse file Copy file name to clipboard +24Lines changed: 24 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const { setTimeout } = require('node:timers/promises'); | | 5 | +const { AsyncLocalStorage } = require('async_hooks'); | | 6 | +const dc = require('diagnostics_channel'); | | 7 | +const assert = require('assert'); | | 8 | + | | 9 | +const channel = dc.tracingChannel('test'); | | 10 | +const store = new AsyncLocalStorage(); | | 11 | + | | 12 | +const context = { foo: 'bar' }; | | 13 | + | | 14 | +channel.start.bindStore(store, common.mustCall(() => { | | 15 | + return context; | | 16 | +})); | | 17 | + | | 18 | +assert.strictEqual(store.getStore(), undefined); | | 19 | +channel.tracePromise(common.mustCall(async () => { | | 20 | + assert.deepStrictEqual(store.getStore(), context); | | 21 | + await setTimeout(1); | | 22 | + assert.deepStrictEqual(store.getStore(), context); | | 23 | +})); | | 24 | +assert.strictEqual(store.getStore(), undefined); |
Collapse file Copy file name to clipboard +21Lines changed: 21 additions & 0 deletions | Original file line number | Diff line number | Diff line change |
|---|
| | 1 | +'use strict'; | | 2 | + | | 3 | +const common = require('../common'); | | 4 | +const { AsyncLocalStorage } = require('async_hooks'); | | 5 | +const dc = require('diagnostics_channel'); | | 6 | +const assert = require('assert'); | | 7 | + | | 8 | +const channel = dc.tracingChannel('test'); | | 9 | +const store = new AsyncLocalStorage(); | | 10 | + | | 11 | +const context = { foo: 'bar' }; | | 12 | + | | 13 | +channel.start.bindStore(store, common.mustCall(() => { | | 14 | + return context; | | 15 | +})); | | 16 | + | | 17 | +assert.strictEqual(store.getStore(), undefined); | | 18 | +channel.traceSync(common.mustCall(() => { | | 19 | + assert.deepStrictEqual(store.getStore(), context); | | 20 | +})); | | 21 | +assert.strictEqual(store.getStore(), undefined); |
|