    <rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:admin="http://webns.net/mvcb/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:content="http://purl.org/rss/1.0/modules/content/">
     <channel>
        <title>ACCU  :: Tracking Exceptions in Web Services with GUIDs</title>
        <link>https://members.accu.org/index.php/journals/842</link>
        <description>Professionalism in Programming</description>
        <dc:language>en-us</dc:language> 
        <dc:creator>Administrator</dc:creator> 
        <admin:generatorAgent rdf:resource="http://www.xaraya.org" /> 
        <admin:errorReportsTo rdf:resource="mailto:webeditor@accu.org" />
       <sy:updatePeriod>hourly</sy:updatePeriod>
       <sy:updateFrequency>1</sy:updateFrequency>
       <docs>http://backend.userland.com/rss</docs>


        <h2>Journal Articles</h2>


<div class="xar-mod-head"><span class="xar-mod-title">CVu Journal Vol 17, #5 - Oct 2005 + Internet Topics</span></div>

<table border="0" cellpadding="1" cellspacing="0">
    <tbody>
    <tr>
        <td valign="top">
            Browse in :
       </td>
       <td valign="top">

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c76/">Journals</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c77/">CVu</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c94/">175</a>
                    (15)
<br />

                                            <a href="https://members.accu.org/index.php/journals/">All</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c13/">Topics</a>

                     &gt;                         <a href="https://members.accu.org/index.php/journals/c69/">Internet</a>
                    (35)
<br />

                                            <a href="https://members.accu.org/index.php/journals/c94-69/">Any of these categories</a>

                    -                        <a href="https://members.accu.org/index.php/journals/c94+69/">All of these categories</a>
<br />
</td>
   </tr>
   </tbody>
</table>




<div class="xar-error">
   <p>
 <strong>Note:</strong> when you create a new publication type,
the articles module will automatically use the templates
<em>user-display-[publicationtype].xt</em>
and <em>user-summary-[publicationtype].xt</em>.
If those templates do not exist when you try to preview or display a new article,
you'll get this warning :-)  Please place your own templates in themes/<em>yourtheme</em>/modules/articles . The templates will get the extension .xt there. </p>
</div>
<div class="xar-norm xar-standard-box-padding">
   <h1><strong>Title:</strong>&nbsp;Tracking Exceptions in Web Services with GUIDs</h1>
