logging每个方法?

而不必为TRACE创build一个自定义的logging器,例如,按照什么方法被调用以及哪些类被实例化了,是否有一种简单的方法可以让所有的方法在一个类日志下面自行完成? 这是一个node.js应用程序。

class MyClass constructor: () -> console.log 'MyClass:constructor' doThat: () -> console.log 'MyClass:doThat' exports.MyClass = MyClass myClass = new MyClass() myClass.doThat() 

如果我有我的方式,你会看到4日志消息,而不是2(因此不得不写更less的代码来追踪发生的事情)。

我最近需要实现这样的事情来追踪一些复杂的OOrecursion的东西。 基本上,我想制定一个“可追溯”的方法而不会污染太多; 所以也许这个解决scheme也可以应用在这里。

首先,添加一个使其他函数可追踪的函数:

 Function::trace = do -> makeTracing = (ctorName, fnName, fn) -> (args...) -> console.log "#{ctorName}:#{fnName}" fn.apply @, args (arg) -> for own name, fn of arg @prototype[name] = makeTracing @name, name, fn 

然后,要使用它,只需在每个要跟踪的方法之前添加@trace

 class MyClass @trace methodA: -> @methodB 42 @trace methodB: -> console.log "method b called with #{n}" 

或者只添加@trace一次,然后将所有可追踪方法缩进一个级别:

 class MyClass @trace methodA: -> @methodB 42 methodB: (n) -> console.log "method b called with #{n}" 

正如你所看到的, trace是一种滥用CoffeeScript语法的东西。 method: -> 'foo'里面的class MyClass是解释一个方法的定义。 但@trace method: -> 'foo'被解释为调用MyClasstrace函数(这是一个Function实例,我们添加了trace函数),通过一个method键传递一个文本对象。 在JavaScript中它将是这样的this.trace({method: function() {return 'foo';}})

trace函数将只是采取该对象,并迭代它的键(方法名称)和值(方法),并添加函数到MyClass原型,logging他们的调用,并依次调用原始方法。

无论如何, (new MyClass).methodA()的输出将是:

 MyClass:methodA MyClass:methodB method b called with 42 

尽pipe这个解决scheme不适用于构造函数,因为它们不仅仅是普通的方法。

你可以很喜欢这个。 如果你愿意,你也可以logging传递给每个方法的参数,返回值,甚至为嵌套调用添加缩进(如果你需要debugging一个复杂的问题= D,那么结果跟踪会非常有用)。


更新:作为一个更有趣的例子,这里是一个典型的复合模式的例子,几何graphics和数字组的小版本: http : //jsfiddle.net/2YuE7/与一个更有趣的跟踪function。 所有的数字都明白move方法。 如果我们有这个综合数字,并呼吁:

 f = new Composite [ new Rectangle 5, 10, 3, 4 new Composite [ new Circle 0, 0, 2 new Circle 0, 0, 4 new Circle 0, 0, 6 ] ] f.move 2, 3 

跟踪输出是:

 (Composite[Rectangle[5,10,3,4],Composite[Circle[0,0,2],Circle[0,0,4],Circle[0,0,6]]]).move(2, 3) | (Rectangle[5,10,3,4]).move(2, 3) | -> Rectangle[7,13,3,4] | (Composite[Circle[0,0,2],Circle[0,0,4],Circle[0,0,6]]).move(2, 3) | | (Circle[0,0,2]).move(2, 3) | | -> Circle[2,3,2] | | (Circle[0,0,4]).move(2, 3) | | -> Circle[2,3,4] | | (Circle[0,0,6]).move(2, 3) | | -> Circle[2,3,6] | -> Composite[Circle[2,3,2],Circle[2,3,4],Circle[2,3,6]] -> Composite[Rectangle[7,13,3,4],Composite[Circle[2,3,2],Circle[2,3,4],Circle[2,3,6]]] 

如果你想用普通的javascript做这样的事情,我创build了一个服务,你可以传递一个对象,使用相同的API来logging每个方法。 请参阅http://jsfiddle.net/mcgraphix/pagkoLjb上应用的polyfill的完整示例

基本的想法是:

 var api = { notAMethod: "blah", foo: function() { console.log("in foo", arguments); }, bar: function(arg) { this.foo(arg); return this.notAMethod; } }; //wrap the api with a logging version //to watch property changes and keep them in sync, you need the polyfill for Object.watch // from https://gist.github.com/eligrey/384583 var createLogger = function(api) { var loggingApi = {}; for (var prop in api) { if (typeof api[prop] !== 'function') { loggingApi[prop] = api[prop]; loggingApi.watch(prop, function(prop, oldVal, newVal){ api[prop] = newVal return newVal; }); } else { loggingApi[prop] = function() { console.log(prop + "() called with args: ", arguments); var returnVal = api[prop].apply(api, arguments); console.log(prop + "() returned: " + returnVal); return returnVal; } } } return loggingApi; }; api.foo('Shhhh... don\'t log me') //no logging createLogger(api).foo(); //with logging