开发者

Custom TraceListener and multiple messages

开发者 https://www.devze.com 2023-03-26 09:12 出处:网络
I\'m having some difficulity with a custom TraceListener. The issue is that writing a single trace line produces two calls, one to Write(), the other to WriteLine(). The call to Write() contains the t

I'm having some difficulity with a custom TraceListener. The issue is that writing a single trace line produces two calls, one to Write(), the other to WriteLine(). The call to Write() contains the trace source, level, and event id. The call to WriteLine() is the actual message

It looks like the trace listener is instantiated only once, so I can't just queue the first call to Write(). It looks like there's no way to correlate the two calls. Unfortunately this is a problem, since it causes me to send 2 messages to the remote service, doubling the overhead.

There doesn't seem any generic way to filter the calls either. I'd accept just ignoring the call with the source and level, but it seems like that might be very prone.

Here's a sample piece o开发者_运维百科f code:

 /// <summary>
 /// When overridden in a derived class, writes the specified message to the listener you create in the derived class.
 /// </summary>
 /// <param name="message">A message to write. </param><filterpriority>2</filterpriority>
 public override void Write(string message)
 {
      _client.Post(message);
 }


 /// <summary>
 /// When overridden in a derived class, writes a message to the listener you create in the derived class, followed by a line terminator.
 /// </summary>
 /// <param name="message">A message to write. </param><filterpriority>2</filterpriority>
 public override void WriteLine(string message)
 {
      _client.Post(message);
 }

Usage is with:

private static readonly TraceSource Ts = new TraceSource("Source");

Ts.TraceEvent(TraceEventType.Error, 0, "Error Message");

Will produce a call to Write() with:

"Source: Error: 0"

And then a call to WriteLine() with

"Error Message"

Is it possible to combine the two messages? Or just filter the first? Thanks!


There's 2 messages with 2 different formats... where are these writing to? Is this using the Enterprise Logging block? If so, you should check the config file - the listener might be registered twice.


I was able to solve this by implementing the TraceListener base class from Ukadc Diagnostics

The base class is:

public abstract class CustomTraceListener : TraceListener
{
    private static readonly TraceSource Trace = new TraceSource("PostmarkTraceListener");

    /// <summary>
    /// Construct an instance of the trace listener
    /// </summary>
    /// <param name="name">The name of the trace listener</param>
    protected CustomTraceListener(string name)
        : base(name)
    {

    }

    #region Abstracts

    /// <summary>
    /// This method must be overriden and forms the core logging method called by all other TraceEvent methods.
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="message">A message to be output regarding the trace event</param>
    protected abstract void TraceEventCore(TraceEventCache eventCache, string source, TraceEventType eventType,
                                           int id, string message);

    /// <summary>
    /// This method must be overriden and forms the core logging method called by all otherTraceData methods.
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="data">The data to be logged</param>
    protected abstract void TraceDataCore(TraceEventCache eventCache, string source, TraceEventType eventType,
                                          int id, params object[] data);

    #endregion

    #region TraceData/TraceEvent Overrides

