使用Ent-Lib拨打跟踪的意外后果,没有错误记录

时间:2011-06-23 20:11:42

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

我使用企业库跟踪和异常日志记录遇到了意外问题。我注意到的是,当我使用“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()中编码。

最终结果是,即使关闭了所有较低级别的跟踪,现在也会被记录。好的一面,我现在记录了我的错误。 ;)
我想看看你推荐的自定义过滤器,看看我是否可以为这种情况做好准备。

1 个答案:

答案 0 :(得分:2)

您所看到的行为似乎是设计上的。

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

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

我可以想出两种方法来解决这个问题:

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

从使用过滤器切换到SourceLevel

不是通过过滤器启用和禁用活动跟踪,而是使用SourceLevel(switchvalue)也可以做到这一点。 E.g删除过滤器,但对于听众“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以获取一个好例子。