Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unique EventId generation

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?

like image 469
Simon Johnson Avatar asked Jan 24 '23 13:01

Simon Johnson


2 Answers

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.

like image 198
Simon Johnson Avatar answered Feb 04 '23 04:02

Simon Johnson


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

like image 29
richardtallent Avatar answered Feb 04 '23 06:02

richardtallent