diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js index 3113aa079da..5d509e4e37b 100644 --- a/lib/internal/bootstrap/node.js +++ b/lib/internal/bootstrap/node.js @@ -64,7 +64,17 @@ if (global.__coverage__) NativeModule.require('internal/process/write-coverage').setup(); - NativeModule.require('internal/trace_events_async_hooks').setup(); + + { + const traceEvents = process.binding('trace_events'); + const traceEventCategory = 'node,node.async_hooks'; + + if (traceEvents.categoryGroupEnabled(traceEventCategory)) { + NativeModule.require('internal/trace_events_async_hooks') + .setup(traceEvents, traceEventCategory); + } + } + if (process.config.variables.v8_enable_inspector) { NativeModule.require('internal/inspector_async_hook').setup(); diff --git a/lib/internal/trace_events_async_hooks.js b/lib/internal/trace_events_async_hooks.js index db38fe99adc..011dc6bbead 100644 --- a/lib/internal/trace_events_async_hooks.js +++ b/lib/internal/trace_events_async_hooks.js @@ -1,71 +1,63 @@ 'use strict'; -const trace_events = process.binding('trace_events'); -const async_wrap = process.binding('async_wrap'); -const async_hooks = require('async_hooks'); +exports.setup = function(traceEvents, traceEventCategory) { + const async_wrap = process.binding('async_wrap'); + const async_hooks = require('async_hooks'); -// Use small letters such that chrome://tracing groups by the name. -// The behavior is not only useful but the same as the events emitted using -// the specific C++ macros. -const BEFORE_EVENT = 'b'.charCodeAt(0); -const END_EVENT = 'e'.charCodeAt(0); + // Use small letters such that chrome://tracing groups by the name. + // The behavior is not only useful but the same as the events emitted using + // the specific C++ macros. + const BEFORE_EVENT = 'b'.charCodeAt(0); + const END_EVENT = 'e'.charCodeAt(0); -// In trace_events it is not only the id but also the name that needs to be -// repeated. Since async_hooks doesn't expose the provider type in the -// non-init events, use a map to manually map the asyncId to the type name. -const typeMemory = new Map(); + // In traceEvents it is not only the id but also the name that needs to be + // repeated. Since async_hooks doesn't expose the provider type in the + // non-init events, use a map to manually map the asyncId to the type name. + const typeMemory = new Map(); -const trace_event_category = 'node,node.async_hooks'; + // It is faster to emit traceEvents directly from C++. Thus, this happens + // in async_wrap.cc. However, events emitted from the JavaScript API or the + // Embedder C++ API can't be emitted from async_wrap.cc. Thus they are + // emitted using the JavaScript API. To prevent emitting the same event + // twice the async_wrap.Providers list is used to filter the events. + const nativeProviders = new Set(Object.keys(async_wrap.Providers)); -// It is faster to emit trace_events directly from C++. Thus, this happens in -// async_wrap.cc. However, events emitted from the JavaScript API or the -// Embedder C++ API can't be emitted from async_wrap.cc. Thus they are -// emitted using the JavaScript API. To prevent emitting the same event -// twice the async_wrap.Providers list is used to filter the events. -const nativeProviders = new Set(Object.keys(async_wrap.Providers)); + async_hooks.createHook({ + init(asyncId, type, triggerAsyncId, resource) { + if (nativeProviders.has(type)) return; -const hook = async_hooks.createHook({ - init(asyncId, type, triggerAsyncId, resource) { - if (nativeProviders.has(type)) return; + typeMemory.set(asyncId, type); + traceEvents.emit(BEFORE_EVENT, traceEventCategory, + type, asyncId, + 'triggerAsyncId', triggerAsyncId, + 'executionAsyncId', async_hooks.executionAsyncId()); + }, - typeMemory.set(asyncId, type); - trace_events.emit(BEFORE_EVENT, trace_event_category, - type, asyncId, - 'triggerAsyncId', triggerAsyncId, - 'executionAsyncId', async_hooks.executionAsyncId()); - }, + before(asyncId) { + const type = typeMemory.get(asyncId); + if (type === undefined) return; - before(asyncId) { - const type = typeMemory.get(asyncId); - if (type === undefined) return; + traceEvents.emit(BEFORE_EVENT, traceEventCategory, + type + '_CALLBACK', asyncId); + }, - trace_events.emit(BEFORE_EVENT, trace_event_category, - type + '_CALLBACK', asyncId); - }, + after(asyncId) { + const type = typeMemory.get(asyncId); + if (type === undefined) return; - after(asyncId) { - const type = typeMemory.get(asyncId); - if (type === undefined) return; + traceEvents.emit(END_EVENT, traceEventCategory, + type + '_CALLBACK', asyncId); + }, - trace_events.emit(END_EVENT, trace_event_category, - type + '_CALLBACK', asyncId); - }, + destroy(asyncId) { + const type = typeMemory.get(asyncId); + if (type === undefined) return; - destroy(asyncId) { - const type = typeMemory.get(asyncId); - if (type === undefined) return; + traceEvents.emit(END_EVENT, traceEventCategory, + type, asyncId); - trace_events.emit(END_EVENT, trace_event_category, - type, asyncId); - - // cleanup asyncId to type map - typeMemory.delete(asyncId); - } -}); - - -exports.setup = function() { - if (trace_events.categoryGroupEnabled(trace_event_category)) { - hook.enable(); - } + // cleanup asyncId to type map + typeMemory.delete(asyncId); + } + }).enable(); };