D0 GROUP LEVEL3
ONLINE LESSONS
Gustaaf Brooijmans
Fermilab, MS # 357
Tel: +1 (630) 840 4269 |
|
Episode XII
Error Logging by Level 3 Tools
by Gustaaf
Brooijmans
This episode will tell you how you
should set up your tool for error logging. It will tell you what
you have to implement in your tool, how you should make errors known to
the program, and how you can test this part of your tool's functionality.
The basics first though: the level
3 filtering program will use a combination of two ZOOM packages
to handle errorlogging: ErrorLogger and Exceptions.
Why two? Because only the combination of both gives us all the functionality
we are looking for. So what are these requirements? Well, it
has to
-
be easy to use,
-
have flexible output in terms of what and where,
-
be able to give us summaries of the errors that occurred,
-
allow us to throw exceptions in a controlled way, and
-
be readily available to developers, both on unix and NT.
Implementation in Tools
This is the part where "easy to use" comes in! These are the steps
I recommend you follow:
-
Have an instance of ErrorLog as a private member : ErrorLog
_myToolLog; (choose your own name)
This implies you have to #include "ErrorLogger/ErrorLog.h".
-
In the MakeMe() method, tell your ErrorLog instance who you are:
_myToolLog.setPackage("myTool's
name") (this isn't functional yet - 10-Feb-99 - but will be soon)
-
In the MakeMe() method, tell Exceptions about your logger: L3ZMxel::setLogger(ZMexErrorLog(_myToolLog)
);
You'll have to #include "l3utilities/L3ZMxel.hpp" and #include
"ZMtools/ZMexErrorLog.h" to get that one right.
That's it!
No kidding? But how do I tell the program I have an Error??
Sending Error Messages
This part's really easy: to flag an error, you start by creating an error
object:
ErrorObj myerror( ELwarning, " Negative ET !?");
where ELwarning is a severity level (#include "ErrorLogger/ELseverityLevel.h"
-follow
this link for a list of the available severity levels and their meaning
in level 3), and the second argument is some text which effectively
becomes the error identifier (in this case it's Negative ET !?).
So if later in the code you want to record more errors with the same ID,
you want to use the same text there.
After that, you can still add more text to the error message (but this
doesn't add to the identifier):
myerror << " and this crazy ET value is " << _ET <<
endmsg;
and you can go on this way until you end the message with endmsg
(or
by starting a new error). Once you're finished, you send the error
to the logger using the instruction
_myToolLog(myerror);
Ok, but what if my error is so bad that we should stop processing the
event (or worse, restart the program)?
Throwing Exceptions
When you decide this event shouldn't be processed further (because the
data is corrupted for example), or worse, the program should stop (the
geometry is corrupted for example), then you should "throw" the error,
rather than just logging it.
Create an ErrorObj just like you do for errors that aren't as
bad, but with severity ELsevere or ELsevere2 (to stop processing
an event) or ELabort or ELfatal (to stop the program), and
instead of sending it to the logger throw it:
// Construct ErrorObj
ErrorObj myerror( ELsevere, " Raw Data Corrupted ! " );
// Throw
ZMthrow( L3ZMxel ( myerror ));
(you'll need to #include Exceptions/ZMthrow.h).
This will stop execution dead in its tracks and delete all the local
variables from the stack. We'll catch this higher up in the program
and move to the next event or stop and restart, depending on the severity.
What Happens Behind My Back?
The tools that are instantiated first are ErrorHandling tools, of which
there may be one or more. Each of these correspond to a particular
destination the error messages are sent to (which can be the Significant
Event Server, a file on the node, etc.). It logs the messages above
a certain severity level and keeps statistics on the number of occurrences
of each message. It also keeps the most recent errors in a buffer
(not implemented yet), allowing trace-back.
How Do I Test This Stuff?
For all of this to work in your component and integrated tests, you want
to instantiate an L3ErrHandlingTool (Otherwise
your messages will not be going anywhere!). For an example,
look at l3exceptions/src/L3ErrHandleTool_t.cpp
(the corresponding
trigger list is L3Err.lst), or the trigger lists in the l3ftools
component tests (but unfortunately not the integrated test) - I put in
comments showing how things are done. It's also a simple example
of how you can test a tool (component test only though).
As usual: comments, questions? -> Feel free to contact me.