views:

108

answers:

3

I want to wrap every function call with some logging code. Something that would produce output like:

func1(param1, param2)
func2(param1)
func3()
func4(param1, param2)

Ideally, I would like an API of the form:

function globalBefore(func);
function globalAfter(func);

I've googled quite a bit for this, but it seems like there's only aspect-oriented solutions that require you to wrap the specific functions you want to log, or whatever. I want something that applies to every function in the global scope (except itself, obviously).

A: 

Maybe you could have a function to which you pass the function to execute as a parameter:

function runner(func_to_run) {
    alert('about to run ' + func_to_run.name);

    func_to_run();

}

function test() {
    alert ('in test');
}

runner(test)
jira
A: 

jquery-aop might do the trick?

Nils Weinander
+2  A: 

A simple approach would be something like this

var functionPool = {} // create a variable to hold the original versions of the functions

for( var func in window ) // scan all items in window scope
{
  if (typeof(window[func]) === 'function') // if item is a function
  {
    functionPool[func] = window[func]; // store the original to our global pool
    (function(){ // create an closure to maintain function name
         var functionName = func;
         window[functionName] = function(){ // overwrite the function with our own version
         var args = [].splice.call(arguments,0); // convert arguments to array
         // do the logging before callling the method
         console.log('logging: ' + functionName + '('+args.join(',')+')');
         // call the original method but in the window scope, and return the results
         return functionPool[functionName].apply(window, args );
         // additional logging could take place here if we stored the return value ..
        }
      })();
  }
}

To undo you would need to run the

for (func in functionPool)
  window[func] = functionPool[func];

Notes
This handles only global functions, but you can easily extend it to handle specific objects or methods etc..

Gaby
Pretty sweet, this is more than enough to get me started. Thanks!
blake8086
@blake, you are welcome..
Gaby
If you define your Globally scoped functions as `function myFunction() { ... }` or `var myFunction = function() { ... }`, this won't work in IE8 or below (but it does in IE9 beta!) because they won't be enumerated. For this to work in IE8 or below, you'll need to define your functions instead as `this.myFunction = function() { ... }` or `window.myFunction = function() { ... }`.
gilly3
@gilly, thanks for the heads-up. I was not aware of this, and it is good to know ..
Gaby