AJS_Logger User-Guide

Applying LogDefs

As with AJS_Validator and AJS_ODL, LogDefs can be applied to methods in two ways. The immediate way is to use the applyLogDef method of a given logger-object, which accepts two arguments: a reference to an object to which the LoadDef in question should be applied – the MethodOwner – and the LogDef object itself. The logger will then use the AJS object to attach a prefix- and suffix-function to each of the methods nominated in the LogDef (or all methods, in the absence of a MethodNames property).

Following application of the logging-affixes to the appropriate methods in the object, all calls to those methods cause the prefix to execute automatically and transparently first, causing that event to be recorded to the log. Similarly, on return from the method, the suffix executes (equally transparently, from the application's point of view), and writes that event to the log. Note that any preLogger and postLogger defined by the LogDef are also executed as part of this process – see the Pre- and Post-Loggers page for precise details.

Example 5 demonstrates the effect of applying a LogDef to the three methods of MyObj and then calling each of those methods.

Note that if a given MethodNames property does not refer to a function-property of the MethodOwner, then the AJS_DefMgr object that the logger in question uses will throw call its exception handler, passing an appropriate message. This will occur even in the absence of AJS_Logger.val.js.

Contents Applying LogDefs
LogDef Queues
Suspension and Resumption
LogDefs and Constructors

 // -- Example 5 --------------------------------------------------------------

 var Logger     = createLogger ();  // Assume createLogger has been instantiated
                                    // as shown in Examples 2 or 4.
 var MyObj      =
    {
    method_A    : function () { },
    method_B    : function () { },
    method_C    : function () { }
    };

 var MyLogDef   =
    {
    MethodNames :
       [
       "method_A",
       "method_C"
       ]

    };

 Logger.applyLogDef (MyObj, MyLogDef);

 MyObj .method_A    ();
 MyObj .method_B    ();
 MyObj .method_C    ();

 -- Output --------------------------------------------------------------------

 method_A Entry
 method_A Exit
 method_C Entry
 method_C Exit
      

Note too that you do not have to name your LogDefs and then pass them to applyLogDef (or pushLogDef – explored below) in two steps. You can simplify your code, and de-clutter the namespace too by defining LogDefs 'inline' in your calls to a logger's methods. Given this, Example 6 re-presents a section of the code in Example 5 in such a fashion (which many of the examples in this guide use).


 // -- Example 6 --------------------------------------------------------------

 Logger.applyLogDef (MyObj,
    {
    MethodNames :
       [
       "method_A",
       "method_C"
       ]

    });
      

LogDef Queues

The second way of applying LogDefs involves the use of the pushLogDef method. This also accepts two arguments, which are the MethodOwner, and the LogDef that should be applied to that object's methods; and it adds the LogDef to an internal queue, where it remains until a subsequent call to the applyLogDefQueue method. A call to that method then applies each LogDef to its respective object in the order in which the LogDefs were pushed onto the queue, emptying the queue as it does.

Example 7 demonstrates the use of pushLogDef and applyLogDefQueue.

Note that the issues that apply to LogDef queues are identical to those that apply to ValidationDef- and LoadDef-queues, and so you should read the section on definition queues in the Technical Overview page for information on these important points.

Note also that application of a given LogDef, to the same method of the same method-owner through the same logger is disallowed, although you can apply the same LogDef to the same method through different loggers, and this idea is explored after the sections on streams.


 // -- Example 7 --------------------------------------------------------------

 var Logger     = createLogger ();

 var MyObj      =
    {
    someMethod  : function () { },
    };

 var MyOtherObj =
    {
    SomeOtherMethod : function () { },
    };

 // -------------------------------------

 Logger    .pushLogDef       (MyObj,      { });
 Logger    .pushLogDef       (MyOtherObj, { });

 Logger    .applyLogDefQueue ();

 MyObj     .someMethod       ();
 MyOtherObj.SomeOtherMethod  ();


 -- Output --------------------------------------------------------------------

 someMethod Entry
 someMethod Exit
 SomeOtherMethod Entry
 SomeOtherMethod Exit
      

Suspension and Resumption

As with AJS_Validator, you can suspend the behaviour of a given logger object by calling that object's suspend method. That is to say, by calling MyLogger.suspend, calling applyLogDef, pushLogDef and applyLogDefQueue on that object subsequently will have no effect. This extends to any LogDefs that have already been applied to methods in the application via that logger, which is to say that, following a call to suspend, the execution of methods that are subject normally to logging will not be logged, nor will their Pre- and Post-Loggers execute.

The complimentary method, resume, reverses the action of suspend, such that calling MyLogger.resume subsequent to a call to suspend on that object, will reinstate that object's logging-behaviour along with the execution of any Pre- and Post-Loggers in the LogDefs that have been applied through that object.

You can suspend and resume the action of a given logger as many times as you want during a run of the application concerned. Note also that calling suspend a second or third time etc. on a given logger before calling resume has no effect, nor do similarly-repeated calls to resume. That is to say that suspend and resume do not exhibit 'stack-like' or 'push-down/pop-up' behaviour where, say, three calls to suspend require three complimentary calls to resume to cause the logger in question to resume normal operation.

Example 8 shows suspend and resume in action.


 // -- Example 8 --------------------------------------------------------------

 var Logger  = createLogger ();

 var MyObj   =
    {
    method_A : function () { },
    };

 Logger.applyLogDef (MyObj, { });

 MyObj .method_A    ();

 Logger.suspend     ();

 MyObj .method_A    ();

 Logger.resume      ();

 MyObj .method_A    ();

 -- Output --------------------------------------------------------------------

 method_A Entry
 method_A Exit
 method_A Entry
 method_A Exit
      

LogDefs and Constructors

Note that you can apply a LogDef to any method in an application, other than constructors. The AJS-object user guide goes into this in depth, but to summarise here: applying a LogDef to a constructor will work in terms of logging method-entry and -exit, but the reference returned to the constructor's caller will not point to the new object but will be a reference to the proxy-function that the AJS object emplaced when the LogDef was applied.

This means that using AJS_Logger to log constructor calls directly will cause working code to fail. Given this, and as the AJS-object user guide states, the (somewhat awkward) solution in this case is to wrap the call to a given constructor in a forwarding-method and to apply the LogDef to that.