ZOOMZOOM

Augmented Exception Framework

This section contains the necessary components to set up a framework for augmented exceptions. Although this page does contain enough information to get started, it may be more easily understood (and definitely more useful) once one is familiar with setting up error logs.

Defining an Augmented Exception Class

Declare a ZMexAugmented exception class at global scope with some sort of extraObj:

    //When deriving from a regular ZMexception use ZMexAugmented<>
  #include "ErrLogEx/ZMexAugmented.h"
  typedef ZMexAugmented<ZMexception, point> overQuota;  //point is my extraObj

    //When deriving from a ZMexAugmented<> use ZMexDerivedAug<>
  #include "ErrLogEx/ZMexDerivedAug.h"
  typedef ZMexDerivedAug<overQuota> whoopsee;       //derive from overQuota class
  typedef ZMexDerivedAug<whoopsee> whoopseedaisy;   //derive from whoopsee
Notice that these derived classes only take one argument and will have the same type for their extraObj as their parent class (in this case a 'point').

Once all the classes are declared you can #include the physicist's module. Be careful not to include it before these declaration or the physicist's code will not know about them and won't be able to throw them.

Setting up the Logger

An ELadministrator must be created, and the output of the exceptions may be sent to log files or to an ostream via the attach function. The syntax is the same as setting up an ErrorLogger.
Here are the minimum requirements to log an augmented exception to cout and a file whenever the exception is ZMthrow'n :

  #include "ErrorLogger/ELadministrator.h"
  #include "ErrorLogger/ELoutput.h"

  int main() {
    ELadministrator* logger = ELadministrator::instance();
    logger->attach(ELoutput(std::cout));        //output logs to cout
    logger->attach(ELoutput("filename.log"));   //and to file "filename.log"
    //...
  }

Creating A Custom Handler

Because the extra object can be of any type, the handler must know how to deal with it. Thus, a new handler class derived from ZMexHandlerBehavior must be created by the frameworker. It should #include the file that has the declarations of the augmented exception classes. Here is what the constructor should look like:


  class ZMexAugHandler : public ZMexHandlerBehavior {
   public:
    ZMexAugHandler() : ZMexHandlerBehavior( "ZMexAugHandler" ) { }
    //...
  }
The handler requires a clone( ) function that must look like this:
  virtual ZM_COVARIANT_TYPE(ZMexHandlerBehavior,ZMexAugHandler)*
    clone() const { return  new ZMexAugHandler( *this ); }
The most important function of the handler class is takeCareOf( ). It determines if its argument is actually an augmented exception, and it examines or alters the extra object. This function can also determine whether the exception should be logged at all.
  virtual ZMexAction takeCareOf( const ZMexception & x ) {
    if (!(overQuota::isBaseOf(x)))    //is x an augmented exception?
      return standardHandling( x,     //if not, log exception the regular way
                             true );  //and throw it

    overQuota& blah = (overQuota&) x; //convert x to an augmented exception
    point& p = blah.extraObj;         //access its extraObj
    ErrorObj& o = blah.getErrorObj(); //access its ErrorObj

      //do whatever you want with it here. Maybe put extraObj into your log:
    o << "x-coord =" << p.x  << " y-coord =" << p.y;
    if( p == origin )
      return standardHandling( x,     //log exception in the regular way
                            false );  //and do not throw it
    else return ZMexIgnoreIt;         //don't even log it
  }
The standardHandling function shown above takes an exception as its first argument and a bool for its second argument. It calls the exception's ZMexLogger, and the bool determines whether the exception should be thrown (true) or not (false). If for some reason the frameworker does not want the exception to be logged by the ZMexLogger he/she can just return either ZMexIgnoreIt which will continue with the program or ZMexThrowIt which will exit the program (neither of which will log the exception).

Heirarchy based on Name and Facility
In the example above, the isBaseOf( ) function determines whether 'overQuota' is a base class of 'x' by comparing its own name and facility to that of the exception's ancestors, so it is important that the names of different augmented exception classes do not coincide.

The constructor and the two functions above are required in your handler. takeCareOf( ) will have some other content in order to deal with the user's extra object while everything else should only differ in name.

Custom Modifications

Most of the modifications to the output of an augmented exception log can be accomplished in the same manner one would modify an ErrorLogger log, but here are a few particularly helpful tips.


  • Suppressing a timestamp - Since there are two timestamps on an augmented exception's log, the frameworker may want to remove one. To remove the ErrorObj timestamp:
      #include "ErrorLogger/ELdestControl.h"
      /...
      ELdestControl dest=logger->attach(ELoutput(std::cout));
      dest.suppressTime();
    
    Other formatting control options are found in the ErrorLogger Package.
  • Outputting ErrorLogger summaries - to declare a statistics destination called "stats" and then output a summary to an ELdestControl:
      ELstatistics stats(cout);
      stats->summary(dest);
    
    For other summary options and a description of the summary output take a look at the summary information in the ErrorLogger Package.

  • BACK TO THE AUGMENTED EXCEPTION MAIN PAGE
    FPCLTF Home Page- Fermilab at Work- Fermilab Home


    Last modified: Feb 22 2001