【问题标题】:Custom TraceListener and multiple messages自定义 TraceListener 和多条消息
【发布时间】:2011-10-21 00:33:10
【问题描述】:

我在使用自定义 TraceListener 时遇到了一些困难。问题是写入单个跟踪行会产生两个调用,一个调用 Write(),另一个调用 WriteLine()。对 Write() 的调用包含跟踪源、级别和事件 ID。对 WriteLine() 的调用是实际的消息

看起来跟踪侦听器只实例化了一次,所以我不能只对 Write() 的第一次调用进行排队。看起来没有办法将这两个电话联系起来。不幸的是,这是一个问题,因为它导致我向远程服务发送 2 条消息,从而使开销加倍。

似乎也没有任何通用的方法来过滤调用。我会接受只是忽略源和级别的调用,但这似乎很容易发生。

这是一段示例代码:

 /// <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);
 }

用法与:

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

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

将产生对 Write() 的调用:

“来源:错误:0”

然后使用

调用 WriteLine()

“错误信息”

是否可以合并这两条消息?还是只过滤第一个?谢谢!

【问题讨论】:

  • 你能发布你的整个 TraceListener 吗?除了 Write 和 WriteLine 方法之外,您的代码中的其他地方可能存在问题。也许您也可以尝试编写一个更简单的 TraceListener,它只写入控制台或调试器或其他东西。看看你能不能让它工作,然后解决为什么基于 Web 服务的服务不能工作。此外,如果您使用 System.Diagnostics,您可能会考虑使用此项目来获得一些自定义格式化功能,类似于您可以使用 log4net 和 NLog 执行的操作。 ukadcdiagnostics.codeplex.com
  • 我得到了相同的行为,而且我的行为非常简单,我只是在 write 和 writeline 中打断点。我还看到两个电话中有消息。你找到解决办法了吗?
  • 我很抱歉,我应该回答我的问题。我确实找到了解决方案,但我并不完全理解它。检查我刚刚发布的答案和github链接。

标签: c# asp.net .net logging system.diagnostics


【解决方案1】:

我能够通过从Ukadc Diagnostics 实现 TraceListener 基类来解决这个问题

基类是:

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
}

还有我的自定义 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
    }
}

您可以在我的 github account 上找到一个工作示例

【讨论】:

    【解决方案2】:

    有 2 条具有 2 种不同格式的消息...这些消息要写到哪里?这是使用企业日志记录块吗?如果是这样,您应该检查配置文件 - 侦听器可能会注册两次。

    【讨论】:

    • 它正在写入外部服务。 _client.Post() 正在进行 Web 服务调用。它没有注册两次。就是消息的一部分调用Write(),另一部分调用WriteLine()。这似乎是设计使然。消息没有重复,只是分成两半。它没有使用企业日志记录块。只需一个简单的跟踪侦听器和一个调用它的 1 行演示程序即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多