<p><strong>Author:</strong>&nbsp;</p>
<p>
<strong>Date:</strong> 02 October 2005 06:00:00 +01:00 or Sun, 02 October 2005 06:00:00 +01:00</p>
<p><strong>Summary:</strong>&nbsp;<p>This article demonstrates a technique for tracking exceptions
across process boundaries in distributed systems using Globally
Unique Identifiers (GUIDs); data from log files, bug reports, and
on-screen error messages can then be correlated, allowing specific
errors to be pinpointed.</p>
</p>
<p><strong>Body:</strong>&nbsp;<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e31" id="d0e31"></a>Synopsis</h2>
</div>
<p>This article demonstrates a technique for tracking exceptions
across process boundaries in distributed systems using Globally
Unique Identifiers (GUIDs); data from log files, bug reports, and
on-screen error messages can then be correlated, allowing specific
errors to be pinpointed.</p>
<p>Particular attention is paid to XML Web Services, with
additional reference to DCOM, CORBA, Java/RMI and .Net
Remoting..</p>
<p>The examples are given in C#, but the technique can be applied
easily to Java and other languages.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e40" id=
"d0e40"></a>Introduction</h2>
</div>
<p>When dealing with modern distributed applications, it is often
very useful to track an exception as it crosses process and machine
boundaries. A comprehensive picture of the &quot;distributed error&quot; can
then be constructed from log files of the different applications
and components affected.</p>
<p>Languages such as C# and Java have an inbuilt mechanism to
provide detailed error information - the Exception Stack Trace -
which helps greatly to identify the source of runtime application
errors. However, this information in itself does not always provide
the full picture of an error condition.</p>
<p>The approach outlined here uses GUIDs (see Sidebar: GUIDs)
effectively to &quot;tag&quot; exceptions before they leave one part of an
application and appear in another. This allows exceptions to be
tracked irrespective of whether the application is stand-alone or
distributed, and irrespective of the transport, protocol or
component architecture used.</p>
<div class="sidebar">
<p class="title c4">GUIDs</p>
<p>A GUID (pronounced like &quot;squid&quot;) is a Globally Unique
IDentifier, and is normally represented in string form something
like this: <tt class=
"literal">DCF70619-01D8-42a9-97DC-6005F205361A</tt>. The GUID (also
known as UUID - Universal Unique IDentifier) is an IETF standard,
as defined in RFC 4122 [<a href="#_1">_1</a>]. The .Net Framework
documentation for System.Guid [<a href="#_4">_4</a>] has this to
say:</p>
<div class="blockquote">
<blockquote class="blockquote">
<p>A GUID is a 128-bit integer (16 bytes) that can be used across
all computers and networks wherever a unique identifier is
required. Such an identifier has a very low probability of being
duplicated.</p>
</blockquote>
</div>
<p>GUIDs are generated using a variety of data, such as the current
date &amp; time, the IEEE 802 (MAC) address of the machine's
network card, etc.[<a href="#_2">_2</a>]. This is designed to
ensure that the likelihood of generating the same GUID twice is
very small.</p>
<p>There are UUID/GUID implementations for many different languages
and platforms (see Sidebar: GUID Implementations), and even an
online GUID generator [<a href="#_3">_3</a>]. In addition, it is
easy to identify GUIDs written in the standard string
representation (above) using Regular Expressions.</p>
<p><span class="emphasis"><em>Note:</em></span> UUIDs/GUIDs should
not be confused with GIDs/UIDs on *nix systems!</p>
</div>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e80" id="d0e80"></a>XML Web
Services: A Very Brief Introduction</h2>
</div>
<p>XML Web Services is the name given to the latest class of
middleware technologies designed to provide cross-platform Remote
Procedure Calls (RPC). Previous technologies such as DCOM, CORBA
and Java/RMI all have strengths, but often suffer from
implementation difficulties, and none is really both platform- and
language-independent [<a href="#_10">_10</a>], [<a href=
"#_11">_11</a>]. XML Web Services are described concisely in
[<a href="#_16">_16</a>] as follows:</p>
<div class="blockquote">
<blockquote class="blockquote">
<p>Web services are a new breed of Web application. They are
self-contained, self-describing, modular applications that can be
published, located, and invoked across the Web. Web services
perform functions, which can be anything from simple requests to
complicated business processes... Once a Web service is deployed,
other applications (and other Web services) can discover and invoke
the deployed service.</p>
</blockquote>
</div>
<p>The increasing success of XML Web Services, and SOAP [<a href=
"#_9">_9</a>] in particular, as the &quot;glue&quot; for cross-platform RPC
can be put down to several factors, including:</p>
<div class="itemizedlist">
<ul type="disc">
<li>
<p>the technology is &quot;platform-agnostic&quot;, relying only on XML as
the data exchange format</p>
</li>
<li>
<p>there is no explicit transport protocol (most implementations
use HTTP, but SMTP or other protocols are also valid [<a href=
"#_13">_13</a>])</p>
</li>
<li>
<p>the use of these standard protocols allows Web Services to be
accessed behind a firewall (Port 80 for HTTP will usually be left
open, for example)</p>
</li>
<li>
<p>Web Services can be discovered and used automatically using UDDI
[<a href="#_14">_14</a>], due to Web Services being
&quot;self-describing&quot; via WSDL [<a href="#_15">_15</a>].</p>
</li>
</ul>
</div>
<p>All these properties make XML Web Services very attractive for
building scalable, flexible distributed applications. For a more
comprehensive introduction to XML Web Services, see [<a href=
"#_8">_8</a>].</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e129" id="d0e129"></a>SOAP</h2>
</div>
<p>The Simple Object Access Protocol (SOAP) [<a href="#_9">_9</a>]
is probably the most common dialect used by XML Web Services. The
W3 introduction [<a href="#_17">_17</a>] to SOAP states: SOAP is
fundamentally a stateless, one-way message exchange paradigm, but
applications can create more complex interaction patterns (e.g.,
request/response, request/multiple responses, etc.) by combining
such one-way exchanges with features provided by an underlying
protocol and/or application-specific information. Although SOAP
does not specify a transport protocol, HTTP is normally used. With
the resultant &quot;SOAP-HTTP Binding&quot;, XML Web Services using SOAP and
HTTP rely on message exchange using a combination of an HTTP Header
and SOAP (XML) payload.</p>
<p>A SOAP message to retrieve (say) the author and title of a book
might look something like this:</p>
<div class="figure"><a name="d0e142" id="d0e142"></a>
<div class="mediaobject">
<pre class="literallayout">
POST /cgi-bin/book-info.cgi HTTP/1.1
MethodName: GetBookDetails
MessageType: Call
Content-Type: text/xml-SOAP

&lt;GetBookDetails&gt;
  &lt;ISBN&gt;0201615622&lt;/ISBN&gt;
&lt;/GetBookDetails&gt;
</pre></div>
<p class="title c4">Figure 1. SOAP Request</p>
</div>
<p>Notice the standard HTTP POST request (first five lines), and
that the SOAP payload (the <tt class="literal">GetBookDetails</tt>
element) is simply XML.</p>
<p>The response from the Web Service might look like this:</p>
<div class="figure"><a name="d0e156" id="d0e156"></a>
<div class="mediaobject">
<pre class="literallayout">
200 OK
Content-Type: text/xml
Content-Length: 115

&lt;GetBookDetailsResponse&gt;
  &lt;author&gt;
    Herb Sutter
  &lt;/author&gt;
  &lt;title&gt;
    Exceptional C++
  &lt;/title&gt;
