This page describes the definition, use, and logging of ESD Software Exceptions. ESD Software Exceptions provide language-independent exception Definition, Handling, and Logging. It is an object-oriented, corba-based system for use by C++ and Java programs. It is not part of AIDA, but AIDA uses it.
The ESD Software Exceptions System logs an exception by sending log data through the CORBA Event service and logging it into CMLOG. For instructions on starting the Event Service and related processes, see the Err System Administration Guide.
Overall Architecture | Language APIs | |
How to define new ESD Exceptions | Guidelines for using exceptions |
The ESD Software Exception Application Programming Interface (API) that is used by Java and C++ programs is encapsulated in a class called Err. The Err class method called Err.log() is used by programmers to log exceptions into CMLOG via the CORBA Event service. The way the system is designed it is relatively easy to to replace CMLOG with some other error logger in the future.
import edu.stanford.slac.except.*; // exceptions are kept here
import edu.stanford.slac.err.*; // exception logging class Err.class def
Err err = new Err("AIDA Magnet Server"); // Instantiate with your facility name.
try {
...
throw new NoDataSourceException("for LB60:DCCT:SUNY");
}In that case, the text that gets logged into CMLOG looks like this:
catch (Exception ex) {
err.log(ex, "when attempting to acquire the LER current" );
}
throw err.log(new NoDataSourceException("for LB60:DCCT:SUNY"), " when starting ca service");In this case, you might take some different action in the catch block; perhaps additionally logging a different exception appropriate to the higher level of abstraction of the catch block.
static int myFunc() throws NoDataSourceException
{
throw (NoDataSourceException)err.log
(new NoDataSourceException("for LB60:DCCT:SUNY")," when starting ca service");
}
TextOnly ex = new TextOnly("TEXT GOES HERE");Additionally, Err.log() has been overloaded with a no-exception signature for logging just text:
err.log(ex, "when attempting to acquire LER current");
err.log("TEXT GOES HERE");
EXCEPTION_NAME + REASON STRING + SUPPLEMENTAL STRING
an example of how not to name an exception: NoLargeMagnetsExistsInMagnetServerOnTuesday
new NoDataSourceException("for LB60:DCCT:SUNY");
err.log(ex, "when attempting to acquire the LER current");Together, These three strings provide context information and a poor-man's form of exception chaining. Using the example strings above, the logged message text would be:
"NoDataSourceException for LB60:DCCT:SUNY when attempting to acquire the LER current"
#include "except.h" // ESD exceptions are kept here. Feel free to add new ones.
#include "err.h" // ESD exception logging class err is kept here.
Err err("AIDA Magnet Server"); // Instantiate with your facility name
try {In that case, the text that gets logged into CMLOG looks like this
throw except::MissingResourceException();
}
catch (CORBA::Exception ex) {
...
// Log the exception with 'Reason and Supplemental' string).
err.log(ex, "for QUAD:LI01 while moving magnet");
}
In C++, your last catch clause often looks like catch (...). If you use
this
form of catch catch statement, you can not log the exception because
you
don't have an instance of it (or a reference to it). So, the best you
can
do is log some text message.
catch (...) {
err.log("This is a text-only message.");
}
throw (&err.log(except::NoDataSourceException(), "for LB60:DCCT:SUNY while doing trim"));This is how you log some text only (not specifically an exception). This is like err_text() on the SLC system.
err.log("This is a text-only messages log text");
cd $CD_PKG/err/test
Tdriver
All IDL C++ exceptions are derived from CORBA::Exception. So, you
can always catch and log ESD exceptions using a catch statement like
this instead of catching any specific sub-class exception.
catch (CORBA::Exception ex)
A logged exception consists of two strings in C++ which
are concatenated to form the logged message text:
EXCEPTION_NAME +
REASON AND SUPPLEMENTAL STRING
The Reason and Supplemental String are different in C++ than in Java. Due to a limitation the C++ idl exception mapping, you can not supply a Reason string when you instantiate the exception like you can in Java. So, our convention is to supply both the Specific string (nouns) and the Supplemental string (context) when the exception is logged.
The Exception Name (defined in except.idl) should be
general and
systemic (it should not refer to a specific instance of any thing
(proper noun)). Any specific information is to be provided
in the "reason" or "supplemental" strings (see below). The
Exception name should end
with the word "Exception".
Here is a good example of a exception name: NoDataSourceException
Here is an example of how not to name an exception:
NoLargeMagnetsExistsInMagnetServerOnTuesday
The run-time supplied "Reason and Supplemental" String,
should give include nouns describing what caused the error and
give context. It is supplied when the exception is logged
Here is a good example of a Reason and Supplemental string: err.log(except::NoDataSourceException(),
"for quad QUAD:LI22:2:FOO while trimming");
Together, These three strings provide context information and a
poor-man's form of exception chaining. Using the example strings
above, the logged
message text would be:
"NoDataSourceException for LB60:DCCT:SUNY when attempting to acquire
the
LER current"
ESD exceptions are defined in the except.idlfile:
$CD_SOFT/ref/package/except/idl/except.idl
cd ~/dev/test
cvs checkout package/except
Then, use your favorite editor add new exceptions to that file following
the format used by all other exceptions in the file.
cd package/except/idl
edit except.idl here.
Then 'make' the except package in your development directory like this:
cd ~/dev/test/package/except/common/scriptThen, test the java classes and c++ library just created by changing your CLASSPATH and LD_LIBRARY_PATH to point to the files you just created in your development directory. Run some test program you create to test the exceptions.
gmake -f Makefile.sun4
After you are satisfied with your changes to except.idl, CVS commit your except.idl back to CVS and clean up your development area like this:cd ~/dev/test/package/except/idlThen, Make the production except package like this and you're done:
cvs commit
addUserRefWrite
cd $CD_SOFT/ref/package/except/common/script
gmake -f Makefile.sun4
removeUserRefWrite
The new exceptions are now available for you and the rest of ESD to use. Don't forget to remove your development directory from your CLASSPATH and LD_LIBRARY_PATH.cd ~/dev/test
cvs release package/except
rm -fr package
Exceptions Guidelines
This section provides guidelines that apply to both C++ and Java. Guidelines are provided above for language-specific issues.General Exception Guidelines
There are some good guidelines for exceptions on P90-91 of "Advanced
CORBA Programming with C++".
Always throw ESD or Application UserExceptions (not SystemExceptions).
While it is possible to use a concrete exception derived from SystemException,
such as BAD_PARAM, it is strongly recommend to use a UserException. Using
SystemExceptions for user code is considered bad programming style.
The exceptions defined in except.idl may be used by any ESD program.
There is no grouping of exceptions by facility, service, or anything like
that. For example, the NoDataSource exception may be used by any
number of different programs.
When writing an AIDA (or other CORBA) server, you should catch all non-CORBA
exceptions (e.g. C++ or Java exceptions) before they are thrown across
the CORBA boundary to the client. If you don't catch them, it isn't catastrophic,
but it is not clean either. The servant method issues a warning to stdout
and converts the exception to CORBA::UNKNOWN exception which is then received
by the client. There are no contextual details passed in the 'UNKNOWN',
so the client won't be able to log anything meaningful in the error log.
Specify a facility name when you instantiate the exception logger (Err).
[Aida Home Page][SLAC
Controls Software Group][
SLAC Home Page]