Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nodejs/node.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndreas Madsen <amwebdk@gmail.com>2017-07-18 02:47:12 +0300
committerAndreas Madsen <amwebdk@gmail.com>2017-11-16 13:46:54 +0300
commitd217b2850efb9005819d55b697a37cbe5bd0003c (patch)
tree58177a7aa0d00ece9133ac6c2120e2adb940f527 /lib/internal/trace_events_async_hooks.js
parented0327b8868cc3df981f81be6409586b97d06ac8 (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.js67
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();
+ }
+};