如何在node.js中记录每个方法调用而无需在任何地方添加调试行?

时间:2013-04-08 21:57:45

标签: javascript node.js logging coffeescript

我想记录发出请求的人的user_id以及为javascript类调用的每个方法的方法名称。例如:

35 - log_in
35 - list_of_other_users
78 - log_in
35 - send_message_to_user
35 - connect_to_redis
78 - list_of_other_users

由于所有内容都是异步的,因此用户35和78可能会同时执行操作。所以我想确保每个日志行都以他们的user_id开头,这样我就可以为它而烦恼,并且一次只能看到一个用户的活动。

是否有一种超级聪明的方法可以在不向每个方法添加记录器语句的情况下执行此操作?

3 个答案:

答案 0 :(得分:7)

答案基本上是正确的,但这里有如何避免无限递归

<强>的Javascript

(function () {
  var oldCall = Function.prototype.call;
  var newCall = function(self) {
    Function.prototype.call = oldCall;
    console.log('Function called:', this.name);
    var args = Array.prototype.slice.call(arguments, 1);
    var res = this.apply(self, args);
    Function.prototype.call = newCall;
    return res
  }
  Function.prototype.call = newCall;
})();

<强>的CoffeeScript

do ->
  oldCall = Function::call
  newCall = (self) ->
    Function::call = oldCall
    console.log "Function called: #{this.name}"
    args = Array.prototype.slice.call arguments, 1
    res = this.apply self, args
    Function::call = newCall
    res
  Function::call = newCall

答案 1 :(得分:4)

这是另一种选择,但并不完全确定它有多可靠,但感觉有点不对劲:

(function () {
  var oldCall = Function.prototype.call;
  var newCall = function(self) {
    Function.prototype.call = oldCall;
    console.log('Function called:', this.name);
    var args = Array.prototype.slice.call(arguments, 1);
    Function.prototype.call = newCall;
    this.apply(self, args);
  }
  Function.prototype.call = newCall;
})();

如您所见,它会覆盖call函数 - 当您尝试调用console.log()时会产生轻微问题,因此需要重新交换函数。但它似乎有效!

修改

因为这是标记为CoffeeScript:

do ->
  oldCall = Function::call
  newCall = (self) ->
    Function::call = oldCall
    console.log "Function called: #{this.name}"
    args = Array.prototype.slice.call arguments, 1
    Function::call = newCall
    this.apply self, args
  Function::call = newCall

答案 2 :(得分:3)

我猜这是一个网络应用程序,在这种情况下,如果你使用连接,你可以使用记录用户和URL路径的记录器中间件,这可能就足够了。否则,你将不得不在包装函数中包装每个函数的行进行一些元编程来进行日志记录。

function logCall(realFunc, instance) {
    return function() {
      log.debug('User: ' + instance.user_id + ' method ' + realFunc.name);
      return realFunc.apply(instance, arguments);
    };
}

为此,您的类方法必须命名为函数,而不是匿名函数。

function sendMessage() {
    //code to send message
    //can use `this` to access instance properties
}
function MyClass(userId) {
    this.userId = userId; //or whatever
    this.sendMessage = logCall(sendMessage, this);
    //repeat above line for each instance method you want instrumented for logging
}