Example #1
0
function createHook() {
  // 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 hook = async_hooks.createHook({
    init(asyncId, type, triggerAsyncId, resource) {
      if (nativeProviders.has(type)) return;

      typeMemory.set(asyncId, type);
      trace(kBeforeEvent, kTraceEventCategory,
            type, asyncId,
            {
              triggerAsyncId,
              executionAsyncId: async_hooks.executionAsyncId()
            });
    },

    before(asyncId) {
      const type = typeMemory.get(asyncId);
      if (type === undefined) return;

      trace(kBeforeEvent, kTraceEventCategory, `${type}_CALLBACK`, asyncId);
    },

    after(asyncId) {
      const type = typeMemory.get(asyncId);
      if (type === undefined) return;

      trace(kEndEvent, kTraceEventCategory, `${type}_CALLBACK`, asyncId);
    },

    destroy(asyncId) {
      const type = typeMemory.get(asyncId);
      if (type === undefined) return;

      trace(kEndEvent, kTraceEventCategory, type, asyncId);

      // cleanup asyncId to type map
      typeMemory.delete(asyncId);
    }
  });

  return {
    enable() {
      if (this[kEnabled])
        return;
      this[kEnabled] = true;
      hook.enable();
    },

    disable() {
      if (!this[kEnabled])
        return;
      this[kEnabled] = false;
      hook.disable();
      typeMemory.clear();
    }
  };
}
Example #2
0
  constructor(start, {
    allowNoInit = false,
    oninit,
    onbefore,
    onafter,
    ondestroy,
    logid = null,
    logtype = null
  } = {}) {
    this._start = start;
    this._allowNoInit = allowNoInit;
    this._activities = new Map();
    this._logid = logid;
    this._logtype = logtype;

    // Register event handlers if provided
    this.oninit = typeof oninit === 'function' ? oninit : noop;
    this.onbefore = typeof onbefore === 'function' ? onbefore : noop;
    this.onafter = typeof onafter === 'function' ? onafter : noop;
    this.ondestroy = typeof ondestroy === 'function' ? ondestroy : noop;

    // Create the hook with which we'll collect activity data
    this._asyncHook = async_hooks.createHook({
      init: this._init.bind(this),
      before: this._before.bind(this),
      after: this._after.bind(this),
      destroy: this._destroy.bind(this)
    });
  }
Promise.resolve(1).then(common.mustCall(() => {
  async_hooks.createHook({
    init: common.mustCall(),
    before: common.mustCallAtLeast(),
    after: common.mustCallAtLeast(2)
  }).enable();

  process.nextTick(common.mustCall());
}));
Example #4
0
 constructor() {
   this.map = new Map();
   asyncHooks.createHook({
     init: (id, _type, triggerId) => {
       if (this.map.has(triggerId))
         this.map.set(id, this.map.get(triggerId));
     },
     destroy: (id) => this.map.delete(id)
   }).enable();
 }
