Can pass objects to the event writer method

Topics: Semantic Logging Application Block
Mar 25, 2013 at 6:19 AM
Here the method takes Guid as a parameter. Other supported parameter types I could find are string, long, int and bool.

[Event(295, Level = EventLevel.Verbose, Keywords = Keywords.DataAccess, Task = Tasks.SaveExpense, Opcode = Opcodes.QueryFinish, Version = 1)]
    public void SaveExpenseInsertFinished(Guid expenseId, long elapsedMilliseconds)
    {
        if (this.IsEnabled(EventLevel.Verbose, Keywords.DataAccess))
        {
            this.WriteEvent(295, expenseId);
        }
    }
I need to be able to pass an custom object to this method. But currently while running the code it gives a run time error "Unsupported type Object in event source."

It needs to look like this:
[Event(295, Level = EventLevel.Verbose, Keywords = Keywords.DataAccess, Task = Tasks.SaveExpense, Opcode = Opcodes.QueryFinish, Version = 1)]
    public void SaveExpenseInsertFinished(Employee emp, Expense exp, long elapsedMilliseconds)
    {
        if (this.IsEnabled(EventLevel.Verbose, Keywords.DataAccess))
        {
            this.WriteEvent(295, emp, exp); // this may be wrong but I can split it up into strings
        }
    }
Mar 25, 2013 at 7:20 AM
Edited May 1, 2013 at 9:25 PM
As you mention, only certain parameter types are supported by the System.Diagnostics.Tracing.EventSource infrastructure. I assume (guess) these were chosen because they were common types that are used and that the representation, serialization, and marshaling of those types is known.

You can't add a simple helper method to the EventSource that takes the object and then calls the actual EventSource method to do the writing because this will still cause an exception (it looks like manifest generation must look at all methods). You can do something similar to what you want with an extension method. The event source would need to define the specific primitive types:
    [Event(295, Level = EventLevel.Verbose, Keywords = Keywords.DataAccess, Task = Tasks.SaveExpense, Opcode = Opcodes.QueryFinish, Version = 1)]
    public void SaveExpenseInsertFinished(int employeeId, string expenseCode, double expenseAmount, long elapsedMilliseconds)
    {
        if (this.IsEnabled(EventLevel.Verbose, Keywords.DataAccess))
        {
            this.WriteEvent(295, employeeId, expenseCode, expenseAmount, elapsedMilliseconds);
        }
    }
And the extension method could accept the class instances and supply the required arguments to the actual EventSource:
    public static class MyEventSourceExtensions
    {
        public static void SaveExpenseInsertFinished(this MyEventSource eventSource, Employee emp, Expense exp, long elapsedMilliseconds)
        {
               eventSource.SaveExpenseInsertFinished(emp.Id, exp.Code, exp.Amount, elapsedMilliseconds);
        }
    }
~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Apr 9, 2013 at 8:44 AM
Edited Apr 9, 2013 at 11:54 AM
You can mark methods with the NonEventAttribute to prevent EventSource from including methods in the manifest:
[Event(3, Message = "Could not parse {0} file with name {1}", Level = EventLevel.Error)]
internal void FileParsingError(string fileType, string fileName, string exceptionMessage, string stackTrace)
{
    WriteEvent(3, fileType, fileName, exceptionMessage, stackTrace);
}

[NonEvent]
internal void FileParsingError(string fileType, string fileName, Exception ex)
{
    FileParsingError(fileType, fileName, ex.Message, ex.StackTrace);
}
Use like this:
try
{
    KraftvaerkEventSource.Log.StartedFileParsing("Example", "file2.csv");
    throw new Exception("Some parsing error");
}
catch (Exception ex)
{
    KraftvaerkEventSource.Log.FileParsingError("Example", "file2.csv", ex);
}
On a side note: I found this NonEvent attribute by decompiling the EventSource class and looking at the implementation of CreateManifest. Maybe you should include this feature in the developers guide, and include an example for EventSource on MSDN.
Apr 9, 2013 at 10:22 PM
Thanks for posting -- that's a good find!

It looks like it was hiding in plain sight at MSDN. I do think it's a good idea to highlight the usage since I could see this being a common scenario.

~~
Randy Levy
entlib.support@live.com
Enterprise Library support engineer
Support How-to
Apr 26, 2013 at 11:13 AM
Hey agehrke,

Works perfectly. Just what I was looking for. Thanks so much!

Regards,
Himanshu
Jun 4, 2014 at 4:06 PM
This is awesome! Just what I was looking for. I was banging my head against the wall trying to get the WriteEvent(int EventId, params object[] args) overloaded method to work. I kept getting an ArgumentException runtime error calling EnableEvents. This is much cleaner and if I want to change the properties I send to the underlying method, I can without having to change any consumers calling my overloaded method.