trace_events: add support for builtin trace

PR-URL: https://github.com/nodejs/node/pull/21899
Reviewed-By: Ali Ijaz Sheikh <ofrobots@google.com>
This commit is contained in:
James M Snell 2018-05-14 09:25:50 -07:00
parent a706456f71
commit f7454a53f1
4 changed files with 126 additions and 3 deletions

75
benchmark/misc/trace.js Normal file
View File

@ -0,0 +1,75 @@
'use strict';
const common = require('../common.js');
const bench = common.createBenchmark(main, {
n: [100000],
method: ['trace', 'emit', 'isTraceCategoryEnabled', 'categoryGroupEnabled']
}, {
flags: ['--expose-internals', '--trace-event-categories', 'foo']
});
const {
trace,
isTraceCategoryEnabled,
emit,
categoryGroupEnabled
} = process.binding('trace_events');
const {
TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN: kBeforeEvent
} = process.binding('constants').trace;
function doEmit(n) {
bench.start();
for (var i = 0; i < n; i++) {
emit(kBeforeEvent, 'foo', 'test', 0, 'arg1', 1);
}
bench.end(n);
}
function doTrace(n) {
bench.start();
for (var i = 0; i < n; i++) {
trace(kBeforeEvent, 'foo', 'test', 0, 'test');
}
bench.end(n);
}
function doIsTraceCategoryEnabled(n) {
bench.start();
for (var i = 0; i < n; i++) {
isTraceCategoryEnabled('foo');
isTraceCategoryEnabled('bar');
}
bench.end(n);
}
function doCategoryGroupEnabled(n) {
bench.start();
for (var i = 0; i < n; i++) {
categoryGroupEnabled('foo');
categoryGroupEnabled('bar');
}
bench.end(n);
}
function main({ n, method }) {
switch (method) {
case '':
case 'trace':
doTrace(n);
break;
case 'emit':
doEmit(n);
break;
case 'isTraceCategoryEnabled':
doIsTraceCategoryEnabled(n);
break;
case 'categoryGroupEnabled':
doCategoryGroupEnabled(n);
break;
default:
throw new Error(`Unexpected method "${method}"`);
}
}

View File

@ -1282,6 +1282,35 @@ void DefineDLOpenConstants(Local<Object> target) {
#endif
}
void DefineTraceConstants(Local<Object> target) {
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_BEGIN);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_END);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_COMPLETE);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_INSTANT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_ASYNC_BEGIN);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_ASYNC_STEP_INTO);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_ASYNC_STEP_PAST);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_ASYNC_END);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_NESTABLE_ASYNC_BEGIN);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_NESTABLE_ASYNC_END);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_NESTABLE_ASYNC_INSTANT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_FLOW_BEGIN);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_FLOW_STEP);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_FLOW_END);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_METADATA);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_COUNTER);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_SAMPLE);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_CREATE_OBJECT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_SNAPSHOT_OBJECT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_DELETE_OBJECT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_MEMORY_DUMP);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_MARK);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_CLOCK_SYNC);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_ENTER_CONTEXT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_LEAVE_CONTEXT);
NODE_DEFINE_CONSTANT(target, TRACE_EVENT_PHASE_LINK_IDS);
}
} // anonymous namespace
void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
@ -1315,6 +1344,10 @@ void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
CHECK(dlopen_constants->SetPrototype(env->context(),
Null(env->isolate())).FromJust());
Local<Object> trace_constants = Object::New(isolate);
CHECK(trace_constants->SetPrototype(env->context(),
Null(env->isolate())).FromJust());
DefineErrnoConstants(err_constants);
DefineWindowsErrorConstants(err_constants);
DefineSignalConstants(sig_constants);
@ -1323,6 +1356,7 @@ void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
DefineCryptoConstants(crypto_constants);
DefineZlibConstants(zlib_constants);
DefineDLOpenConstants(dlopen_constants);
DefineTraceConstants(trace_constants);
// Define libuv constants.
NODE_DEFINE_CONSTANT(os_constants, UV_UDP_REUSEADDR);
@ -1334,6 +1368,7 @@ void DefineConstants(v8::Isolate* isolate, Local<Object> target) {
target->Set(OneByteString(isolate, "fs"), fs_constants);
target->Set(OneByteString(isolate, "crypto"), crypto_constants);
target->Set(OneByteString(isolate, "zlib"), zlib_constants);
target->Set(OneByteString(isolate, "trace"), trace_constants);
}
} // namespace node

View File

@ -232,6 +232,19 @@ void Initialize(Local<Object> target,
target->Set(FIXED_ONE_BYTE_STRING(env->isolate(), "CategorySet"),
category_set->GetFunction());
Local<String> isTraceCategoryEnabled =
FIXED_ONE_BYTE_STRING(env->isolate(), "isTraceCategoryEnabled");
Local<String> trace = FIXED_ONE_BYTE_STRING(env->isolate(), "trace");
// Grab the trace and isTraceCategoryEnabled intrinsics from the binding
// object and expose those to our binding layer.
Local<Object> binding = context->GetExtrasBindingObject();
target->Set(context, isTraceCategoryEnabled,
binding->Get(context, isTraceCategoryEnabled).ToLocalChecked())
.FromJust();
target->Set(context, trace,
binding->Get(context, trace).ToLocalChecked()).FromJust();
}
} // namespace node

View File

@ -5,7 +5,7 @@ const constants = process.binding('constants');
const assert = require('assert');
assert.deepStrictEqual(
Object.keys(constants).sort(), ['crypto', 'fs', 'os', 'zlib']
Object.keys(constants).sort(), ['crypto', 'fs', 'os', 'trace', 'zlib']
);
assert.deepStrictEqual(
@ -26,6 +26,6 @@ function test(obj) {
}
[
constants, constants.crypto, constants.fs, constants.os, constants.zlib,
constants.os.dlopen, constants.os.errno, constants.os.signals
constants, constants.crypto, constants.fs, constants.os, constants.trace,
constants.zlib, constants.os.dlopen, constants.os.errno, constants.os.signals
].forEach(test);