console: add trace-events for time and count
Add the `node.console` trace event category to capture `console.count()`, `console.countReset()`, `console.time()`, `console.timeLog()`, and `console.timeEnd()` to the trace event log. PR-URL: https://github.com/nodejs/node/pull/23703 Reviewed-By: Luigi Pinca <luigipinca@gmail.com> Reviewed-By: Richard Lau <riclau@uk.ibm.com>
This commit is contained in:
parent
bf7ed80475
commit
9c82a1e7ba
@ -18,6 +18,8 @@ The available categories are:
|
|||||||
The [`async_hooks`] events have a unique `asyncId` and a special `triggerId`
|
The [`async_hooks`] events have a unique `asyncId` and a special `triggerId`
|
||||||
`triggerAsyncId` property.
|
`triggerAsyncId` property.
|
||||||
* `node.bootstrap` - Enables capture of Node.js bootstrap milestones.
|
* `node.bootstrap` - Enables capture of Node.js bootstrap milestones.
|
||||||
|
* `node.console` - Enables capture of `console.time()` and `console.count()`
|
||||||
|
output.
|
||||||
* `node.environment` - Enables capture of Node.js Environment milestones.
|
* `node.environment` - Enables capture of Node.js Environment milestones.
|
||||||
* `node.fs.sync` - Enables capture of trace data for file system sync methods.
|
* `node.fs.sync` - Enables capture of trace data for file system sync methods.
|
||||||
* `node.perf` - Enables capture of [Performance API] measurements.
|
* `node.perf` - Enables capture of [Performance API] measurements.
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
|
const { trace } = internalBinding('trace_events');
|
||||||
const {
|
const {
|
||||||
isStackOverflowError,
|
isStackOverflowError,
|
||||||
codes: {
|
codes: {
|
||||||
@ -37,6 +38,12 @@ const {
|
|||||||
} = util.types;
|
} = util.types;
|
||||||
const kCounts = Symbol('counts');
|
const kCounts = Symbol('counts');
|
||||||
|
|
||||||
|
const kTraceConsoleCategory = 'node,node.console';
|
||||||
|
const kTraceCount = 'C'.charCodeAt(0);
|
||||||
|
const kTraceBegin = 'b'.charCodeAt(0);
|
||||||
|
const kTraceEnd = 'e'.charCodeAt(0);
|
||||||
|
const kTraceInstant = 'n'.charCodeAt(0);
|
||||||
|
|
||||||
const {
|
const {
|
||||||
keys: ObjectKeys,
|
keys: ObjectKeys,
|
||||||
values: ObjectValues,
|
values: ObjectValues,
|
||||||
@ -232,6 +239,7 @@ Console.prototype.time = function time(label = 'default') {
|
|||||||
process.emitWarning(`Label '${label}' already exists for console.time()`);
|
process.emitWarning(`Label '${label}' already exists for console.time()`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
trace(kTraceBegin, kTraceConsoleCategory, `time::${label}`, 0);
|
||||||
this._times.set(label, process.hrtime());
|
this._times.set(label, process.hrtime());
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -239,6 +247,7 @@ Console.prototype.timeEnd = function timeEnd(label = 'default') {
|
|||||||
// Coerces everything other than Symbol to a string
|
// Coerces everything other than Symbol to a string
|
||||||
label = `${label}`;
|
label = `${label}`;
|
||||||
const hasWarned = timeLogImpl(this, 'timeEnd', label);
|
const hasWarned = timeLogImpl(this, 'timeEnd', label);
|
||||||
|
trace(kTraceEnd, kTraceConsoleCategory, `time::${label}`, 0);
|
||||||
if (!hasWarned) {
|
if (!hasWarned) {
|
||||||
this._times.delete(label);
|
this._times.delete(label);
|
||||||
}
|
}
|
||||||
@ -248,6 +257,7 @@ Console.prototype.timeLog = function timeLog(label, ...data) {
|
|||||||
// Coerces everything other than Symbol to a string
|
// Coerces everything other than Symbol to a string
|
||||||
label = `${label}`;
|
label = `${label}`;
|
||||||
timeLogImpl(this, 'timeLog', label, data);
|
timeLogImpl(this, 'timeLog', label, data);
|
||||||
|
trace(kTraceInstant, kTraceConsoleCategory, `time::${label}`, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Returns true if label was not found
|
// Returns true if label was not found
|
||||||
@ -308,6 +318,7 @@ Console.prototype.count = function count(label = 'default') {
|
|||||||
else
|
else
|
||||||
count++;
|
count++;
|
||||||
counts.set(label, count);
|
counts.set(label, count);
|
||||||
|
trace(kTraceCount, kTraceConsoleCategory, `count::${label}`, 0, count);
|
||||||
this.log(`${label}: ${count}`);
|
this.log(`${label}: ${count}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -318,7 +329,7 @@ Console.prototype.countReset = function countReset(label = 'default') {
|
|||||||
process.emitWarning(`Count for '${label}' does not exist`);
|
process.emitWarning(`Count for '${label}' does not exist`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
trace(kTraceCount, kTraceConsoleCategory, `count::${label}`, 0, 0);
|
||||||
counts.delete(`${label}`);
|
counts.delete(`${label}`);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
62
test/parallel/test-trace-events-console.js
Normal file
62
test/parallel/test-trace-events-console.js
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
'use strict';
|
||||||
|
const common = require('../common');
|
||||||
|
const assert = require('assert');
|
||||||
|
const cp = require('child_process');
|
||||||
|
const path = require('path');
|
||||||
|
const fs = require('fs');
|
||||||
|
const tmpdir = require('../common/tmpdir');
|
||||||
|
|
||||||
|
// Tests that node.console trace events for counters and time methods are
|
||||||
|
// emitted as expected.
|
||||||
|
|
||||||
|
const names = [
|
||||||
|
'time::foo',
|
||||||
|
'count::bar'
|
||||||
|
];
|
||||||
|
const expectedCounts = [ 1, 2, 0 ];
|
||||||
|
const expectedTimeTypes = [ 'b', 'n', 'e' ];
|
||||||
|
|
||||||
|
if (process.argv[2] === 'child') {
|
||||||
|
// The following console outputs exercise the test, causing node.console
|
||||||
|
// trace events to be emitted for the counter and time calls.
|
||||||
|
console.count('bar');
|
||||||
|
console.count('bar');
|
||||||
|
console.countReset('bar');
|
||||||
|
console.time('foo');
|
||||||
|
setImmediate(() => {
|
||||||
|
console.timeLog('foo');
|
||||||
|
setImmediate(() => {
|
||||||
|
console.timeEnd('foo');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
tmpdir.refresh();
|
||||||
|
|
||||||
|
const proc = cp.fork(__filename,
|
||||||
|
[ 'child' ], {
|
||||||
|
cwd: tmpdir.path,
|
||||||
|
execArgv: [
|
||||||
|
'--trace-event-categories',
|
||||||
|
'node.console'
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
proc.once('exit', common.mustCall(async () => {
|
||||||
|
const file = path.join(tmpdir.path, 'node_trace.1.log');
|
||||||
|
|
||||||
|
assert(fs.existsSync(file));
|
||||||
|
const data = await fs.promises.readFile(file, { encoding: 'utf8' });
|
||||||
|
JSON.parse(data).traceEvents
|
||||||
|
.filter((trace) => trace.cat !== '__metadata')
|
||||||
|
.forEach((trace) => {
|
||||||
|
assert.strictEqual(trace.pid, proc.pid);
|
||||||
|
assert(names.includes(trace.name));
|
||||||
|
if (trace.name === 'count::bar')
|
||||||
|
assert.strictEqual(trace.args.data, expectedCounts.shift());
|
||||||
|
else if (trace.name === 'time::foo')
|
||||||
|
assert.strictEqual(trace.ph, expectedTimeTypes.shift());
|
||||||
|
});
|
||||||
|
assert.strictEqual(expectedCounts.length, 0);
|
||||||
|
assert.strictEqual(expectedTimeTypes.length, 0);
|
||||||
|
}));
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user