Ricks
Ricks

Reputation: 11

Catching C# errors at the class library level

I am trying to work out an error logging solution for an enterprise-level class library. Some of the requirements:

There's one more requirement, which is a 'very nice to have'. That is, it's not critical, but if it's not feasibly possible I'd better have a darned good reason for it.

The first three points are not that difficult, all things considered. A quick logging class and some stored procedures, call it a day at noon, right? The last point is something I don't know how to approach, though. I've seen it done before in a friend's code, so I know it is possible, but said friend has unfortunately passed on and his code is lost to the ether. Is there anyone out there who could point me in the correct direction of having a class library object somehow catch all errors coming up from an end-point application to process them?

Upvotes: 1

Views: 2818

Answers (3)

Alois Kraus
Alois Kraus

Reputation: 13535

When I read enterprise level class library I have these requirement in my head:

  • Your component shall not throw exceptions and disturb the system.
  • It shall deal with errors gracefully and be able to recover from errors.

Such requirements are a good read for you as a developer before you go to bed. All error scenarios even the ones in your wildest dreams will become reality sooner or later and you wake up at 3 am in the night screaming.

The requirements sound good but its implications are far reaching. If you try to catch all errors in your component you do nothing else than error hiding. Such systems tend to be slow and sometimes they do simply stop working and nobody knows why because some follow up error did bring the system into a state where really nothing does work. The sad thing is that if you attach a debugger to that stale machine you will not see the original error that caused the problem but a follow up problem from where you have to work backwards to the original problem. If you want to log to SQL server I can assure you that you will end up with no or missing logs quite frequently.

You should consider more reliable log destinations (custom event log, log file, ... or both). And avoid async logging at all costs since an unhandled exception will bring down the process much faster than you are able to log it away in your logging thread.

In reality you need to bring the system to a halt as early as possible when a fatal error has occured. The errors from which you can safely recover without corrupting state are usually very few but they are worth the effort since you need to design your class library to be robust (deal with expected errors) and safe (throw exceptions, log them, ...).

During the design phase it is easier to think of a perfect system that can cope with all errors. Software architects like such systems. And they can get away with it because on paper it looks good. Or to put it in other words: Bubbles don´t crash.

But at execution time your class library is using

  • Real Physical Memory (OutOfMemoryException)
  • Real Hard Disc space (at least log files) (Hard disc full)
  • Real CPU cycles (100% CPU)
  • Real Stack Space (StackOverFlowException)

If you try to hide fatal errors the system has only become harder to debug but it will still fail since your library will is consuming shared resources which do not exclusively belong to your component. It is better to stop working immediately in such situations than to continue and let others fail as well.

The idea to hide all errors inside a component is flawed since you cannot prevent fatal errors inside your component to influence other components in the system.

That beeing said I hope you did not ask how to catch all errors at class library level but at your end-point applications where you display errors to the user and log them (hopefully only once and not again in every layer because you do not trust the other layers). As others have pointed out you can get your hands on unhandled exceptions which did terminate a thread which will in turn terminate your process when your error handler is left. Besides this it is a good idea to put a try/catch block around your Main method to catch errors in the main thread. If you application has an UI (Windows Forms) you should also register to the Application.ThreadException event which will be called when an exception propagates out of a Window message handler.

Yours, Alois Kraus

Upvotes: 1

Jacob
Jacob

Reputation: 78848

If you're wanting to catch all unhandled exceptions not originating within your own call stack, you could look into utilizing the AppDomain object:

AppDomain.CurrentDomain.UnhandledException += (s, e) => {
    // Your logging logic
};

AppDomain.CurrentDomain.FirstChanceException += (s, e) => {
    // Your logging logic
};

Upvotes: 4

Dean North
Dean North

Reputation: 3780

Sounds like the Microsoft Enterprise Library could be of use here...

http://msdn.microsoft.com/en-us/library/ff649552.aspx

Upvotes: 1

Related Questions