babgvant / elmah

Automatically exported from code.google.com/p/elmah
Apache License 2.0
0 stars 0 forks source link

Exception.Data dictionary NOT logged. #162

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
What steps will reproduce the problem?
1. Log any exception with some data in Exception.Data dictionary.
2. go to UI (elmah.axd)
3. search through Details and XML.

What is the expected output? What do you see instead?
- get Exception.Data logged. It's NOT logged.

Original issue reported on code.google.com by Alexande...@gmail.com on 17 Mar 2010 at 6:38

GoogleCodeExporter commented 8 years ago
I have just started using ELMAH in a small MVC 2.0 site and I'm hugely 
impressed by it.

However, currently the exception handler we use for our enterprise ASP.NET app 
lets us add custom text to an additional field in the database (such as an XML 
string that failed to parse etc)

If ELMAH could deal with this through the Exception data dictionary it would be 
an even more attractive option for moving over.

Original comment by marc.c.l...@gmail.com on 28 Oct 2010 at 6:19

GoogleCodeExporter commented 8 years ago
I also think the inclusion of exception data information is important for my 
web applications.

I've attempted to edit ELMAH/Error.cs to append the exception data dictionary 
keys to the ELMAH detail field. The detail field currently contains the stack 
trace, it is my intent to add the exception data information right after the 
stack trace. I started editing Error.cs around line 100 with the following 
changes:

            //_detail = e.ToString();  // this is the original value, it just dumps the stack trace string into the _detail member

            // begin change to exception details to include stack trace and exception data
            System.Text.StringBuilder sbDetail = new System.Text.StringBuilder();
            sbDetail.Append("Stack Trace:");
            sbDetail.Append(Environment.NewLine);
            sbDetail.Append(Environment.NewLine);
            sbDetail.Append(e.ToString());
            sbDetail.Append(Environment.NewLine);
            sbDetail.Append(Environment.NewLine);
            sbDetail.Append("Exception Data (" + e.Data.Keys.Count.ToString() + " items):");
            sbDetail.Append(Environment.NewLine);
            sbDetail.Append(Environment.NewLine);
            foreach (object key in e.Data.Keys)
            {
                sbDetail.Append("    " + key.ToString() + "=" + e.Data[key].ToString() + Environment.NewLine);
            }
            _detail = sbDetail.ToString();
            // end change

When I compiled and dropped the modified Elmah.dll into my project, everything 
seemed to work ok except that my exception data collection always had zero 
keys, even when I explicitly added data from my web application. Here is how I 
threw the exception from my web app:

        Exception testEx = new Exception("Test Exception");
        testEx.Data.Add("Key1", "Value1");
        testEx.Data.Add("Key2", "Value2");
        testEx.Data.Add("Key3", "Value3");
        throw testEx;

Can anyone tell me why I'm not getting the exception data in ELMAH? I've 
attached my modified Error.cs file. Thanks much.

Original comment by david.wh...@gmail.com on 27 Jan 2011 at 6:56

Attachments:

GoogleCodeExporter commented 8 years ago
This issue should probably reclassified as an Enhancement, it really isn't a 
Defect.

Original comment by david.wh...@gmail.com on 27 Jan 2011 at 9:10

GoogleCodeExporter commented 8 years ago
@david IMO it's a defect, it's a key part of the Exception class that is just 
not tracked by ELMAH

Original comment by ch...@marisic.com on 28 Jan 2011 at 7:52

GoogleCodeExporter commented 8 years ago
@david - the reason that you are not seeing your exception data is because your 
looking at the wrong level. ASP.Net wraps your exception up in a 
System.Web.HttpUnhandledException

So if you look at e.InnerException.Data it will be there.

But be careful though, e.InnerException might be null if you call 
Elmah.ErrorSignal.FromCurrentContext().Raise

Also e.Data and e.InnerException.Data could be null as well depending on the 
type of exception that has been raised, so you need to add some checks in for 
that too!

Hope this helps,

James

Original comment by jamesdriscoll71 on 29 Jan 2011 at 11:33

GoogleCodeExporter commented 8 years ago
Hi,

my company is using a modified ELMAH version to log Exception.Data. Today i got 
a go to contribute a patch.

To support Exception.Data we did the same things as ELMAH does for 
Request.Form. 

Perhaps it's useful for somebody.