Example #5
0
test('asyncresource', function (t) {
  t.plan(7);

  var resourceAsyncId;
  var originalExecutionAsyncId;
  var beforeCalled = false;
  var afterCalled = false;
  var destroyCalled = false;

  var hooks = asyncHooks.createHook({
    init: function(asyncId, type, triggerAsyncId, resource) {
      if (type === 'nan:test.DelayRequest') {
        resourceAsyncId = asyncId;
      }
    },
    before: function(asyncId) {
      if (asyncId === resourceAsyncId) {
        beforeCalled = true;
      }
    },
    after: function(asyncId) {
      if (asyncId === resourceAsyncId) {
        afterCalled = true;
      }
    },
    destroy: function(asyncId) {
      if (asyncId === resourceAsyncId) {
        destroyCalled = true;
      }
    }

  });
  hooks.enable();

  originalExecutionAsyncId = asyncHooks.executionAsyncId();
  delay(1000, function() {
    t.equal(asyncHooks.executionAsyncId(), resourceAsyncId,
            'callback should have the correct execution context');
    t.equal(asyncHooks.triggerAsyncId(), originalExecutionAsyncId,
            'callback should have the correct trigger context');
    t.ok(beforeCalled, 'before should have been called');
    t.notOk(afterCalled, 'after should not have been called yet');
    setTimeout(function() {
      t.ok(afterCalled, 'after should have been called');
      t.ok(destroyCalled, 'destroy should have been called');
      t.equal(asyncHooks.triggerAsyncId(), resourceAsyncId,
              'setTimeout should have been triggered by the async resource');
      hooks.disable();
    }, 1);
  });
});
Example #6
0
function collectHandles() {
  const activeHandles = new Map();

  function initHook(asyncId, type) {
    const error = new Error(type);

    if (Error.captureStackTrace) {
      Error.captureStackTrace(error, initHook);
    }

    if (error.stack.includes('Runtime.requireModule')) {
      activeHandles.set(asyncId, error);
    }
  }

  let hook;

  try {
    // $FlowFixMe: Node core module
    const asyncHooks = require('async_hooks');
    hook = asyncHooks.createHook({
      destroy: function(asyncId) {
        activeHandles.delete(asyncId);
      },

      init: initHook
    });

    hook.enable();
  } catch (e) {
    const nodeMajor = Number(process.versions.node.split('.')[0]);
    if (e.code === 'MODULE_NOT_FOUND' && nodeMajor < 8) {
      throw new Error(
        'You can only use --detectOpenHandles on Node 8 and newer.'
      );
    } else {
      throw e;
    }
  }

  return () => {
    hook.disable();

    const result = Array.from(activeHandles.values());
    activeHandles.clear();
    return result;
  };
}
Example #7
0
// Inspired by https://github.com/mafintosh/why-is-node-running/blob/master/index.js
// Extracted as we want to format the result ourselves
export default function collectHandles(): () => Array<Error> {
  const activeHandles: Map<string, Error> = new Map();

  function initHook(asyncId, type) {
    if (type === 'PROMISE' || type === 'TIMERWRAP') {
      return;
    }
    const error = new ErrorWithStack(type, initHook);

    if (stackIsFromUser(error.stack)) {
      activeHandles.set(asyncId, error);
    }
  }

  let hook;

  try {
    // $FlowFixMe: Node core module
    const asyncHooks = require('async_hooks');
    hook = asyncHooks.createHook({
      destroy(asyncId) {
        activeHandles.delete(asyncId);
      },
      init: initHook,
    });

    hook.enable();
  } catch (e) {
    const nodeMajor = Number(process.versions.node.split('.')[0]);
    if (e.code === 'MODULE_NOT_FOUND' && nodeMajor < 8) {
      throw new Error(
        'You can only use --detectOpenHandles on Node 8 and newer.',
      );
    } else {
      throw e;
    }
  }

  return () => {
    hook.disable();

    const result = Array.from(activeHandles.values());
    activeHandles.clear();
    return result;
  };
}
'use strict';
// Flags: --expose_gc

// This test ensures that userland-only AsyncResources cause a destroy event to
// be emitted when they get gced.

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');

const destroyedIds = new Set();
async_hooks.createHook({
  destroy: common.mustCallAtLeast((asyncId) => {
    destroyedIds.add(asyncId);
  }, 1)
}).enable();

let asyncId = null;
{
  const res = new async_hooks.AsyncResource('foobar');
  asyncId = res.asyncId();
}

setImmediate(() => {
  global.gc();
  setImmediate(() => assert.ok(destroyedIds.has(asyncId)));
});
'use strict';

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');

const id_obj = {};
let collect = true;

const hook = async_hooks.createHook({
  before(id) { if (collect) id_obj[id] = true; },
  after(id) { delete id_obj[id]; },
}).enable();

process.once('uncaughtException', common.mustCall((er) => {
  assert.strictEqual(er.message, 'bye');
  collect = false;
}));

