JavaScript attempt at an aspect oriented logger using proxies and reflect

The name of the pictureThe name of the pictureThe name of the pictureClash 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?







share|improve this question

























    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?







    share|improve this question





















      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?







      share|improve this question











      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?









      share|improve this question










      share|improve this question




      share|improve this question









      asked Jul 11 at 14:19









      Jarede

      199116




      199116

























          active

          oldest

          votes











          Your Answer




          StackExchange.ifUsing("editor", function ()
          return StackExchange.using("mathjaxEditing", function ()
          StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
          StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
          );
          );
          , "mathjax-editing");

          StackExchange.ifUsing("editor", function ()
          StackExchange.using("externalEditor", function ()
          StackExchange.using("snippets", function ()
          StackExchange.snippets.init();
          );
          );
          , "code-snippets");

          StackExchange.ready(function()
          var channelOptions =
          tags: "".split(" "),
          id: "196"
          ;
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function()
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled)
          StackExchange.using("snippets", function()
          createEditor();
          );

          else
          createEditor();

          );

          function createEditor()
          StackExchange.prepareEditor(
          heartbeatType: 'answer',
          convertImagesToLinks: false,
          noModals: false,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: null,
          bindNavPrevention: true,
          postfix: "",
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          );



          );








           

          draft saved


          draft discarded


















          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



































          active

          oldest

          votes













          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes










           

          draft saved


          draft discarded


























           


          draft saved


          draft discarded














          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













































































          Popular posts from this blog

          Chat program with C++ and SFML

          Function to Return a JSON Like Objects Using VBA Collections and Arrays

          Will my employers contract hold up in court?