&lt;/GetBookDetailsResponse&gt;
</pre></div>
<p class="title c4">Figure 2. SOAP Response</p>
</div>
<p>The XML payload contains a root element <tt class=
"literal">GetBookDetailsResponse</tt> that is the response to the
original <tt class="literal">GetBookDetails</tt> request.
Real-world SOAP messages would be somewhat more complex, but the
principle above remains. For a much more comprehensive overview of
SOAP, see [<a href="#_10">_10</a>].</p>
<p>SOAP deals with errors using a <tt class="literal">Fault</tt>
response element. Any errors encountered by the Web Service, either
in the request itself, or during the processing of the request, are
detailed in the <tt class="literal">Fault</tt> element. For
example, if the <tt class="literal">GetBookDetails</tt> request
above failed due to an unknown ISBN, the XML payload of the
response might look something like this:</p>
<div class="figure"><a name="d0e185" id="d0e185"></a>
<div class="mediaobject">
<pre class="literallayout">
&lt;GetBookDetailsResponse&gt;
  &lt;fault&gt;
    &lt;faultcode&gt;700&lt;/faultcode&gt;
    &lt;faultstring&gt;Processing Error&lt;/faultstring&gt;
  &lt;runcode&gt;1&lt;/runcode&gt;
    &lt;details&gt;
      &lt;Message&gt;
        ISBN Not Recognised!
      &lt;/Message&gt;
    &lt;/details&gt;
  &lt;/fault&gt;
&lt;/GetBookDetailsResponse&gt;
</pre></div>
<p class="title c4">Figure 3. SOAP Fault</p>
</div>
<p>The <tt class="literal">/fault/details</tt> node contains a
<tt class="literal">Message</tt> element, with an explanation of
the error. (Note: in practice, XML Namespaces would be used for
both the request and the response XML: these have been omitted for
clarity.)</p>
<p>We will return to the SOAP <tt class="literal">Fault</tt>
shortly.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e205" id=
"d0e205"></a>SoapExceptions in the .Net Framework</h2>
</div>
<p>The Microsoft .Net Framework simplifies many of the
implementation details of SOAP web services by classes in the
<tt class="literal">System.Web.Services</tt> namespace [<a href=
"#_20">_20</a>], in particular, the <tt class=
"classname">WebService</tt> class, from which - by default - all
other SOAP Web Services in .Net are derived.<sup>[<a name="d0e219"
href="#ftn.d0e219" id="d0e219">1</a>]</sup></p>
<p>One of the most useful aspects of the Framework is that a SOAP
Fault response is converted automatically to a <tt class=
"exceptionname">System.Web.Services.Protocols.SoapException</tt>
[<a href="#_18">_18</a>], which is thrown in the context of the
calling client. Details of the error contained in the SOAP
<tt class="literal">Fault</tt> element are made available as
properties of the <tt class="exceptionname">SoapException</tt>
instance.<sup>[<a name="d0e236" href="#ftn.d0e236" id=
"d0e236">2</a>]</sup></p>
<p>This conversion also works in the opposite direction: a
<tt class="exceptionname">SoapException</tt> escaping from the Web
Service is converted automatically into a SOAP <tt class=
"literal">Fault</tt> response. In fact, the .Net Framework ensures
that only exceptions of type <tt class=
"exceptionname">SoapException</tt> escape from a Web Service call:
if an uncaught exception raised within a Web Service method is not
a <tt class="exceptionname">SoapException</tt>, the Framework
throws a new <tt class="exceptionname">SoapException</tt>, storing
the uncaught exception as its <tt class=
"exceptionname">InnerException</tt>. Details of the original
exception are extracted into the SOAP <tt class=
"literal">Fault/details</tt> element.</p>
<div class="figure"><a name="d0e265" id="d0e265"></a>
<div class="mediaobject c5"><img src="/var/uploads/journals/resources/Mapping.png" align=
"middle" alt="Mapping SoapExceptions to SOAP Faults"></div>
<p class="title c4">Figure 4. Mapping SoapExceptions to SOAP
Faults</p>
</div>
<p>Figure 4 shows how information about an error in the Web Service
method is transmitted back to the calling client. Thus, if the Web
Service were to create a unique identifier for the error, and pass
that identifier back to the client, we would be able to track that
specific error as it travels across machine/process boundaries.
Assuming that the error is logged in both places, we would have a
way to link together error information from one application
component with that from another.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e273" id="d0e273"></a>Implementing
Exception Tracking with GUIDs</h2>
</div>
<p>Figure 5 shows a C# class definition for a simple base class to
help with tracking exceptions:</p>
<div class="figure"><a name="d0e278" id="d0e278"></a>
<div class="mediaobject">
<pre class="programlisting">
using System;

public class TrackedException : Exception
{
  #region .ctor signatures in System.Exception
  public TrackedException() : this(Guid.NewGuid())
  {}

  public TrackedException(string message) : 
     this(message, Guid.NewGuid())
  {}
  // etc...
  #endregion

  #region .ctors providing tracking ability
  using GUIDs
  protected TrackedException(Guid errorID) :
     base()
  {
    this.errorID = errorID;
  }

