【问题标题】:Unintended consequence of dialing down tracing using Ent-Lib, no error logging使用 Ent-Lib 拨号跟踪的意外后果,没有错误记录
【发布时间】:2011-06-23 20:11:41
【问题描述】:

我在使用企业库跟踪和异常记录时遇到了意外问题。我注意到的是,当我使用“App.Config”中的类别过滤器拨出跟踪日志记录时,我无意中关闭了低于我要过滤的跟踪日志记录级别的错误的错误日志记录。

例如:

Private Sub ProcA()
    Using (New Tracer("Trace High Level")
        Try
            <Do some logic here>
            ProcB()

        Catch ex AS Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Log Only Policy")
            If rethrow Then
                Throw ex
            End If
        End Try
    End Using
End Sub

Private Sub ProcB()
    Using (New Tracer("Trace Mid Level")
        Try
            <Do some logic here>
            ProcC()

        Catch ex AS Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Log Only Policy")
            If rethrow Then
                Throw ex
            End If
        End Try
    End Using
End Sub

Private Sub ProcC()
    Using (New Tracer("Trace Low Level")
        Try
            Throw New Exception("Test error logging")

        Catch ex AS Exception
            Dim rethrow As Boolean = ExceptionPolicy.HandleException(ex, "Log Only Policy")
            If rethrow Then
                Throw ex
            End If
        End Try
    End Using
End Sub

现在,如果我在 App.Config 中设置了我的类别过滤器以允许完全跟踪,我将获得我的所有跟踪消息,并将 ProcC 中抛出的错误消息写入我的日志。但是,如果我拨出跟踪仅记录 "Trace High Level",例如,我会收到高级跟踪消息,但不会记录在 ProcC 中引发的错误。

我已单步执行代码并注意到在 ProcC 中出现错误时 LogEntry 的累积类别包括 "Trace High Level", "Trace Mid Level", "Trace Low Level""Error"。因此,只要我不跟踪记录我的所有级别,在 LogWriterImpl.cs 中对ShouldLog() 的调用就会返回 false,结果是我的错误没有被记录。

我的问题:
在这种情况下,有没有办法配置企业库日志记录,即使我没有在所有级别进行详细的跟踪日志记录,仍然允许记录错误?

回应@Tuzo 的评论:

<exceptionHandling>
    <exceptionPolicies>
      <add name="Exception Policy">
        <exceptionTypes>
          <add name="Exception" type="System.Exception, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
            postHandlingAction="NotifyRethrow">
            <exceptionHandlers>
              <add name="Exception Logging" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging"
                logCategory="Error" eventId="666" severity="Error" title="REPSS .Net Exception Handler"
                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
                priority="1" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
      <add name="Log Only Policy">
        <exceptionTypes>
          <add name="Exception" type="System.Exception, mscorlib" postHandlingAction="None">
            <exceptionHandlers>
              <add name="Exception Logging" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging"
                logCategory="Error" eventId="666" severity="Error" title="REPSS .Net Exception Handler"
                formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling"
                priority="2" />
            </exceptionHandlers>
          </add>
        </exceptionTypes>
      </add>
    </exceptionPolicies>


<loggingConfiguration name="Logging Application Block" tracingEnabled="true"
    defaultCategory="General" logWarningsWhenNoCategoriesMatch="true">
    <listeners>
      <add name="Database Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.Database.FormattedDatabaseTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging.Database"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Database.Configuration.FormattedDatabaseTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging.Database"
        databaseInstanceName="ReiApplicationLogging" writeLogStoredProcName="WriteLog"
        addCategoryStoredProcName="AddCategory" formatter="Database Rei Applications Logging Formatter"
        traceOutputOptions="None" />
      <add name="Formatted EventLog TraceListener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
        source="REPSS .Net" formatter="Text Formatter" log="REI Applications"
        machineName="" traceOutputOptions="LogicalOperationStack" />
      <add name="SDSCellPhone" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.EmailTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging"
        toAddress="sstudy@flexifloat.com" fromAddress="sstudy@flexifloat.com"
        subjectLineStarter="REPSS .Net: " subjectLineEnder="(sms forward)"
        smtpServer="REISRV05" smtpPort="25" formatter="Cell Phone Formatter"
        authenticationMode="WindowsCredentials" traceOutputOptions="LogicalOperationStack, DateTime, Timestamp, ProcessId, ThreadId, Callstack"
        filter="Off" />
      <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=null"
        listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=null"
        fileName="C:\Users\sstudy\Documents\Visual Studio Projects\_Production\Win Forms\REPSS\REPSS .Net Solution\RepssDN\repps net rolling error.log"
        footer="^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"
        formatter="Text Formatter" header="vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv"
        rollInterval="Week" traceOutputOptions="LogicalOperationStack, Callstack" />
    </listeners>
    <formatters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        template="Timestamp: {timestamp(local:F)}&#xD;&#xA;Title:{title}&#xD;&#xA;Machine: {machine}"
        name="Cell Phone Formatter" />
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        template="{newline}{newline}________________________&#xD;&#xA;&#xD;&#xA;Timestamp: {timestamp(local:F)}&#xD;&#xA;&#xD;&#xA;Title:{title}&#xD;&#xA;Process: {processName}&#xD;&#xA;&#xD;&#xA;Extended Properties: &#xD;&#xA;&#xD;&#xA;{dictionary({key} - {value}&#xD;&#xA;&#xD;&#xA;)}{newline}&#xD;&#xA;&#xD;&#xA;Category: {category}&#xD;&#xA;&#xD;&#xA;Priority: {priority}&#xD;&#xA;&#xD;&#xA;EventId: {eventid}&#xD;&#xA;&#xD;&#xA;Severity: {severity}&#xD;&#xA;&#xD;&#xA;Machine: {machine}&#xD;&#xA;&#xD;&#xA;Application Domain: {processName}&#xD;&#xA;&#xD;&#xA;{newline}&#xD;&#xA;&#xD;&#xA;Message: {message}&#xD;&#xA;&#xD;&#xA;{newline}"
        name="Database Rei Applications Logging Formatter" />
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging"
        template="Timestamp: {timestamp(local:F)}&#xD;&#xA;Title:{title}&#xD;&#xA;Message: {message}&#xD;&#xA;{newline}&#xD;&#xA;Category: {category}&#xD;&#xA;Priority: {priority}&#xD;&#xA;EventId: {eventid}&#xD;&#xA;Severity: {severity}&#xD;&#xA;Machine: {machine}&#xD;&#xA;Application Domain: {processName}&#xD;&#xA;Process Id: {processId}&#xD;&#xA;Process Name: {processName}&#xD;&#xA;Win32 Thread Id: {win32ThreadId}&#xD;&#xA;Thread Name: {threadName}&#xD;&#xA;{newline}&#xD;&#xA;Extended Properties: &#xD;&#xA;{dictionary({key} - {value}&#xD;&#xA;)}"
        name="Text Formatter" />
    </formatters>
    <logFilters>
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.LogEnabledFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=null"
        enabled="true" name="Enable All Logging" />
      <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Filters.CategoryFilter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=null"
        categoryFilterMode="AllowAllExceptDenied" name="Trace Filter">
        <categoryFilters>
          <add name="Trace Insane Detail" />
          <add name="Trace Low Level" />
        </categoryFilters>
      </add>
    </logFilters>
    <categorySources>
      <add switchValue="Error" name="Development Error">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
          <add name="SDSCellPhone" />
        </listeners>
      </add>
      <add switchValue="Error" name="Error">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
          <add name="SDSCellPhone" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Feature Usage">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="All" name="General">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="All" name="Security">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Start Up">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Shut Down">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Menu Item Selected">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace High Level">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Mid Level">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Low Level">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Detail">
        <listeners>
          <add name="Database Trace Listener" />
        </listeners>
      </add>
      <add switchValue="ActivityTracing" name="Trace Insane Detail">
        <listeners>
          <add name="Database Trace Listener" />
        </listeners>
      </add>
      <add switchValue="All" name="Trace">
        <listeners>
          <add name="Rolling Flat File Trace Listener" />
        </listeners>
      </add>
      <add switchValue="Verbose" name="Useful Info">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </add>
    </categorySources>
    <specialSources>
      <allEvents switchValue="All" name="All Events">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </allEvents>
      <notProcessed switchValue="All" name="Unprocessed Category">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </notProcessed>
      <errors switchValue="All" name="Logging Errors &amp; Warnings">
        <listeners>
          <add name="Database Trace Listener" />
          <add name="SDSCellPhone" />
          <add name="Formatted EventLog TraceListener" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>

尝试使用@Tuzo 推荐的“SourceLevel”:
@Tuzo,我尝试了“SourceLevel”开关并修改了 app.config 以“关闭”较低级别的跟踪类别。有趣的是,这会产生相反的问题。由于跟踪被链接在一起,EntLib 看到链中至少有一个跟踪类别不是“关闭”(在我的测试用例中,“跟踪高级别”)并继续并将关闭的跟踪记录在较低级别。
这个 EntLib 逻辑在 LogWriterImpl 类的 ProcessLog() 中编码。

最终结果是所有较低级别的跟踪现在都被记录下来,即使它们已关闭。从好的方面来说,我现在确实记录了我的错误。 ;)

我想我会看看你推荐的自定义过滤器,看看我是否可以让它适用于这种情况。

【问题讨论】:

  • 你不应该只使用Throw而不是Throw ex吗?
  • 你能发布你的配置吗?您为 Logging Handler 使用什么类别?
  • @Tuzo,我不确定您想查看多少配置文件。上面的代码只是我为演示我的问题而键入的内容,而不是我为演示问题而运行的实际代码。我遇到此问题的程序中的 app.config 非常大,其中很多内容可能与此特定问题无关。但是,当我的所有日​​志记录工作时,这是类别过滤器部分的 sn-p:
  • 异常处理(有问题的策略)和日志配置会很有用。您可以编辑问题并将其放入代码块中,因为它可能非常大。
  • @Tuzo。会做。只需阅读此评论,让我抓住这些部分并重新编辑。

标签: .net error-handling enterprise-library trace


【解决方案1】:

您看到的行为似乎是设计使然。

如果存在过滤器,则 LogEntry 必须成功通过所有过滤器。与类别过滤器类似,如果您指定为 AllowAllExceptDenied 并且其中一个类别出现在日志条目中,那么它将不会通过类别过滤器并且不会记录消息。

“告诉我一些我还不知道的事情”,你是在说。 :)

我可以想到 2 种方法来解决这个问题:

  • 从使用过滤器切换到 SourceLevel
  • 创建一个完全符合您需要的自定义过滤器

从使用过滤器切换到 SourceLevel

除了通过过滤器启用和禁用活动跟踪之外,您还可以使用 SourceLevel(开关值)来做到这一点。例如,删除您的过滤器,但对于侦听器“Trace Insane Detail”和“Trace Low Level”(如您的过滤器),将 switchValue 设置为 Off;您仍然可以启用“Trace Mid Level”。

  <add switchValue="Off" name="Trace Insane Detail">
    <listeners>
      <add name="Database Trace Listener" />
    </listeners>
  </add>
  <add switchValue="ActivityTracing" name="Trace Mid Level">
    <listeners>
      <add name="Database Trace Listener" />
      <add name="Formatted EventLog TraceListener" />
    </listeners>
  </add>
  <add switchValue="Off" name="Trace Low Level">
    <listeners>
      <add name="Database Trace Listener" />
      <add name="Formatted EventLog TraceListener" />
    </listeners>
  </add>

创建一个自定义过滤器 正是你需要的

自定义过滤器可让您做几乎任何您想做的事情。它更复杂,所以可能只有在绝对必要的情况下才应该这样做。请参阅 Using Custom Filters in the Enterprise Library Logging Block 了解一个很好的例子。

【讨论】:

  • 好吧,自定义过滤器可以解决我的问题。再次感谢@Tuzo。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-09
  • 2010-12-29
  • 2020-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多