Bubble up exception with custom properties and log with serilog - c#

I came across a situation where I thought it'd be good to rethrow an exception, appending additional information to it (for example in properties in a custom exception) that when caught further up the stack would be logged with the additional info in the form of properties of a message template in Serilog - the end goal being so I can then filter on those properties in Seq. This scenario might be a warning that I need to rethink my exception handling, but I thought I'd ask if this has been done before with Serilog? Recommended/discouraged?
Update
Here's an example scenario:
Using serilog and Seq we apply a "Department" property to a log so that a department can easily see all exceptions that are likely their responsibility.
Now the app for this scenario basically does two things:
Step 1: Query data.
Step 2: If no exceptions in step 1, post it somewhere else.
A few layers deep in step 1 there is a particular exception that I know is the responsibility of a particular department. So I'd like to apply a department property to this exception when it is logged but at the same time have it be caught further up the stack so that the exception prevents continuation of everything else. Also, I only want to log the exception once.
My current approach is to define a custom exception with a dictionary that can hold properties for the log:
public class ExtPropertiesException : Exception
{
// Constructors here...
/// <summary>
/// Properties to log with the error message
/// </summary>
public Dictionary<string, object> ExtProperties { get; set; }
}
So when I catch an exception I know is a particular departments responsibility I rethrow it as ExtPropertiesException or as an exception that inherits it, attaching the original exception as the inner exception.
Then back up the stack where the general steps are I've got a catch:
try
{
// Step 1
// Step 2
}
catch (ExtPropertiesException ex)
{
if (ex.ExtProperties != null)
{
foreach (var prop in ex.ExtProperties)
{
logger = logger.ForContext(prop.Key, prop.Value);
}
}
logger.Error(ex, ex.Message);
}
This seems to be doing what I need, but it'd be great to know whether it's a best practice before repeating it elsewhere.
I was initially doing the logs and applying the property at the time I catch the exception and then just returning false or null to indicate failure and abandon future steps, however I've found it difficult for unit testing as I can't determine the type of errors from outside the methods.
Thanks

Best practice is hard to judge; rather than the ForContext() code above you can do:
try
{
// Step 1
// Step 2
}
catch (ExtPropertiesException ex)
{
logger.Error(ex, "Exception caught, data is {#ExtProperties}", ex.ExtProperties);
}
This will attach a single "object" property to the event, carrying the data from ExtProperties.

Related

Exception handling best practices in multi-tier architecture

