how can I log every method call in node.js without adding debug lines everywhere?

前端 未结 3 692
栀梦
栀梦 2021-02-08 03:00

I would like to log the user_id of the person making a request and the method name of every method called for a javascript class. For example:

35 - log_in
35 -          


        
相关标签:
3条回答
  • 2021-02-08 03:22

    This is one alternative, not entirely sure how reliable it is though, it feels a bit wrong:

    (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;
    })();
    

    As you can see, it overwrites the call function - this creates a slight problem when you try to call console.log() so you need to swap the function back. But it seems to work!

    EDIT

    Since this is tagged 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
    
    0 讨论(0)
  • 2021-02-08 03:23

    I'm guessing this is a web app, in which case if you are using connect you can use a logger middleware that logs the user and the URL path, which is probably sufficient. Otherwise, you are going to have to do some metaprogramming along the lines of wrapping each function in a wrapper function to do the logging.

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

    For this to work, your class method's must be named functions, not anonymous.

    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
    }
    
    0 讨论(0)
  • 2021-02-08 03:28

    The answer is essentially correct, but here's how to avoid infinite recursion

    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
    
    0 讨论(0)
提交回复
热议问题