JavaScript attempt at an aspect oriented logger using proxies and reflect
Clash Royale CLAN TAG#URR8PPP
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;
up vote
2
down vote
favorite
I've been playing around with AOP in JavaScript to create a Logger that I can attach to classes and output what is going on (mainly instantiation, calling of functions and the results from functions). I've done this by creating a static class (static method in a class) that essentially is a factory that uses a proxy to trap the instantiation of a class (or just a function) and applies another proxy to the instantiated class to capture function calls on that class.
Beyond sanity/standards checking what I've written, I must admit I haven't come up with better tests than checking to make sure it instantiates a class correctly and that any function called on a class will return the expected results. I'd be interested to know of better ways of testing this.
I've had to tell it that it shouldn't try and apply itself, due to it being a static class and my not wanting to instantiate itself.
it takes an eventEmitter
object as the first argument that should have a method of publish accepting at least a string.
class Logger
static ClassHandler(eventEmitter, obj)
const InstanceHandler =
get(target, prop, receiver)
eventEmitter.publish(`$prop called on $target.constructor.name`);
const orig = Reflect.get(target, prop, receiver);
if (typeof orig == "function" &&
prop !== 'Logger')
return function (...args)
eventEmitter.publish(`Method $prop called with $JSON.stringify(args)`);
let result = orig.apply(this, args);
eventEmitter.publish(`Result from $prop is: $JSON.stringify(result)`);
return result;
;
else
return orig;
const handler =
construct(target, args)
eventEmitter.publish(`$target.name instantiated`);
const instance = Reflect.construct(...arguments);
return new Proxy(instance, InstanceHandler);
,
apply(target, thisArg, argumentsList)
eventEmitter.publish(`$target.name called with with $JSON.stringify(argumentsList)`);
const result = Reflect.apply(...arguments);
eventEmitter.publish(`Result from $target.name is: $JSON.stringify(result)`);
return result;
,
return new Proxy(obj, handler);
module.exports = Logger;
So to use it, something like this:
SimpleClass.js
class SimpleClass
constructor()
shoutOut()
return 'hello!';
returnValue(value)
return value;
module.exports = SimpleClass;
Publisher.js
class Publisher
constructor()
publish(event)
console.log(event);
module.exports = Publisher;
index.js
const Logger = require('Logger');
const Publisher = require('Publisher');
const publisher = new Publisher();
const SimpleClass = Logger.ClassHandler(publisher, require('SimpleClass'));
const simpleClass = new SimpleClass();
simpleClass.shoutOut();
this is it at it's most simple and should produce the output:
SimpleClass instantiated
shoutOut called on SimpleClass
if you then called the returnValue('hi there')
method you'd get;
SimpleClass instantiated
returnValue called on SimpleClass
Method returnValue called with ["hi there"]
Result from returnValue is: "hi there"
How can i better test this? Can I improve my Logger at all? Have I done the right thing with Proxies and Reflect?
javascript object-oriented ecmascript-6 proxy aspect-oriented
add a comment |Â
up vote
2
down vote
favorite
I've been playing around with AOP in JavaScript to create a Logger that I can attach to classes and output what is going on (mainly instantiation, calling of functions and the results from functions). I've done this by creating a static class (static method in a class) that essentially is a factory that uses a proxy to trap the instantiation of a class (or just a function) and applies another proxy to the instantiated class to capture function calls on that class.
Beyond sanity/standards checking what I've written, I must admit I haven't come up with better tests than checking to make sure it instantiates a class correctly and that any function called on a class will return the expected results. I'd be interested to know of better ways of testing this.
I've had to tell it that it shouldn't try and apply itself, due to it being a static class and my not wanting to instantiate itself.
it takes an eventEmitter
object as the first argument that should have a method of publish accepting at least a string.
class Logger
static ClassHandler(eventEmitter, obj)
const InstanceHandler =
get(target, prop, receiver)
eventEmitter.publish(`$prop called on $target.constructor.name`);
const orig = Reflect.get(target, prop, receiver);
if (typeof orig == "function" &&
prop !== 'Logger')
return function (...args)
eventEmitter.publish(`Method $prop called with $JSON.stringify(args)`);
let result = orig.apply(this, args);
eventEmitter.publish(`Result from $prop is: $JSON.stringify(result)`);
return result;
;
else
return orig;
const handler =
construct(target, args)
eventEmitter.publish(`$target.name instantiated`);
const instance = Reflect.construct(...arguments);
return new Proxy(instance, InstanceHandler);
,
apply(target, thisArg, argumentsList)
eventEmitter.publish(`$target.name called with with $JSON.stringify(argumentsList)`);
const result = Reflect.apply(...arguments);
eventEmitter.publish(`Result from $target.name is: $JSON.stringify(result)`);
return result;
,
return new Proxy(obj, handler);
module.exports = Logger;
So to use it, something like this:
SimpleClass.js
class SimpleClass
constructor()
shoutOut()
return 'hello!';
returnValue(value)
return value;
module.exports = SimpleClass;
Publisher.js
class Publisher
constructor()
publish(event)
console.log(event);
module.exports = Publisher;
index.js
const Logger = require('Logger');
const Publisher = require('Publisher');
const publisher = new Publisher();
const SimpleClass = Logger.ClassHandler(publisher, require('SimpleClass'));
const simpleClass = new SimpleClass();
simpleClass.shoutOut();
this is it at it's most simple and should produce the output:
SimpleClass instantiated
shoutOut called on SimpleClass
if you then called the returnValue('hi there')
method you'd get;
SimpleClass instantiated
returnValue called on SimpleClass
Method returnValue called with ["hi there"]
Result from returnValue is: "hi there"
How can i better test this? Can I improve my Logger at all? Have I done the right thing with Proxies and Reflect?
javascript object-oriented ecmascript-6 proxy aspect-oriented
add a comment |Â
up vote
2
down vote
favorite
up vote
2
down vote
favorite
I've been playing around with AOP in JavaScript to create a Logger that I can attach to classes and output what is going on (mainly instantiation, calling of functions and the results from functions). I've done this by creating a static class (static method in a class) that essentially is a factory that uses a proxy to trap the instantiation of a class (or just a function) and applies another proxy to the instantiated class to capture function calls on that class.
Beyond sanity/standards checking what I've written, I must admit I haven't come up with better tests than checking to make sure it instantiates a class correctly and that any function called on a class will return the expected results. I'd be interested to know of better ways of testing this.
I've had to tell it that it shouldn't try and apply itself, due to it being a static class and my not wanting to instantiate itself.
it takes an eventEmitter
object as the first argument that should have a method of publish accepting at least a string.
class Logger
static ClassHandler(eventEmitter, obj)
const InstanceHandler =
get(target, prop, receiver)
eventEmitter.publish(`$prop called on $target.constructor.name`);
const orig = Reflect.get(target, prop, receiver);
if (typeof orig == "function" &&
prop !== 'Logger')
return function (...args)
eventEmitter.publish(`Method $prop called with $JSON.stringify(args)`);
let result = orig.apply(this, args);
eventEmitter.publish(`Result from $prop is: $JSON.stringify(result)`);
return result;
;
else
return orig;
const handler =
construct(target, args)
eventEmitter.publish(`$target.name instantiated`);
const instance = Reflect.construct(...arguments);
return new Proxy(instance, InstanceHandler);
,
apply(target, thisArg, argumentsList)
eventEmitter.publish(`$target.name called with with $JSON.stringify(argumentsList)`);
const result = Reflect.apply(...arguments);
eventEmitter.publish(`Result from $target.name is: $JSON.stringify(result)`);
return result;
,
return new Proxy(obj, handler);
module.exports = Logger;
So to use it, something like this:
SimpleClass.js
class SimpleClass
constructor()
shoutOut()
return 'hello!';
returnValue(value)
return value;
module.exports = SimpleClass;
Publisher.js
class Publisher
constructor()
publish(event)
console.log(event);
module.exports = Publisher;
index.js
const Logger = require('Logger');
const Publisher = require('Publisher');
const publisher = new Publisher();
const SimpleClass = Logger.ClassHandler(publisher, require('SimpleClass'));
const simpleClass = new SimpleClass();
simpleClass.shoutOut();
this is it at it's most simple and should produce the output:
SimpleClass instantiated
shoutOut called on SimpleClass
if you then called the returnValue('hi there')
method you'd get;
SimpleClass instantiated
returnValue called on SimpleClass
Method returnValue called with ["hi there"]
Result from returnValue is: "hi there"
How can i better test this? Can I improve my Logger at all? Have I done the right thing with Proxies and Reflect?
javascript object-oriented ecmascript-6 proxy aspect-oriented
I've been playing around with AOP in JavaScript to create a Logger that I can attach to classes and output what is going on (mainly instantiation, calling of functions and the results from functions). I've done this by creating a static class (static method in a class) that essentially is a factory that uses a proxy to trap the instantiation of a class (or just a function) and applies another proxy to the instantiated class to capture function calls on that class.
Beyond sanity/standards checking what I've written, I must admit I haven't come up with better tests than checking to make sure it instantiates a class correctly and that any function called on a class will return the expected results. I'd be interested to know of better ways of testing this.
I've had to tell it that it shouldn't try and apply itself, due to it being a static class and my not wanting to instantiate itself.
it takes an eventEmitter
object as the first argument that should have a method of publish accepting at least a string.
class Logger
static ClassHandler(eventEmitter, obj)
const InstanceHandler =
get(target, prop, receiver)
eventEmitter.publish(`$prop called on $target.constructor.name`);
const orig = Reflect.get(target, prop, receiver);
if (typeof orig == "function" &&
prop !== 'Logger')
return function (...args)
eventEmitter.publish(`Method $prop called with $JSON.stringify(args)`);
let result = orig.apply(this, args);
eventEmitter.publish(`Result from $prop is: $JSON.stringify(result)`);
return result;
;
else
return orig;
const handler =
construct(target, args)
eventEmitter.publish(`$target.name instantiated`);
const instance = Reflect.construct(...arguments);
return new Proxy(instance, InstanceHandler);
,
apply(target, thisArg, argumentsList)
eventEmitter.publish(`$target.name called with with $JSON.stringify(argumentsList)`);
const result = Reflect.apply(...arguments);
eventEmitter.publish(`Result from $target.name is: $JSON.stringify(result)`);
return result;
,
return new Proxy(obj, handler);
module.exports = Logger;
So to use it, something like this:
SimpleClass.js
class SimpleClass
constructor()
shoutOut()
return 'hello!';
returnValue(value)
return value;
module.exports = SimpleClass;
Publisher.js
class Publisher
constructor()
publish(event)
console.log(event);
module.exports = Publisher;
index.js
const Logger = require('Logger');
const Publisher = require('Publisher');
const publisher = new Publisher();
const SimpleClass = Logger.ClassHandler(publisher, require('SimpleClass'));
const simpleClass = new SimpleClass();
simpleClass.shoutOut();
this is it at it's most simple and should produce the output:
SimpleClass instantiated
shoutOut called on SimpleClass
if you then called the returnValue('hi there')
method you'd get;
SimpleClass instantiated
returnValue called on SimpleClass
Method returnValue called with ["hi there"]
Result from returnValue is: "hi there"
How can i better test this? Can I improve my Logger at all? Have I done the right thing with Proxies and Reflect?
javascript object-oriented ecmascript-6 proxy aspect-oriented
asked Jul 11 at 14:19
Jarede
199116
199116
add a comment |Â
add a comment |Â
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
active
oldest
votes
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f198292%2fjavascript-attempt-at-an-aspect-oriented-logger-using-proxies-and-reflect%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password