    /// <summary>
    /// Write a trace event
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="message">A message to be output regarding the trace event</param>
    public override sealed void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType,
                                           int id, string message)
    {
        FilterTraceEventCore(eventCache, source, eventType, id, message);
    }

    /// <summary>
    /// Write a trace event
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="format">A string format specification for the trace event</param>
    /// <param name="args">Arguments used within the format specification string</param>
    public override sealed void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType,
                                           int id, string format, params object[] args)
    {
        string message = string.Format(CultureInfo.CurrentCulture, format, args);

        FilterTraceEventCore(eventCache, source, eventType, id, message);
    }

    /// <summary>
    /// Write a trace event
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    public override sealed void TraceEvent(TraceEventCache eventCache, string source, TraceEventType eventType,
                                           int id)
    {
        FilterTraceEventCore(eventCache, source, eventType, id, null);
    }

    /// <summary>
    /// Write a trace event
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="data">The data to be written</param>
    public override sealed void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType,
                                          int id, object data)
    {
        FilterTraceDataCore(eventCache, source, eventType, id, data);
    }

    /// <summary>
    /// Write a trace event
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="data">The data to be written</param>
    public override sealed void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType,
                                          int id, params object[] data)
    {
        FilterTraceDataCore(eventCache, source, eventType, id, data);
    }

    #endregion

    #region Write Methods

    /// <summary>
    /// Write a message to the trace listeners
    /// </summary>
    /// <param name="message">The message to write</param>
    public override void Write(string message)
    {
        FilterTraceEventCore(null, string.Empty, TraceEventType.Information, 0, message);
    }

    /// <summary>
    /// Write a message to the trace listeners
    /// </summary>
    /// <param name="message">The message to write</param>
    public override void WriteLine(string message)
    {
        Write(message);
    }

    #endregion

    #region ShouldTrace

    /// <summary>
    /// Determines whether a filter is attached to this listener and, if so, asks whether it ShouldTrace applies to this data.
    /// </summary>
    protected virtual bool ShouldTrace(TraceEventCache eventCache, string source, TraceEventType eventType, int id,
                                       string formatOrMessage, object[] args, object data1, object[] data)
    {
        return !(Filter != null && !Filter.ShouldTrace(eventCache, source, eventType, id, formatOrMessage, args, data1, data));
    }

    #endregion

    #region FilterTraceCore

    /// <summary>
    /// Called before the main TraceEventCore method and applies any filter by calling ShouldTrace.
    /// </summary>
    protected virtual void FilterTraceEventCore(TraceEventCache eventCache, string source, TraceEventType eventType,
                                                int id, string message)
    {
        try
        {
            if (!ShouldTrace(eventCache, source, eventType, id, message, null, null, null))
                return;

            TraceEventCore(eventCache, source, eventType, id, message);
        }
        catch (Exception exc)
        {
            Trace.TraceEvent(TraceEventType.Error, 0, "{0}", exc);
        }
    }

    /// <summary>
    /// Called before the main TraceDataCore method and applies any filter by calling ShouldTrace.
    /// </summary>
    protected virtual void FilterTraceDataCore(TraceEventCache eventCache, string source, TraceEventType eventType,
                                               int id, params object[] data)
    {
        try
        {
            if (!ShouldTrace(eventCache, source, eventType, id, null, null, null, data))
                return;

            TraceDataCore(eventCache, source, eventType, id, data);
        }
        catch (Exception exc)
        {
            Trace.TraceEvent(TraceEventType.Error, 0, "{0}", exc);
        }
    }

    #endregion
}

and my custom TraceListener:

public class PostmarkTraceListener : CustomTraceListener
{
    #region CustomTraceListener Overrides

    /// <summary>
    /// This method must be overriden and forms the core logging method called by all other TraceEvent methods.
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="message">A message to be output regarding the trace event</param>
    protected override void TraceEventCore(TraceEventCache eventCache, string source, TraceEventType eventType,
                                           int id, string message)
    {
        SendPostmarkMessage(eventCache, source, eventType, id, message, null);
    }

    /// <summary>
    /// This method must be overriden and forms the core logging method called by all otherTraceData methods.
    /// </summary>
    /// <param name="eventCache">A cache of data that defines the trace event</param>
    /// <param name="source">The trace source</param>
    /// <param name="eventType">The type of event</param>
    /// <param name="id">The unique ID of the trace event</param>
    /// <param name="data">The data to be logged</param>
    protected override void TraceDataCore(TraceEventCache eventCache, string source, TraceEventType eventType,
                                          int id, params object[] data)
    {
        SendPostmarkMessage(eventCache, source, eventType, id, null, data);
    }

    #endregion

    private void SendPostmarkMessage(TraceEventCache eventCache, string source, TraceEventType eventType, int id, params object[] data)
    {
        // do your work here
    }
}

You can find a working example on my github account

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号