Skip to content

Commit 7d37dcd

Browse files
Stephen BelangerRafaelGSS
Stephen Belanger
authored andcommitted
lib: add tracing channel to diagnostics_channel
PR-URL: #44943 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Chengzhong Wu <legendecas@gmail.com> Reviewed-By: Colin Ihrig <cjihrig@gmail.com> Reviewed-By: Gerhard Stöbich <deb2001-github@yahoo.de> Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Bryan English <bryan@bryanenglish.com>
1 parent cbb3627 commit 7d37dcd

13 files changed

+1309
-35
lines changed

doc/api/diagnostics_channel.md

+647
Large diffs are not rendered by default.

lib/diagnostics_channel.js

+282-25
Large diffs are not rendered by default.

src/node_util.cc

+4-9
Original file line numberDiff line numberDiff line change
@@ -262,18 +262,13 @@ void WeakReference::Get(const FunctionCallbackInfo<Value>& args) {
262262
args.GetReturnValue().Set(weak_ref->target_.Get(isolate));
263263
}
264264

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-
272265
void WeakReference::IncRef(const FunctionCallbackInfo<Value>& args) {
273266
WeakReference* weak_ref = Unwrap<WeakReference>(args.Holder());
274267
weak_ref->reference_count_++;
275268
if (weak_ref->target_.IsEmpty()) return;
276269
if (weak_ref->reference_count_ == 1) weak_ref->target_.ClearWeak();
270+
args.GetReturnValue().Set(
271+
v8::Number::New(args.GetIsolate(), weak_ref->reference_count_));
277272
}
278273

279274
void WeakReference::DecRef(const FunctionCallbackInfo<Value>& args) {
@@ -282,6 +277,8 @@ void WeakReference::DecRef(const FunctionCallbackInfo<Value>& args) {
282277
weak_ref->reference_count_--;
283278
if (weak_ref->target_.IsEmpty()) return;
284279
if (weak_ref->reference_count_ == 0) weak_ref->target_.SetWeak();
280+
args.GetReturnValue().Set(
281+
v8::Number::New(args.GetIsolate(), weak_ref->reference_count_));
285282
}
286283

287284
static void GuessHandleType(const FunctionCallbackInfo<Value>& args) {
@@ -365,7 +362,6 @@ void RegisterExternalReferences(ExternalReferenceRegistry* registry) {
365362
registry->Register(ArrayBufferViewHasBuffer);
366363
registry->Register(WeakReference::New);
367364
registry->Register(WeakReference::Get);
368-
registry->Register(WeakReference::GetRef);
369365
registry->Register(WeakReference::IncRef);
370366
registry->Register(WeakReference::DecRef);
371367
registry->Register(GuessHandleType);
@@ -457,7 +453,6 @@ void Initialize(Local<Object> target,
457453
WeakReference::kInternalFieldCount);
458454
weak_ref->Inherit(BaseObject::GetConstructorTemplate(env));
459455
SetProtoMethod(isolate, weak_ref, "get", WeakReference::Get);
460-
SetProtoMethod(isolate, weak_ref, "getRef", WeakReference::GetRef);
461456
SetProtoMethod(isolate, weak_ref, "incRef", WeakReference::IncRef);
462457
SetProtoMethod(isolate, weak_ref, "decRef", WeakReference::DecRef);
463458
SetConstructorFunction(context, target, "WeakReference", weak_ref);

src/node_util.h

-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ class WeakReference : public SnapshotableObject {
2121
v8::Local<v8::Object> target);
2222
static void New(const v8::FunctionCallbackInfo<v8::Value>& args);
2323
static void Get(const v8::FunctionCallbackInfo<v8::Value>& args);
24-
static void GetRef(const v8::FunctionCallbackInfo<v8::Value>& args);
2524
static void IncRef(const v8::FunctionCallbackInfo<v8::Value>& args);
2625
static void DecRef(const v8::FunctionCallbackInfo<v8::Value>& args);
2726

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
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;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
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+
);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
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);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
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);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
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);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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),
19+
end: common.mustCall(check),
20+
asyncStart: common.mustNotCall(),
21+
asyncEnd: common.mustNotCall(),
22+
error: common.mustCall((found) => {
23+
check(found);
24+
assert.deepStrictEqual(found.error, expectedError);
25+
})
26+
};
27+
28+
channel.subscribe(handlers);
29+
try {
30+
channel.traceSync(function(err) {
31+
assert.deepStrictEqual(this, thisArg);
32+
assert.strictEqual(err, expectedError);
33+
throw err;
34+
}, input, thisArg, expectedError);
35+
36+
throw new Error('It should not reach this error');
37+
} catch (error) {
38+
assert.deepStrictEqual(error, expectedError);
39+
}

0 commit comments

Comments
 (0)