  protected TrackedException(string message,
     Guid errorID) : base(message)
  {
    this.errorID = errorID;
  }
  // etc...
  #endregion

  #region Tracking
  private Guid errorID;
  /// &lt;summary&gt;
  /// Uniquely identifies this exception
  /// &lt;/summary&gt;
  public Guid ErrorID
  {
    get { return errorID; }
  }
  #endregion
}
</pre></div>
<p class="title c4">Figure 5. A basic TrackedException base
class</p>
</div>
<p>The <tt class="exceptionname">TrackedException</tt> class in
Figure 5 automatically creates a new GUID in its constructors.
Derived classes therefore do not need to concern themselves with
GUID creation: in fact, they cannot, as the constructors relating
to GUIDs are protected. Other useful base class constructors could
be defined (e.g. matching the signatures of <tt class=
"literal">System.Exception</tt>), also priming the <tt class=
"varname">ErrorID</tt> property.</p>
<p>Wherever a <tt class="exceptionname">TrackedException</tt> is
thrown in code, we know that it will have a GUID-based <tt class=
"varname">ErrorID</tt> property, which we can include in log file
data.</p>
<p>Crucially, however, in the context of Web Services, we can also
include this GUID in the SOAP <tt class="literal">Fault</tt>
response, by throwing explicitly a <tt class=
"exceptionname">SoapException</tt> from within a Web Service method
if an exception is thrown during processing:</p>
<div class="figure"><a name="d0e312" id="d0e312"></a>
<div class="mediaobject">
<pre class="programlisting">
[WebMethod] //Attribute needed for Web Service
           //'plumbing'
