views:

569

answers:

6

I have code that is logging ex.Message. However I read an article that it's better to use ex.ToString(). This way you retain more crucial information about the error.

Is this true, and is it safe to go ahead and replace all code logging ex.Message?

I'm also using an XML based layout for log4net. Do you think the ex.ToString() will contain any invalid characters for XML based logging?

+11  A: 

Exception.Message contains only the message (doh) associated with the exception. Example:

Object reference not set to an instance of an object

The Exception.ToString() method will give a much more verbose output, containing the exception type, the message (from before), a stack trace, and all of these things again for nested/inner exceptions. More precisely, the method returns the following:

ToString returns a representation of the current exception that is intended to be understood by humans. Where the exception contains culture-sensitive data, the string representation returned by ToString is required to take into account the current system culture. Although there are no exact requirements for the format of the returned string, it should attempt to reflect the value of the object as perceived by the user.

The default implementation of ToString obtains the name of the class that threw the current exception, the message, the result of calling ToString on the inner exception, and the result of calling Environment.StackTrace. If any of these members is a null reference (Nothing in Visual Basic), its value is not included in the returned string.

If there is no error message or if it is an empty string (""), then no error message is returned. The name of the inner exception and the stack trace are returned only if they are not a null reference (Nothing in Visual Basic).

Jørn Schou-Rode
A: 

Well, I'd say it depends what you want to see in the logs, doesn't it? If you're happy with what ex.Message provides, use that. Otherwise, use ex.toString() or even log the stack trace.

Thorsten Dittmar
ex.ToString includes the stack trace
John Saunders
A: 

Depends on the information you need. For debugging the stack trace & inner exception are useful:

    string message =
        "Exception type " + ex.GetType() + Environment.NewLine +
        "Exception message: " + ex.Message + Environment.NewLine +
        "Stack trace: " + ex.StackTrace + Environment.NewLine;
    if (ex.InnerException != null)
    {
        message += "---BEGIN InnerException--- " + Environment.NewLine +
                   "Exception type " + ex.InnerException.GetType() + Environment.NewLine +
                   "Exception message: " + ex.InnerException.Message + Environment.NewLine +
                   "Stack trace: " + ex.InnerException.StackTrace + Environment.NewLine +
                   "---END Inner Exception";
    }
Carra
This is more or less what `Exception.ToString()` will give you, right?
Jørn Schou-Rode
use stringbuilder
Matt Joslin
@Matt: Constructing an instance of `StringBuilder` in this scenario may well be more expensive than two new string allocations, it's highly debatable it would be more efficient here. It's not like we're dealing with iterations. Horses for courses.
Wim Hollebrandse
@Wim: Huh? Forgive may (temporary) witlessness, but there are whole lot more than two instances created. Basically, for each +operator(string,string) you get a new instance. Apart from that, you may be right however, that it will not make any difference.
Christian.K
Problem here is, that you'll only get the "InnerException" of the outermost exception. IOW, if InnerException itself has an InnerException set, you'll not dump it (assuming that you want to in the first place). I'd really stick with ToString().
Christian.K
@Christian: yes, you're right, for each +, so indeed more than 2. My initial assessment didn't go further than `message=` and `message+=`. It may just balance out in this case to be honest. `String.Format` is probably what I would have used in this specific case (for mainly readability), which I think actually uses `StringBuilder` under the hood.
Wim Hollebrandse
Just use ex.ToString. It gets you all the details.
John Saunders
+7  A: 

In addition to what's already been said, don't use ToString() on the exception object for displaying to the user. Just the Message property should suffice, or a higher level custom message.

In terms of logging purposes, definitely use ToString() on the Exception, not just the Message property, as in most scenarios, you will be left scratching your head where specifically this exception occurred, and what the call stack was. The stacktrace would have told you all that.

Wim Hollebrandse
A: 

I'd say Wim is right. You should use ToString() for logfiles - assuming a technical audience - and Message, if at all, to display to the user. One could argue that even that is not suitable for a user, for every exception type and occurance out there (think of ArgumentExceptions, etc.).

Also, in addition to the StackTrace, ToString() will include information you will not get otherwise. For example the output of fusion, if enabled to include log messages in exception "messages".

Some exception types even include additional information (for example from custom properties) in ToString(), but not in the Message.

Christian.K
A: 

In terms of the XML format for log4net, you need not worry about ex.ToString() for the logs. Simply pass the exception object itself and log4net does the rest do give you all of the details in its pre-configured XML format. The only thing I run into on occasion is new line formatting, but that's when I'm reading the files raw. Otherwise parsing the XML works great.

Dillie-O