I have an application with three-tire architecture. And I don't understand how to work with exceptions in this context. I collected some questions:
1 . Do I need to create a generic exceptions, like PersistentException, and make all DAO classes methods to throw exeption only of one type - PersistentException? I.e. inside every DAO method (CRUD) do like this:
public create(Entity instance) {
try {
...// all operations here
} catch(Exception e) {
throw new PersistentException(e);
}
}
2 . It's OK to create one exception class for every EJB service (One exception per EJB interface)?
I.e. suppose I have a EJB beans like PersonManagementBean, OrganizationManagementBean, EmployeeManagementBean with corresponding #local and #remote interfaces. They are exposed to clients, i.e. in fact they are Session Facades (so they are located in service layer). So it's good idea to create corresponding Exception classes for every bean (PersonManagementException,OrganizationManagementException, EmployeeManagementException)?
Or it's better to have only one exception called ServiceException (as in case of DAOs)?
3 . What type of exceptions can throw my service (busyness) level (in common case)? Can I propagate DAO (PersistentException) exceptions to clients? i.e.
public void relocatePerson() {
try {
Person p = personDao.getPerson(); // can throw PersistentException
....
if (someCondition) {
throw new PersonManagementException(); // throwing same PersonManagementException
}
....
} catch(PersonManagementException e) {
throw e; //don't need to rewrap same exception
} catch(PersistentException e) {
throw e; // DO I need to throw it as PersistentException to client? Or it's better to rewrap it as PersonManagementException?
} catch(Exception e) {
throw new PersonManagementException(e) //throwing all exception as service specific exception
}
}
Or I need to rethrow all exceptions (in common case) as service-specific exceptions?
"In common case" I mean here that I know that in some cases some methods can throw additional exceptions with some helpful information (for example ValidationException with information about which objects don't pass validation rules)
Yes, you should make all DAO classes methods to throw exeption only of one type - PersistentException. Because it may help you to catch every kind of DB related exceptions into 1 type. Moreover, you can set messages about the particular exception while setting it into PersistantException using parametrized constructor. i.e. throw new PersistentException("Exception while opening a connection",e);
Your second question totally depends on your requirement. If you want to show different errors and showing different error pages and want to handle them (errors of each bean) separately then you should create separate exception class for each of your beans.
Your third question, as per my point of view its fine. You can propagate PersistentException to the level from where DAO or Helpers are being called first - i.e. ActionBean OR servlet.
There you can set your error messages and then you can throw them to your architecture level handlers (which is generally configured in configuration or xml files)
While working with exceptions dont forget that "to throw early and catch late"
For any exception that signals failure, use just one exception. Rationale: the client can't do anything in this case but log the stacktrace and/or report the error to the user.
I some special circumstances you'll need to throw an exception just to signal that an alternative approach to serving the request is needed. Only these cases need a specific exception.
The remote client will almost never want to know anything else than that a failure occurred; be very careful not to burden your remote interface with redundant exception classes.

Two exception management questions

I have a couple of questions around exception management for a website:
in the catch block can I have a static class with a handle exception method that handles the exception like so:
catch (Exception ex)
{
throw ExceptionHandler.HandleException(...);
}
where ExceptionHandler.HandleException is a static method that returns a variable of type System.Exception. Is this a good practice? Any possible problems with this approach? Will it be thread safe?
In my application I have a DAL layer that is called by the Business layer and the Business layer is called by the UI. So, is it a good practice to just re-throw all Custom exceptions so they bubble up right up to the UI where they get displayed whereas System.Exception types get logged and I throw a custom exception in the catch block?
for eg in DAL and Business Layer like so:
catch (CustomExceptionBase ex)
{
throw;
}
catch (Exception sysEx)
{
ICustomExceptionBase ex = new SysException(sysEx);
ex.Handle();
throw BusinessException("Some problem while serving your request");
}
In the UI layer like so
catch (CustomExceptionBase ex)
{
//when custom exception bubbles up; code to display text to user on screen
}
catch (Exception sysEx)
{
ICustomExceptionBase ex = new SysException(sysEx);
ex.Handle();
//display error on screen;
}
Here CustomExceptionBase implements ICustomExceptionBase and inherits Exception. SysException & BusinessException both inherit from CustomExceptionBase.
Thanks for your time...
EDIT
The intent of rethrowing in the system.Exceptions block is so that if there is a fatal error like database connection lost or something similar then I log it for the technical helpdesk and return a ticket number and rethrow the same so the user knows that something went wrong and this is your reference number to follow up. For all custom exceptions in the DAL layer or Business layer, I just bubble it up all the way to the UI where the text gets displayed.
I suspect some of the answers at least are entirely down to your architecture. In the first case it all depends on what ExceptionHandler.HandleException does exactly. Does it generate a new exception based on some criteria or is it just going to return the original exception?
Whether its thread-safe or not entirely depends on its implementation. For example in the following trivial case I'd say it was thread safe:
public static Exception ExceptionHandler.HandleException(Exception ex)
{
return ex;
}
In other cases it could easily be not thread safe. eg:
public static string message;
public static Exception ExceptionHandler.HandleException(Exception ex)
{
message = ex.ToString;
sleep(2000);
return new Exception(message);
}
The latter example clearly has scope for the message variable to be changed by another thread while this one is asleep.
As for the second... Exceptions should be handled where it makes sense to handle them. There is no hard and fast rule. If some part of the code can effect a recovery from an exception (or is willing to skip over it) then catch it at that point and not earlier. If an exception is truly fatal then nothing should be trying to catch it and pretend otherwise so you should just let it bubble right up to the top and do something like alert your user that things have crashed and that you need to restart or whatever.
So really it depends on what your custom exceptions mean. If they just mean "You want to retry this" then that is different from an exception saying "Data integrity has been compromised: 0==1". both of these may be custom so really its for you to decide where to handle things.
Yes, you can call a static exception handler inside a catch block and it will likely be threadsafe as long as you don't reference any static variables.
You should look at Microsoft's Enterprise Library. It has nearly this same design but uses exception policies defined in the web.config to control how the exception is bubbled, wrapped or discarded. Couple that with the Application Logging block and you have a complete solution.
In itself there aren't any technical problems having a static method to handle exceptions / rethrow exceptions, however from a best practices point of view having a single method that magically "handles" exceptions strikes me as a potential code smell. Exceptions are by their very name exceptional, each individual case requires thought to go into it to make sure that you are doing the correct thing and so I find it unlikely that your HandleException method will always be doing something sensible.
As an extreme example I know of one such application where pretty much every single method was wrapped in a try-catch block with a call to an static exception handler method which threw a generic MyApplicationException type. This is an extremely bad idea:
It clutters the code
It makes it harder to make sense of stack traces
It makes it very difficult for callers to catch and handle specific exceptions types
It makes throwing an exception an even bigger performance penalty than before
My favourite was a method which wasn't implemented which looked a bit like this:
void SomeException()
{
try
{
throw new NotImplementedException();
}
catch(Exception ex)
{
throw ExceptionHandler.HandleException(...);
}
}
The worst bit of this of course that it is completely mindless. As I said before exceptions are exceptional - each try ... catch block requires careful thought and consideration to be put into how it should behave, the use of a generic HandleException method is an immediate warning flag that this probably isn't the case.
Rethrowing exceptions
Generally speaking you should only rethrow an exception in two cases:
When you want to add contextual information to an exception (such as the name of the current file being processed)
When you had to catch an exception in order to handle some specific case, e.g. handling an "out of disk space" error
catch (IOException ex)
{
long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
if (win32ErrorCode == ERROR_HANDLE_DISK_FULL || win32ErrorCode == ERROR_DISK_FULL)
{
// Specific "out of disk space" error handling code
}
else
{
throw;
}
}
"Bubbling" (i.e. catching and rethrowing an exception without doing anything with it) is completely unneccessary - this is what exceptions are already designed to do all by themselves!
Handling exceptions
Other people have said "exceptions should be handled where it makes sense" and I have even given this advice myself, but in hindsight I don't think thats particularly useful advice! :)
What people generally mean by that is that you should handle exceptions for specific reasons, and that you should choose where in your application to handle that exception depending on that reason.
For example if you want to display an error message to inform the user that they don't have permission to modify a file if you get an access denied error then you may have a specific try-catch block in your UI code that does this:
catch (IOException ex)
{
long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
if (win32ErrorCode == ERROR_ACCESS_DENIED)
{
// Display "access denied error"
}
else
{
throw;
}
}
Note that this is very specific to this one case that we wish to handle - it catches only the specific exception type were are interested in and performs additional checks to filter down to the specific case we are interested in.
Alternatively if you want to log unhandled errors or gracefully display error messages to the user instead of an IIS 505 error screen then the place to do this is either in Global.asax or through a custom error page - ASP.Net Custom Error Pages
My point is that when handling exceptions we are are thinking carefully about what it is we want to achieve in terms of application functionality (e.g. retry logic, error messages, logging etc...) and implementing our exception handling logic to specifically address those requirements in the most targeted way possible - there is no magic exception handing framework and there is no boilerplate code.
Avoid exceptions entirely whenever possible!
I usually find that the best strategy is simply to avoid exceptions entirely whever possible! For example if your page parses user enter numbers and you want to display validation messages when they enter stupid values then validate your input up-front instead of catching exceptions:
Bad:
void DoSomething()
{
int age = int.Parse(ageTextBox.Text);
if (age < 0)
{
throw new ArgumentOutOfRangeException("age must be positive");
}
if (age >= 1000)
{
throw new ArgumentOutOfRangeException("age must be less than 1000");
}
}
void Button_Click(object sender, EventArgs e)
{
try
{
DoSomething();
}
catch (Exception ex)
{
DisplayError(ex.Message);
}
}
Good:
void Button_Click(object sender, EventArgs e)
{
int age;
if (!int.TryParse(ageTextBox.Text, out age))
{
DisplayError("Invalid age entered");
}
if (age < 0)
{
DisplayError("age must be positive");
}
if (age >= 1000)
{
DisplayError("age must be less than 1000");
}
DoSomething();
}
Users enter invalid data all of the time - handling this is really application logic and shouldn't fall into the real of exception handling - its certainly not an event that I would call "exceptional".
Of course this isn't always possible, however I find that using this strategy simplifies the code and makes it easier to follow application logic.
First of all we need to consider Exception types, In any business exception can be either BusinessException or Technical/SystemException.
In BusinessException we can send custom exceptions with error
details.
In Technical/System Exception we should not handle it, but let it
popup to UI layer.UI Can decide what error should be displayed in
case of exceptions.
In your approaches, if you handle exception or throw the custom
exception the call trace is lost.

Exception handling with Elmah

I log exceptions with Elmah and was wondering if the technique I am using is good design?
Right now I catch and re throw exceptions that occur in various classes and methods, and log them to Elmah in the main try-catch block of the program.
// Main Program
try
{
// Some code that fires off other classes, etc...
MyTestClass myTestClass = new MyTestClass();
myTestClass.Execute();
}
catch(Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
}
// MyTestClass
public class MyTestClass
{
public object ApiResult { get; set; }
public string Execute()
{
try
{
// execute some code
// ....
// set xml message
ApiResult = "User information xml response";
}
catch (Exception ex)
{
// set xml message
ApiResult = "something went wrong xml error response...";
throw;
}
}
}
Would it be better to log the exceptions where they occur? Another question, should I log errors that I can handle without catching exceptions? For example if something is null, should I do a test for that (if null...) and log a message in Elmah?
Rather than manually logging an error using Elmah's ErrorSignal class you should instead strive to let ELMAH log errors for you automatically, which occurs when the application's Error event is raised.
In your example there's a serious problem with Main Program. Namely, it is swallowing exceptions, at least for the end user. Yes, the exception is getting logged in ELMAH but you are hiding the error from the user. The end user will think her form submission (or whatever) went through without error, when in actuality there was a grave problem.
In short, try...catch blocks should only be used sparingly, such as in cases where you can recover from an error or when the error is a "minor" one and should not stop the workflow. But the majority of errors are real show stoppers and don't have graceful workaround. For this majority you'd want to let the error percolate up to the ASP.NET runtime where ELMAH will automatically log it and where the user will see an error page, alerted them to the fact that an error has occurred.
Check out this article of mine: Exception Handling Advice for ASP.NET Web Applications.
I think the following situation will give you an idea for when to use ErrorSignal.FromCurrentContext().Raise(ex);
var bo = new CustomerBO();
bo.Update(customer);
try
{
Email.SendProfileChangedNotification();
}
catch(Exception ex)
{
ErrorSignal.FromCurrentContext().Raise(ex);
}
Response.Redirect(Constants.ProfilePage);
Email.SendProfileChangedNotification method is not so important in this code, I mean, I can leave with it if it has any errors and I don't want to show them to the user. The important part is that his/her profile is updated and the user is aware of it by seeing the profile page.
So I believe there places in code which may fail constantly, I would like to get notified about them, but I don't want to break down the entire action.

Exceptions from SoapHttpClientProtocol.Invoke Method .NET web service

I am calling a web service from a C# forms based app.
ServReturnType obj = ServProxyClass(int i, int k);
I have the potential to get back an exception. The exception could be that the service didn't connect at all, that there was a failure on the receive, but the original message went, or anything in between. I then need to make a decision based on the exception thrown, either on the type, or the message, or both, as to do one of two actions next.
try
{
ServReturnType obj = ServProxyClass(int i, int k);
}
catch (WebException ex)
{
DoAction1();
}
catch(SocketException ex)
{
DoAction2();
}
catch(SoapException ex)
{
DoAction1()
}
The issues is, my choice of subsequent actions depends on whether or not the first call made it to the server before failing. How can I find a list of all possible exceptions thrown, and what they might mean, as this is all code in the framework. I looked that MSDN docs, and saw that SoapHttpClientProtocol.Invoke can throw a SoapException, however there are methods called by this method that bubble up System.Net.WebExceptions. So I need a list of the whole call stack and what it can throw, and what that means.
Any ideas?
Update 1
Darin, your answer more or less confirms my suspicions that what I want doesn't really make sense. I have opted to do more detective work first, then use that to decide what to do next. Unfortunately in this case, since we are processing credit cards, it really matters what exactly has happened, and whether or not we sent data.
The complete list of exceptions that can be thrown from a web service call is so vast that I really don't think that it is a good idea to test for every type of exception possible. In many cases it would be enough to catch for SoapException which could contain some business errors transmitted through the SOAP Fault Element and every other exception could be considered as a non handled error:
try
{
ServReturnType obj = ServProxyClass(int i, int k);
}
catch(SoapException ex)
{
//Serialize and analyze the fault message from the exception to obtain more info.
DoSomethingWithTheInfo();
}
catch(Exception ex)
{
LogTheExceptionSoThatLaterYouKnowWhatHappened(ex);
SayToTheUserThatSomethingTerriblyWrongHappened();
}
Here's a nice article explaining how to raise and handle SoapExceptions.

Easy way to catch all unhandled exceptions in C#.NET

I have a website built in C#.NET that tends to produce a fairly steady stream of SQL timeouts from various user controls and I want to easily pop some code in to catch all unhandled exceptions and send them to something that can log them and display a friendly message to the user.
How do I, through minimal effort, catch all unhandled exceptions?
this question seems to say it's impossible, but that doesn't make sense to me (and it's about .NET 1.1 in windows apps):
All unhandled exceptions finally passed through Application_Error in global.asax. So, to give general exception message or do logging operations, see Application_Error.
If you need to catch exeptions in all threads the best aproach is to implement UnhandledExceptionModule and add it to you application look here
for an example
Use the Application_Error method in your Global.asax file. Inside your Application_Error method implementation call Server.GetLastError(), log the details of the exception returned by Server.GetLastError() however you wish.
e.g.
void Application_Error(object sender, EventArgs e)
{
// Code that runs when an unhandled error occurs
log4net.ILog log = log4net.LogManager.GetLogger(typeof(object));
using (log4net.NDC.Push(this.User.Identity.Name))
{
log.Fatal("Unhandled Exception", Server.GetLastError());
}
}
Don't pay too much attention to the log4net stuff, Server.GetLastError() is the most useful bit, log the details however you prefer.
The ELMAH project sounds worth a try, its list of features include:
ELMAH (Error Logging Modules and
Handlers) is an application-wide error
logging facility that is completely
pluggable. It can be dynamically added
to a running ASP.NET web application,
or even all ASP.NET web applications
on a machine, without any need for
re-compilation or re-deployment.
Logging of nearly all unhandled exceptions.
A web page to remotely view the entire log of recoded exceptions.
A web page to remotely view the full details of any one logged
exception.
In many cases, you can review the original yellow screen of death that
ASP.NET generated for a given
exception, even with customErrors mode
turned off.
An e-mail notification of each error at the time it occurs.
An RSS feed of the last 15 errors from the log.
A number of backing storage implementations for the log
More on using ELMAH from dotnetslackers
You can subscribe to the AppDomain.CurrentDomain.UnhandledException event.
It's probably important to note that you are not supposed to catch unhandled exceptions. If you are having SQL timeout issues, you should specifically catch those.
Do you mean handling it in all threads, including ones created by third-party code? Within "known" threads just catch Exception at the top of the stack.
I'd recommend looking at log4net and seeing if that's suitable for the logging part of the question.
If using .net 2.0 framework, I use the built in Health Monitoring services. There's a nice article describing this method here: https://web.archive.org/web/20210305134220/https://aspnet.4guysfromrolla.com/articles/031407-1.aspx
If you're stuck with the 1.0 framework, I would use ELMAH:
http://msdn.microsoft.com/en-us/library/aa479332.aspx
hope this helps
There are 2 parts to this problem handling & identifying.
Identifying
This is what you do when the exception is finally caught, not necessarily where it is thrown. So the exception at that stage must have enough context information for you to idenitfy what the problem was
Handling
For handling, you can
a) add a HttpModeule. See
http://www.eggheadcafe.com/articles/20060305.asp
I would suggest this approach only when there is absolutely no context informaatn available and there might be issuus wiih IIS/aspnet, In short for catastrophic situations
b) Create a abstract class called AbstractBasePage which derives from Page class and have all your codebehind classes derive from AbstractBasePage
The AbstractBasePage can implement that Page.Error delegate so that all exceptions which percolate up through the n-tier architecture can be caught here(and possibly logged)
I would suggest this cause for the kind of exceptions you are talking about (SQlException) there is enough context information for you to identify that it was a timeout and take possible action. This action might include redirecting user to a custom error page with appropriate message for each different kind of exception (Sql, webservice, async call timeouts etc).
Thanks
RVZ
One short answer is to use (Anonymous) delegate methods with common handling code when the delegate is invoked.
Background: If you have targeted the weak points, or have some boilerplate error handling code you need to universally apply to a particular class of problem, and you don't want to write the same try..catch for every invocation location, (such as updating a specific control on every page, etc).
Case study: A pain point is web forms and saving data to the database. We have a control that displays the saved status to the user, and we wanted to have common error handling code as well as common display without copy-pasting-reuse in every page. Also, each page did it's own thing in it's own way, so the only really common part of the code was the error handling and display.
Now, before being slammed, this is no replacement for a data-access layer and data access code. That's all still assumed to exist, good n-tier separation, etc. This code is UI-layer specific to allow us to write clean UI code and not repeat ourselves. We're big believers in not quashing exceptions, but certain exceptions shouldn't necessitate the user getting a generic error page and losing their work. There will be sql timeouts, servers go down, deadlocks, etc.
A Solution: The way we did it was to pass an anonymous delegate to a method on a custom control and essentially inject the try block using anonymous delegates.
// normal form code.
private void Save()
{
// you can do stuff before and after. normal scoping rules apply
saveControl.InvokeSave(
delegate
{
// everywhere the save control is used, this code is different
// but the class of errors and the stage we are catching them at
// is the same
DataContext.SomeStoredProcedure();
DataContext.SomeOtherStoredProcedure();
DataContext.SubmitChanges();
});
}
The SaveControl itself has the method like:
public delegate void SaveControlDelegate();
public void InvokeSave(SaveControlDelegate saveControlDelegate)
{
// I've changed the code from our code.
// You'll have to make up your own logic.
// this just gives an idea of common handling.
retryButton.Visible = false;
try
{
saveControlDelegate.Invoke();
}
catch (SqlTimeoutException ex)
{
// perform other logic here.
statusLabel.Text = "The server took too long to respond.";
retryButton.Visible = true;
LogSqlTimeoutOnSave(ex);
}
// catch other exceptions as necessary. i.e.
// detect deadlocks
catch (Exception ex)
{
statusLabel.Text = "An unknown Error occurred";
LogGenericExceptionOnSave(ex);
}
SetSavedStatus();
}
There are other ways to achieve this (e.g. common base class, intefaces), but in our case this had the best fit.
This isn't a replacement to a great tool such as Elmah for logging all unhandled exceptions. This is a targeted approach to handling certain exceptions in a standard manner.
Timeout errors typically occur if you are not forcefully closing your sqlconnections.
so if you had a
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
}
If anything goes wrong with that ExecuteReader your connection will not be closed. Always add a finally block.
try {
conn.Open();
cmd.ExecuteReader();
conn.Close();
} catch (SqlException ex) {
//do whatever
} finally {
if(conn.State != ConnectionState.Closed)
conn.Close();
}
This is old question, but the best method (for me) is not listed here. So here we are:
ExceptionFilterAttribute is nice and easy solution for me. Source: http://weblogs.asp.net/fredriknormen/asp-net-web-api-exception-handling.
public class ExceptionHandlingAttribute : ExceptionFilterAttribute
{
public override void OnException(HttpActionExecutedContext context)
{
var exception = context.Exception;
if(exception is SqlTimeoutException)
{
//do some handling for this type of exception
}
}
}
And attach it to f.e. HomeController:
[ExceptionHandling]
public class HomeController: Controller
{
}

Categories

Resources