public string GetBananaPrice(string cityName)
{
  try
  {
    // some processing
  }
  catch (TrackedException te)
  {
    string message = te.GetType().Name + &quot; &quot; +
       te.Message;
    // N.B. Constructor parameters simplified
    // here
    throw new SoapException(
      message, 
      ExceptionHelper.WrapDetails(te.ErrorID),
      te);
  }
}
</pre></div>
<p class="title c4">Figure 6. Using a TrackedException in a Web
Service</p>
</div>
<p>The call to the hypothetical <tt class=
"methodname">ExceptionHelper.WrapDetails()</tt> method returns a
<tt class="classname">System.Xml.XmlNode</tt> object that will be
inserted into the SOAP <tt class="literal">Fault</tt> response XML
payload.</p>
<p>The client calling the Web Service in Figure 6 would use code
like this:</p>
<div class="figure"><a name="d0e332" id="d0e332"></a>
<div class="mediaobject">
<pre class="programlisting">
// Create local proxy for Web Service
// Connection to remote machine is handled 
// automatically
PricesWebService ws = new PricesWebService();
try
{
  string bananaPrice = 
     ws.GetBananaPrice(&quot;Havana&quot;);
}
catch (SoapException se)
{
  // Extract the GUID stored by the Web
  // Service from the XML
  string errorGUID = se.Details.InnerText; 
  string message = se.Message;
  // Log the error here at the client...
  Console.Out.WriteLine(&quot;Error when calling 
     GetBananaPrice(): &quot; + message + &quot; GUID: &quot;
     + errorGUID);
  // TODO: 
  // Present the GUID to the user 
  // Notify admin using GUID
}
</pre></div>
<p class="title c4">Figure 7. Catching a SoapException at the
client and logging the GUID</p>
</div>
<p>The <tt class="varname">Details</tt> property of the <tt class=
"exceptionname">SoapException</tt> at the client contains the XML
from the <tt class="classname">XmlNode</tt> that was inserted in
the catch handler of the Web Service method: the GUID of the
original exception (see Figure 6). Logging this at the client will
allow us to tie together the error logs from the two applications;
showing the GUID to the user (see Figure 8) would allow her to
copy/paste the GUID into a bug report (for example), further
correlating the error information.</p>
<p>The same GUID appearing in different log files will refer to the
same exception instance; due to the nature of GUIDs (see Sidebar:
GUIDs) we can assume that a GUID will never be duplicated.</p>
<p>There is an advantage in presenting only a GUID rather than
detailed error information to the user: it may not always be
appropriate to divulge the details of an error (for security
reasons, for example). The GUID acts as an opaque handle to the
already-logged error; a bug report containing just the GUID should
be enough to put that report in context.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e354" id="d0e354"></a>Other
Technologies</h2>
</div>
<p>It is fairly easy to extend the GUID-based error tracking to
certain other frameworks and technologies. For Java/RMI (and its
.Net analogue, .Net Remoting), it is basically enough to make the
<tt class="exceptionname">TrackedException</tt> class available to
each side of the Remoting channel.<sup>[<a name="d0e362" href=
"#ftn.d0e362" id="d0e362">3</a>]</sup> The <tt class=
"varname">ErrorID</tt> property of the exception instance will be
serialized along with the rest of the object, and therefore be
available to the calling client. [Note that a <tt class=
"classname">UUID</tt> class was introduced only in Java 2 SE 1.5,
so earlier versions of Java will have to rely on other UUID
implementations - see Sidebar: GUID Implementations, [c]]</p>
<div class="figure"><a name="d0e375" id="d0e375"></a>
<div class="mediaobject c5"><img src="/var/uploads/journals/resources/Error_Report.jpg"
align="middle" alt="Presenting the error GUID to the user"></div>
<p class="title c4">Figure 8. Presenting the error GUID to the
user</p>
</div>
<div class="sidebar">
<p class="title c4">GUID Implementations</p>
<div class="orderedlist">
<ol type="a">
<li>
<p>Python: <a href=
"http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/163604"
target=
"_top">http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/163604</a>
and <a href=
"http://pyro.sourceforge.net/manual/11-implementation.html#util"
target=
"_top">http://pyro.sourceforge.net/manual/11-implementation.html#util</a></p>
</li>
<li>
<p>Perl: <a href="http://cpan.uwinnipeg.ca/dist/Data-UUID" target=
"_top">http://cpan.uwinnipeg.ca/dist/Data-UUID</a> and <a href=
"http://perl.apache.org/docs/2.0/api/APR/UUID.html" target=
"_top">http://perl.apache.org/docs/2.0/api/APR/UUID.html</a></p>
</li>
<li>
<p>Java: [in standard Java 1.4 there is no UUID class] <a href=
"http://platform.jxta.org/nonav/java/impl/net/jxta/impl/id/UUID/UUID.html"
target=
"_top">http://platform.jxta.org/nonav/java/impl/net/jxta/impl/id/UUID/UUID.html</a>
(Java 1.4.2) and <a href=
"http://java.sun.com/j2se/1.5.0/docs/api/java/util/UUID.html"
target=
"_top">http://java.sun.com/j2se/1.5.0/docs/api/java/util/UUID.html</a>
(Java 2 SE 5.0)</p>
</li>
<li>
<p>SQL: &quot;UUID() was added in MySQL 4.1.2.&quot; - <a href=
"http://dev.mysql.com/doc/mysql/en/miscellaneous-functions.html"
target=
"_top">http://dev.mysql.com/doc/mysql/en/miscellaneous-functions.html</a>
(MySQL) and &quot;Using GUIDs with IDS 9.x&quot; - <a href=
"http://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0401roy/"
target=
"_top">http://www-128.ibm.com/developerworks/db2/library/techarticle/dm-0401roy/</a>
(DB2)</p>
</li>
</ol>
</div>
</div>
<p>CORBA and DCOM differ substantially in their support for
exceptions. DCOM does not transmit exception details from server to
client, relying instead on (much less useful) &quot;HRESULT&quot; return
codes [<a href="#_5">_5</a>] [<a href="#_22">_22</a>]. There is
therefore no simple way to extend the GUID-based exception tracking
to DCOM.<sup>[<a name="d0e427" href="#ftn.d0e427" id=
"d0e427">4</a>]</sup></p>
<p>Unlike DCOM, CORBA does transmit exceptions across the
communication channel. If we make TrackedException a
CORBA::UserException, we can define a public property errorID,
which will contain the string representation of the GUID:</p>
<div class="figure"><a name="d0e435" id="d0e435"></a>
<div class="mediaobject">
<pre class="programlisting">
// CORBA IDL
#pragma prefix &quot;example.com&quot;
module TrackedExceptionExample
{
  interface FruitPrices
  {
    exception TrackedException
    {
      string errorID;
    };

    string get_banana_price(
       in string cityName)
            raises (TrackedException);
    };
};
</pre></div>
<p class="title c4">Figure 9. TrackedException in CORBA</p>
</div>
<p>Some CORBA implementations already provide for a way to
associate extra information with the exception - see [<a href=
"#_23">_23</a>].</p>
<p>However, for situations that do not provide this ability to
'hook' the exception GUID (for example, in 'interop' scenarios
[<a href="#_21">_21</a>] <sup>[<a name="d0e452" href="#ftn.d0e452"
id="d0e452">5</a>]</sup>), it may be possible to append the GUID to
the error message. C# code for a modified version of the
TrackedException class to append the GUID to the error message
would look like this:</p>
<div class="figure"><a name="d0e459" id="d0e459"></a>
<div class="mediaobject">
<pre class="programlisting">
using System;
public class TrackedException : Exception
{
  #region .ctor signatures in System.Exception
  public TrackedException() : 
     this(Guid.NewGuid())
  {}
  public TrackedException(string message) :
     this(message, Guid.NewGuid())
  {}
  // etc...
  #endregion
  #region .ctors providing tracking ability
     using GUIDs
  protected TrackedException(Guid errorID) :
     base(String.Format(FormatString,
          &quot;TrackedException&quot;, errorID))
  {
    this.errorID = errorID;
  }
  protected TrackedException(string message,
     Guid errorID) : base(String.Format
     (FormatString, message, errorID))
  {
    this.errorID = errorID;
  }