setImmediate(common.mustCall(() => {
  process.nextTick(common.mustCall(() => {
    assert.strictEqual(Object.keys(id_obj).length, 0);
    hook.disable();
  }));

  // Create a stack of async ids that will need to be emitted in the case of
  // an uncaught exception.
  const ar1 = new async_hooks.AsyncResource('Mine');
  ar1.emitBefore();

  const ar2 = new async_hooks.AsyncResource('Mine');
Example #10
0
const asyncHook = createHook({
  init(asyncId, type, triggerAsyncId, resource) {
    if (process.domain !== null && process.domain !== undefined) {
      // If this operation is created while in a domain, let's mark it
      pairing.set(asyncId, process.domain[kWeak]);
      Object.defineProperty(resource, 'domain', {
        configurable: true,
        enumerable: false,
        value: process.domain,
        writable: true
      });
    }
  },
  before(asyncId) {
    const current = pairing.get(asyncId);
    if (current !== undefined) { // Enter domain for this cb
      // We will get the domain through current.get(), because the resource
      // object's .domain property makes sure it is not garbage collected.
      current.get().enter();
    }
  },
  after(asyncId) {
    const current = pairing.get(asyncId);
    if (current !== undefined) { // Exit domain for this cb
      current.get().exit();
    }
  },
  destroy(asyncId) {
    pairing.delete(asyncId); // cleaning up
  }
});
 assert.throws(() => {
   async_hooks.createHook({ [field]: badArg });
 }, common.expectsError({
Example #12
0
'use strict';

const common = require('../common');
const async_hooks = require('async_hooks');
const fs = require('fs');

const nestedHook = async_hooks.createHook({
  init: common.mustNotCall()
});
let nestedCall = false;

async_hooks.createHook({
  init: common.mustCall(() => {
    nestedHook.enable();
    if (!nestedCall) {
      nestedCall = true;
      fs.access(__filename, common.mustCall());
    }
  }, 2)
}).enable();

fs.access(__filename, common.mustCall());
// Test async-hooks fired on right
// asyncIds & triggerAsyncId for async-await
'use strict';

require('../common');
const async_hooks = require('async_hooks');
const assert = require('assert');

const asyncIds = [];
async_hooks.createHook({
  init: (asyncId, type, triggerAsyncId) => {
    asyncIds.push([triggerAsyncId, asyncId]);
  }
}).enable();

async function main() {
  await null;
}

main().then(() => {
  // Verify the relationships between async ids
  // 1 => 2, 2 => 3 etc
  assert.strictEqual(asyncIds[0][1], asyncIds[1][0]);
  assert.strictEqual(asyncIds[0][1], asyncIds[3][0]);
  assert.strictEqual(asyncIds[1][1], asyncIds[2][0]);
});
Example #14
0
'use strict';

const common = require('../../common');
const assert = require('assert');
const async_hooks = require('async_hooks');
const binding = require(`./build/${common.buildType}/binding`);

// Baseline to make sure the internal field isn't being set.
assert.strictEqual(
  binding.getPromiseField(Promise.resolve(1)),
  0,
  'Promise internal field used despite missing enabled AsyncHook');

const hook0 = async_hooks.createHook({}).enable();

// Check that no PromiseWrap is created when there are no hook callbacks.
assert.strictEqual(
  binding.getPromiseField(Promise.resolve(1)),
  0,
  'Promise internal field used despite missing enabled AsyncHook');

hook0.disable();

let pwrap = null;
const hook1 = async_hooks.createHook({
  init(id, type, tid, resource) {
    pwrap = resource;
  }
}).enable();

// Check that the internal field returns the same PromiseWrap passed to init().

process.on('beforeExit', common.mustCall(() => {
  process.removeAllListeners('uncaughtException');
  hooks.disable();
  assert.strictEqual(typeof call_id, 'number');
  assert.deepStrictEqual(call_log, [1, 1, 1, 1]);
}));


hooks = async_hooks.createHook({
  init(id, type) {
    if (type === 'RANDOMBYTESREQUEST')
      call_id = id;
  },
  before(id) {
    if (id === call_id) call_log[0]++;
  },
  after(id) {
    if (id === call_id) call_log[3]++;
  },
}).enable();


process.on('uncaughtException', common.mustCall(() => {
  assert.strictEqual(call_id, async_hooks.executionAsyncId());
  call_log[2]++;
}));


require('crypto').randomBytes(1, common.mustCall(() => {
  assert.strictEqual(call_id, async_hooks.executionAsyncId());
'use strict';

// This tests that AsyncResource throws an error if bad parameters are passed

const common = require('../common');
const async_hooks = require('async_hooks');
const { AsyncResource } = async_hooks;

// Setup init hook such parameters are validated
async_hooks.createHook({
  init() {}
}).enable();

common.expectsError(() => {
  return new AsyncResource();
}, {
  code: 'ERR_INVALID_ARG_TYPE',
  type: TypeError,
});

common.expectsError(() => {
  new AsyncResource('');
}, {
  code: 'ERR_ASYNC_TYPE',
  type: TypeError,
});

common.expectsError(() => {
  new AsyncResource('type', -4);
}, {
  code: 'ERR_INVALID_ASYNC_ID',
    return;
  if (p_er !== null)
    throw p_er;
  // Expecint exactly 2 PROMISE types to reach init.
  assert.strictEqual(p_inits, EXPECTED_INITS);
});

const mustCallInit = common.mustCall(function init(id, type, tid, resource) {
  if (type !== 'PROMISE')
    return;
  p_inits++;
  p_resource = resource.promise;
}, EXPECTED_INITS);

const hook = async_hooks.createHook({
  init: mustCallInit
// Enable then disable to test whether disable() actually works.
}).enable().disable().disable();

new Promise(common.mustCall((res) => {
  res(42);
})).then(common.mustCall((val) => {
  hook.enable().enable();
  const p = new Promise((res) => res(val));
  assert.strictEqual(p, p_resource);
  hook.disable();
  return p;
})).then(common.mustCall((val2) => {
  hook.enable();
  const p = new Promise((res) => res(val2));
  hook.disable();
  return p;
'use strict'

var benchmark = require('../lib/benchmark')

var suite = benchmark.createBenchmark({
  name: 'async hooks',
  async: true,
  fn: runBenchmark
})

var asyncHooks = require('async_hooks')
var noopHook = asyncHooks.createHook({
  init: function() {},
  before: function() {},
  after: function() {},
  destroy: function() {}
})

var tests = [
  {name: 'no agent, no hooks'},
  {
    name: 'no agent, noop async hooks',
    before: function registerHook() {
      noopHook.enable()
    },
    after: function deregisterHook() {
      noopHook.disable()
    }
  },
  {
    name: 'instrumentation',
if (!common.isMainThread)
  common.skip('Worker bootstrapping works differently -> different timing');

const async_hooks = require('async_hooks');

const seenEvents = [];

const p = new Promise((resolve) => resolve(1));
p.then(() => seenEvents.push('then'));

const hooks = async_hooks.createHook({
  init: common.mustNotCall(),

  before: common.mustCall((id) => {
    assert.ok(id > 1);
    seenEvents.push('before');
  }),

  after: common.mustCall((id) => {
    assert.ok(id > 1);
    seenEvents.push('after');
    hooks.disable();
  })
});

setImmediate(() => {
  assert.deepStrictEqual(seenEvents, ['before', 'then', 'after']);
});

hooks.enable(); // After `setImmediate` in order to not catch its init event.
Example #20
0
const hook_result = {
  id: null,
  init_called: false,
  before_called: false,
  after_called: false,
  destroy_called: false,
};
const test_hook = async_hooks.createHook({
  init: (id, type) => {
    if (type === 'test') {
      hook_result.id = id;
      hook_result.init_called = true;
    }
  },
  before: (id) => {
    if (id === hook_result.id) hook_result.before_called = true;
  },
  after: (id) => {
    if (id === hook_result.id) hook_result.after_called = true;
  },
  destroy: (id) => {
    if (id === hook_result.id) hook_result.destroy_called = true;
  },
});

test_hook.enable();
makeCallback(process, function() {});

assert.strictEqual(hook_result.init_called, true);
assert.strictEqual(hook_result.before_called, true);
assert.strictEqual(hook_result.after_called, true);
Example #21
0
    return (!name || (name !== 'async_hooks.js' && name !== 'internal/async_hooks.js'));
  });
});

chain.extend.attach(function (error, frames) {
  const lastTrace = traces.get(asyncHook.executionAsyncId());
  frames.push.apply(frames, lastTrace);
  return frames;
});

//
// Track handle objects
//
const hooks = asyncHook.createHook({
  init: asyncInit,
  before: asyncBefore,
  after: asyncAfter,
  destroy: asyncDestroy
});
hooks.enable();

function getCallSites(skip) {
  const limit = Error.stackTraceLimit;

  Error.stackTraceLimit = limit + skip;
  const stack = chain.callSite({
    extend: false,
    filter: true,
    slice: skip
  });
  Error.stackTraceLimit = limit;
Example #22
0
// https://gist.github.com/boneskull/7fe75b63d613fa940db7ec990a5f5843
'use strict';

const {createHook} = require('async_hooks');
const {stackTraceFilter} = require('mocha/lib/utils');
const allResources = new Map();

// this will pull Mocha internals out of the stacks
const filterStack = stackTraceFilter();

const hook = createHook({
  init(asyncId, type, triggerAsyncId) {
    allResources.set(asyncId, {type, triggerAsyncId, stack: (new Error()).stack});
  },
  destroy(asyncId) {
    allResources.delete(asyncId);
  }
}).enable();

global.asyncDump = module.exports = () => {
  hook.disable();
  console.error(`STUFF STILL IN THE EVENT LOOP:`)
  allResources.forEach(value=> {
    console.error(`Type: ${value.type}`);
    console.error(filterStack(value.stack));
    console.error('\n');
  });
};
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);
  }
});
Example #24
0
File: test.js Project: asbeane/node
let before = 0;
let after = 0;
let destroy = 0;

async_hooks.createHook({
  init(id, type, triggerAsyncId, resource) {
    assert.strictEqual(typeof id, 'number');
    assert.strictEqual(typeof resource, 'object');
    assert(id > 1);
    if (type === 'foobär') {
      assert.strictEqual(resource.kObjectTag, kObjectTag);
      assert.strictEqual(triggerAsyncId, expectedTriggerId);
      bindingUids.push(id);
    }
  },

  before(id) {
    if (bindingUids.includes(id)) before++;
  },

  after(id) {
    if (bindingUids.includes(id)) after++;
  },

  destroy(id) {
    if (bindingUids.includes(id)) destroy++;
  }
}).enable();

for (const call of [binding.callViaFunction,
                    binding.callViaString,
                    binding.callViaUtf8Name]) {
 assert.throws(() => {
   async_hooks.createHook({ [field]: badArg });
 }, new RegExp(`^TypeError: ${field} must be a function$`));
Example #26
0
    	parentID = asyncId;

    	//Because the order of creating callbacks is not the same as
    	//the order in which these callbacks are executed, a timeline
    	//can be kept
    	timeline.push({"ID": asyncId, "start": process.hrtime()[1]});
	},

	after(asyncId) 
	{
		//Duration can be computed
		timeline[timeline.length - 1]["end"] = process.hrtime()[1];
	}
}

var AsyncHook = async_hooks.createHook(handlers);
AsyncHook.enable();


function printasyncCallbacks(){
  console.log(asyncCallbacks);
}

function get_tree( asyncCallbacks ) {
  var tree = { 0:{} }
  get_tree_helper(asyncCallbacks, tree[0],  0 );
  return tree;
}

function get_tree_helper(asyncCallbacks, tree, prevParent ) {
    for (var j = 0; j < asyncCallbacks.length; j++){
'use strict';

// Regression test for https://github.com/nodejs/node/issues/13262

const common = require('../common');
const assert = require('assert');
const async_hooks = require('async_hooks');

if (!common.isMainThread)
  common.skip('Worker bootstrapping works differently -> different async IDs');

let seenId, seenResource;

async_hooks.createHook({
  init: common.mustCall((id, provider, triggerAsyncId, resource) => {
    seenId = id;
    seenResource = resource;
    assert.strictEqual(provider, 'Immediate');
    assert.strictEqual(triggerAsyncId, 1);
  }),
  before: common.mustNotCall(),
  after: common.mustNotCall(),
  destroy: common.mustCall((id) => {
    assert.strictEqual(seenId, id);
  })
}).enable();

const immediate = setImmediate(common.mustNotCall());
assert.strictEqual(immediate, seenResource);
clearImmediate(immediate);