mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 21:58:48 +02:00
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>
This commit is contained in:
parent
ed0327b886
commit
d217b2850e
18 changed files with 607 additions and 73 deletions
67
lib/internal/trace_events_async_hooks.js
Normal file
67
lib/internal/trace_events_async_hooks.js
Normal file
|
@ -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();
|
||||
}
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue