'use strict'; const trace_events = process.binding('trace_events'); const async_wrap = process.binding('async_wrap'); const async_hooks = require('async_hooks'); // Use small letters such that chrome://traceing groups by the name. // The behaviour 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(); // 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)); const hook = async_hooks.createHook({ init(asyncId, type, triggerAsyncId, resource) { if (nativeProviders.has(type)) return; typeMemory.set(asyncId, type); trace_events.emit(BEFORE_EVENT, 'node.async_hooks', type, asyncId, 'triggerAsyncId', triggerAsyncId, 'executionAsyncId', async_hooks.executionAsyncId()); }, before(asyncId) { const type = typeMemory.get(asyncId); if (type === undefined) return; trace_events.emit(BEFORE_EVENT, 'node.async_hooks', type + '_CALLBACK', asyncId); }, after(asyncId) { const type = typeMemory.get(asyncId); if (type === undefined) return; trace_events.emit(END_EVENT, 'node.async_hooks', type + '_CALLBACK', asyncId); }, destroy(asyncId) { const type = typeMemory.get(asyncId); if (type === undefined) return; trace_events.emit(END_EVENT, 'node.async_hooks', type, asyncId); // cleanup asyncId to type map typeMemory.delete(asyncId); } }); exports.setup = function() { if (trace_events.categoryGroupEnabled('node.async_hooks')) { hook.enable(); } };