Martin   

Original comment by cubicl...@gmail.com on 31 Jan 2011 at 2:47

Attachments:

GoogleCodeExporter commented 8 years ago
@James, thanks for your help. Your suggestions fixed my problem. I appreciate 
your assistance.

Original comment by david.wh...@gmail.com on 31 Jan 2011 at 7:30

GoogleCodeExporter commented 8 years ago
@Martin Thanks for that patch, I've applied it to my local build ==> works 
great (on a first test) 
Let's hope it gets accepted in the main build.

Original comment by sotto...@gmail.com on 12 Feb 2011 at 3:23

GoogleCodeExporter commented 8 years ago
Patch is working for me as well.  Using tips.

Original comment by masil...@gmail.com on 20 Feb 2011 at 8:12

GoogleCodeExporter commented 8 years ago
Very helpful patch. Put this into action a few days ago.

Original comment by laka...@gmail.com on 21 Feb 2011 at 5:21

GoogleCodeExporter commented 8 years ago
Thank you very much for the patch. It's very useful.
Will it be included in the next release of Elmah? It should.

I had to change on thing, though. The following piece of code walks down the 
inner exceptions to find the first one with Data. baseException may not have 
Data, but an outer exception may.

Exception exceptionForData = e;
while (exceptionForData != null)
{
    if ((exceptionForData.Data != null) && (exceptionForData.Data.Count > 0))
    {
        _data = CopyCollection(exceptionForData.Data);
        break;
    }
    exceptionForData = e.InnerException;
}

The fact that Elmah logs only the base exception has always been an issue for 
me. It should process the whole exception tree, just as Microsoft's Exception 
Handling Application Block.
If several exceptions have data in Data, we should see all of it. Elmah should 
give us all the details about each exception in the exception tree.

Original comment by fabrice....@gmail.com on 12 May 2011 at 10:20

GoogleCodeExporter commented 8 years ago
> …logs only the base exception has always been an issue…
> It should process the whole exception tree…
> If several exceptions have data in Data, we should see all of it…
> …should give us all the details about each exception in the exception tree.

A little known fact about ELMAH is that it has been independent of .NET 
exceptions from day one! It is the reason that ELMAH calls them errors and not 
exceptions, the idea being to imply a disconnect. Yes, ELMAH runs on .NET and 
yes it is a little biased towards web applications but those are just 
implementation details.

If you look at the Error object or its XML and JSON data format 
representations, it does not imply anything about .NET exceptions or nesting 
levels and data dictionaries. There is an error that can have a message, 
detail, type, source, application and so on but those are all just 
informational strings. ELMAH maps .NET exceptions to those error attributes 
during logging. The stack trace, for example, usually goes into the error 
detail. In fact, what goes in there is whatever the ToString() implementation 
of an Exception object supplies. Fortunately, most implementations (especially 
the default) provide the complete stack trace of all nested exceptions.

Since ELMAH logs errors, you can pretty much put a fault/error/exceptions from 
Ruby, JavaScript, Python, or what have you, into an error log and ELMAH can 
read it back as long as you can find a reasonable mapping between the error 
attributes and the platform-specific representation of a fault.

You can read more about ELMAH's idea of errors in an old and deprecated 
Technical Notes document[1]. Quite a bit of it still, in fact, relevant. The 
main things to remember is that errors are portable and exceptions are not; 
they're considered a runtime artifact.

The fact that data dictionaries are not captured can be frustrating but what's 
keeping from banging out this feature is some thinking that's needed to map 
into a portable idea. The current error formats and class representation is 
also coming of age and needs revision for v2. Hopefully data dictionaries can 
be rolled in during the revision. Ideas welcome. 

[1] 
http://code.google.com/p/elmah/wiki/TechnicalNotes#Error:_The_Phantom_Exception

Original comment by azizatif on 12 May 2011 at 8:57

GoogleCodeExporter commented 8 years ago
Thank you for the explanation. I didn't know about the roots of ELMAH.

It's not clear that this independence from .NET is still important. After all, 
ELMAH's tag line is "Error Logging Modules and Handlers for ASP.NET", isn't it?

Original comment by fabrice....@gmail.com on 12 May 2011 at 9:06

GoogleCodeExporter commented 8 years ago
> this independence from .NET is still important.

