Thursday, 20 February 2014

[bug] DiagnosticMonitorTraceListener doesn't use filter

Due to some kind of mistake, the Azure DiagnosticMonitorTraceListener doesn't honour the filter tag in config. In other words, if you add something like <filter initializedata="Warning" type="System.Diagnostics.EventTypeFilter">, it won't make any difference, all events will be logged.

Even though you can specify the level of logs to transfer from local to diagnostics tables in your storage account, I don't really want to log loads of events locally, especially the weird ones from the Azure environment which don't mean anything.

I found a forum post with a very painful response from the MS tech team, the type of reply that says, "are you saying...?" to which the original poster says, "no, that is not what I am saying"! The gist was that the only way to do this was to subclass the DiagnosticMonitorTraceListener and add the filtering functionality in.

I used reflector to open both the normal TraceListener class and the DiagnosticMonitorTraceListener and found that the DiagnosticMonitorTraceListener had overridden base class functions and somehow missed the filtering code. I also found out, like many MS library classes, that some functions were marked internal and were not accessible to me, I did however get it to work using the following code:

public class DiagnosticMonTraceListener : DiagnosticMonitorTraceListener
{
    public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
    {
        if (this.Filter != null && !this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, null, data))
        {
            return;
        }
        base.TraceData(eventCache, source, eventType, id, data);
    }

    public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data)
    {
        if (this.Filter != null && !this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null))
        {
            return;
        }
        base.TraceData(eventCache, source, eventType, id, data);
    }

    public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id)
    {
        this.TraceEvent(eventCache, source, eventType, id, string.Empty);
    }

    public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string message)
    {
        if (this.Filter != null && !this.Filter.ShouldTrace(eventCache, source, eventType, id, message, null, null, null))
        {
            return;
        }
        base.TraceEvent(eventCache, source, eventType, id, message);
    }

    public override void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType, int id, string format, params object[] args)
    {
        if (this.Filter != null && !this.Filter.ShouldTrace(eventCache, source, eventType, id, format, args, null, null))
        {
            return;
        }
        base.TraceEvent(eventCache, source, eventType, id, format, args);
    }
}

Which I then used in my web.config in place of the DiagnosticMonitorTraceListener.
Post a Comment