Skip to content

Commit 46314ef

Browse files
committed
trace_events: export v8 trace api
export v8 trace api, so user can use it to trace custom events and collect the data by using inspector or the trace_events.createTracing method
1 parent 934a3aa commit 46314ef

File tree

4 files changed

+122
-14
lines changed

4 files changed

+122
-14
lines changed

doc/api/tracing.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,61 @@ t2.enable();
226226
console.log(trace_events.getEnabledCategories());
227227
```
228228

229+
### `trace_events.trace(phase, category, name, id, data)`
230+
231+
<!-- YAML
232+
added: REPLACEME
233+
-->
234+
235+
use `trace_events.trace` to product trace events data, then this data can be
236+
collected by the `inspector` module or the `trace_events.createTracing` method.
237+
238+
The following example is used to product custom trace event, and collect
239+
the data by using the inspector.
240+
241+
```js
242+
'use strict';
243+
244+
const {
245+
trace,
246+
events: {
247+
TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: kBeforeEvent
248+
},
249+
} = require('trace_events');
250+
251+
const { Session } = require('inspector');
252+
253+
const session = new Session();
254+
255+
function post(message, data) {
256+
return new Promise((resolve, reject) => {
257+
session.post(message, data, (err, result) => {
258+
if (err)
259+
reject(new Error(JSON.stringify(err)));
260+
else
261+
resolve(result);
262+
});
263+
});
264+
}
265+
266+
async function test() {
267+
session.connect();
268+
const events = [];
269+
session.on('NodeTracing.dataCollected', (n) => {
270+
events.push(...n.params.value.filter((v) => v.cat !== '__metadata'));
271+
});
272+
session.on('NodeTracing.tracingComplete', () => console.log(events));
273+
274+
const traceConfig = { includedCategories: ['custom'] };
275+
await post('NodeTracing.start', { traceConfig });
276+
trace(kBeforeEvent, 'custom', 'hello', 0, 'world');
277+
await post('NodeTracing.stop', { traceConfig });
278+
session.disconnect();
279+
}
280+
281+
test();
282+
```
283+
229284
[Performance API]: perf_hooks.md
230285
[V8]: v8.md
231286
[`Worker`]: worker_threads.md#class-worker

lib/trace_events.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const { hasTracing } = internalBinding('config');
1111
const kHandle = Symbol('handle');
1212
const kEnabled = Symbol('enabled');
1313
const kCategories = Symbol('categories');
14-
14+
const { isMainThread } = require('worker_threads');
1515
const kMaxTracingCount = 10;
1616

1717
const {
@@ -24,7 +24,8 @@ const { ownsProcessState } = require('internal/worker');
2424
if (!hasTracing || !ownsProcessState)
2525
throw new ERR_TRACE_EVENTS_UNAVAILABLE();
2626

27-
const { CategorySet, getEnabledCategories } = internalBinding('trace_events');
27+
const { CategorySet, getEnabledCategories, trace } = internalBinding('trace_events');
28+
const constants = internalBinding('constants');
2829
const { customInspectSymbol } = require('internal/util');
2930
const { format } = require('internal/util/inspect');
3031
const {
@@ -98,5 +99,7 @@ function createTracing(options) {
9899

99100
module.exports = {
100101
createTracing,
101-
getEnabledCategories
102+
getEnabledCategories,
103+
trace: isMainThread ? trace : null,
104+
events: constants.trace
102105
};
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767
5+
6+
const assert = require('assert');
7+
const fs = require('fs');
8+
const path = require('path');
9+
const cp = require('child_process');
10+
const tmpdir = require('../common/tmpdir');
11+
12+
if (process.argv[2] === 'isChild') {
13+
const {
14+
createTracing,
15+
trace,
16+
events: {
17+
TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: kBeforeEvent,
18+
TRACE_EVENT_PHASE_NESTABLE_ASYNC_END: kEndEvent
19+
},
20+
} = require('trace_events');
21+
22+
const tracing = createTracing({ categories: [ 'custom' ] });
23+
tracing.enable();
24+
trace(kBeforeEvent, 'custom', 'hello', 0, 'world');
25+
setTimeout(() => {
26+
trace(kEndEvent, 'custom', 'hello', 0, 'world');
27+
tracing.disable();
28+
}, 1);
29+
} else {
30+
tmpdir.refresh();
31+
const parentDir = process.cwd();
32+
process.chdir(tmpdir.path);
33+
const proc = cp.fork(__filename, ['isChild'], {
34+
execArgv: [
35+
'--trace-event-categories',
36+
'custom',
37+
]
38+
});
39+
40+
proc.once('exit', common.mustCall(() => {
41+
const file = path.join(tmpdir.path, 'node_trace.1.log');
42+
assert(fs.existsSync(file));
43+
fs.readFile(file, { encoding: 'utf-8' }, common.mustSucceed((data) => {
44+
const traces = JSON.parse(data).traceEvents.filter((trace) => trace.cat !== '__metadata');
45+
assert.strictEqual(traces.length, 2);
46+
traces.forEach((trace) => {
47+
assert.strictEqual(trace.cat, 'custom');
48+
assert.strictEqual(trace.name, 'hello');
49+
assert.strictEqual(trace.args.data, 'world');
50+
});
51+
}));
52+
process.chdir(parentDir);
53+
}));
54+
}

test/parallel/test-trace-events-dynamic-enable.js

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,16 @@
1-
// Flags: --expose-internals
21
'use strict';
32

43
const common = require('../common');
54

65
common.skipIfInspectorDisabled();
76
common.skipIfWorker(); // https://github.com/nodejs/node/issues/22767
87

9-
const { internalBinding } = require('internal/test/binding');
10-
118
const {
12-
trace: {
9+
trace,
10+
events: {
1311
TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: kBeforeEvent
14-
}
15-
} = internalBinding('constants');
16-
17-
const { trace } = internalBinding('trace_events');
12+
},
13+
} = require('trace_events');
1814

1915
const assert = require('assert');
2016
const { Session } = require('inspector');
@@ -37,11 +33,11 @@ async function test() {
3733

3834
const events = [];
3935
let tracingComplete = false;
40-
session.on('NodeTracing.dataCollected', (n) => {
36+
session.on('NodeTracing.dataCollected', common.mustCallAtLeast((n) => {
4137
assert.ok(n && n.params && n.params.value);
4238
events.push(...n.params.value); // append the events.
43-
});
44-
session.on('NodeTracing.tracingComplete', () => tracingComplete = true);
39+
}));
40+
session.on('NodeTracing.tracingComplete', common.mustCall(() => tracingComplete = true));
4541

4642
trace(kBeforeEvent, 'foo', 'test1', 0, 'test');
4743

0 commit comments

Comments
 (0)