It's not as much about independence from .NET as it is about have a separation 
between the runtime and data models. This separation has two main benefits. 
One, it enables errors to survive past .NET versions, assemblies and types. 
Two, it enables web applications from different platforms to write to a shared 
error log store and use ELMAH, for example, to view them back as long as the 
data contract/format is compatible. I don't think anyone has exercised this 
really to a large extent but people are beginning to use ELMAH, for example, to 
log client-side JavaScript errors[1].

> ELMAH's tag line is "Error Logging Modules and Handlers for 
> ASP.NET", isn't it?

Not a tagline. ELMAH is an acronym for Error Logging Modules And Handlers. I'm 
thinking, however, of changing the acronym to stand for Error Loathing Monsters 
And Hamsters going forward. Now there's no ASP.NET in sight. :)

The goal is not of platform-independent code goal. Rather it's one of data 
portability. It's not an easy one but worth the effort and paid off. For 
example, check out the recent ELMAH Offline Viewer project. It has no reference 
to any of the ELMAH libraries and works purely off the XML format to provide 
search, reporting and charts.

I think we can fit data dictionaries in somewhere; just missing the think time 
cycles the problem deserves. The biggest problem with dictionaries is that 
neither the keys not their values are plain strings. They are arbitrary .NET 
objects and one has to come up with some method to encode them. I don't think 
just calling ToString() on every value helps (though it may be the only 
workable answer) as it creates a dumb dumping ground. The web collections 
(ServerVariables and company) don't have the same problem as the values of 
their entires are already text in their native form.

Incidentally, do you use the Exception.Data property *a lot* or just on rare 
occasions?

[1] http://ivanz.com/2011/05/08/logging-javascript-errors-with-elmah/
[2] 
http://stackoverflow.com/questions/2764525/clientside-error-logging-using-elmah/
5912482#5912482
[3] http://code.google.com/p/elmahofflineviewer/

Original comment by azizatif on 12 May 2011 at 9:48

GoogleCodeExporter commented 8 years ago
I use Exception.Data as a way to provide context.

For example, when deleting an Order object, the Exception.Message may be "Error 
deleting order", and I may put the order ID in Exception.Data for inspection.
Another example: "Invalid order number format.", with the order number logged 
in Data.

The values do not belong to the message. Data is one place to put them.
Do you have another suggestion?
What's your way of doing things?

Original comment by fabrice....@gmail.com on 12 May 2011 at 10:16

GoogleCodeExporter commented 8 years ago
I've just begun evaluating ELMAH and I've run into the same problem.  We also 
place custom error/context info into the exception.data  and would love the 
ability to include .data in the log. 

I think it makes sense to provide this enhanced logging as a configuration 
option in the web.config.  The application could then configure ELMAH to 
optionally log ALL data elements or log from a list of specific data keys.  
This way you can add custom exception data elements and log only your own 
custom data. 

Original comment by lle...@larrylewis.net on 22 Aug 2011 at 2:56

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
I'm trying to attach a user + session object to the exception and also hope 
this is an enhancement that can be added.

Currently we have to serialize all the objects and attach them to 
Exception.Message, very inefficient!

Original comment by jason.hu...@gmail.com on 7 Nov 2011 at 9:49

GoogleCodeExporter commented 8 years ago
This "issue" really should to be fixed.

We also use it for context when working with SOAP exceptions, logging some 
specific session values, eg. userID and such.

Without the Exception.Data being logged we have almost no way to see what 
custom data we are working with. The Exception.Message is read-only, so it's 
not possible to add the data there.

If the problem is the fact that each entry is an object/object pair, then how 
about serializing the collection or each entry to XML?

public static string SerializeObject(object obj)
{
    if (obj == null)
    {
        return string.Empty;
    }

    var x = new System.Xml.Serialization.XmlSerializer(obj.GetType());
    var sb = new System.Text.StringBuilder();
    var xml = System.Xml.XmlWriter.Create(sb);
    x.Serialize(xml, obj);
    xml.Flush();
    xml.Close();
    return sb.ToString();
}

public static T DeserializeObject<T>(string xmlStr)
{
    var x = new System.Xml.Serialization.XmlSerializer(typeof(T));
    var stringReader = new StringReader(xmlStr);
    var xmlReader = new XmlTextReader(stringReader);
    var xml = x.Deserialize(xmlReader);
    xmlReader.Close();
    stringReader.Close();

    return (T)xml;
}

