开发者

What to log when an exception is raised

Until now I was logging开发者_JAVA百科 the Error message and the stack trace of an exception. However, I don't think doing that is very helpful, if I don't log all the variables used inside the try block. If I can see all the variables used inside the try block, I think I will have a better idea on what caused the exception and may be I can avoid it from happening again.

What do you guys log?

Thanks


As others said, when logging an exception I usually log exception.ToString(), which usually contains only the message, the stack trace and the inner exception.

However there's a property defined on System.Exception that is often forgotten, but might be what you are looking for. It is the IDictionary Data property. In that Dictionary you can put whatever you feel like, and then use it when logging the exception.

Here's a short example with a buggy function, another one using it, and a method that is called whenever there is an uncatched exception unwinding the stack:

public static int BuggyFoo(int notZeroPlease)
{
    return 5 / notZeroPlease;
}

public static int UseBuggyFoo(int userInput)
{
    var myValue = userInput >> 2;
    try
    {
        var foo = BuggyFoo(myValue);
        return (foo + 5);
    }
    catch (Exception e)
    {
        e.Data["userInput"] = userInput;
        e.Data["myValue"] = myValue;
        throw;
    }
}

public static void Application_OnError(Exception e)
{
    var sb = new StringBuilder();
    foreach (var k in e.Data.Keys)
    {
        sb.AppendFormat("Data[{0}] = {1}\n", k, e.Data[k])
    }
    Utilities.Logger.Log(sb.ToString(), e);
}

But this should be used with moderation... otherwise (if your code is buggy) you would have huge log files!

Good luck!

EDIT: If you are not sure about that Application_OnError() method, here is a possible illustration:

public static void Application_OnError(Exception e)
{ /* ... */ }

public static void Main()
{
    try
    {
        /* ... */
    }
    catch (Exception e)
    {
        Application_OnError(e);
    }
}

If you are creating a Web App, using ASP.NET, let's say, then you should already have an Application_OnError method that will be called under these circumstances.


Mainly we log the error message and the stack trace. We also add comments to the logging as to a possible reason why it happened. These messages are often like "If it fails here, the user session isn't set, and this has possibly happened because of a session reset." Normally the messages are something to get us looking in the right direction.

If your try catch block is too big to do this, I would think about separating it out to smaller blocks. If you don't want to do that, then I would start setting up different catch blocks for different types of exceptions.

catch(FileNotFoundException ex)
{}
catch(Exception regularException)
{}

This way you can tailor any additional information to that type of exception, and have a general exception as the last catch block to make sure that something doesn't accidently escape.


I would always be wary of attempting to log everything within a method, primarily because of the huge maintenance overhead of maintaining the code in future.

Additionally you will probably have to ensure that your logging code is context aware, i.e. if you are using properties nested within an object your logging code will need to understand how to get to these variables during the log, and on top of this you have to ensure that any requests the logger may make doesn't affect the state of anything or it'll be unrepresentative of the actual state.

Why not put the effort into validating your parameters at the beginning of the method then have null checks throughout your code where needed?


In general I only log the exception message and stack trace and I try to log enough debug information so that I can tell what happened from the context. Usually this is more than enough detail to figure out what went wrong.

In cases where I simply cannot figure out how an exception is occurring, I add additional debug logging of applicable variable values. Granted, this only works because I have an easy availability to the application and can temporarily swap out the assembly if needed. If don't have that type of accessibility then you might want to take a look at Gibraltar. It provides a wealth of debug information that can be sent from remote clients and has all sorts of nifty forms to view it.


Occasionally, I will log the inner exception along with the main exception message. This can provide more specific exception information and allow easier debugging.


I have an object that I call 'UserAction' and each time the user interacts with the UI in some way, push another UserAction on a list with information like "clicked x" or "dragged p from x to y". It also has information like the date/time, username, etc. When an exception happens, the software auto-emails the exception message, stack trace and the dump of the UserAction log. It can be quite helpful in trying to repro the problem.

I usually know what the problem is before the user has a chance to get to my office.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