diff options
author | Andreas Madsen <amwebdk@gmail.com> | 2017-07-18 02:47:12 +0300 |
---|---|---|
committer | Andreas Madsen <amwebdk@gmail.com> | 2017-11-16 13:46:54 +0300 |
commit | d217b2850efb9005819d55b697a37cbe5bd0003c (patch) | |
tree | 58177a7aa0d00ece9133ac6c2120e2adb940f527 /lib/internal/trace_events_async_hooks.js | |
parent | ed0327b8868cc3df981f81be6409586b97d06ac8 (diff) |
async_hooks: add trace events to async_hooks
This will allow trace event to record timing information for all
asynchronous operations that are observed by async_hooks.
PR-URL: https://github.com/nodejs/node/pull/15538
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Diffstat (limited to 'lib/internal/trace_events_async_hooks.js')
-rw-r--r-- | lib/internal/trace_events_async_hooks.js | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/lib/internal/trace_events_async_hooks.js b/lib/internal/trace_events_async_hooks.js new file mode 100644 index 00000000000..9f47f2aa5fd --- /dev/null +++ b/lib/internal/trace_events_async_hooks.js @@ -0,0 +1,67 @@ +'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); + }, + + 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(); + } +}; |