views:

181

answers:

5

I'm using the Windows Event Log to record some events. Events within the Windows Event Log can be assigned a handful of properties. One of which, is an EventID.

Now I want to use the EventId to try and group related errors. I could just pick a number for each call to the logging method I do, but that seems a little tedious.

I want the system to do this automatically. It would choose an eventId that is "unique" to the position in the code where the logging event occurred. Now, there's only 65536 unique event IDs, so there are likely to be collisions but they should be rare enough to make the EventId a useful way to group errors.

One strategy would be to take the hashcode of the stacktrace but that would mean that the first and second calls in the following code would have generate the same event ID.

public void TestLog()
{
   LogSomething("Moo");
   // Do some stuff and then a 100 lines later..
   LogSomething("Moo");
}

I thought of walking up the call stack using the StackFrame class which has a GetFileLineNumber method. The problem with this strategy is that it will only work when built with debug symbols on. I need it to work in production code too.

Does anyone have any ideas?

A: 

Now I want to use the EventId to try and group related errors.

You have filters in event viewer so why (Go to find ? You have 65536 unique event IDs too.

Or rather use log4net or something ??

just my ideas....

abmv
Two problems with this. First, even if I used log4net that wouldn't solve my grouping problem. Secondly, I want the EventId to be used *because* I want to use the filters. This is a very poor answer, which is why I've voted it down.
Simon Johnson
well you could write your own code....
abmv
A: 

Thanks for the idea of hashing the call stack, I was going to ask that very same question of how to pick an eventId.

I recommend putting a static variable in LogSomething that increments each time it is called.

MatthewMartin
+1  A: 

The IL offset number is available without debug symbols. Combined with the stack information and hashed, I think that would do the trick.

Here's an article that, in part, covers retrieving the IL offset (for the purpose of logging it for an offline match to PDB files--different problem but I think it'll show you what you need):

http://timstall.dotnetdevelopersjournal.com/getting_file_and_line_numbers_without_deploying_the_pdb_file.htm

richardtallent
I don't know how I missed this, but cheers. That's exactly what I was looking for.
Simon Johnson
+1  A: 

Create a hash using the ILOffset of the last but one stack frame instead of the line number (i.e. the stack frame of your TestLog method above).

Alan Moore
+1  A: 

Here is some code you can use to generate an EventID with the properties I describe in my question:

 public static int GenerateEventId()
 {
     StackTrace trace = new StackTrace();

     StringBuilder builder = new StringBuilder();
     builder.Append(Environment.StackTrace);

     foreach (StackFrame frame in trace.GetFrames())
     {
           builder.Append(frame.GetILOffset());
           builder.Append(",");
     }

     return builder.ToString().GetHashCode() & 0xFFFF;
 }

The frame.GetILOffset() method call gives the position within that particular frame at the time of execution.

I concatenate these offsets with the entire stacktrace to give a unique string for the current position within the program.

Finally, since there are only 65536 unique event IDs I logical AND the hashcode against 0xFFFF to extract least significant 16-bits. This value then becomes the EventId.

Simon Johnson