从 Node.js 中的模拟函数中跟踪调用链



我需要编写一个应该跟踪函数调用链的自动测试。在下面的示例中,函数称为 nativefn1nativefn2 。我无法更改他们的代码以使跟踪成为可能,因此我需要一些解决方法来应对这种情况。

var async = require('async')
nativefn1 = function(input, cb) {
  setTimeout(
    function() { cb(null,"<" + input + ">") },
    Math.floor(Math.random() * 1000)
  )
}
nativefn2 = function(input, cb) {
  setTimeout(
    function() { nativefn1(input, function(err,result) { cb(null,"<<" + result + ">>") } ) },
    Math.floor(Math.random() * 1000)
  )
}
var callchain_counter = 0
var debug_results = { "???": [] }
var original = {
  nativefn1: nativefn1,
  nativefn2: nativefn2,
}
nativefn2 = function(input, cb) {
  var callchain_number = callchain_counter++
  debug_results[callchain_number] = []
  debug_results[callchain_number].push("Callchain #" + callchain_number + ": nativefn2 call:", arguments)
  original.nativefn2(input,function(err,result) {
    debug_results[callchain_number].push("Callchain #" + callchain_number + ": nativefn2 call result:", arguments)
    cb(null,result)
  })
}
nativefn1 = function(input, cb) {
  var callchain_number = "???"
  debug_results[callchain_number].push("Callchain #" + callchain_number + ": nativefn1 call:", arguments)
  original.nativefn1(input,function(err,result) {
    debug_results[callchain_number].push("Callchain #" + callchain_number + ": nativefn1 call result:", arguments)
    cb(null,result)
  })
}
async.parallel(
  [
    function(done) { nativefn2("Lorem",done) },
    function(done) { nativefn2("ipsum",done) },
    function(done) { nativefn2("dolor",done) },
    function(done) { nativefn2("amet",done) },
    function(done) { nativefn2("sit",done) },
  ],
  function(err,result) {
    console.log(debug_results)
  }
)

执行时,此代码将打印如下debug_results

{ '0': 
   [ 'Callchain #0: nativefn2 call:',
     { '0': 'Lorem', '1': [Function] },
     'Callchain #0: nativefn2 call result:',
     { '0': null, '1': '<<<Lorem>>>' } ],
  '1': 
   [ 'Callchain #1: nativefn2 call:',
     { '0': 'ipsum', '1': [Function] },
     'Callchain #1: nativefn2 call result:',
     { '0': null, '1': '<<<ipsum>>>' } ],
  '2': 
   [ 'Callchain #2: nativefn2 call:',
     { '0': 'dolor', '1': [Function] },
     'Callchain #2: nativefn2 call result:',
     { '0': null, '1': '<<<dolor>>>' } ],
  '3': 
   [ 'Callchain #3: nativefn2 call:',
     { '0': 'amet', '1': [Function] },
     'Callchain #3: nativefn2 call result:',
     { '0': null, '1': '<<<amet>>>' } ],
  '4': 
   [ 'Callchain #4: nativefn2 call:',
     { '0': 'sit', '1': [Function] },
     'Callchain #4: nativefn2 call result:',
     { '0': null, '1': '<<<sit>>>' } ],
  '???': 
   [ 'Callchain #???: nativefn1 call:',
     { '0': 'ipsum', '1': [Function] },
     'Callchain #???: nativefn1 call result:',
     { '0': null, '1': '<ipsum>' },
     'Callchain #???: nativefn1 call:',
     { '0': 'Lorem', '1': [Function] },
     'Callchain #???: nativefn1 call:',
     { '0': 'amet', '1': [Function] },
     'Callchain #???: nativefn1 call:',
     { '0': 'dolor', '1': [Function] },
     'Callchain #???: nativefn1 call:',
     { '0': 'sit', '1': [Function] },
     'Callchain #???: nativefn1 call result:',
     { '0': null, '1': '<Lorem>' },
     'Callchain #???: nativefn1 call result:',
     { '0': null, '1': '<amet>' },
     'Callchain #???: nativefn1 call result:',
     { '0': null, '1': '<dolor>' },
     'Callchain #???: nativefn1 call result:',
     { '0': null, '1': '<sit>' } ] }