  // etc...
  #endregion
  #region Tracking
  public static readonly string FormatString = 
     &quot;{0} - ErrorID: {1}&quot;;
  private Guid errorID;
  // &lt;summary&gt;
  // Uniquely identifies this exception
  // &lt;/summary&gt;
  public Guid ErrorID
  {
    get { return errorID; }
  }
  #endregion
}
</pre></div>
<p class="title c4">Figure 10. TrackedException modified to store
the GUID in the error message</p>
</div>
<p>The constructors ensure that a GUID is associated with the
exception (as in Figure 5), but also automatically store the string
version of the GUID in the Message property of the exception, by
modifying the data passed to the base class constructor.</p>
<p>This approach sacrifices encapsulation for the ability to track
exceptions across process and machine boundaries. Logging the
received error message would still allow the correlation of error
information from the various parts of the distributed system,
because the original exception GUID is stored in the error
message.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e470" id="d0e470"></a>Future
Developments</h2>
</div>
<p>The <tt class="classname">System.Exception</tt> class in C# 2.0
(currently in Beta, and due for release some time in 2005) has a
new member: <tt class="varname">Data</tt> of type <tt class=
"type">IDictionary</tt>. This allows the association of arbitrary
named data items with a given exception. The <tt class=
"varname">ErrorID</tt> property of <tt class=
"exceptionname">TrackedException</tt> could be re-implemented to
store the GUID in the <tt class="classname">Exception.Data</tt>
dictionary, because this would remove the need for special
treatment:</p>
<div class="figure"><a name="d0e493" id="d0e493"></a>
<div class="mediaobject">
<pre class="programlisting">
public class TrackedException : Exception
{
  // Constructors go here...
  // ...
  // for example:
  public TrackedException (Guid errorID) :
     base ()
  {
    this.Data[&quot;GUID&quot;] = errorID;
  }
  public Guid ErrorID
  {
    get
    {
      return this.Data[&quot;GUID&quot;] as Guid;
    }
  }
}
</pre></div>
<p class="title c4">Figure 11. ErrorID implementation on C# 2.0</p>
</div>
<p>The reason for this becomes clear when logging exceptions, we
would just log all information in the Data dictionary (logging the
Name, and calling <tt class="methodname">.ToString()</tt> on the
Value for each entry):</p>
<div class="figure"><a name="d0e505" id="d0e505"></a>
<div class="mediaobject">
<pre class="programlisting">
try
{
  // some processing...
}
catch (Exception ex)
{
  // In practice, this code would go in a 
  // generic logging method somewhere...
  Exception innerException = ex;
  while (null!=innerException)
  {
    // Log the basic exception details here
    // e.g. StackTrace, Message, etc....
    // Log the Data dictionary entries
    string[] names = ex.Data.Names;
    foreach (string name in names)
    {
      Log.WriteLine(name + &quot; = &quot; + 
                    ex.Data[name]);
    }
    innerException = innerException.InnerException;
  }
}
</pre></div>
<p class="title c4">Figure 12. Logging Exception GUIDs in C#
2.0</p>
</div>
<p>Arguably, the need for a separate <tt class=
"exceptionname">TrackedException</tt> class is removed with C# 2.0,
because any and every exception can have a tracking GUID associated
with it, stored as a named entry in the <tt class=
"type">IDictionary</tt> <tt class="varname">Data</tt> member,
rather than needing a separate property <tt class=
"varname">ErrorID</tt>.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e526" id="d0e526"></a>Observations
and Notes</h2>
</div>
<p>The concept of exception tracking presented in this article is
similar to the idea presented in [<a href="#_6">_6</a>] and
[<a href="#_7">_7</a>], where contextual information associated
with an exception is maintained for later analysis. This article
extends the idea across process, machine and protocol boundaries,
however, relying on offline log file analysis to restore the
contextual information.</p>
<p>The overhead associated with generating and transmitting a GUID
may be unacceptable in some cases. However, in most situations, the
benefits gained from being able to track exceptions using a string
of 30-something characters will probably outweigh the slight
performance hit.</p>
<p>An example project demonstrating the ideas in this article is
available from <a href="http://www.accu.org" target=
"_top">www.accu.org</a>.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e544" id="d0e544"></a>Summary</h2>
</div>
<p>This article demonstrated a simple scheme to track exceptions
across Web Services and other distributed systems using GUIDs.</p>
<p>The benefits of using this scheme become apparent when the need
arises to correlate information from multiple error logs and bug
reports: the details of specific exceptions can be reconstructed at
a later stage, and problems diagnosed more thoroughly.</p>
<p>A prototype of this scheme has been in operation for several
months for a real-world project using SOAP Web Services
(http://www.lamip.org/) and proven to be very useful indeed.</p>
</div>
<div class="sect1" lang="en">
<div class="titlepage">
<h2><a name="d0e553" id=
"d0e553"></a>Acknowledgements</h2>
</div>
<p>Thanks to the Editor, Paul Johnson, for requesting this
article.</p>
<p>Thanks also to Kev Watkins, Liz Chapman, Mike Graves, Jason
Neylon, Besim Atalay, Gerald Krafft, Denny De La Haye, Esme Tearle,
and Rebecca Dyer for help and suggestions.</p>
</div>
<div class="bibliography">
<div class="titlepage">
<h2><a name="d0e560" id="d0e560"></a>References</h2>
</div>
<div class="bibliomixed"><a name="_1"></a>
<p class="bibliomixed">[_1] GUID/UUID Specification - <span class=
"bibliomisc"><a href="http://www.ietf.org/rfc/rfc4122.txt" target=
"_top">http://www.ietf.org/rfc/rfc4122.txt</a></span></p>
</div>
<div class="bibliomixed"><a name="_2"></a>
<p class="bibliomixed">[_2] Background to UUIDs/GUIDs (UUIDs in DCE
RPC) - <span class="bibliomisc"><a href=
"http://www.opengroup.org/onlinepubs/9629399/apdxa.htm" target=
"_top">http://www.opengroup.org/onlinepubs/9629399/apdxa.htm</a></span></p>
</div>
<div class="bibliomixed"><a name="_3"></a>
<p class="bibliomixed">[_3] Online GUID Generator: <span class=
"bibliomisc"><a href="http://kruithof.xs4all.nl/uuid/uuidgen"
target="_top">http://kruithof.xs4all.nl/uuid/uuidgen</a></span></p>
</div>
<div class="bibliomixed"><a name="_4"></a>
<p class="bibliomixed">[_4] System.Guid documentation for the .Net
Framework: <span class="bibliomisc"><a href=
"http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemguidclasstopic.asp"
target=
"_top">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemguidclasstopic.asp</a></span></p>
</div>
<div class="bibliomixed"><a name="_5"></a>
<p class="bibliomixed">[_5] Get Seamless .NET Exception Logging
From COM Clients&hellip; - <span class="bibliomisc"><a href=
"http://msdn.microsoft.com/msdnmag/issues/05/01/ExceptionLogging/"
target=
"_top">http://msdn.microsoft.com/msdnmag/issues/05/01/ExceptionLogging/</a></span></p>
</div>
<div class="bibliomixed"><a name="_6"></a>
<p class="bibliomixed">[_6] Hughes, Rob, 'Maintaining Context for
Exceptions' CVu 15.4 (August 2003)</p>
</div>
<div class="bibliomixed"><a name="_7"></a>
<p class="bibliomixed">[_7] Nibbs, Andy, 'Maintaining Context for
Exceptions (Alternative)', CVu 15.6 (December 2003)</p>
</div>
<div class="bibliomixed"><a name="_8"></a>
<p class="bibliomixed">[_8] A Web Services Primer - Venu Vasudevan
<span class="bibliomisc"><a href=
"http://webservices.xml.com/lpt/a/ws/2001/04/04/webservices/index.html"
target=
"_top">http://webservices.xml.com/lpt/a/ws/2001/04/04/webservices/index.html</a></span></p>
</div>
<div class="bibliomixed"><a name="_9"></a>
<p class="bibliomixed">[_9] SOAP Specification - <span class=
"bibliomisc"><a href="http://www.w3.org/TR/soap/" target=
"_top">http://www.w3.org/TR/soap/</a></span></p>
</div>
<div class="bibliomixed"><a name="_10"></a>
<p class="bibliomixed">[_10] SOAP (Introduction) - <span class=
"bibliomisc"><a href=
"http://www.microsoft.com/mind/0100/soap/soap.asp" target=
"_top">http://www.microsoft.com/mind/0100/soap/soap.asp</a></span></p>
</div>
<div class="bibliomixed"><a name="_11"></a>
<p class="bibliomixed">[_11] Java RMI, CORBA or COM? - Prithvi Rao
- <span class="bibliomisc"><a href=
"http://www.usenix.org/publications/java/usingjava13.html" target=
"_top">http://www.usenix.org/publications/java/usingjava13.html</a></span></p>
</div>
<div class="bibliomixed"><a name="_12"></a>
<p class="bibliomixed">[_12] Box, Don A Young Person's Guide to The
Simple Object Access Protocol - <span class="bibliomisc"><a href=
"http://msdn.microsoft.com/msdnmag/issues/0300/soap/" target=
"_top">http://msdn.microsoft.com/msdnmag/issues/0300/soap/</a></span></p>
</div>
<div class="bibliomixed"><a name="_13"></a>
<p class="bibliomixed">[_13] SMTP as a [SOAP] Transport -
<span class="bibliomisc"><a href=
"http://blogs.msdn.com/rdias/archive/2004/06/17/158802.aspx"
target="_top">http://blogs.msdn.com/rdias/archive/2004/06/17/158802.aspx</a></span></p>
</div>
<div class="bibliomixed"><a name="_14"></a>
<p class="bibliomixed">[_14] UDDI - <span class=
"bibliomisc"><a href="http://www.uddi.org/whitepapers.html" target=
"_top">http://www.uddi.org/whitepapers.html</a></span></p>
</div>
<div class="bibliomixed"><a name="_15"></a>
<p class="bibliomixed">[_15] WSDL Specification - <span class=
"bibliomisc"><a href="http://www.w3.org/TR/wsdl" target=
"_top">http://www.w3.org/TR/wsdl</a></span></p>
</div>
<div class="bibliomixed"><a name="_16"></a>
<p class="bibliomixed">[_16] Web Services - The Web's next
revolution - IBM DeveloperWorks - <span class="bibliomisc"><a href=
"http://www6.software.ibm.com/developerworks/education/wsbasics/wsbasics-ltr.pdf"
target=
"_top">http://www6.software.ibm.com/developerworks/education/wsbasics/wsbasics-ltr.pdf</a></span></p>
</div>
<div class="bibliomixed"><a name="_17"></a>
<p class="bibliomixed">[_17] SOAP Version 1.2 - <span class=
"bibliomisc"><a href=
"http://www.w3.org/TR/2003/REC-soap12-part0-20030624/" target=
"_top">http://www.w3.org/TR/2003/REC-soap12-part0-20030624/</a></span></p>
</div>
<div class="bibliomixed"><a name="_18"></a>
<p class="bibliomixed">[_18] SoapException documentation -
<span class="bibliomisc"><a href=
"http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebservicesprotocolssoapexceptionclasstopic.asp"
target=
"_top">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebservicesprotocolssoapexceptionclasstopic.asp</a></span></p>
</div>
<div class="bibliomixed"><a name="_19"></a>
<p class="bibliomixed">[_19] Using Web Services with J2EE -
<span class="bibliomisc"><a href=
"http://webservices.sys-con.com/read/39434.htm" target=
"_top">http://webservices.sys-con.com/read/39434.htm</a></span></p>
</div>
<div class="bibliomixed"><a name="_20"></a>
<p class="bibliomixed">[_20] The .Net System.Web.Services namespace
- <span class="bibliomisc"><a href=
"http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebservices.asp"
target=
"_top">http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfsystemwebservices.asp</a></span></p>
</div>
<div class="bibliomixed"><a name="_21"></a>
<p class="bibliomixed">[_21] CORBA / .Net interop: Janeva -
<span class="bibliomisc"><a href=
"http://www.devx.com/interop/Article/19916/1954?pf=true%20and%20http://www.borland.com/us/products/janeva/"
target=
"_top">http://www.devx.com/interop/Article/19916/1954?pf=true and
http://www.borland.com/us/products/janeva/</a></span></p>
</div>
<div class="bibliomixed"><a name="_22"></a>
<p class="bibliomixed">[_22] Exceptions in COM - Bob DeRemer -
<span class="bibliomisc"><a href=
"http://msdn.microsoft.com/msdnmag/issues/04/03/ExceptionsinCOM/default.aspx"
target=
"_top">http://msdn.microsoft.com/msdnmag/issues/04/03/ExceptionsinCOM/default.aspx</a></span></p>
</div>
<div class="bibliomixed"><a name="_23"></a>
<p class="bibliomixed">[_23] CORBA CORBA::UserException::id()
method - <span class="bibliomisc"><a href=
"http://publib.boulder.ibm.com/infocenter/adiehelp/index.jsp?topic=/com.ibm.wasee.doc/info/ee/corba/concepts/ccor_ipgmce.html"
target=
"_top">http://publib.boulder.ibm.com/infocenter/adiehelp/index.jsp?topic=/com.ibm.wasee.doc/info/ee/corba/concepts/ccor_ipgmce.html</a></span></p>
</div>
</div>
<div class="footnotes"><br>
<hr class="c6" width="100">
<div class="footnote">
<p><sup>[<a name="ftn.d0e219" href="#d0e219" id=
"ftn.d0e219">1</a>]</sup> Web Services in .Net can also be built
'from scratch' if required.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e236" href="#d0e236" id=
"ftn.d0e236">2</a>]</sup> There are similar implementations for
Java: see [<a href="#_19">_19</a>] for an example.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e362" href="#d0e362" id=
"ftn.d0e362">3</a>]</sup> Technically, it will also be necessary to
ensure that the class is serializable. For a C# class with simple
(serializable) fields, it is sufficient to mark the class with the
[<tt class="literal">Serializable</tt>] attribute.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e427" href="#d0e427" id=
"ftn.d0e427">4</a>]</sup> The target COM Object could be made to
support the <tt class="literal">IErrorInfo</tt> interface, which
could then be queried for the exception GUID.</p>
</div>
<div class="footnote">
<p><sup>[<a name="ftn.d0e452" href="#d0e452" id=
"ftn.d0e452">5</a>]</sup> See also <a href=
"http://udk.openoffice.org/common/man/uno_the_idea.html" target=
"_top">http://udk.openoffice.org/common/man/uno_the_idea.html</a>
for an interesting discussion on Java/RMI, CORBA and DCOM.</p>
</div>
</div>
</p>
<p><strong>Notes:</strong>&nbsp;</p>
<p><em>More fields may be available via dynamicdata ..</em></p>
</div>
</channel>
</rss>
