Logging Exceptions
We just took a rather long detour to talk about Exceptions, and now you're
very knowledgeable about them. But how do we use them in our code?
The upshot of this lesson is that there's a
special wyvern.lib.Kernel method devoted to printing out
Exception stack traces, and it's
called wyvern.lib.Kernel.throwing() . If you want to
catch an Exception in your code and print it out, you can using
throwing() just like the other Kernel logging methods.
A common example is when you're trying to instantiate a particular
archetype in your code. For example, here's a simple Monster Dispenser —
just a subclass of Lever that creates an Orc when you pull it:
<span class='string'>"""</span> <span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>:<br><span class='keyword'></span>A<span class='keyword'></span> <span class='keyword'></span>lever<span class='keyword'></span> <span class='keyword'></span>that<span class='keyword'></span> <span class='keyword'></span>creates<span class='keyword'></span> <span class='keyword'></span>an<span class='keyword'></span> <span class='keyword'></span>Orc<span class='keyword'></span> <span class='keyword'></span>whenever<span class='keyword'></span> <span class='keyword'></span>you<span class='keyword'></span> <span class='keyword'></span>apply<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<br><span class='string'>"""</span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span>.<span class='keyword'></span>classes<span class='keyword'></span>.<span class='keyword'></span>construct<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Lever<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Kernel<span class='keyword'></span><br><br><span class='keyword'>class</span> <span class='function'>monster_dispenser</span>(Lever):<br> <span class='keyword'>def</span> <span class='function'>apply</span>(self, agent):<br> <span class='keyword'></span>mon<span class='keyword'></span> = <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>instantiate<span class='keyword'></span>('<span class='keyword'></span>monsters<span class='keyword'></span>/<span class='keyword'></span>goblin<span class='keyword'></span>/<span class='keyword'></span>orc<span class='keyword'></span>')<br> <span class='keyword'></span>map<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getMap<span class='keyword'></span>()<br> <span class='keyword'></span>ref<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getReferenceLoc<span class='keyword'></span>()<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>setMap<span class='keyword'></span>(<span class='keyword'></span>map<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>x<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>y<span class='keyword'></span>)<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>start<span class='keyword'></span>()
|
If, for some reason, it failed to instantiate the Orc, it would
throw an Exception that you'd never see, because it would be
passed up to the ApplyCommand and be out of your reach. If you
had logging statements like this:
<span class='string'>"""</span> <span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>:<br><span class='keyword'></span>A<span class='keyword'></span> <span class='keyword'></span>lever<span class='keyword'></span> <span class='keyword'></span>that<span class='keyword'></span> <span class='keyword'></span>creates<span class='keyword'></span> <span class='keyword'></span>an<span class='keyword'></span> <span class='keyword'></span>Orc<span class='keyword'></span> <span class='keyword'></span>whenever<span class='keyword'></span> <span class='keyword'></span>you<span class='keyword'></span> <span class='keyword'></span>apply<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<br><span class='keyword'></span>This<span class='keyword'></span> <span class='keyword'></span>version<span class='keyword'></span> <span class='keyword'></span>uses<span class='keyword'></span> <span class='keyword'></span>Logging<span class='keyword'></span> <span class='keyword'></span>to<span class='keyword'></span> <span class='keyword'></span>try<span class='keyword'></span> <span class='keyword'></span>to<span class='keyword'></span> <span class='keyword'></span>figure<span class='keyword'></span> <span class='keyword'></span>out<span class='keyword'></span> <span class='keyword'></span>the<span class='keyword'></span> <span class='keyword'></span>problem<span class='keyword'></span>.<br><span class='string'>"""</span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span>.<span class='keyword'></span>classes<span class='keyword'></span>.<span class='keyword'></span>construct<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Lever<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Kernel<span class='keyword'></span><br><br><span class='keyword'>class</span> <span class='function'>monster_dispenser</span>(Lever):<br><br> <span class='keyword'>def</span> <span class='function'>initialize</span>(self):<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>super__initialize<span class='keyword'></span>()<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span> = '<span class='keyword'></span>wiz<span class='keyword'></span>/<span class='keyword'></span>rhialto<span class='keyword'></span>/<span class='keyword'></span>python<span class='keyword'></span>/<span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>'<br><br> <span class='keyword'>def</span> <span class='function'>apply</span>(self, agent):<br> <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>fine<span class='keyword'></span>(<span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span>, '<span class='keyword'></span>apply<span class='keyword'></span>', '<span class='keyword'></span>instantiating<span class='keyword'></span> <span class='keyword'></span>an<span class='keyword'></span> <span class='keyword'></span>Orc<span class='keyword'></span>')<br> <span class='keyword'></span>mon<span class='keyword'></span> = <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>instantiate<span class='keyword'></span>('<span class='keyword'></span>monsters<span class='keyword'></span>/<span class='keyword'></span>groblin<span class='keyword'></span>/<span class='keyword'></span>orc<span class='keyword'></span>')<br> <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>fine<span class='keyword'></span>(<span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span>, '<span class='keyword'></span>apply<span class='keyword'></span>', '<span class='keyword'></span>got<span class='keyword'></span> <span class='keyword'></span>Orc<span class='keyword'></span>!')<br> <span class='keyword'></span>map<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getMap<span class='keyword'></span>()<br> <span class='keyword'></span>ref<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getReferenceLoc<span class='keyword'></span>()<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>setMap<span class='keyword'></span>(<span class='keyword'></span>map<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>x<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>y<span class='keyword'></span>)<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>start<span class='keyword'></span>()
|
Well, you'd be confused, because your first logging statement
would get executed, but the second one wouldn't. The Exception
would just shoot straight out of the method, up to the caller.
You can catch the Exception and print it out like this:
<span class='string'>"""</span> <span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>:<br><span class='keyword'></span>A<span class='keyword'></span> <span class='keyword'></span>lever<span class='keyword'></span> <span class='keyword'></span>that<span class='keyword'></span> <span class='keyword'></span>creates<span class='keyword'></span> <span class='keyword'></span>an<span class='keyword'></span> <span class='keyword'></span>Orc<span class='keyword'></span> <span class='keyword'></span>whenever<span class='keyword'></span> <span class='keyword'></span>you<span class='keyword'></span> <span class='keyword'></span>apply<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<br><span class='keyword'></span>This<span class='keyword'></span> <span class='keyword'></span>version<span class='keyword'></span> <span class='keyword'></span>has<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span> <span class='keyword'></span>handling<span class='keyword'></span>.<br><span class='string'>"""</span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span>.<span class='keyword'></span>classes<span class='keyword'></span>.<span class='keyword'></span>construct<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Lever<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Kernel<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>java<span class='keyword'></span>.<span class='keyword'></span>lang<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span><br><br><span class='keyword'>class</span> <span class='function'>monster_dispenser</span>(Lever):<br><br> <span class='keyword'>def</span> <span class='function'>initialize</span>(self):<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>super__initialize<span class='keyword'></span>()<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span> = '<span class='keyword'></span>wiz<span class='keyword'></span>/<span class='keyword'></span>rhialto<span class='keyword'></span>/<span class='keyword'></span>python<span class='keyword'></span>/<span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>'<br><br> <span class='keyword'>def</span> <span class='function'>apply</span>(self, agent):<br> <span class='keyword'></span>try<span class='keyword'></span>:<br> <span class='keyword'></span>mon<span class='keyword'></span> = <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>instantiate<span class='keyword'></span>('<span class='keyword'></span>monsters<span class='keyword'></span>/<span class='keyword'></span>groblin<span class='keyword'></span>/<span class='keyword'></span>orc<span class='keyword'></span>')<br> <span class='keyword'></span>map<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getMap<span class='keyword'></span>()<br> <span class='keyword'></span>ref<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getReferenceLoc<span class='keyword'></span>()<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>setMap<span class='keyword'></span>(<span class='keyword'></span>map<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>x<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>y<span class='keyword'></span>)<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>start<span class='keyword'></span>()<br><br> <span class='keyword'></span>except<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span>, <span class='keyword'></span>xc<span class='keyword'></span>:<br> <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>throwing<span class='keyword'></span>(<span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span>, '<span class='keyword'></span>apply<span class='keyword'></span>', <span class='keyword'></span>xc<span class='keyword'></span>)
|
Now when you clone the object, drop it, and apply it, you get
— nothing! It doesn't work, but we're not seeing the Exception
stack trace, either.
That's because Kernel.throwing() only prints the
Exception stack trace if the log level is set to FINER. So we do
this:
debug finer wiz/rhialto/python/monster_dispenser.py
You will start seeing log messages at level FINER for wiz/rhialto/python/monster_dispenser.py
apply dispenser
--wiz/rhialto/python/monster_dispenser.py.apply():
java.io.FileNotFoundException: \games\wyvern\arch\monsters\groblin\orc.arch
(The system cannot find the path specified)
at java.io.FileInputStream.open(Native Method)
at java.io.FileInputStream.(FileInputStream.java:103)
at java.io.FileInputStream.(FileInputStream.java:66)
at wyvern.kernel.properties.XMLWrapper.parseArchetypeFile(XMLWrapper.j
at wyvern.kernel.properties.ArchetypeManager.parseArchetypeFile(Archet
at wyvern.kernel.properties.ArchetypeManager.parseSystemArchetype(Arch
at wyvern.kernel.properties.ArchetypeManager.loadArchetype(ArchetypeMa
at wyvern.kernel.properties.ArchetypeManager.instantiate(ArchetypeMana
at wyvern.lib.Kernel.instantiate(Kernel.java:81)
at sun.reflect.GeneratedMethodAccessor45.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAcc
at java.lang.reflect.Method.invoke(Method.java:324)
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.ja
at org.python.core.PyReflectedFunction.__call__(PyReflectedFunction.ja
at org.python.core.PyObject.__call__(PyObject.java)
at org.python.core.PyObject.invoke(PyObject.java)
at org.python.pycode._pyx81.apply$3(/games/wyvern/wiz/rhialto/python/m
at org.python.pycode._pyx81.call_function(/games/wyvern/wiz/rhialto/py
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyTableCode.call(PyTableCode.java)
at org.python.core.PyFunction.__call__(PyFunction.java)
at org.python.core.PyMethod.__call__(PyMethod.java)
at org.python.core.PyObject.__call__(PyObject.java)
at org.python.core.PyObject._jcallexc(PyObject.java)
at org.python.core.PyObject._jcall(PyObject.java)
at org.python.proxies.main$monster_dispenser$41.apply(Unknown Source)
at wyvern.lib.commands.ApplyCommand.execute(ApplyCommand.java:207)
at wyvern.kernel.kernel.Executive.dispatchEvent(Executive.java:852)
at wyvern.kernel.kernel.Executive.workerLoop(Executive.java:750)
at wyvern.kernel.kernel.Executive.access$0(Executive.java:43)
at wyvern.kernel.kernel.Executive$WorkerThread.run(Executive.java:71
That's great! The very first line told us the problem — namely, the
game doesn't know what the heck this is:
\games\wyvern\arch\monsters\groblin\orc.arch
We just need to change "groblin" to "goblin", and we're all set.
It sure would be nice if we didn't have to have the rest of that
stack trace printed, since the first line told us what we wanted
to know (which happens a lot of the time.) Well, our wish is
granted. Should've wished for a million bucks. But here's
what you can do:
<span class='string'>"""</span> <span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>:<br><span class='keyword'></span>A<span class='keyword'></span> <span class='keyword'></span>lever<span class='keyword'></span> <span class='keyword'></span>that<span class='keyword'></span> <span class='keyword'></span>creates<span class='keyword'></span> <span class='keyword'></span>an<span class='keyword'></span> <span class='keyword'></span>Orc<span class='keyword'></span> <span class='keyword'></span>whenever<span class='keyword'></span> <span class='keyword'></span>you<span class='keyword'></span> <span class='keyword'></span>apply<span class='keyword'></span> <span class='keyword'></span>it<span class='keyword'></span>.<br><span class='keyword'></span>This<span class='keyword'></span> <span class='keyword'></span>version<span class='keyword'></span> <span class='keyword'></span>has<span class='keyword'></span> <span class='keyword'></span>FINE<span class='keyword'></span>-<span class='keyword'></span>level<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span> <span class='keyword'></span>message<span class='keyword'></span> <span class='keyword'></span>printing<span class='keyword'></span>,<br><span class='keyword'></span>and<span class='keyword'></span> <span class='keyword'></span>FINER<span class='keyword'></span>-<span class='keyword'></span>level<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span> <span class='keyword'></span>stack<span class='keyword'></span> <span class='keyword'></span>trace<span class='keyword'></span> <span class='keyword'></span>printing<span class='keyword'></span>.<br><span class='string'>"""</span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span>.<span class='keyword'></span>classes<span class='keyword'></span>.<span class='keyword'></span>construct<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Lever<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>wyvern<span class='keyword'></span>.<span class='keyword'></span>lib<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Kernel<span class='keyword'></span><br><span class='keyword'></span>from<span class='keyword'></span> <span class='keyword'></span>java<span class='keyword'></span>.<span class='keyword'></span>lang<span class='keyword'></span> <span class='keyword'></span>import<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span><br><br><span class='keyword'>class</span> <span class='function'>monster_dispenser</span>(Lever):<br><br> <span class='keyword'>def</span> <span class='function'>initialize</span>(self):<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>super__initialize<span class='keyword'></span>()<br> <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span> = '<span class='keyword'></span>wiz<span class='keyword'></span>/<span class='keyword'></span>rhialto<span class='keyword'></span>/<span class='keyword'></span>python<span class='keyword'></span>/<span class='keyword'></span>monster_dispenser<span class='keyword'></span>.<span class='keyword'></span>py<span class='keyword'></span>'<br><br> <span class='keyword'>def</span> <span class='function'>apply</span>(self, agent):<br> <span class='keyword'></span>try<span class='keyword'></span>:<br> <span class='keyword'></span>mon<span class='keyword'></span> = <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>instantiate<span class='keyword'></span>('<span class='keyword'></span>monsters<span class='keyword'></span>/<span class='keyword'></span>groblin<span class='keyword'></span>/<span class='keyword'></span>orc<span class='keyword'></span>')<br> <span class='keyword'></span>map<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getMap<span class='keyword'></span>()<br> <span class='keyword'></span>ref<span class='keyword'></span> = <span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>getReferenceLoc<span class='keyword'></span>()<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>setMap<span class='keyword'></span>(<span class='keyword'></span>map<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>x<span class='keyword'></span>, <span class='keyword'></span>ref<span class='keyword'></span>.<span class='keyword'></span>y<span class='keyword'></span>)<br> <span class='keyword'></span>mon<span class='keyword'></span>.<span class='keyword'></span>start<span class='keyword'></span>()<br><br> <span class='keyword'></span>except<span class='keyword'></span> <span class='keyword'></span>Exception<span class='keyword'></span>, <span class='keyword'></span>xc<span class='keyword'></span>:<br><span class='comment'> # print the Exception message at level FINE, and print</span><br><span class='comment'> # the entire Exception stack trace at level FINER</span><br> <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>fine<span class='keyword'></span>(<span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span>, '<span class='keyword'></span>apply<span class='keyword'></span>', <span class='keyword'></span>xc<span class='keyword'></span>.<span class='keyword'></span>getMessage<span class='keyword'></span>())<br> <span class='keyword'></span>Kernel<span class='keyword'></span>.<span class='keyword'></span>throwing<span class='keyword'></span>(<span class='keyword'></span><span class='instance'>self</span><span class='keyword'></span>.<span class='keyword'></span>logname<span class='keyword'></span>, '<span class='keyword'></span>apply<span class='keyword'></span>', <span class='keyword'></span>xc<span class='keyword'></span>)<br><br><span class='comment'> # tell the agent an error occurred</span><br> <span class='keyword'></span>agent<span class='keyword'></span>.<span class='keyword'></span>message<span class='keyword'></span>('<span class='keyword'></span>The<span class='keyword'></span> <span class='keyword'></span>dispenser<span class='keyword'></span> <span class='keyword'></span>appears<span class='keyword'></span> <span class='keyword'></span>to<span class='keyword'></span> <span class='keyword'></span>be<span class='keyword'></span> <span class='keyword'></span>broken<span class='keyword'></span>')
|
Now we can debug the class at level FINE, and we'll only see the
first line of the stack trace:
debug fine wiz/rhialto/python/monster_dispenser.py
You will start seeing log messages at level FINE for wiz/rhialto/python/monster_dispenser.py
apply dispenser
--wiz/rhialto/python/monster_dispenser.py.apply():
\games\wyvern\arch\monsters\groblin\orc.arch (The system cannot find the path specified)
Ahhh, satisfaction at last. Everything is set up perfectly:
-
We catch Exceptions in our code and handle them (in this case,
by telling the agent that the dispenser is busted)
-
We've got a FINE logging message that should tell us what's
going wrong if there's a problem
-
If the FINE message isn't good enough, we can get very
detailed information at the FINER level.
And that, as they say, is that. Now you know all about
logging Exceptions. You're also ready to start coding with logging!
|