Original comment by nikkelma...@gmail.com on 21 Aug 2012 at 8:19

GoogleCodeExporter commented 8 years ago
I agree. I used most of Martin's suggestion and fixed so it works with the 
current version. If you wan't to use it in your project you can get it from 
here https://github.com/boena/elmah-with-exception-data

Original comment by m...@boena.net on 23 Nov 2012 at 2:36

GoogleCodeExporter commented 8 years ago
Hello @Boena\@cubicl...@gmail.com;
I have been tasked to "display data in exception data dictionary" using Elmah. 
I see that you have already created a fork for it and created a download link 
for it.  However your link "https://github.com/boena/elmah-with-exception-data" 
does not work. Would you have this code lying around somewhere? Can you please 
help?

Original comment by ajitg...@gmail.com on 19 Feb 2013 at 3:55

GoogleCodeExporter commented 8 years ago
@ajit it looks like https://github.com/boena/elmah-with-custom-data and 
https://github.com/boena/elmah-log-analyzer-with-custom-data

Original comment by ch...@marisic.com on 19 Feb 2013 at 4:26

GoogleCodeExporter commented 8 years ago
> Incidentally, do you use the Exception.Data property *a lot* or just on rare 
occasions?

I use it a lot to add context to the exceptions (Id, parameter...). I think 
ELMAH should support it.

> The biggest problem with dictionaries is that neither the keys not their 
values are plain strings.

Exception.Data is a Dictionary<string, object>. The key wouldn't be an issue 
then, I also agree that you could just apply a ToString() to the value (I took 
the habit to serialize it as a string anyway).

Original comment by gabrielw...@gmail.com on 24 Feb 2013 at 10:52

GoogleCodeExporter commented 8 years ago
[deleted comment]
GoogleCodeExporter commented 8 years ago
This defect was raised in 2010, its now 2014 and this is still not fixed. 
Ideally, this should be fixed by Microsoft, Exception.ToString() should add the 
Data field.

However, Elmah should definately fix this. There is no reason, to not do so. 
Exception Data is used in Entity Framework very frequently and there are many 
other use cases.

Original comment by rehansa...@gmail.com on 27 Apr 2015 at 11:44

GoogleCodeExporter commented 8 years ago
@rehansaeed Actually it's 2015.

Original comment by azizatif on 27 Apr 2015 at 7:09

GoogleCodeExporter commented 8 years ago
@gabrielw : no it is a non generic Dictionary
The line below will work:
new Exception("Fail"){ Data = {{new Object(), new Object()}}}

But the most reasonable thing to put as a key would be a string.

@azizatif : maybe it would be appropriate to just call ToString() on the key of 
each dictionary entry to get the string that should be displayed?

(I'm thinking of putting an "error id" in the data dictionary of each thrown 
exception. The error id should be visible in the log and output to user to be 
able to use in the id support work)

Original comment by mortenby...@gmail.com on 11 May 2015 at 2:04

GoogleCodeExporter commented 8 years ago
So this thread is alive again :)

Aziz has clearly expressed that he did not want Elmah to have knowledge of the 
Data field.

If you want to add custom metadata, a cumbersome way would be use your own 
exception type and override ToString(), this is what Elmah is using to display 
the Exception in the yellow block at the top of the page.

If you want a cleaner solution you'll have to fork it or use one of the forks 
mentioned in the comments. There are not a lot of commits in the project so 
keeping up to date will not be hard.

Original comment by gabrielw...@gmail.com on 11 May 2015 at 11:02

GoogleCodeExporter commented 8 years ago
I don't know if this solution has already been suggested, but here goes. Rather 
than forking the entire ELMAH source, you should be able to create a class 
extending the error log implementation you are using. Say you are using the SQL 
Server error logger, just create a class extending the SqlErrorLog, creating 
your own logic for persisting the data (based on the existing SQL Server schema 
extended with table for key/values). I think you will be able to use the normal 
elmah.corelibrary package, combined with your own errorlog implementation. At 
least this is what I've done for the https://elmah.io error logger (disclamer: 
elmah.io is a commercial product and I'm one of the founders of that).

Original comment by thomasar...@gmail.com on 13 May 2015 at 5:34