减少异常/ Environment.StackTrace有意义

时间:2011-06-24 18:40:56

标签: .net debugging stack-trace text-parsing error-logging

我正在分析遗留应用程序中的错误,因为我将其清理并进行改进。我有一些堆栈跟踪记录到数据库,但有一个限制(VARCHAR2(1000))存储多少,并且错误发生在System.Data深层......

   at System.Data.OracleClient.OracleConnection.CheckError(OciErrorHandle errorHandle, Int32 rc)
   at System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle, CommandBehavior behavior, Boolean needRowid, OciRowidDescriptor& rowidDescriptor, ArrayList& resultParameterOrdinals)
   at System.Data.OracleClient.OracleCommand.Execute(OciStatementHandle statementHandle, CommandBehavior behavior, ArrayList& resultParameterOrdinals)
   at System.Data.OracleClient.OracleCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.OracleClient.OracleCommand.ExecuteDbDataReader(CommandBehavior behavior)
   at System.Data.Common.DbCommand.System.Data.IDbCommand.ExecuteReader(CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.FillInternal(DataSet dataset, DataTable[] datatables, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet, Int32 startRecord, Int32 maxRecords, String srcTable, IDbCommand command, CommandBehavior behavior)
   at System.Data.Common.DbDataAdapter.Fill(DataSet dataSet)

我不关心所有这些 - 我只需要找到哪些C#代码和哪个proc产生错误。因此,我可以找出根本原因,将代码重构为质量并改进每个模块,因为我点击了最低挂起最错误的代码。

在我去写东西之前,有人会有一些东西会限制堆栈跟踪到某些程序集,所以我可以找到根本原因吗?或者是堆栈跟踪解析器或现成的东西,我可以用来在记录错误之前删除我不感兴趣的东西?

3 个答案:

答案 0 :(得分:2)

减少.Net异常的代码

你很幸运 - 有人读过你的帖子!我想通过将我的错误重新格式化为这样的东西,至少从史蒂文金小说的阅读中拯救了我的眼睛:

(< pre>不尊重我的tabstops,所以它在现实生活中看起来更好)

System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
FUNCTION    FILE    LINE
CoCreateInstance    (no .PDB)
CreateWithoutLicense    (no .PDB)
CreateWithLicense   (no .PDB)
CreateInstanceCore  (no .PDB)
CreateInstance  (no .PDB)
GetOcxCreate    (no .PDB)
TransitionUpTo  (no .PDB)
CreateHandle    (no .PDB)
CreateControl   (no .PDB)
CreateControl   (no .PDB)
EndInit (no .PDB)
InitializeComponent frmGetSig.Designer.vb   187
ctor    frmGetSig.vb    264
btnSign_Click   ucSignCapture_v2.vb 306

使用此代码:

Public Shared Function ReduceError(ByVal stExceptionToString As String) As String
    Try
        ''// split into message and stack trace items
        Dim stMainSplit() As String = Split(stExceptionToString, vbCrLf & "   at ")
        If UBound(stMainSplit) = 0 Then
            Return stExceptionToString
        End If
        ''// add the message
        Dim stResults As String = stMainSplit(0) & vbCrLf
        Dim bLastWasInner As Boolean
        ''// Headings, if there is a stack trace
        If UBound(stMainSplit) > 0 Then
            stResults &= "FUNCTION" & vbTab & "FILE" & vbTab & "LINE" & vbCrLf
        End If
        ''// reduce the stack trace
        For i As Integer = 1 To UBound(stMainSplit)
            Dim st As String = stMainSplit(i)
            ''// skip the line following inner exception in stack trace
            If Not bLastWasInner Then
                ''// split the sub from line # info
                Dim stln() As String = Split(st, ")")
                If UBound(stln) = 1 Then
                    ''// first put the sub on there
                    Dim stsub As String = Mid(stln(0), 1, InStrRev(stln(0), "(") - 1)
                    If InStr(stsub, ".") <> 0 Then
                        stsub = Mid(stsub, InStrRev(stsub, ".") + 1)
                    End If
                    stResults &= stsub & vbTab
                    ''// Now if there is file/line # info, add that. 
                    Dim stFile As String = "(no .PDB)"
                    If 0 <> InStr(stln(1), "\") Then '' " //good grief SOF learn vb ;-)
                        stFile = Replace(Mid(stln(1), InStrRev(stln(1), "\") + 1), ":line ", vbTab) '' "
                        ''// take off CR and 'inner exception..." text
                        If InStr(stFile, vbCrLf) > 1 Then
                            stFile = Mid(stFile, 1, InStr(stFile, vbCrLf) - 1)
                        End If
                    End If
                    stResults &= stFile & vbCrLf
                Else
                    stResults &= "Line split by ) has no (" & vbTab & vbCrLf
                End If
            End If
            If 0 <> InStr(st, "End of inner exception stack trace") Then
                bLastWasInner = True
            Else
                bLastWasInner = False
            End If
        Next
        Return stResults
    Catch ex As Exception 
        ''// might want to return orig error here as well..
        Return "Error summarizing routine as error'd: " & ex.ToString
    End Try
End Function

它放入我在文本框中使用的标签,如果你愿意,很容易改变;如果你不关心system.data行,你可以随时排除它们。为.net 1.1编写,应该转换为c#well。

答案 1 :(得分:1)

最简单的方法是增加限制。

亚军最简单的方法是修改日志记录,使其占用堆栈跟踪的最后1000个字符(如果它更长),而不是插入整个内容。任何其他解决方案还必须修改日志记录或作为MitM拦截和更改信息,然后再继续使用记录器。

您无法更改.NET生成堆栈跟踪文本的方式(例如忽略某些程序集),因此在记录之前这一切都归结为字符串操作。

答案 2 :(得分:0)

我最后只使用正则表达式删除了我不想要的行:

Trace = Regex.Replace(Trace
                      , "^.*" + FilterPattern + ".*$\n"
                      , string.Empty
                      , RegexOptions.Multiline | RegexOptions.IgnoreCase);