但是所有nativefn1电话都没有跟踪,因为我找不到一种方法将callchain_number从嘲笑nativefn2传递到嘲笑nativefn1。是否可以访问调用上下文或以某种方式创建一些额外的调用上下文以使其成为可能?必须并行调用函数。

我发现可以使用域来完成它,但由于域已被弃用,我想知道我应该用什么替换它们。

var async = require('async')
var domain = require('domain')
nativefn1 = function(input, cb) 
{
    setTimeout(
        function() { cb(null,"<" + input + ">") },
        Math.floor(Math.random() * 1000)
    )
}
nativefn2 = function(input, cb) 
{
    setTimeout(
        function() { nativefn1(input, function(err,result) { cb(null,"<<" + result + ">>") } ) },
        Math.floor(Math.random() * 1000)
    )
}
var context_counter = 0
var callchain_counter = 0
var debug_results = {}
var original = 
{
    nativefn1: nativefn1,
    nativefn2: nativefn2,
}
nativefn2 = function(input, cb) 
{
    var d = domain.create()
    var args = arguments
    d.callchain_number = callchain_counter++
    d.run(function()
    {
        debug_results[domain.active.callchain_number] = []
        debug_results[domain.active.callchain_number].push("Callchain #" + domain.active.callchain_number + ": nativefn2 call:", args)
        original.nativefn2(input,function(err,result) 
        {
            debug_results[domain.active.callchain_number].push("Callchain #" + domain.active.callchain_number + " nativefn2 call result:", arguments)
            cb(null,result)
        })
    })
}
nativefn1 = function(input, cb) 
{
    debug_results[domain.active.callchain_number].push("Callchain #" + domain.active.callchain_number + ": nativefn1 call:", arguments)
    original.nativefn1(input,function(err,result) 
    {
        debug_results[domain.active.callchain_number].push("Callchain #" + domain.active.callchain_number + ": nativefn1 call result:", arguments)    
        cb(null,result)
    })
}
async.parallel(
  [
    function(done) { nativefn2("Lorem",done) },
    function(done) { nativefn2("ipsum",done) },
    function(done) { nativefn2("dolor",done) },
    function(done) { nativefn2("amet",done) },
    function(done) { nativefn2("sit",done) },
  ],
  function(err,result) {
    console.log(debug_results)
  }
)

输出:

{ '0': 
   [ 'Callchain #0: nativefn2 call:',
     { '0': 'Lorem', '1': [Function] },
     'Callchain #0: nativefn1 call:',
     { '0': 'Lorem', '1': [Function] },
     'Callchain #0: nativefn1 call result:',
     { '0': null, '1': '<Lorem>' },
     'Callchain #0 nativefn2 call result:',
     { '0': null, '1': '<<<Lorem>>>' } ],
  '1': 
   [ 'Callchain #1: nativefn2 call:',
     { '0': 'ipsum', '1': [Function] },
     'Callchain #1: nativefn1 call:',
     { '0': 'ipsum', '1': [Function] },
     'Callchain #1: nativefn1 call result:',
     { '0': null, '1': '<ipsum>' },
     'Callchain #1 nativefn2 call result:',
     { '0': null, '1': '<<<ipsum>>>' } ],
  '2': 
   [ 'Callchain #2: nativefn2 call:',
     { '0': 'dolor', '1': [Function] },
     'Callchain #2: nativefn1 call:',
     { '0': 'dolor', '1': [Function] },
     'Callchain #2: nativefn1 call result:',
     { '0': null, '1': '<dolor>' },
     'Callchain #2 nativefn2 call result:',
     { '0': null, '1': '<<<dolor>>>' } ],
  '3': 
   [ 'Callchain #3: nativefn2 call:',
     { '0': 'amet', '1': [Function] },
     'Callchain #3: nativefn1 call:',
     { '0': 'amet', '1': [Function] },
     'Callchain #3: nativefn1 call result:',
     { '0': null, '1': '<amet>' },
     'Callchain #3 nativefn2 call result:',
     { '0': null, '1': '<<<amet>>>' } ],
  '4': 
   [ 'Callchain #4: nativefn2 call:',
     { '0': 'sit', '1': [Function] },
     'Callchain #4: nativefn1 call:',
     { '0': 'sit', '1': [Function] },
     'Callchain #4: nativefn1 call result:',
     { '0': null, '1': '<sit>' },
     'Callchain #4 nativefn2 call result:',
     { '0': null, '1': '<<<sit>>>' } ] }

最新更新